1use std::net::IpAddr;
9
10use chrono::{DateTime, Utc};
11use rand::RngExt;
12use serde::Serialize;
13use ulid::Ulid;
14use url::Url;
15
16use crate::UlidExt as _;
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
19pub struct MatrixUser {
20 pub mxid: String,
21 pub display_name: Option<String>,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
25pub struct User {
26 pub id: Ulid,
27 pub username: String,
28 pub sub: String,
29 pub created_at: DateTime<Utc>,
30 pub locked_at: Option<DateTime<Utc>>,
31 pub deactivated_at: Option<DateTime<Utc>>,
32 pub can_request_admin: bool,
33 pub is_guest: bool,
34}
35
36impl User {
37 #[must_use]
39 pub fn is_valid(&self) -> bool {
40 self.locked_at.is_none() && self.deactivated_at.is_none()
41 }
42
43 #[must_use]
53 pub fn is_valid_actor(&self) -> bool {
54 self.deactivated_at.is_none()
55 }
56}
57
58impl User {
59 #[doc(hidden)]
60 #[must_use]
61 pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl RngExt) -> Vec<Self> {
62 vec![User {
63 id: Ulid::from_datetime_with_rng(now, rng),
64 username: "john".to_owned(),
65 sub: "123-456".to_owned(),
66 created_at: now,
67 locked_at: None,
68 deactivated_at: None,
69 can_request_admin: false,
70 is_guest: false,
71 }]
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
76pub struct Password {
77 pub id: Ulid,
78 pub hashed_password: String,
79 pub version: u16,
80 pub upgraded_from_id: Option<Ulid>,
81 pub created_at: DateTime<Utc>,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
85pub struct Authentication {
86 pub id: Ulid,
87 pub created_at: DateTime<Utc>,
88 pub authentication_method: AuthenticationMethod,
89}
90
91#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
92pub enum AuthenticationMethod {
93 Password { user_password_id: Ulid },
94 UpstreamOAuth2 { upstream_oauth2_session_id: Ulid },
95 Unknown,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
104pub struct UserRecoverySession {
105 pub id: Ulid,
106 pub email: String,
107 pub user_agent: String,
108 pub ip_address: Option<IpAddr>,
109 pub locale: String,
110 pub created_at: DateTime<Utc>,
111 pub consumed_at: Option<DateTime<Utc>>,
112}
113
114#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
120pub struct UserRecoveryTicket {
121 pub id: Ulid,
122 pub user_recovery_session_id: Ulid,
123 pub user_email_id: Ulid,
124 pub ticket: String,
125 pub created_at: DateTime<Utc>,
126 pub expires_at: DateTime<Utc>,
127}
128
129impl UserRecoveryTicket {
130 #[must_use]
131 pub fn active(&self, now: DateTime<Utc>) -> bool {
132 now < self.expires_at
133 }
134}
135
136#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
138pub struct UserEmailAuthentication {
139 pub id: Ulid,
140 pub user_session_id: Option<Ulid>,
141 pub user_registration_id: Option<Ulid>,
142 pub email: String,
143 pub created_at: DateTime<Utc>,
144 pub completed_at: Option<DateTime<Utc>>,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
149pub struct UserEmailAuthenticationCode {
150 pub id: Ulid,
151 pub user_email_authentication_id: Ulid,
152 pub code: String,
153 pub created_at: DateTime<Utc>,
154 pub expires_at: DateTime<Utc>,
155}
156
157#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
158pub struct BrowserSession {
159 pub id: Ulid,
160 pub user: User,
161 pub created_at: DateTime<Utc>,
162 pub finished_at: Option<DateTime<Utc>>,
163 pub user_agent: Option<String>,
164 pub last_active_at: Option<DateTime<Utc>>,
165 pub last_active_ip: Option<IpAddr>,
166}
167
168impl BrowserSession {
169 #[must_use]
170 pub fn active(&self) -> bool {
171 self.finished_at.is_none() && self.user.is_valid()
172 }
173}
174
175impl BrowserSession {
176 #[must_use]
177 pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl RngExt) -> Vec<Self> {
178 User::samples(now, rng)
179 .into_iter()
180 .map(|user| BrowserSession {
181 id: Ulid::from_datetime_with_rng(now, rng),
182 user,
183 created_at: now,
184 finished_at: None,
185 user_agent: Some(
186 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36".to_owned()
187 ),
188 last_active_at: Some(now),
189 last_active_ip: None,
190 })
191 .collect()
192 }
193}
194
195#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
196pub struct UserEmail {
197 pub id: Ulid,
198 pub user_id: Ulid,
199 pub email: String,
200 pub created_at: DateTime<Utc>,
201}
202
203impl UserEmail {
204 #[must_use]
205 pub fn samples(now: chrono::DateTime<Utc>, rng: &mut impl RngExt) -> Vec<Self> {
206 vec![
207 Self {
208 id: Ulid::from_datetime_with_rng(now, rng),
209 user_id: Ulid::from_datetime_with_rng(now, rng),
210 email: "alice@example.com".to_owned(),
211 created_at: now,
212 },
213 Self {
214 id: Ulid::from_datetime_with_rng(now, rng),
215 user_id: Ulid::from_datetime_with_rng(now, rng),
216 email: "bob@example.com".to_owned(),
217 created_at: now,
218 },
219 ]
220 }
221}
222
223#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
224pub struct UserRegistrationPassword {
225 pub hashed_password: String,
226 pub version: u16,
227}
228
229#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
230pub struct UserRegistrationToken {
231 pub id: Ulid,
232 pub token: String,
233 pub usage_limit: Option<u32>,
234 pub times_used: u32,
235 pub created_at: DateTime<Utc>,
236 pub last_used_at: Option<DateTime<Utc>>,
237 pub expires_at: Option<DateTime<Utc>>,
238 pub revoked_at: Option<DateTime<Utc>>,
239}
240
241impl UserRegistrationToken {
242 #[must_use]
244 pub fn is_valid(&self, now: DateTime<Utc>) -> bool {
245 if self.revoked_at.is_some() {
247 return false;
248 }
249
250 if let Some(expires_at) = self.expires_at
252 && now >= expires_at
253 {
254 return false;
255 }
256
257 if let Some(usage_limit) = self.usage_limit
259 && self.times_used >= usage_limit
260 {
261 return false;
262 }
263
264 true
265 }
266
267 #[must_use]
270 pub fn can_be_used(&self, now: DateTime<Utc>) -> bool {
271 self.is_valid(now)
272 }
273}
274
275#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
276pub struct UserRegistration {
277 pub id: Ulid,
278 pub username: String,
279 pub display_name: Option<String>,
280 pub terms_url: Option<Url>,
281 pub email_authentication_id: Option<Ulid>,
282 pub user_registration_token_id: Option<Ulid>,
283 pub password: Option<UserRegistrationPassword>,
284 pub upstream_oauth_authorization_session_id: Option<Ulid>,
285 pub post_auth_action: Option<serde_json::Value>,
286 pub ip_address: Option<IpAddr>,
287 pub user_agent: Option<String>,
288 pub created_at: DateTime<Utc>,
289 pub completed_at: Option<DateTime<Utc>>,
290}