Skip to main content

alibi_core/store/stateless/
users.rs

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