1use async_trait::async_trait;
16use chrono::{DateTime, Utc};
17use serde::{Deserialize, Serialize};
18use uuid::Uuid;
19
20use crate::{Error, error::ValidationError, storage::NewUser};
21
22#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
25pub struct UserId(String);
26
27impl UserId {
28 pub fn new(id: &str) -> Self {
29 UserId(id.to_string())
30 }
31
32 pub fn new_random() -> Self {
33 UserId(Uuid::new_v4().to_string())
34 }
35
36 pub fn into_inner(self) -> String {
37 self.0
38 }
39
40 pub fn as_str(&self) -> &str {
41 &self.0
42 }
43}
44
45impl Default for UserId {
46 fn default() -> Self {
47 Self::new_random()
48 }
49}
50
51impl From<String> for UserId {
52 fn from(s: String) -> Self {
53 Self(s)
54 }
55}
56
57impl From<&str> for UserId {
58 fn from(s: &str) -> Self {
59 Self(s.to_string())
60 }
61}
62
63impl std::fmt::Display for UserId {
64 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65 write!(f, "{}", self.0)
66 }
67}
68
69#[async_trait]
74pub trait UserManager: Send + Sync + 'static {
75 async fn create_user(&self, user: &NewUser) -> Result<User, Error>;
77
78 async fn get_user(&self, id: &UserId) -> Result<Option<User>, Error>;
80
81 async fn get_user_by_email(&self, email: &str) -> Result<Option<User>, Error>;
83
84 async fn get_or_create_user_by_email(&self, email: &str) -> Result<User, Error>;
86
87 async fn update_user(&self, user: &User) -> Result<User, Error>;
89
90 async fn delete_user(&self, id: &UserId) -> Result<(), Error>;
92
93 async fn set_user_email_verified(&self, user_id: &UserId) -> Result<(), Error>;
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct User {
103 pub id: UserId,
105
106 pub name: Option<String>,
108
109 pub email: String,
111
112 pub email_verified_at: Option<DateTime<Utc>>,
114
115 pub created_at: DateTime<Utc>,
117
118 pub updated_at: DateTime<Utc>,
120}
121
122impl User {
123 pub fn builder() -> UserBuilder {
124 UserBuilder::default()
125 }
126
127 pub fn is_email_verified(&self) -> bool {
129 self.email_verified_at.is_some()
130 }
131}
132
133#[derive(Default)]
134pub struct UserBuilder {
135 id: Option<UserId>,
136 name: Option<String>,
137 email: Option<String>,
138 email_verified_at: Option<DateTime<Utc>>,
139 created_at: Option<DateTime<Utc>>,
140 updated_at: Option<DateTime<Utc>>,
141}
142
143impl UserBuilder {
144 pub fn id(mut self, id: UserId) -> Self {
145 self.id = Some(id);
146 self
147 }
148
149 pub fn name(mut self, name: Option<String>) -> Self {
150 self.name = name;
151 self
152 }
153
154 pub fn email(mut self, email: String) -> Self {
155 self.email = Some(email);
156 self
157 }
158
159 pub fn email_verified_at(mut self, email_verified_at: Option<DateTime<Utc>>) -> Self {
160 self.email_verified_at = email_verified_at;
161 self
162 }
163
164 pub fn created_at(mut self, created_at: DateTime<Utc>) -> Self {
165 self.created_at = Some(created_at);
166 self
167 }
168
169 pub fn updated_at(mut self, updated_at: DateTime<Utc>) -> Self {
170 self.updated_at = Some(updated_at);
171 self
172 }
173
174 pub fn build(self) -> Result<User, Error> {
175 let now = Utc::now();
176 Ok(User {
177 id: self.id.unwrap_or_default(),
178 name: self.name,
179 email: self.email.ok_or(ValidationError::InvalidField(
180 "Email is required".to_string(),
181 ))?,
182 email_verified_at: self.email_verified_at,
183 created_at: self.created_at.unwrap_or(now),
184 updated_at: self.updated_at.unwrap_or(now),
185 })
186 }
187}
188
189pub struct DefaultUserManager<S>
194where
195 S: crate::storage::UserStorage,
196{
197 storage: std::sync::Arc<S>,
198}
199
200impl<S> DefaultUserManager<S>
201where
202 S: crate::storage::UserStorage,
203{
204 pub fn new(storage: std::sync::Arc<S>) -> Self {
206 Self { storage }
207 }
208}
209
210#[async_trait]
211impl<S> UserManager for DefaultUserManager<S>
212where
213 S: crate::storage::UserStorage,
214{
215 async fn create_user(&self, user: &NewUser) -> Result<User, Error> {
216 self.storage
217 .create_user(user)
218 .await
219 .map_err(|e| Error::Storage(crate::error::StorageError::Database(e.to_string())))
220 }
221
222 async fn get_user(&self, id: &UserId) -> Result<Option<User>, Error> {
223 self.storage
224 .get_user(id)
225 .await
226 .map_err(|e| Error::Storage(crate::error::StorageError::Database(e.to_string())))
227 }
228
229 async fn get_user_by_email(&self, email: &str) -> Result<Option<User>, Error> {
230 self.storage
231 .get_user_by_email(email)
232 .await
233 .map_err(|e| Error::Storage(crate::error::StorageError::Database(e.to_string())))
234 }
235
236 async fn get_or_create_user_by_email(&self, email: &str) -> Result<User, Error> {
237 self.storage
238 .get_or_create_user_by_email(email)
239 .await
240 .map_err(|e| Error::Storage(crate::error::StorageError::Database(e.to_string())))
241 }
242
243 async fn update_user(&self, user: &User) -> Result<User, Error> {
244 self.storage
245 .update_user(user)
246 .await
247 .map_err(|e| Error::Storage(crate::error::StorageError::Database(e.to_string())))
248 }
249
250 async fn delete_user(&self, id: &UserId) -> Result<(), Error> {
251 self.storage
252 .delete_user(id)
253 .await
254 .map_err(|e| Error::Storage(crate::error::StorageError::Database(e.to_string())))
255 }
256
257 async fn set_user_email_verified(&self, user_id: &UserId) -> Result<(), Error> {
258 self.storage
259 .set_user_email_verified(user_id)
260 .await
261 .map_err(|e| Error::Storage(crate::error::StorageError::Database(e.to_string())))
262 }
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
266pub struct OAuthAccount {
267 pub user_id: UserId,
268 pub provider: String,
269 pub subject: String,
270 pub created_at: DateTime<Utc>,
271 pub updated_at: DateTime<Utc>,
272}
273
274impl OAuthAccount {
275 pub fn builder() -> OAuthAccountBuilder {
276 OAuthAccountBuilder::default()
277 }
278}
279
280#[derive(Default)]
281pub struct OAuthAccountBuilder {
282 user_id: Option<UserId>,
283 provider: Option<String>,
284 subject: Option<String>,
285 created_at: Option<DateTime<Utc>>,
286 updated_at: Option<DateTime<Utc>>,
287}
288
289impl OAuthAccountBuilder {
290 pub fn user_id(mut self, user_id: UserId) -> Self {
291 self.user_id = Some(user_id);
292 self
293 }
294
295 pub fn provider(mut self, provider: String) -> Self {
296 self.provider = Some(provider);
297 self
298 }
299
300 pub fn subject(mut self, subject: String) -> Self {
301 self.subject = Some(subject);
302 self
303 }
304
305 pub fn created_at(mut self, created_at: DateTime<Utc>) -> Self {
306 self.created_at = Some(created_at);
307 self
308 }
309
310 pub fn updated_at(mut self, updated_at: DateTime<Utc>) -> Self {
311 self.updated_at = Some(updated_at);
312 self
313 }
314
315 pub fn build(self) -> Result<OAuthAccount, Error> {
316 let now = Utc::now();
317 Ok(OAuthAccount {
318 user_id: self.user_id.ok_or(ValidationError::MissingField(
319 "User ID is required".to_string(),
320 ))?,
321 provider: self.provider.ok_or(ValidationError::MissingField(
322 "Provider is required".to_string(),
323 ))?,
324 subject: self.subject.ok_or(ValidationError::MissingField(
325 "Subject is required".to_string(),
326 ))?,
327 created_at: self.created_at.unwrap_or(now),
328 updated_at: self.updated_at.unwrap_or(now),
329 })
330 }
331}
332
333#[cfg(test)]
334mod tests {
335 use super::*;
336
337 #[test]
338 fn test_user_id() {
339 let user_id = UserId::new("test");
340 assert_eq!(user_id.as_str(), "test");
341
342 let user_id_from_str = UserId::from(user_id.as_str());
343 assert_eq!(user_id_from_str, user_id);
344
345 let user_id_random = UserId::new_random();
346 assert_ne!(user_id_random, user_id);
347 }
348}