1use chrono::{DateTime, Utc};
16use serde::{Deserialize, Serialize};
17use uuid::Uuid;
18
19use crate::{Error, error::ValidationError};
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
23pub struct UserId(String);
24
25impl UserId {
26 pub fn new(id: &str) -> Self {
27 UserId(id.to_string())
28 }
29
30 pub fn new_random() -> Self {
31 UserId(Uuid::new_v4().to_string())
32 }
33
34 pub fn into_inner(self) -> String {
35 self.0
36 }
37
38 pub fn as_uuid(&self) -> Uuid {
39 Uuid::parse_str(&self.0).unwrap()
40 }
41
42 pub fn as_str(&self) -> &str {
43 &self.0
44 }
45}
46
47impl Default for UserId {
48 fn default() -> Self {
49 Self::new_random()
50 }
51}
52
53impl From<String> for UserId {
54 fn from(s: String) -> Self {
55 Self(s)
56 }
57}
58
59impl From<&str> for UserId {
60 fn from(s: &str) -> Self {
61 Self(s.to_string())
62 }
63}
64
65impl std::fmt::Display for UserId {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 write!(f, "{}", self.0)
68 }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct User {
77 pub id: UserId,
79
80 pub name: Option<String>,
82
83 pub email: String,
85
86 pub email_verified_at: Option<DateTime<Utc>>,
88
89 pub created_at: DateTime<Utc>,
91
92 pub updated_at: DateTime<Utc>,
94}
95
96impl User {
97 pub fn builder() -> UserBuilder {
98 UserBuilder::default()
99 }
100
101 pub fn is_email_verified(&self) -> bool {
103 self.email_verified_at.is_some() && self.email_verified_at.unwrap() < Utc::now()
104 }
105}
106
107#[derive(Default)]
108pub struct UserBuilder {
109 id: Option<UserId>,
110 name: Option<String>,
111 email: Option<String>,
112 email_verified_at: Option<DateTime<Utc>>,
113 created_at: Option<DateTime<Utc>>,
114 updated_at: Option<DateTime<Utc>>,
115}
116
117impl UserBuilder {
118 pub fn id(mut self, id: UserId) -> Self {
119 self.id = Some(id);
120 self
121 }
122
123 pub fn name(mut self, name: Option<String>) -> Self {
124 self.name = name;
125 self
126 }
127
128 pub fn email(mut self, email: String) -> Self {
129 self.email = Some(email);
130 self
131 }
132
133 pub fn email_verified_at(mut self, email_verified_at: Option<DateTime<Utc>>) -> Self {
134 self.email_verified_at = email_verified_at;
135 self
136 }
137
138 pub fn created_at(mut self, created_at: DateTime<Utc>) -> Self {
139 self.created_at = Some(created_at);
140 self
141 }
142
143 pub fn updated_at(mut self, updated_at: DateTime<Utc>) -> Self {
144 self.updated_at = Some(updated_at);
145 self
146 }
147
148 pub fn build(self) -> Result<User, Error> {
149 let now = Utc::now();
150 Ok(User {
151 id: self.id.unwrap_or(UserId::new_random()),
152 name: self.name,
153 email: self.email.ok_or(ValidationError::InvalidField(
154 "Email is required".to_string(),
155 ))?,
156 email_verified_at: self.email_verified_at,
157 created_at: self.created_at.unwrap_or(now),
158 updated_at: self.updated_at.unwrap_or(now),
159 })
160 }
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
164pub struct OAuthAccount {
165 pub user_id: UserId,
166 pub provider: String,
167 pub subject: String,
168 pub created_at: DateTime<Utc>,
169 pub updated_at: DateTime<Utc>,
170}
171
172impl OAuthAccount {
173 pub fn builder() -> OAuthAccountBuilder {
174 OAuthAccountBuilder::default()
175 }
176}
177
178#[derive(Default)]
179pub struct OAuthAccountBuilder {
180 user_id: Option<UserId>,
181 provider: Option<String>,
182 subject: Option<String>,
183 created_at: Option<DateTime<Utc>>,
184 updated_at: Option<DateTime<Utc>>,
185}
186
187impl OAuthAccountBuilder {
188 pub fn user_id(mut self, user_id: UserId) -> Self {
189 self.user_id = Some(user_id);
190 self
191 }
192
193 pub fn provider(mut self, provider: String) -> Self {
194 self.provider = Some(provider);
195 self
196 }
197
198 pub fn subject(mut self, subject: String) -> Self {
199 self.subject = Some(subject);
200 self
201 }
202
203 pub fn created_at(mut self, created_at: DateTime<Utc>) -> Self {
204 self.created_at = Some(created_at);
205 self
206 }
207
208 pub fn updated_at(mut self, updated_at: DateTime<Utc>) -> Self {
209 self.updated_at = Some(updated_at);
210 self
211 }
212
213 pub fn build(self) -> Result<OAuthAccount, Error> {
214 let now = Utc::now();
215 Ok(OAuthAccount {
216 user_id: self.user_id.ok_or(ValidationError::MissingField(
217 "User ID is required".to_string(),
218 ))?,
219 provider: self.provider.ok_or(ValidationError::MissingField(
220 "Provider is required".to_string(),
221 ))?,
222 subject: self.subject.ok_or(ValidationError::MissingField(
223 "Subject is required".to_string(),
224 ))?,
225 created_at: self.created_at.unwrap_or(now),
226 updated_at: self.updated_at.unwrap_or(now),
227 })
228 }
229}
230
231#[cfg(test)]
232mod tests {
233 use super::*;
234
235 #[test]
236 fn test_user_id() {
237 let user_id = UserId::new("test");
238 assert_eq!(user_id.as_str(), "test");
239
240 let user_id_from_str = UserId::from(user_id.as_str());
241 assert_eq!(user_id_from_str, user_id);
242
243 let user_id_random = UserId::new_random();
244 assert_ne!(user_id_random, user_id);
245 }
246}