Skip to main content

better_auth_core/adapters/
traits.rs

1use async_trait::async_trait;
2use chrono::{DateTime, Utc};
3
4use crate::entity::{
5    AuthAccount, AuthApiKey, AuthInvitation, AuthMember, AuthOrganization, AuthPasskey,
6    AuthSession, AuthTwoFactor, AuthUser, AuthVerification,
7};
8use crate::error::AuthResult;
9use crate::types::{
10    CreateAccount, CreateApiKey, CreateInvitation, CreateMember, CreateOrganization, CreatePasskey,
11    CreateSession, CreateTwoFactor, CreateUser, CreateVerification, InvitationStatus,
12    UpdateAccount, UpdateApiKey, UpdateOrganization, UpdateUser,
13};
14
15/// User persistence operations.
16#[async_trait]
17pub trait UserOps: Send + Sync + 'static {
18    type User: AuthUser;
19
20    async fn create_user(&self, user: CreateUser) -> AuthResult<Self::User>;
21    async fn get_user_by_id(&self, id: &str) -> AuthResult<Option<Self::User>>;
22    async fn get_user_by_email(&self, email: &str) -> AuthResult<Option<Self::User>>;
23    async fn get_user_by_username(&self, username: &str) -> AuthResult<Option<Self::User>>;
24    async fn update_user(&self, id: &str, update: UpdateUser) -> AuthResult<Self::User>;
25    async fn delete_user(&self, id: &str) -> AuthResult<()>;
26}
27
28/// Session persistence operations.
29#[async_trait]
30pub trait SessionOps: Send + Sync + 'static {
31    type Session: AuthSession;
32
33    async fn create_session(&self, session: CreateSession) -> AuthResult<Self::Session>;
34    async fn get_session(&self, token: &str) -> AuthResult<Option<Self::Session>>;
35    async fn get_user_sessions(&self, user_id: &str) -> AuthResult<Vec<Self::Session>>;
36    async fn update_session_expiry(&self, token: &str, expires_at: DateTime<Utc>)
37    -> AuthResult<()>;
38    async fn delete_session(&self, token: &str) -> AuthResult<()>;
39    async fn delete_user_sessions(&self, user_id: &str) -> AuthResult<()>;
40    async fn delete_expired_sessions(&self) -> AuthResult<usize>;
41    async fn update_session_active_organization(
42        &self,
43        token: &str,
44        organization_id: Option<&str>,
45    ) -> AuthResult<Self::Session>;
46}
47
48/// Account (OAuth provider linking) persistence operations.
49#[async_trait]
50pub trait AccountOps: Send + Sync + 'static {
51    type Account: AuthAccount;
52
53    async fn create_account(&self, account: CreateAccount) -> AuthResult<Self::Account>;
54    async fn get_account(
55        &self,
56        provider: &str,
57        provider_account_id: &str,
58    ) -> AuthResult<Option<Self::Account>>;
59    async fn get_user_accounts(&self, user_id: &str) -> AuthResult<Vec<Self::Account>>;
60    async fn update_account(&self, id: &str, update: UpdateAccount) -> AuthResult<Self::Account>;
61    async fn delete_account(&self, id: &str) -> AuthResult<()>;
62}
63
64/// Verification token persistence operations.
65#[async_trait]
66pub trait VerificationOps: Send + Sync + 'static {
67    type Verification: AuthVerification;
68
69    async fn create_verification(
70        &self,
71        verification: CreateVerification,
72    ) -> AuthResult<Self::Verification>;
73    async fn get_verification(
74        &self,
75        identifier: &str,
76        value: &str,
77    ) -> AuthResult<Option<Self::Verification>>;
78    async fn get_verification_by_value(
79        &self,
80        value: &str,
81    ) -> AuthResult<Option<Self::Verification>>;
82    async fn get_verification_by_identifier(
83        &self,
84        identifier: &str,
85    ) -> AuthResult<Option<Self::Verification>> {
86        let _ = identifier;
87        Ok(None)
88    }
89    /// Atomically consume a verification token identified by `(identifier, value)`.
90    ///
91    /// Implementations should remove the token if it exists and is valid, then
92    /// return the removed record. This prevents replay and race windows from
93    /// split read-then-delete flows.
94    async fn consume_verification(
95        &self,
96        identifier: &str,
97        value: &str,
98    ) -> AuthResult<Option<Self::Verification>>;
99    async fn delete_verification(&self, id: &str) -> AuthResult<()>;
100    async fn delete_expired_verifications(&self) -> AuthResult<usize>;
101}
102
103/// Organization persistence operations.
104#[async_trait]
105pub trait OrganizationOps: Send + Sync + 'static {
106    type Organization: AuthOrganization;
107
108    async fn create_organization(&self, org: CreateOrganization) -> AuthResult<Self::Organization>;
109    async fn get_organization_by_id(&self, id: &str) -> AuthResult<Option<Self::Organization>>;
110    async fn get_organization_by_slug(&self, slug: &str) -> AuthResult<Option<Self::Organization>>;
111    async fn update_organization(
112        &self,
113        id: &str,
114        update: UpdateOrganization,
115    ) -> AuthResult<Self::Organization>;
116    async fn delete_organization(&self, id: &str) -> AuthResult<()>;
117    async fn list_user_organizations(&self, user_id: &str) -> AuthResult<Vec<Self::Organization>>;
118}
119
120/// Organization member persistence operations.
121#[async_trait]
122pub trait MemberOps: Send + Sync + 'static {
123    type Member: AuthMember;
124
125    async fn create_member(&self, member: CreateMember) -> AuthResult<Self::Member>;
126    async fn get_member(
127        &self,
128        organization_id: &str,
129        user_id: &str,
130    ) -> AuthResult<Option<Self::Member>>;
131    async fn get_member_by_id(&self, id: &str) -> AuthResult<Option<Self::Member>>;
132    async fn update_member_role(&self, member_id: &str, role: &str) -> AuthResult<Self::Member>;
133    async fn delete_member(&self, member_id: &str) -> AuthResult<()>;
134    async fn list_organization_members(
135        &self,
136        organization_id: &str,
137    ) -> AuthResult<Vec<Self::Member>>;
138    async fn count_organization_members(&self, organization_id: &str) -> AuthResult<usize>;
139    async fn count_organization_owners(&self, organization_id: &str) -> AuthResult<usize>;
140}
141
142/// Invitation persistence operations.
143#[async_trait]
144pub trait InvitationOps: Send + Sync + 'static {
145    type Invitation: AuthInvitation;
146
147    async fn create_invitation(&self, invitation: CreateInvitation)
148    -> AuthResult<Self::Invitation>;
149    async fn get_invitation_by_id(&self, id: &str) -> AuthResult<Option<Self::Invitation>>;
150    async fn get_pending_invitation(
151        &self,
152        organization_id: &str,
153        email: &str,
154    ) -> AuthResult<Option<Self::Invitation>>;
155    async fn update_invitation_status(
156        &self,
157        id: &str,
158        status: InvitationStatus,
159    ) -> AuthResult<Self::Invitation>;
160    async fn list_organization_invitations(
161        &self,
162        organization_id: &str,
163    ) -> AuthResult<Vec<Self::Invitation>>;
164    async fn list_user_invitations(&self, email: &str) -> AuthResult<Vec<Self::Invitation>>;
165}
166
167/// Two-factor authentication persistence operations.
168#[async_trait]
169pub trait TwoFactorOps: Send + Sync + 'static {
170    type TwoFactor: AuthTwoFactor;
171
172    async fn create_two_factor(&self, two_factor: CreateTwoFactor) -> AuthResult<Self::TwoFactor>;
173    async fn get_two_factor_by_user_id(&self, user_id: &str)
174    -> AuthResult<Option<Self::TwoFactor>>;
175    async fn update_two_factor_backup_codes(
176        &self,
177        user_id: &str,
178        backup_codes: &str,
179    ) -> AuthResult<Self::TwoFactor>;
180    async fn delete_two_factor(&self, user_id: &str) -> AuthResult<()>;
181}
182
183/// API key persistence operations.
184#[async_trait]
185pub trait ApiKeyOps: Send + Sync + 'static {
186    type ApiKey: AuthApiKey;
187
188    async fn create_api_key(&self, input: CreateApiKey) -> AuthResult<Self::ApiKey>;
189    async fn get_api_key_by_id(&self, id: &str) -> AuthResult<Option<Self::ApiKey>>;
190    async fn get_api_key_by_hash(&self, hash: &str) -> AuthResult<Option<Self::ApiKey>>;
191    async fn list_api_keys_by_user(&self, user_id: &str) -> AuthResult<Vec<Self::ApiKey>>;
192    async fn update_api_key(&self, id: &str, update: UpdateApiKey) -> AuthResult<Self::ApiKey>;
193    async fn delete_api_key(&self, id: &str) -> AuthResult<()>;
194}
195
196/// Passkey persistence operations.
197#[async_trait]
198pub trait PasskeyOps: Send + Sync + 'static {
199    type Passkey: AuthPasskey;
200
201    async fn create_passkey(&self, input: CreatePasskey) -> AuthResult<Self::Passkey>;
202    async fn get_passkey_by_id(&self, id: &str) -> AuthResult<Option<Self::Passkey>>;
203    async fn get_passkey_by_credential_id(
204        &self,
205        credential_id: &str,
206    ) -> AuthResult<Option<Self::Passkey>>;
207    async fn list_passkeys_by_user(&self, user_id: &str) -> AuthResult<Vec<Self::Passkey>>;
208    async fn update_passkey_counter(&self, id: &str, counter: u64) -> AuthResult<Self::Passkey>;
209    async fn update_passkey_name(&self, id: &str, name: &str) -> AuthResult<Self::Passkey>;
210    async fn delete_passkey(&self, id: &str) -> AuthResult<()>;
211}