Skip to main content

alibi_core/store/contracts/
account.rs

1use crate::{AdapterRecord, AuthAccount};
2use crate::{AuthError, AuthResult, AuthSchema, CreateAccount, UpdateAccount};
3use async_trait::async_trait;
4#[async_trait]
5pub trait AccountStore<S: AuthSchema>: Send + Sync {
6    /// Apply the physical token TEXT column's scalar affinity before persistence.
7    /// SQL adapters override this for their own boolean/numeric representation.
8    async fn provider_token_text(&self, value: &serde_json::Value) -> AuthResult<Option<String>> {
9        if value.is_null() {
10            return Ok(None);
11        }
12        if value.is_object() || value.is_array() {
13            return Err(AuthError::internal(
14                "Unsupported provider token SQL parameter",
15            ));
16        }
17        crate::utils::json::JsValue::from(value.clone())
18            .coerce_string()
19            .map(Some)
20            .map_err(AuthError::internal)
21    }
22
23    /// Return a retained adapter record. The default is the physical model's
24    /// serialized snapshot; initialized stores apply their declared output policy.
25    async fn create_account_record(
26        &self,
27        create_account: CreateAccount,
28    ) -> AuthResult<AdapterRecord<S::Account>> {
29        AdapterRecord::physical(self.create_account(create_account).await?)
30    }
31
32    /// Return a retained adapter record. The default is the physical model's
33    /// serialized snapshot; initialized stores apply their declared output policy.
34    async fn get_account_record(
35        &self,
36        provider: &str,
37        provider_account_id: &str,
38    ) -> AuthResult<Option<AdapterRecord<S::Account>>> {
39        self.get_account(provider, provider_account_id)
40            .await?
41            .map(AdapterRecord::physical)
42            .transpose()
43    }
44
45    /// Return a retained adapter record. The default is the physical model's
46    /// serialized snapshot; initialized stores apply their declared output policy.
47    /// Retain the selected physical credential result. Initialization applies
48    /// output policy only to that selected row, never unrelated linked accounts.
49    async fn get_credential_account_record(
50        &self,
51        user_id: &str,
52    ) -> AuthResult<Option<AdapterRecord<S::Account>>> {
53        self.get_user_accounts(user_id)
54            .await?
55            .into_iter()
56            .find(|account| {
57                account.provider_id() == "credential" && account.account_id() == user_id
58            })
59            .map(AdapterRecord::physical)
60            .transpose()
61    }
62
63    async fn get_user_accounts_record(
64        &self,
65        user_id: &str,
66    ) -> AuthResult<Vec<AdapterRecord<S::Account>>> {
67        self.get_user_accounts(user_id)
68            .await?
69            .into_iter()
70            .map(AdapterRecord::physical)
71            .collect()
72    }
73
74    /// Return a retained adapter record. The default is the physical model's
75    /// serialized snapshot; initialized stores apply their declared output policy.
76    async fn update_account_record(
77        &self,
78        id: &str,
79        update: UpdateAccount,
80    ) -> AuthResult<AdapterRecord<S::Account>> {
81        AdapterRecord::physical(self.update_account(id, update).await?)
82    }
83
84    async fn create_account(&self, create_account: CreateAccount) -> AuthResult<S::Account>;
85    /// Resolve a global provider identity only when exactly one physical row matches.
86    /// Duplicate rows (including duplicates owned by one user) must return
87    /// `DatabaseError::AmbiguousAccount`; choosing a row would make ownership arbitrary.
88    async fn get_account(
89        &self,
90        provider: &str,
91        provider_account_id: &str,
92    ) -> AuthResult<Option<S::Account>>;
93    /// Return all scoped physical rows in the adapter's native order. Do not
94    /// select or collapse duplicate provider identities, or sort by mutable dates.
95    async fn get_user_accounts(&self, user_id: &str) -> AuthResult<Vec<S::Account>>;
96    async fn update_account(&self, id: &str, update: UpdateAccount) -> AuthResult<S::Account>;
97    async fn delete_account(&self, id: &str) -> AuthResult<()>;
98}