1use async_trait::async_trait;
2use chrono::{DateTime, Utc};
3use std::collections::HashMap;
4use std::sync::{Arc, Mutex};
5use uuid::Uuid;
6
7use crate::error::{AuthError, AuthResult};
8use crate::types::{
9 Account, CreateAccount, CreateSession, CreateUser, CreateVerification, Session, UpdateUser,
10 User, Verification,
11};
12
13#[async_trait]
15pub trait DatabaseAdapter: Send + Sync {
16 async fn create_user(&self, user: CreateUser) -> AuthResult<User>;
18 async fn get_user_by_id(&self, id: &str) -> AuthResult<Option<User>>;
19 async fn get_user_by_email(&self, email: &str) -> AuthResult<Option<User>>;
20 async fn get_user_by_username(&self, username: &str) -> AuthResult<Option<User>>;
21 async fn update_user(&self, id: &str, update: UpdateUser) -> AuthResult<User>;
22 async fn delete_user(&self, id: &str) -> AuthResult<()>;
23
24 async fn create_session(&self, session: CreateSession) -> AuthResult<Session>;
26 async fn get_session(&self, token: &str) -> AuthResult<Option<Session>>;
27 async fn get_user_sessions(&self, user_id: &str) -> AuthResult<Vec<Session>>;
28 async fn update_session_expiry(&self, token: &str, expires_at: DateTime<Utc>)
29 -> AuthResult<()>;
30 async fn delete_session(&self, token: &str) -> AuthResult<()>;
31 async fn delete_user_sessions(&self, user_id: &str) -> AuthResult<()>;
32 async fn delete_expired_sessions(&self) -> AuthResult<usize>;
33
34 async fn create_account(&self, account: CreateAccount) -> AuthResult<Account>;
36 async fn get_account(
37 &self,
38 provider: &str,
39 provider_account_id: &str,
40 ) -> AuthResult<Option<Account>>;
41 async fn get_user_accounts(&self, user_id: &str) -> AuthResult<Vec<Account>>;
42 async fn delete_account(&self, id: &str) -> AuthResult<()>;
43
44 async fn create_verification(
46 &self,
47 verification: CreateVerification,
48 ) -> AuthResult<Verification>;
49 async fn get_verification(
50 &self,
51 identifier: &str,
52 value: &str,
53 ) -> AuthResult<Option<Verification>>;
54 async fn get_verification_by_value(&self, value: &str) -> AuthResult<Option<Verification>>;
55 async fn delete_verification(&self, id: &str) -> AuthResult<()>;
56 async fn delete_expired_verifications(&self) -> AuthResult<usize>;
57}
58
59pub struct MemoryDatabaseAdapter {
61 users: Arc<Mutex<HashMap<String, User>>>,
62 sessions: Arc<Mutex<HashMap<String, Session>>>,
63 accounts: Arc<Mutex<HashMap<String, Account>>>,
64 verifications: Arc<Mutex<HashMap<String, Verification>>>,
65 email_index: Arc<Mutex<HashMap<String, String>>>, username_index: Arc<Mutex<HashMap<String, String>>>, }
68
69impl MemoryDatabaseAdapter {
70 pub fn new() -> Self {
71 Self {
72 users: Arc::new(Mutex::new(HashMap::new())),
73 sessions: Arc::new(Mutex::new(HashMap::new())),
74 accounts: Arc::new(Mutex::new(HashMap::new())),
75 verifications: Arc::new(Mutex::new(HashMap::new())),
76 email_index: Arc::new(Mutex::new(HashMap::new())),
77 username_index: Arc::new(Mutex::new(HashMap::new())),
78 }
79 }
80}
81
82impl Default for MemoryDatabaseAdapter {
83 fn default() -> Self {
84 Self::new()
85 }
86}
87
88#[async_trait]
89impl DatabaseAdapter for MemoryDatabaseAdapter {
90 async fn create_user(&self, create_user: CreateUser) -> AuthResult<User> {
91 let mut users = self.users.lock().unwrap();
92 let mut email_index = self.email_index.lock().unwrap();
93 let mut username_index = self.username_index.lock().unwrap();
94
95 let id = create_user.id.unwrap_or_else(|| Uuid::new_v4().to_string());
96
97 if let Some(email) = &create_user.email
99 && email_index.contains_key(email)
100 {
101 return Err(AuthError::config("Email already exists"));
102 }
103
104 if let Some(username) = &create_user.username
106 && username_index.contains_key(username)
107 {
108 return Err(AuthError::conflict(
109 "A user with this username already exists",
110 ));
111 }
112
113 let now = Utc::now();
114 let user = User {
115 id: id.clone(),
116 name: create_user.name,
117 email: create_user.email.clone(),
118 email_verified: create_user.email_verified.unwrap_or(false),
119 image: create_user.image,
120 created_at: now,
121 updated_at: now,
122 username: create_user.username.clone(),
123 display_username: create_user.display_username,
124 two_factor_enabled: false,
125 role: create_user.role,
126 banned: false,
127 ban_reason: None,
128 ban_expires: None,
129 metadata: create_user.metadata.unwrap_or_default(),
130 };
131
132 users.insert(id.clone(), user.clone());
133
134 if let Some(email) = &create_user.email {
135 email_index.insert(email.clone(), id.clone());
136 }
137
138 if let Some(username) = &create_user.username {
139 username_index.insert(username.clone(), id);
140 }
141
142 Ok(user)
143 }
144
145 async fn get_user_by_id(&self, id: &str) -> AuthResult<Option<User>> {
146 let users = self.users.lock().unwrap();
147 Ok(users.get(id).cloned())
148 }
149
150 async fn get_user_by_email(&self, email: &str) -> AuthResult<Option<User>> {
151 let email_index = self.email_index.lock().unwrap();
152 let users = self.users.lock().unwrap();
153
154 if let Some(user_id) = email_index.get(email) {
155 Ok(users.get(user_id).cloned())
156 } else {
157 Ok(None)
158 }
159 }
160
161 async fn get_user_by_username(&self, username: &str) -> AuthResult<Option<User>> {
162 let username_index = self.username_index.lock().unwrap();
163 let users = self.users.lock().unwrap();
164
165 if let Some(user_id) = username_index.get(username) {
166 Ok(users.get(user_id).cloned())
167 } else {
168 Ok(None)
169 }
170 }
171
172 async fn update_user(&self, id: &str, update: UpdateUser) -> AuthResult<User> {
173 let mut users = self.users.lock().unwrap();
174 let mut email_index = self.email_index.lock().unwrap();
175 let mut username_index = self.username_index.lock().unwrap();
176
177 let user = users.get_mut(id).ok_or(AuthError::UserNotFound)?;
178
179 if let Some(new_email) = &update.email {
181 if let Some(old_email) = &user.email {
182 email_index.remove(old_email);
183 }
184 email_index.insert(new_email.clone(), id.to_string());
185 user.email = Some(new_email.clone());
186 }
187
188 if let Some(name) = update.name {
189 user.name = Some(name);
190 }
191
192 if let Some(image) = update.image {
193 user.image = Some(image);
194 }
195
196 if let Some(email_verified) = update.email_verified {
197 user.email_verified = email_verified;
198 }
199
200 if let Some(ref username) = update.username {
201 if let Some(old_username) = &user.username {
203 username_index.remove(old_username);
204 }
205 username_index.insert(username.clone(), id.to_string());
206 user.username = Some(username.clone());
207 }
208
209 if let Some(display_username) = update.display_username {
210 user.display_username = Some(display_username);
211 }
212
213 if let Some(role) = update.role {
214 user.role = Some(role);
215 }
216
217 if let Some(banned) = update.banned {
218 user.banned = banned;
219 }
220
221 if let Some(ban_reason) = update.ban_reason {
222 user.ban_reason = Some(ban_reason);
223 }
224
225 if let Some(ban_expires) = update.ban_expires {
226 user.ban_expires = Some(ban_expires);
227 }
228
229 if let Some(two_factor_enabled) = update.two_factor_enabled {
230 user.two_factor_enabled = two_factor_enabled;
231 }
232
233 if let Some(metadata) = update.metadata {
234 user.metadata = metadata;
235 }
236
237 user.updated_at = Utc::now();
238
239 Ok(user.clone())
240 }
241
242 async fn delete_user(&self, id: &str) -> AuthResult<()> {
243 let mut users = self.users.lock().unwrap();
244 let mut email_index = self.email_index.lock().unwrap();
245 let mut username_index = self.username_index.lock().unwrap();
246
247 if let Some(user) = users.remove(id) {
248 if let Some(email) = &user.email {
249 email_index.remove(email);
250 }
251 if let Some(username) = &user.username {
252 username_index.remove(username);
253 }
254 }
255
256 Ok(())
257 }
258
259 async fn create_session(&self, create_session: CreateSession) -> AuthResult<Session> {
260 let mut sessions = self.sessions.lock().unwrap();
261
262 let token = format!("session_{}", Uuid::new_v4());
263 let now = Utc::now();
264 let session = Session {
265 id: Uuid::new_v4().to_string(),
266 expires_at: create_session.expires_at,
267 token: token.clone(),
268 created_at: now,
269 updated_at: now,
270 ip_address: create_session.ip_address,
271 user_agent: create_session.user_agent,
272 user_id: create_session.user_id,
273 impersonated_by: create_session.impersonated_by,
274 active_organization_id: create_session.active_organization_id,
275 active: true,
276 };
277
278 sessions.insert(token, session.clone());
279 Ok(session)
280 }
281
282 async fn get_session(&self, token: &str) -> AuthResult<Option<Session>> {
283 let sessions = self.sessions.lock().unwrap();
284 Ok(sessions.get(token).cloned())
285 }
286
287 async fn get_user_sessions(&self, user_id: &str) -> AuthResult<Vec<Session>> {
288 let sessions = self.sessions.lock().unwrap();
289 Ok(sessions
290 .values()
291 .filter(|session| session.user_id == user_id && session.active)
292 .cloned()
293 .collect())
294 }
295
296 async fn update_session_expiry(
297 &self,
298 token: &str,
299 expires_at: DateTime<Utc>,
300 ) -> AuthResult<()> {
301 let mut sessions = self.sessions.lock().unwrap();
302 if let Some(session) = sessions.get_mut(token) {
303 session.expires_at = expires_at;
304 }
305 Ok(())
306 }
307
308 async fn delete_session(&self, token: &str) -> AuthResult<()> {
309 let mut sessions = self.sessions.lock().unwrap();
310 sessions.remove(token);
311 Ok(())
312 }
313
314 async fn delete_user_sessions(&self, user_id: &str) -> AuthResult<()> {
315 let mut sessions = self.sessions.lock().unwrap();
316 sessions.retain(|_, session| session.user_id != user_id);
317 Ok(())
318 }
319
320 async fn delete_expired_sessions(&self) -> AuthResult<usize> {
321 let mut sessions = self.sessions.lock().unwrap();
322 let now = Utc::now();
323 let initial_count = sessions.len();
324
325 sessions.retain(|_, session| session.expires_at > now && session.active);
326
327 Ok(initial_count - sessions.len())
328 }
329
330 async fn create_account(&self, create_account: CreateAccount) -> AuthResult<Account> {
331 let mut accounts = self.accounts.lock().unwrap();
332
333 let now = Utc::now();
334 let account = Account {
335 id: Uuid::new_v4().to_string(),
336 account_id: create_account.account_id,
337 provider_id: create_account.provider_id,
338 user_id: create_account.user_id,
339 access_token: create_account.access_token,
340 refresh_token: create_account.refresh_token,
341 id_token: create_account.id_token,
342 access_token_expires_at: create_account.access_token_expires_at,
343 refresh_token_expires_at: create_account.refresh_token_expires_at,
344 scope: create_account.scope,
345 password: create_account.password,
346 created_at: now,
347 updated_at: now,
348 };
349
350 accounts.insert(account.id.clone(), account.clone());
351 Ok(account)
352 }
353
354 async fn get_account(
355 &self,
356 provider: &str,
357 provider_account_id: &str,
358 ) -> AuthResult<Option<Account>> {
359 let accounts = self.accounts.lock().unwrap();
360 Ok(accounts
361 .values()
362 .find(|acc| acc.provider_id == provider && acc.account_id == provider_account_id)
363 .cloned())
364 }
365
366 async fn get_user_accounts(&self, user_id: &str) -> AuthResult<Vec<Account>> {
367 let accounts = self.accounts.lock().unwrap();
368 Ok(accounts
369 .values()
370 .filter(|acc| acc.user_id == user_id)
371 .cloned()
372 .collect())
373 }
374
375 async fn delete_account(&self, id: &str) -> AuthResult<()> {
376 let mut accounts = self.accounts.lock().unwrap();
377 accounts.remove(id);
378 Ok(())
379 }
380
381 async fn create_verification(
382 &self,
383 create_verification: CreateVerification,
384 ) -> AuthResult<Verification> {
385 let mut verifications = self.verifications.lock().unwrap();
386
387 let now = Utc::now();
388 let verification = Verification {
389 id: Uuid::new_v4().to_string(),
390 identifier: create_verification.identifier,
391 value: create_verification.value.clone(),
392 expires_at: create_verification.expires_at,
393 created_at: now,
394 updated_at: now,
395 };
396
397 verifications.insert(verification.id.clone(), verification.clone());
398 Ok(verification)
399 }
400
401 async fn get_verification(
402 &self,
403 identifier: &str,
404 value: &str,
405 ) -> AuthResult<Option<Verification>> {
406 let verifications = self.verifications.lock().unwrap();
407 let now = Utc::now();
408
409 Ok(verifications
410 .values()
411 .find(|v| v.identifier == identifier && v.value == value && v.expires_at > now)
412 .cloned())
413 }
414
415 async fn get_verification_by_value(&self, value: &str) -> AuthResult<Option<Verification>> {
416 let verifications = self.verifications.lock().unwrap();
417 let now = Utc::now();
418
419 Ok(verifications
420 .values()
421 .find(|v| v.value == value && v.expires_at > now)
422 .cloned())
423 }
424
425 async fn delete_verification(&self, id: &str) -> AuthResult<()> {
426 let mut verifications = self.verifications.lock().unwrap();
427 verifications.remove(id);
428 Ok(())
429 }
430
431 async fn delete_expired_verifications(&self) -> AuthResult<usize> {
432 let mut verifications = self.verifications.lock().unwrap();
433 let now = Utc::now();
434 let initial_count = verifications.len();
435
436 verifications.retain(|_, verification| verification.expires_at > now);
437
438 Ok(initial_count - verifications.len())
439 }
440}
441
442#[cfg(feature = "sqlx-postgres")]
443pub mod sqlx_adapter {
444 use super::*;
445 use sqlx::PgPool;
446
447 pub struct SqlxAdapter {
448 pool: PgPool,
449 }
450
451 impl SqlxAdapter {
452 pub async fn new(database_url: &str) -> Result<Self, sqlx::Error> {
453 let pool = PgPool::connect(database_url).await?;
454 Ok(Self { pool })
455 }
456
457 pub async fn with_config(
459 database_url: &str,
460 config: PoolConfig,
461 ) -> Result<Self, sqlx::Error> {
462 let pool = sqlx::postgres::PgPoolOptions::new()
463 .max_connections(config.max_connections)
464 .min_connections(config.min_connections)
465 .acquire_timeout(config.acquire_timeout)
466 .idle_timeout(config.idle_timeout)
467 .max_lifetime(config.max_lifetime)
468 .connect(database_url)
469 .await?;
470 Ok(Self { pool })
471 }
472
473 pub fn from_pool(pool: PgPool) -> Self {
474 Self { pool }
475 }
476
477 pub async fn test_connection(&self) -> Result<(), sqlx::Error> {
479 sqlx::query("SELECT 1").execute(&self.pool).await?;
480 Ok(())
481 }
482
483 pub fn pool_stats(&self) -> PoolStats {
485 PoolStats {
486 size: self.pool.size(),
487 idle: self.pool.num_idle(),
488 }
489 }
490
491 pub async fn close(&self) {
493 self.pool.close().await;
494 }
495 }
496
497 #[derive(Debug, Clone)]
499 pub struct PoolConfig {
500 pub max_connections: u32,
501 pub min_connections: u32,
502 pub acquire_timeout: std::time::Duration,
503 pub idle_timeout: Option<std::time::Duration>,
504 pub max_lifetime: Option<std::time::Duration>,
505 }
506
507 impl Default for PoolConfig {
508 fn default() -> Self {
509 Self {
510 max_connections: 10,
511 min_connections: 0,
512 acquire_timeout: std::time::Duration::from_secs(30),
513 idle_timeout: Some(std::time::Duration::from_secs(600)), max_lifetime: Some(std::time::Duration::from_secs(1800)), }
516 }
517 }
518
519 #[derive(Debug, Clone)]
521 pub struct PoolStats {
522 pub size: u32,
523 pub idle: usize,
524 }
525
526 #[async_trait]
527 impl DatabaseAdapter for SqlxAdapter {
528 async fn create_user(&self, create_user: CreateUser) -> AuthResult<User> {
529 let id = create_user.id.unwrap_or_else(|| Uuid::new_v4().to_string());
530 let now = Utc::now();
531
532 let user = sqlx::query_as::<_, User>(
533 r#"
534 INSERT INTO users (id, email, name, image, email_verified, created_at, updated_at, metadata)
535 VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
536 RETURNING id, email, name, image, email_verified, created_at, updated_at, metadata
537 "#
538 )
539 .bind(&id)
540 .bind(&create_user.email)
541 .bind(&create_user.name)
542 .bind(&create_user.image)
543 .bind(false)
544 .bind(&now)
545 .bind(&now)
546 .bind(sqlx::types::Json(create_user.metadata.unwrap_or_default()))
547 .fetch_one(&self.pool)
548 .await?;
549
550 Ok(user)
551 }
552
553 async fn get_user_by_id(&self, id: &str) -> AuthResult<Option<User>> {
554 let user = sqlx::query_as::<_, User>(
555 r#"
556 SELECT id, email, name, image, email_verified, created_at, updated_at, metadata
557 FROM users WHERE id = $1
558 "#,
559 )
560 .bind(id)
561 .fetch_optional(&self.pool)
562 .await?;
563
564 Ok(user)
565 }
566
567 async fn get_user_by_email(&self, email: &str) -> AuthResult<Option<User>> {
568 let user = sqlx::query_as::<_, User>(
569 r#"
570 SELECT id, email, name, image, email_verified, created_at, updated_at, metadata
571 FROM users WHERE email = $1
572 "#,
573 )
574 .bind(email)
575 .fetch_optional(&self.pool)
576 .await?;
577
578 Ok(user)
579 }
580
581 async fn get_user_by_username(&self, username: &str) -> AuthResult<Option<User>> {
582 let user = sqlx::query_as::<_, User>(
583 r#"
584 SELECT id, email, name, image, email_verified, created_at, updated_at, metadata
585 FROM users WHERE username = $1
586 "#,
587 )
588 .bind(username)
589 .fetch_optional(&self.pool)
590 .await?;
591
592 Ok(user)
593 }
594
595 async fn update_user(&self, id: &str, update: UpdateUser) -> AuthResult<User> {
596 let mut query = sqlx::QueryBuilder::new("UPDATE users SET updated_at = NOW()");
597 let mut has_updates = false;
598
599 if let Some(email) = &update.email {
600 query.push(", email = ");
601 query.push_bind(email);
602 has_updates = true;
603 }
604
605 if let Some(name) = &update.name {
606 query.push(", name = ");
607 query.push_bind(name);
608 has_updates = true;
609 }
610
611 if let Some(image) = &update.image {
612 query.push(", image = ");
613 query.push_bind(image);
614 has_updates = true;
615 }
616
617 if let Some(email_verified) = update.email_verified {
618 query.push(", email_verified = ");
619 query.push_bind(email_verified);
620 has_updates = true;
621 }
622
623 if let Some(metadata) = &update.metadata {
624 query.push(", metadata = ");
625 query.push_bind(sqlx::types::Json(metadata.clone()));
626 has_updates = true;
627 }
628
629 if !has_updates {
630 return self
632 .get_user_by_id(id)
633 .await?
634 .ok_or(AuthError::UserNotFound);
635 }
636
637 query.push(" WHERE id = ");
638 query.push_bind(id);
639 query.push(" RETURNING id, email, name, image, email_verified, created_at, updated_at, metadata");
640
641 let user = query.build_query_as::<User>().fetch_one(&self.pool).await?;
642
643 Ok(user)
644 }
645
646 async fn delete_user(&self, id: &str) -> AuthResult<()> {
647 sqlx::query("DELETE FROM users WHERE id = $1")
648 .bind(id)
649 .execute(&self.pool)
650 .await?;
651
652 Ok(())
653 }
654
655 async fn create_session(&self, create_session: CreateSession) -> AuthResult<Session> {
656 let id = Uuid::new_v4().to_string();
657 let token = format!("session_{}", Uuid::new_v4());
658 let now = Utc::now();
659
660 let session = sqlx::query_as::<_, Session>(
661 r#"
662 INSERT INTO sessions (id, user_id, token, expires_at, created_at, ip_address, user_agent, active)
663 VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
664 RETURNING id, user_id, token, expires_at, created_at, ip_address, user_agent, active
665 "#
666 )
667 .bind(&id)
668 .bind(&create_session.user_id)
669 .bind(&token)
670 .bind(&create_session.expires_at)
671 .bind(&now)
672 .bind(&create_session.ip_address)
673 .bind(&create_session.user_agent)
674 .bind(true)
675 .fetch_one(&self.pool)
676 .await?;
677
678 Ok(session)
679 }
680
681 async fn get_session(&self, token: &str) -> AuthResult<Option<Session>> {
682 let session = sqlx::query_as::<_, Session>(
683 r#"
684 SELECT id, user_id, token, expires_at, created_at, updated_at, ip_address, user_agent, active, impersonated_by, active_organization_id
685 FROM sessions
686 WHERE token = $1 AND active = true
687 "#
688 )
689 .bind(token)
690 .fetch_optional(&self.pool)
691 .await?;
692
693 Ok(session)
694 }
695
696 async fn get_user_sessions(&self, user_id: &str) -> AuthResult<Vec<Session>> {
697 let sessions = sqlx::query_as::<_, Session>(
698 r#"
699 SELECT id, user_id, token, expires_at, created_at, updated_at, ip_address, user_agent, active, impersonated_by, active_organization_id
700 FROM sessions
701 WHERE user_id = $1 AND active = true
702 ORDER BY created_at DESC
703 "#
704 )
705 .bind(user_id)
706 .fetch_all(&self.pool)
707 .await?;
708
709 Ok(sessions)
710 }
711
712 async fn update_session_expiry(
713 &self,
714 token: &str,
715 expires_at: DateTime<Utc>,
716 ) -> AuthResult<()> {
717 sqlx::query(
718 r#"
719 UPDATE sessions
720 SET expires_at = $1
721 WHERE token = $2 AND active = true
722 "#,
723 )
724 .bind(&expires_at)
725 .bind(token)
726 .execute(&self.pool)
727 .await?;
728
729 Ok(())
730 }
731
732 async fn delete_session(&self, token: &str) -> AuthResult<()> {
733 sqlx::query("DELETE FROM sessions WHERE token = $1")
734 .bind(token)
735 .execute(&self.pool)
736 .await?;
737
738 Ok(())
739 }
740
741 async fn delete_user_sessions(&self, user_id: &str) -> AuthResult<()> {
742 sqlx::query("DELETE FROM sessions WHERE user_id = $1")
743 .bind(user_id)
744 .execute(&self.pool)
745 .await?;
746
747 Ok(())
748 }
749
750 async fn delete_expired_sessions(&self) -> AuthResult<usize> {
751 let result =
752 sqlx::query("DELETE FROM sessions WHERE expires_at < NOW() OR active = false")
753 .execute(&self.pool)
754 .await?;
755
756 Ok(result.rows_affected() as usize)
757 }
758
759 async fn create_account(&self, create_account: CreateAccount) -> AuthResult<Account> {
760 let id = Uuid::new_v4().to_string();
761 let now = Utc::now();
762
763 let account = sqlx::query_as::<_, Account>(
764 r#"
765 INSERT INTO accounts (id, account_id, provider_id, user_id, access_token, refresh_token, id_token, access_token_expires_at, refresh_token_expires_at, scope, password, created_at, updated_at)
766 VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
767 RETURNING *
768 "#
769 )
770 .bind(&id)
771 .bind(&create_account.account_id)
772 .bind(&create_account.provider_id)
773 .bind(&create_account.user_id)
774 .bind(&create_account.access_token)
775 .bind(&create_account.refresh_token)
776 .bind(&create_account.id_token)
777 .bind(&create_account.access_token_expires_at)
778 .bind(&create_account.refresh_token_expires_at)
779 .bind(&create_account.scope)
780 .bind(&create_account.password)
781 .bind(&now)
782 .bind(&now)
783 .fetch_one(&self.pool)
784 .await?;
785
786 Ok(account)
787 }
788
789 async fn get_account(
790 &self,
791 provider: &str,
792 provider_account_id: &str,
793 ) -> AuthResult<Option<Account>> {
794 let account = sqlx::query_as::<_, Account>(
795 r#"
796 SELECT *
797 FROM accounts
798 WHERE provider_id = $1 AND account_id = $2
799 "#,
800 )
801 .bind(provider)
802 .bind(provider_account_id)
803 .fetch_optional(&self.pool)
804 .await?;
805
806 Ok(account)
807 }
808
809 async fn get_user_accounts(&self, user_id: &str) -> AuthResult<Vec<Account>> {
810 let accounts = sqlx::query_as::<_, Account>(
811 r#"
812 SELECT id, user_id, provider, provider_account_id, access_token, refresh_token, expires_at, token_type, scope, created_at
813 FROM accounts
814 WHERE user_id = $1
815 ORDER BY created_at DESC
816 "#
817 )
818 .bind(user_id)
819 .fetch_all(&self.pool)
820 .await?;
821
822 Ok(accounts)
823 }
824
825 async fn delete_account(&self, id: &str) -> AuthResult<()> {
826 sqlx::query("DELETE FROM accounts WHERE id = $1")
827 .bind(id)
828 .execute(&self.pool)
829 .await?;
830
831 Ok(())
832 }
833
834 async fn create_verification(
835 &self,
836 create_verification: CreateVerification,
837 ) -> AuthResult<Verification> {
838 let id = Uuid::new_v4().to_string();
839 let now = Utc::now();
840
841 let verification = sqlx::query_as::<_, Verification>(
842 r#"
843 INSERT INTO verifications (id, identifier, value, expires_at, created_at, updated_at)
844 VALUES ($1, $2, $3, $4, $5, $6)
845 RETURNING *
846 "#
847 )
848 .bind(&id)
849 .bind(&create_verification.identifier)
850 .bind(&create_verification.value)
851 .bind(&create_verification.expires_at)
852 .bind(&now)
853 .bind(&now)
854 .fetch_one(&self.pool)
855 .await?;
856
857 Ok(verification)
858 }
859
860 async fn get_verification(
861 &self,
862 identifier: &str,
863 value: &str,
864 ) -> AuthResult<Option<Verification>> {
865 let verification = sqlx::query_as::<_, Verification>(
866 r#"
867 SELECT *
868 FROM verifications
869 WHERE identifier = $1 AND value = $2 AND expires_at > NOW()
870 "#,
871 )
872 .bind(identifier)
873 .bind(value)
874 .fetch_optional(&self.pool)
875 .await?;
876
877 Ok(verification)
878 }
879
880 async fn get_verification_by_value(&self, value: &str) -> AuthResult<Option<Verification>> {
881 let verification = sqlx::query_as::<_, Verification>(
882 r#"
883 SELECT *
884 FROM verifications
885 WHERE value = $1 AND expires_at > NOW()
886 "#,
887 )
888 .bind(value)
889 .fetch_optional(&self.pool)
890 .await?;
891
892 Ok(verification)
893 }
894
895 async fn delete_verification(&self, id: &str) -> AuthResult<()> {
896 sqlx::query("DELETE FROM verifications WHERE id = $1")
897 .bind(id)
898 .execute(&self.pool)
899 .await?;
900
901 Ok(())
902 }
903
904 async fn delete_expired_verifications(&self) -> AuthResult<usize> {
905 let result = sqlx::query("DELETE FROM verifications WHERE expires_at < NOW()")
906 .execute(&self.pool)
907 .await?;
908
909 Ok(result.rows_affected() as usize)
910 }
911 }
912}
913
914#[cfg(feature = "sqlx-postgres")]
915pub use sqlx_adapter::SqlxAdapter;