alibi_core/store/stateless/
users.rs1use 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}