Skip to main content

alibi_core/store/stateless/
users.rs

1use crate::store::UserStore;
2use crate::store::stateless::{StatelessSchema, StatelessStore, members};
3use crate::{AuthError, AuthResult, CreateUser, ListUsersParams, UpdateUser, UserView};
4use async_trait::async_trait;
5use chrono::Utc;
6#[async_trait]
7impl UserStore<StatelessSchema> for StatelessStore {
8    async fn create_user(&self, mut create_user: CreateUser) -> AuthResult<UserView> {
9        create_user.email = create_user.email.map(|email| email.to_lowercase());
10        UserStore::<StatelessSchema>::create_user_prepared(
11            self,
12            crate::user_validation::PreparedUserCreation::from_data(create_user),
13        )
14        .await
15    }
16
17    async fn create_user_prepared(
18        &self,
19        prepared: crate::user_validation::PreparedUserCreation,
20    ) -> AuthResult<UserView> {
21        let (create_user, defaults) = prepared.into_parts();
22        let mut create_user = defaults.apply(create_user)?;
23        create_user
24            .additional_fields
25            .apply_adapter_transforms_async()
26            .await?;
27        let now = Utc::now();
28        let id = create_user
29            .id
30            .unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
31        let mut omitted_fields = std::collections::BTreeSet::new();
32        for (name, absent) in [
33            ("name", create_user.name.is_none()),
34            ("email", create_user.email.is_none()),
35            ("image", create_user.image.is_none()),
36            ("username", create_user.username.is_none()),
37            ("displayUsername", create_user.display_username.is_none()),
38        ] {
39            if absent && !create_user.additional_fields.contains_key(name) {
40                _ = omitted_fields.insert(name.to_owned());
41            }
42        }
43        let username = create_user.username.map(|username| username.to_lowercase());
44        let user = UserView {
45            omitted_fields,
46            id: id.clone(),
47            name: create_user.name,
48            email: create_user.email,
49            email_verified: create_user.email_verified.unwrap_or(false),
50            image: create_user.image,
51            created_at: create_user.created_at.unwrap_or(now),
52            updated_at: create_user.updated_at.unwrap_or(now),
53            username,
54            display_username: create_user.display_username,
55            two_factor_enabled: create_user.two_factor_enabled,
56            role: create_user.role,
57            banned: create_user.banned,
58            ban_reason: None,
59            ban_expires: None,
60            metadata: create_user
61                .metadata
62                .unwrap_or_else(|| serde_json::json!({})),
63            is_anonymous: create_user.is_anonymous,
64            phone_number: create_user.phone_number,
65            phone_number_verified: create_user.phone_number_verified,
66            last_login_method: create_user.last_login_method,
67            extension_fields: create_user
68                .additional_fields
69                .into_iter()
70                .map(|(key, value)| value.to_json_value().map(|value| (key, value)))
71                .collect::<Result<_, _>>()?,
72        };
73        let mut state = self.lock()?;
74        if state.users.contains_key(&id)
75            || state
76                .users
77                .values()
78                .any(|existing| user.email.is_some() && existing.email == user.email)
79        {
80            return Err(AuthError::bad_request("User already exists"));
81        }
82        _ = state.users.insert(id, user.clone());
83        Ok(user)
84    }
85
86    async fn get_user_by_id(&self, id: &str) -> AuthResult<Option<UserView>> {
87        Ok(self.lock()?.users.get(id).cloned())
88    }
89
90    async fn list_users_by_ids(&self, ids: &[String]) -> AuthResult<Vec<UserView>> {
91        let state = self.lock()?;
92        Ok(ids
93            .iter()
94            .filter_map(|id| state.users.get(id).cloned())
95            .collect())
96    }
97
98    async fn list_users_by_ids_page(
99        &self,
100        ids: &[String],
101        limit: f64,
102    ) -> AuthResult<Vec<UserView>> {
103        let mut users: Vec<_> = self
104            .lock()?
105            .users
106            .values()
107            .filter(|user| ids.contains(&user.id))
108            .cloned()
109            .collect();
110        users.truncate(members::slice_index(limit, users.len()));
111        Ok(users)
112    }
113
114    async fn get_user_by_email(&self, email: &str) -> AuthResult<Option<UserView>> {
115        Ok(self
116            .lock()?
117            .users
118            .values()
119            .find(|user| user.email.as_deref() == Some(&email.to_lowercase()))
120            .cloned())
121    }
122
123    async fn get_user_by_username(&self, username: &str) -> AuthResult<Option<UserView>> {
124        let normalized = username.to_lowercase();
125        Ok(self
126            .lock()?
127            .users
128            .values()
129            .find(|user| user.username.as_deref() == Some(&normalized))
130            .cloned())
131    }
132
133    async fn get_user_by_phone_number(&self, phone_number: &str) -> AuthResult<Option<UserView>> {
134        Ok(self
135            .lock()?
136            .users
137            .values()
138            .find(|user| user.phone_number.as_deref() == Some(phone_number))
139            .cloned())
140    }
141
142    async fn update_user(&self, id: &str, mut update: UpdateUser) -> AuthResult<UserView> {
143        update
144            .additional_fields
145            .apply_adapter_transforms_async()
146            .await?;
147        let mut state = self.lock()?;
148        let user = state.users.get_mut(id).ok_or(AuthError::UserNotFound)?;
149        if let Some(email) = update.email {
150            user.email = Some(email.to_lowercase());
151        }
152        if let Some(name) = update.name {
153            user.name = Some(name);
154        }
155        if let Some(image) = update.image {
156            user.image = Some(image);
157        }
158        if update.provider_image == Some(serde_json::Value::Null) {
159            user.image = None;
160        }
161        if let Some(email_verified) = update.email_verified {
162            user.email_verified = email_verified;
163        }
164        if let Some(username) = update.username {
165            user.username = Some(username.to_lowercase());
166        }
167        if let Some(display_username) = update.display_username {
168            user.display_username = Some(display_username);
169        }
170        if let Some(role) = update.role {
171            user.role = Some(role);
172        }
173        if let Some(banned) = update.banned {
174            user.banned = Some(banned);
175            if !banned {
176                user.ban_reason = None;
177                user.ban_expires = None;
178            }
179        }
180        if let Some(ban_reason) = update.ban_reason {
181            user.ban_reason = Some(ban_reason);
182        }
183        if let Some(ban_expires) = update.ban_expires {
184            user.ban_expires = ban_expires;
185        }
186        if let Some(two_factor_enabled) = update.two_factor_enabled {
187            user.two_factor_enabled = Some(two_factor_enabled);
188        }
189        if let Some(metadata) = update.metadata {
190            user.metadata = metadata;
191        }
192        if let Some(is_anonymous) = update.is_anonymous {
193            user.is_anonymous = Some(is_anonymous);
194        }
195        if let Some(phone_number) = update.phone_number {
196            user.phone_number = phone_number;
197        }
198        if let Some(phone_number_verified) = update.phone_number_verified {
199            user.phone_number_verified = Some(phone_number_verified);
200        }
201        if let Some(last_login_method) = update.last_login_method {
202            user.last_login_method = last_login_method;
203        }
204        for (key, value) in update.additional_fields {
205            _ = user.extension_fields.insert(key, value.to_json_value()?);
206        }
207        for (name, present) in [
208            ("name", user.name.is_some()),
209            ("email", user.email.is_some()),
210            ("image", user.image.is_some()),
211            ("username", user.username.is_some()),
212            ("displayUsername", user.display_username.is_some()),
213        ] {
214            if present {
215                _ = user.omitted_fields.remove(name);
216            }
217        }
218        user.updated_at = Utc::now();
219        Ok(user.clone())
220    }
221
222    async fn delete_user(&self, id: &str) -> AuthResult<()> {
223        _ = self.lock()?.users.shift_remove(id);
224        Ok(())
225    }
226
227    async fn list_users(&self, _params: ListUsersParams) -> AuthResult<(Vec<UserView>, usize)> {
228        let users: Vec<_> = self.lock()?.users.values().cloned().collect();
229        Ok(crate::user_query::apply_list_users(users, &_params))
230    }
231}