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, ApiKey, CreateAccount, CreateApiKey, CreateInvitation, CreateMember,
10 CreateOrganization, CreatePasskey, CreateSession, CreateTwoFactor, CreateUser,
11 CreateVerification, Invitation, InvitationStatus, Member, Organization, Passkey, Session,
12 TwoFactor, UpdateAccount, UpdateApiKey, UpdateOrganization, UpdateUser, User, Verification,
13};
14
15pub use super::memory_traits::{
16 MemoryAccount, MemoryApiKey, MemoryInvitation, MemoryMember, MemoryOrganization, MemoryPasskey,
17 MemorySession, MemoryTwoFactor, MemoryUser, MemoryVerification,
18};
19
20use super::traits::{
21 AccountOps, ApiKeyOps, InvitationOps, MemberOps, OrganizationOps, PasskeyOps, SessionOps,
22 TwoFactorOps, UserOps, VerificationOps,
23};
24
25pub struct MemoryDatabaseAdapter<
40 U = User,
41 S = Session,
42 A = Account,
43 O = Organization,
44 M = Member,
45 I = Invitation,
46 V = Verification,
47 P = Passkey,
48> {
49 users: Arc<Mutex<HashMap<String, U>>>,
50 sessions: Arc<Mutex<HashMap<String, S>>>,
51 accounts: Arc<Mutex<HashMap<String, A>>>,
52 verifications: Arc<Mutex<HashMap<String, V>>>,
53 email_index: Arc<Mutex<HashMap<String, String>>>,
54 username_index: Arc<Mutex<HashMap<String, String>>>,
55 organizations: Arc<Mutex<HashMap<String, O>>>,
56 members: Arc<Mutex<HashMap<String, M>>>,
57 invitations: Arc<Mutex<HashMap<String, I>>>,
58 slug_index: Arc<Mutex<HashMap<String, String>>>,
59 two_factors: Arc<Mutex<HashMap<String, TwoFactor>>>,
60 api_keys: Arc<Mutex<HashMap<String, ApiKey>>>,
61 passkeys: Arc<Mutex<HashMap<String, P>>>,
62 passkey_credential_index: Arc<Mutex<HashMap<String, String>>>,
63}
64
65impl MemoryDatabaseAdapter {
68 pub fn new() -> Self {
69 Self::default()
70 }
71}
72
73impl<U, S, A, O, M, I, V, P> Default for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P> {
74 fn default() -> Self {
75 Self {
76 users: Arc::new(Mutex::new(HashMap::new())),
77 sessions: Arc::new(Mutex::new(HashMap::new())),
78 accounts: Arc::new(Mutex::new(HashMap::new())),
79 verifications: Arc::new(Mutex::new(HashMap::new())),
80 email_index: Arc::new(Mutex::new(HashMap::new())),
81 username_index: Arc::new(Mutex::new(HashMap::new())),
82 organizations: Arc::new(Mutex::new(HashMap::new())),
83 members: Arc::new(Mutex::new(HashMap::new())),
84 invitations: Arc::new(Mutex::new(HashMap::new())),
85 slug_index: Arc::new(Mutex::new(HashMap::new())),
86 two_factors: Arc::new(Mutex::new(HashMap::new())),
87 api_keys: Arc::new(Mutex::new(HashMap::new())),
88 passkeys: Arc::new(Mutex::new(HashMap::new())),
89 passkey_credential_index: Arc::new(Mutex::new(HashMap::new())),
90 }
91 }
92}
93
94#[async_trait]
97impl<U, S, A, O, M, I, V, P> UserOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
98where
99 U: MemoryUser,
100 S: MemorySession,
101 A: MemoryAccount,
102 O: MemoryOrganization,
103 M: MemoryMember,
104 I: MemoryInvitation,
105 V: MemoryVerification,
106 P: MemoryPasskey,
107{
108 type User = U;
109
110 async fn create_user(&self, create_user: CreateUser) -> AuthResult<U> {
111 let mut users = self.users.lock().unwrap();
112 let mut email_index = self.email_index.lock().unwrap();
113 let mut username_index = self.username_index.lock().unwrap();
114
115 let id = create_user
116 .id
117 .clone()
118 .unwrap_or_else(|| Uuid::new_v4().to_string());
119
120 if let Some(email) = &create_user.email
121 && email_index.contains_key(email)
122 {
123 return Err(AuthError::config("Email already exists"));
124 }
125
126 if let Some(username) = &create_user.username
127 && username_index.contains_key(username)
128 {
129 return Err(AuthError::conflict(
130 "A user with this username already exists",
131 ));
132 }
133
134 let now = Utc::now();
135 let user = U::from_create(id.clone(), &create_user, now);
136
137 users.insert(id.clone(), user.clone());
138
139 if let Some(email) = &create_user.email {
140 email_index.insert(email.clone(), id.clone());
141 }
142 if let Some(username) = &create_user.username {
143 username_index.insert(username.clone(), id);
144 }
145
146 Ok(user)
147 }
148
149 async fn get_user_by_id(&self, id: &str) -> AuthResult<Option<U>> {
150 let users = self.users.lock().unwrap();
151 Ok(users.get(id).cloned())
152 }
153
154 async fn get_user_by_email(&self, email: &str) -> AuthResult<Option<U>> {
155 let email_index = self.email_index.lock().unwrap();
156 let users = self.users.lock().unwrap();
157
158 if let Some(user_id) = email_index.get(email) {
159 Ok(users.get(user_id).cloned())
160 } else {
161 Ok(None)
162 }
163 }
164
165 async fn get_user_by_username(&self, username: &str) -> AuthResult<Option<U>> {
166 let username_index = self.username_index.lock().unwrap();
167 let users = self.users.lock().unwrap();
168
169 if let Some(user_id) = username_index.get(username) {
170 Ok(users.get(user_id).cloned())
171 } else {
172 Ok(None)
173 }
174 }
175
176 async fn update_user(&self, id: &str, update: UpdateUser) -> AuthResult<U> {
177 let mut users = self.users.lock().unwrap();
178 let mut email_index = self.email_index.lock().unwrap();
179 let mut username_index = self.username_index.lock().unwrap();
180
181 let user = users.get_mut(id).ok_or(AuthError::UserNotFound)?;
182
183 if let Some(new_email) = &update.email {
185 if let Some(old_email) = user.email() {
186 email_index.remove(old_email);
187 }
188 email_index.insert(new_email.clone(), id.to_string());
189 }
190
191 if let Some(ref new_username) = update.username {
192 if let Some(old_username) = user.username() {
193 username_index.remove(old_username);
194 }
195 username_index.insert(new_username.clone(), id.to_string());
196 }
197
198 user.apply_update(&update);
199 Ok(user.clone())
200 }
201
202 async fn delete_user(&self, id: &str) -> AuthResult<()> {
203 let mut users = self.users.lock().unwrap();
204 let mut email_index = self.email_index.lock().unwrap();
205 let mut username_index = self.username_index.lock().unwrap();
206
207 if let Some(user) = users.remove(id) {
208 if let Some(email) = user.email() {
209 email_index.remove(email);
210 }
211 if let Some(username) = user.username() {
212 username_index.remove(username);
213 }
214 }
215
216 Ok(())
217 }
218}
219
220#[async_trait]
223impl<U, S, A, O, M, I, V, P> SessionOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
224where
225 U: MemoryUser,
226 S: MemorySession,
227 A: MemoryAccount,
228 O: MemoryOrganization,
229 M: MemoryMember,
230 I: MemoryInvitation,
231 V: MemoryVerification,
232 P: MemoryPasskey,
233{
234 type Session = S;
235
236 async fn create_session(&self, create_session: CreateSession) -> AuthResult<S> {
237 let mut sessions = self.sessions.lock().unwrap();
238
239 let id = Uuid::new_v4().to_string();
240 let token = format!("session_{}", Uuid::new_v4());
241 let now = Utc::now();
242 let session = S::from_create(id, token.clone(), &create_session, now);
243
244 sessions.insert(token, session.clone());
245 Ok(session)
246 }
247
248 async fn get_session(&self, token: &str) -> AuthResult<Option<S>> {
249 let sessions = self.sessions.lock().unwrap();
250 Ok(sessions.get(token).cloned())
251 }
252
253 async fn get_user_sessions(&self, user_id: &str) -> AuthResult<Vec<S>> {
254 let sessions = self.sessions.lock().unwrap();
255 Ok(sessions
256 .values()
257 .filter(|s| s.user_id() == user_id && s.active())
258 .cloned()
259 .collect())
260 }
261
262 async fn update_session_expiry(
263 &self,
264 token: &str,
265 expires_at: DateTime<Utc>,
266 ) -> AuthResult<()> {
267 let mut sessions = self.sessions.lock().unwrap();
268 if let Some(session) = sessions.get_mut(token) {
269 session.set_expires_at(expires_at);
270 }
271 Ok(())
272 }
273
274 async fn delete_session(&self, token: &str) -> AuthResult<()> {
275 let mut sessions = self.sessions.lock().unwrap();
276 sessions.remove(token);
277 Ok(())
278 }
279
280 async fn delete_user_sessions(&self, user_id: &str) -> AuthResult<()> {
281 let mut sessions = self.sessions.lock().unwrap();
282 sessions.retain(|_, s| s.user_id() != user_id);
283 Ok(())
284 }
285
286 async fn delete_expired_sessions(&self) -> AuthResult<usize> {
287 let mut sessions = self.sessions.lock().unwrap();
288 let now = Utc::now();
289 let initial_count = sessions.len();
290 sessions.retain(|_, s| s.expires_at() > now && s.active());
291 Ok(initial_count - sessions.len())
292 }
293
294 async fn update_session_active_organization(
295 &self,
296 token: &str,
297 organization_id: Option<&str>,
298 ) -> AuthResult<S> {
299 let mut sessions = self.sessions.lock().unwrap();
300 let session = sessions.get_mut(token).ok_or(AuthError::SessionNotFound)?;
301 session.set_active_organization_id(organization_id.map(|s| s.to_string()));
302 session.set_updated_at(Utc::now());
303 Ok(session.clone())
304 }
305}
306
307#[async_trait]
310impl<U, S, A, O, M, I, V, P> AccountOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
311where
312 U: MemoryUser,
313 S: MemorySession,
314 A: MemoryAccount,
315 O: MemoryOrganization,
316 M: MemoryMember,
317 I: MemoryInvitation,
318 V: MemoryVerification,
319 P: MemoryPasskey,
320{
321 type Account = A;
322
323 async fn create_account(&self, create_account: CreateAccount) -> AuthResult<A> {
324 let mut accounts = self.accounts.lock().unwrap();
325
326 let id = Uuid::new_v4().to_string();
327 let now = Utc::now();
328 let account = A::from_create(id.clone(), &create_account, now);
329
330 accounts.insert(id, account.clone());
331 Ok(account)
332 }
333
334 async fn get_account(
335 &self,
336 provider: &str,
337 provider_account_id: &str,
338 ) -> AuthResult<Option<A>> {
339 let accounts = self.accounts.lock().unwrap();
340 Ok(accounts
341 .values()
342 .find(|acc| acc.provider_id() == provider && acc.account_id() == provider_account_id)
343 .cloned())
344 }
345
346 async fn get_user_accounts(&self, user_id: &str) -> AuthResult<Vec<A>> {
347 let accounts = self.accounts.lock().unwrap();
348 Ok(accounts
349 .values()
350 .filter(|acc| acc.user_id() == user_id)
351 .cloned()
352 .collect())
353 }
354
355 async fn update_account(&self, id: &str, update: UpdateAccount) -> AuthResult<A> {
356 let mut accounts = self.accounts.lock().unwrap();
357 let account = accounts
358 .get_mut(id)
359 .ok_or_else(|| AuthError::not_found("Account not found"))?;
360 account.apply_update(&update);
361 Ok(account.clone())
362 }
363
364 async fn delete_account(&self, id: &str) -> AuthResult<()> {
365 let mut accounts = self.accounts.lock().unwrap();
366 accounts.remove(id);
367 Ok(())
368 }
369}
370
371#[async_trait]
374impl<U, S, A, O, M, I, V, P> VerificationOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
375where
376 U: MemoryUser,
377 S: MemorySession,
378 A: MemoryAccount,
379 O: MemoryOrganization,
380 M: MemoryMember,
381 I: MemoryInvitation,
382 V: MemoryVerification,
383 P: MemoryPasskey,
384{
385 type Verification = V;
386
387 async fn create_verification(&self, create_verification: CreateVerification) -> AuthResult<V> {
388 let mut verifications = self.verifications.lock().unwrap();
389
390 let id = Uuid::new_v4().to_string();
391 let now = Utc::now();
392 let verification = V::from_create(id.clone(), &create_verification, now);
393
394 verifications.insert(id, verification.clone());
395 Ok(verification)
396 }
397
398 async fn get_verification(&self, identifier: &str, value: &str) -> AuthResult<Option<V>> {
399 let verifications = self.verifications.lock().unwrap();
400 let now = Utc::now();
401 Ok(verifications
402 .values()
403 .find(|v| v.identifier() == identifier && v.value() == value && v.expires_at() > now)
404 .cloned())
405 }
406
407 async fn get_verification_by_value(&self, value: &str) -> AuthResult<Option<V>> {
408 let verifications = self.verifications.lock().unwrap();
409 let now = Utc::now();
410 Ok(verifications
411 .values()
412 .find(|v| v.value() == value && v.expires_at() > now)
413 .cloned())
414 }
415
416 async fn get_verification_by_identifier(&self, identifier: &str) -> AuthResult<Option<V>> {
417 let verifications = self.verifications.lock().unwrap();
418 let now = Utc::now();
419 Ok(verifications
420 .values()
421 .find(|v| v.identifier() == identifier && v.expires_at() > now)
422 .cloned())
423 }
424
425 async fn consume_verification(&self, identifier: &str, value: &str) -> AuthResult<Option<V>> {
426 let mut verifications = self.verifications.lock().unwrap();
427 let now = Utc::now();
428
429 let matched_id = verifications
430 .iter()
431 .filter_map(|(id, verification)| {
432 if verification.identifier() == identifier
433 && verification.value() == value
434 && verification.expires_at() > now
435 {
436 Some((id, verification.created_at()))
437 } else {
438 None
439 }
440 })
441 .max_by_key(|(_, created_at)| *created_at)
442 .map(|(id, _)| id.clone());
443
444 if let Some(id) = matched_id {
445 Ok(verifications.remove(&id))
446 } else {
447 Ok(None)
448 }
449 }
450
451 async fn delete_verification(&self, id: &str) -> AuthResult<()> {
452 let mut verifications = self.verifications.lock().unwrap();
453 verifications.remove(id);
454 Ok(())
455 }
456
457 async fn delete_expired_verifications(&self) -> AuthResult<usize> {
458 let mut verifications = self.verifications.lock().unwrap();
459 let now = Utc::now();
460 let initial_count = verifications.len();
461 verifications.retain(|_, v| v.expires_at() > now);
462 Ok(initial_count - verifications.len())
463 }
464}
465
466#[async_trait]
469impl<U, S, A, O, M, I, V, P> OrganizationOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
470where
471 U: MemoryUser,
472 S: MemorySession,
473 A: MemoryAccount,
474 O: MemoryOrganization,
475 M: MemoryMember,
476 I: MemoryInvitation,
477 V: MemoryVerification,
478 P: MemoryPasskey,
479{
480 type Organization = O;
481
482 async fn create_organization(&self, create_org: CreateOrganization) -> AuthResult<O> {
483 let mut organizations = self.organizations.lock().unwrap();
484 let mut slug_index = self.slug_index.lock().unwrap();
485
486 if slug_index.contains_key(&create_org.slug) {
487 return Err(AuthError::conflict("Organization slug already exists"));
488 }
489
490 let id = create_org
491 .id
492 .clone()
493 .unwrap_or_else(|| Uuid::new_v4().to_string());
494 let now = Utc::now();
495 let organization = O::from_create(id.clone(), &create_org, now);
496
497 organizations.insert(id.clone(), organization.clone());
498 slug_index.insert(create_org.slug.clone(), id);
499
500 Ok(organization)
501 }
502
503 async fn get_organization_by_id(&self, id: &str) -> AuthResult<Option<O>> {
504 let organizations = self.organizations.lock().unwrap();
505 Ok(organizations.get(id).cloned())
506 }
507
508 async fn get_organization_by_slug(&self, slug: &str) -> AuthResult<Option<O>> {
509 let slug_index = self.slug_index.lock().unwrap();
510 let organizations = self.organizations.lock().unwrap();
511
512 if let Some(org_id) = slug_index.get(slug) {
513 Ok(organizations.get(org_id).cloned())
514 } else {
515 Ok(None)
516 }
517 }
518
519 async fn update_organization(&self, id: &str, update: UpdateOrganization) -> AuthResult<O> {
520 let mut organizations = self.organizations.lock().unwrap();
521 let mut slug_index = self.slug_index.lock().unwrap();
522
523 let org = organizations
524 .get_mut(id)
525 .ok_or_else(|| AuthError::not_found("Organization not found"))?;
526
527 if let Some(new_slug) = &update.slug {
529 let current_slug = org.slug().to_string();
530 if *new_slug != current_slug {
531 if slug_index.contains_key(new_slug.as_str()) {
532 return Err(AuthError::conflict("Organization slug already exists"));
533 }
534 slug_index.remove(¤t_slug);
535 slug_index.insert(new_slug.clone(), id.to_string());
536 }
537 }
538
539 org.apply_update(&update);
540 Ok(org.clone())
541 }
542
543 async fn delete_organization(&self, id: &str) -> AuthResult<()> {
544 let mut organizations = self.organizations.lock().unwrap();
545 let mut slug_index = self.slug_index.lock().unwrap();
546 let mut members = self.members.lock().unwrap();
547 let mut invitations = self.invitations.lock().unwrap();
548
549 if let Some(org) = organizations.remove(id) {
550 slug_index.remove(org.slug());
551 }
552
553 members.retain(|_, m| m.organization_id() != id);
554 invitations.retain(|_, i| i.organization_id() != id);
555
556 Ok(())
557 }
558
559 async fn list_user_organizations(&self, user_id: &str) -> AuthResult<Vec<O>> {
560 let members = self.members.lock().unwrap();
561 let organizations = self.organizations.lock().unwrap();
562
563 let org_ids: Vec<String> = members
564 .values()
565 .filter(|m| m.user_id() == user_id)
566 .map(|m| m.organization_id().to_string())
567 .collect();
568
569 let orgs = org_ids
570 .iter()
571 .filter_map(|id| organizations.get(id).cloned())
572 .collect();
573
574 Ok(orgs)
575 }
576}
577
578#[async_trait]
581impl<U, S, A, O, M, I, V, P> MemberOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
582where
583 U: MemoryUser,
584 S: MemorySession,
585 A: MemoryAccount,
586 O: MemoryOrganization,
587 M: MemoryMember,
588 I: MemoryInvitation,
589 V: MemoryVerification,
590 P: MemoryPasskey,
591{
592 type Member = M;
593
594 async fn create_member(&self, create_member: CreateMember) -> AuthResult<M> {
595 let mut members = self.members.lock().unwrap();
596
597 let exists = members.values().any(|m| {
598 m.organization_id() == create_member.organization_id
599 && m.user_id() == create_member.user_id
600 });
601
602 if exists {
603 return Err(AuthError::conflict(
604 "User is already a member of this organization",
605 ));
606 }
607
608 let id = Uuid::new_v4().to_string();
609 let now = Utc::now();
610 let member = M::from_create(id.clone(), &create_member, now);
611
612 members.insert(id, member.clone());
613 Ok(member)
614 }
615
616 async fn get_member(&self, organization_id: &str, user_id: &str) -> AuthResult<Option<M>> {
617 let members = self.members.lock().unwrap();
618 Ok(members
619 .values()
620 .find(|m| m.organization_id() == organization_id && m.user_id() == user_id)
621 .cloned())
622 }
623
624 async fn get_member_by_id(&self, id: &str) -> AuthResult<Option<M>> {
625 let members = self.members.lock().unwrap();
626 Ok(members.get(id).cloned())
627 }
628
629 async fn update_member_role(&self, member_id: &str, role: &str) -> AuthResult<M> {
630 let mut members = self.members.lock().unwrap();
631 let member = members
632 .get_mut(member_id)
633 .ok_or_else(|| AuthError::not_found("Member not found"))?;
634 member.set_role(role.to_string());
635 Ok(member.clone())
636 }
637
638 async fn delete_member(&self, member_id: &str) -> AuthResult<()> {
639 let mut members = self.members.lock().unwrap();
640 members.remove(member_id);
641 Ok(())
642 }
643
644 async fn list_organization_members(&self, organization_id: &str) -> AuthResult<Vec<M>> {
645 let members = self.members.lock().unwrap();
646 Ok(members
647 .values()
648 .filter(|m| m.organization_id() == organization_id)
649 .cloned()
650 .collect())
651 }
652
653 async fn count_organization_members(&self, organization_id: &str) -> AuthResult<usize> {
654 let members = self.members.lock().unwrap();
655 Ok(members
656 .values()
657 .filter(|m| m.organization_id() == organization_id)
658 .count())
659 }
660
661 async fn count_organization_owners(&self, organization_id: &str) -> AuthResult<usize> {
662 let members = self.members.lock().unwrap();
663 Ok(members
664 .values()
665 .filter(|m| m.organization_id() == organization_id && m.role() == "owner")
666 .count())
667 }
668}
669
670#[async_trait]
673impl<U, S, A, O, M, I, V, P> InvitationOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
674where
675 U: MemoryUser,
676 S: MemorySession,
677 A: MemoryAccount,
678 O: MemoryOrganization,
679 M: MemoryMember,
680 I: MemoryInvitation,
681 V: MemoryVerification,
682 P: MemoryPasskey,
683{
684 type Invitation = I;
685
686 async fn create_invitation(&self, create_inv: CreateInvitation) -> AuthResult<I> {
687 let mut invitations = self.invitations.lock().unwrap();
688
689 let id = Uuid::new_v4().to_string();
690 let now = Utc::now();
691 let invitation = I::from_create(id.clone(), &create_inv, now);
692
693 invitations.insert(id, invitation.clone());
694 Ok(invitation)
695 }
696
697 async fn get_invitation_by_id(&self, id: &str) -> AuthResult<Option<I>> {
698 let invitations = self.invitations.lock().unwrap();
699 Ok(invitations.get(id).cloned())
700 }
701
702 async fn get_pending_invitation(
703 &self,
704 organization_id: &str,
705 email: &str,
706 ) -> AuthResult<Option<I>> {
707 let invitations = self.invitations.lock().unwrap();
708 Ok(invitations
709 .values()
710 .find(|i| {
711 i.organization_id() == organization_id
712 && i.email().to_lowercase() == email.to_lowercase()
713 && *i.status() == InvitationStatus::Pending
714 })
715 .cloned())
716 }
717
718 async fn update_invitation_status(&self, id: &str, status: InvitationStatus) -> AuthResult<I> {
719 let mut invitations = self.invitations.lock().unwrap();
720 let invitation = invitations
721 .get_mut(id)
722 .ok_or_else(|| AuthError::not_found("Invitation not found"))?;
723 invitation.set_status(status);
724 Ok(invitation.clone())
725 }
726
727 async fn list_organization_invitations(&self, organization_id: &str) -> AuthResult<Vec<I>> {
728 let invitations = self.invitations.lock().unwrap();
729 Ok(invitations
730 .values()
731 .filter(|i| i.organization_id() == organization_id)
732 .cloned()
733 .collect())
734 }
735
736 async fn list_user_invitations(&self, email: &str) -> AuthResult<Vec<I>> {
737 let invitations = self.invitations.lock().unwrap();
738 let now = Utc::now();
739 Ok(invitations
740 .values()
741 .filter(|i| {
742 i.email().to_lowercase() == email.to_lowercase()
743 && *i.status() == InvitationStatus::Pending
744 && i.expires_at() > now
745 })
746 .cloned()
747 .collect())
748 }
749}
750
751#[async_trait]
754impl<U, S, A, O, M, I, V, P> TwoFactorOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
755where
756 U: MemoryUser,
757 S: MemorySession,
758 A: MemoryAccount,
759 O: MemoryOrganization,
760 M: MemoryMember,
761 I: MemoryInvitation,
762 V: MemoryVerification,
763 P: MemoryPasskey,
764{
765 type TwoFactor = TwoFactor;
766
767 async fn create_two_factor(&self, create: CreateTwoFactor) -> AuthResult<TwoFactor> {
768 let mut two_factors = self.two_factors.lock().unwrap();
769
770 if two_factors.values().any(|tf| tf.user_id == create.user_id) {
772 return Err(AuthError::conflict(
773 "Two-factor authentication already enabled for this user",
774 ));
775 }
776
777 let id = Uuid::new_v4().to_string();
778 let now = Utc::now();
779 let two_factor: TwoFactor = MemoryTwoFactor::from_create(id.clone(), &create, now);
780
781 two_factors.insert(id, two_factor.clone());
782 Ok(two_factor)
783 }
784
785 async fn get_two_factor_by_user_id(&self, user_id: &str) -> AuthResult<Option<TwoFactor>> {
786 let two_factors = self.two_factors.lock().unwrap();
787 Ok(two_factors
788 .values()
789 .find(|tf| tf.user_id == user_id)
790 .cloned())
791 }
792
793 async fn update_two_factor_backup_codes(
794 &self,
795 user_id: &str,
796 backup_codes: &str,
797 ) -> AuthResult<TwoFactor> {
798 let mut two_factors = self.two_factors.lock().unwrap();
799 let two_factor = two_factors
800 .values_mut()
801 .find(|tf| tf.user_id == user_id)
802 .ok_or_else(|| AuthError::not_found("Two-factor record not found"))?;
803 two_factor.set_backup_codes(backup_codes.to_string());
804 Ok(two_factor.clone())
805 }
806
807 async fn delete_two_factor(&self, user_id: &str) -> AuthResult<()> {
808 let mut two_factors = self.two_factors.lock().unwrap();
809 two_factors.retain(|_, tf| tf.user_id != user_id);
810 Ok(())
811 }
812}
813
814#[async_trait]
817impl<U, S, A, O, M, I, V, P> ApiKeyOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
818where
819 U: MemoryUser,
820 S: MemorySession,
821 A: MemoryAccount,
822 O: MemoryOrganization,
823 M: MemoryMember,
824 I: MemoryInvitation,
825 V: MemoryVerification,
826 P: MemoryPasskey,
827{
828 type ApiKey = ApiKey;
829
830 async fn create_api_key(&self, input: CreateApiKey) -> AuthResult<ApiKey> {
831 let mut api_keys = self.api_keys.lock().unwrap();
832
833 if api_keys.values().any(|k| k.key_hash == input.key_hash) {
834 return Err(AuthError::conflict("API key already exists"));
835 }
836
837 let id = Uuid::new_v4().to_string();
838 let now = Utc::now();
839 let api_key: ApiKey = MemoryApiKey::from_create(id.clone(), &input, now);
840
841 api_keys.insert(id, api_key.clone());
842 Ok(api_key)
843 }
844
845 async fn get_api_key_by_id(&self, id: &str) -> AuthResult<Option<ApiKey>> {
846 let api_keys = self.api_keys.lock().unwrap();
847 Ok(api_keys.get(id).cloned())
848 }
849
850 async fn get_api_key_by_hash(&self, hash: &str) -> AuthResult<Option<ApiKey>> {
851 let api_keys = self.api_keys.lock().unwrap();
852 Ok(api_keys.values().find(|k| k.key_hash == hash).cloned())
853 }
854
855 async fn list_api_keys_by_user(&self, user_id: &str) -> AuthResult<Vec<ApiKey>> {
856 let api_keys = self.api_keys.lock().unwrap();
857 let mut keys: Vec<ApiKey> = api_keys
858 .values()
859 .filter(|k| k.user_id == user_id)
860 .cloned()
861 .collect();
862 keys.sort_by(|a, b| b.created_at.cmp(&a.created_at));
863 Ok(keys)
864 }
865
866 async fn update_api_key(&self, id: &str, update: UpdateApiKey) -> AuthResult<ApiKey> {
867 let mut api_keys = self.api_keys.lock().unwrap();
868 let api_key = api_keys
869 .get_mut(id)
870 .ok_or_else(|| AuthError::not_found("API key not found"))?;
871 api_key.apply_update(&update);
872 Ok(api_key.clone())
873 }
874
875 async fn delete_api_key(&self, id: &str) -> AuthResult<()> {
876 let mut api_keys = self.api_keys.lock().unwrap();
877 api_keys.remove(id);
878 Ok(())
879 }
880}
881
882#[async_trait]
885impl<U, S, A, O, M, I, V, P> PasskeyOps for MemoryDatabaseAdapter<U, S, A, O, M, I, V, P>
886where
887 U: MemoryUser,
888 S: MemorySession,
889 A: MemoryAccount,
890 O: MemoryOrganization,
891 M: MemoryMember,
892 I: MemoryInvitation,
893 V: MemoryVerification,
894 P: MemoryPasskey,
895{
896 type Passkey = P;
897
898 async fn create_passkey(&self, input: CreatePasskey) -> AuthResult<P> {
899 let mut credential_index = self.passkey_credential_index.lock().unwrap();
900 let mut passkeys = self.passkeys.lock().unwrap();
901
902 if credential_index.contains_key(&input.credential_id) {
903 return Err(AuthError::conflict(
904 "A passkey with this credential ID already exists",
905 ));
906 }
907
908 let id = Uuid::new_v4().to_string();
909 let now = Utc::now();
910 let passkey = P::from_create(id.clone(), &input, now);
911
912 credential_index.insert(input.credential_id.clone(), id.clone());
913 passkeys.insert(id, passkey.clone());
914 Ok(passkey)
915 }
916
917 async fn get_passkey_by_id(&self, id: &str) -> AuthResult<Option<P>> {
918 let passkeys = self.passkeys.lock().unwrap();
919 Ok(passkeys.get(id).cloned())
920 }
921
922 async fn get_passkey_by_credential_id(&self, credential_id: &str) -> AuthResult<Option<P>> {
923 let passkey_id = {
924 let credential_index = self.passkey_credential_index.lock().unwrap();
925 credential_index.get(credential_id).cloned()
926 };
927
928 let passkeys = self.passkeys.lock().unwrap();
929
930 if let Some(id) = passkey_id {
931 Ok(passkeys.get(&id).cloned())
932 } else {
933 Ok(None)
934 }
935 }
936
937 async fn list_passkeys_by_user(&self, user_id: &str) -> AuthResult<Vec<P>> {
938 let passkeys = self.passkeys.lock().unwrap();
939 let mut matched: Vec<P> = passkeys
940 .values()
941 .filter(|p| p.user_id() == user_id)
942 .cloned()
943 .collect();
944 matched.sort_by_key(|p| std::cmp::Reverse(p.created_at()));
945 Ok(matched)
946 }
947
948 async fn update_passkey_counter(&self, id: &str, counter: u64) -> AuthResult<P> {
949 let mut passkeys = self.passkeys.lock().unwrap();
950 let passkey = passkeys
951 .get_mut(id)
952 .ok_or_else(|| AuthError::not_found("Passkey not found"))?;
953 passkey.set_counter(counter);
954 Ok(passkey.clone())
955 }
956
957 async fn update_passkey_name(&self, id: &str, name: &str) -> AuthResult<P> {
958 let mut passkeys = self.passkeys.lock().unwrap();
959 let passkey = passkeys
960 .get_mut(id)
961 .ok_or_else(|| AuthError::not_found("Passkey not found"))?;
962 passkey.set_name(name.to_string());
963 Ok(passkey.clone())
964 }
965
966 async fn delete_passkey(&self, id: &str) -> AuthResult<()> {
967 let mut credential_index = self.passkey_credential_index.lock().unwrap();
968 let mut passkeys = self.passkeys.lock().unwrap();
969
970 if let Some(passkey) = passkeys.remove(id) {
971 credential_index.remove(passkey.credential_id());
972 }
973 Ok(())
974 }
975}