1use crate::AuthError;
12use crate::types::InvitationStatus;
13use crate::{AdapterOutput, AuthResult};
14use chrono::{DateTime, Utc};
15use serde::{Deserialize, Serialize};
16use std::borrow::Cow;
17
18pub trait AuthTimestamp: Sized {
23 type UtcValue;
25 fn from_utc(value: Self::UtcValue) -> Self;
27 fn into_utc(self) -> Self::UtcValue;
29}
30
31impl AuthTimestamp for chrono::NaiveDateTime {
32 type UtcValue = DateTime<Utc>;
33 fn from_utc(value: Self::UtcValue) -> Self {
34 value.naive_utc()
35 }
36 fn into_utc(self) -> Self::UtcValue {
37 self.and_utc()
38 }
39}
40
41impl<Tz: chrono::TimeZone> AuthTimestamp for DateTime<Tz>
42where
43 Self: From<DateTime<Utc>>,
44{
45 type UtcValue = DateTime<Utc>;
46 fn from_utc(value: Self::UtcValue) -> Self {
47 value.into()
48 }
49 fn into_utc(self) -> Self::UtcValue {
50 self.with_timezone(&Utc)
51 }
52}
53
54impl<T: AuthTimestamp> AuthTimestamp for Option<T> {
55 type UtcValue = Option<T::UtcValue>;
56 fn from_utc(value: Self::UtcValue) -> Self {
57 value.map(T::from_utc)
58 }
59 fn into_utc(self) -> Self::UtcValue {
60 self.map(T::into_utc)
61 }
62}
63
64pub trait AuthUser: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
69 fn secondary_snapshot(&self) -> AuthResult<serde_json::Value> {
72 Err(AuthError::NotImplemented(
73 "Secondary model encoding is unsupported".into(),
74 ))
75 }
76 fn from_secondary_snapshot(_snapshot: serde_json::Value) -> AuthResult<Self> {
78 Err(AuthError::NotImplemented(
79 "Secondary model decoding is unsupported".into(),
80 ))
81 }
82
83 fn adapter_snapshot(&self) -> Option<&AdapterOutput> {
85 None
86 }
87 fn retained_user_view(&self) -> Option<&crate::UserView> {
89 None
90 }
91 fn additional_fields(&self) -> crate::field_policy::FieldOutput {
93 crate::field_policy::FieldOutput::new()
94 }
95 fn id(&self) -> Cow<'_, str>;
96 fn email(&self) -> Option<&str>;
97 fn name(&self) -> Option<&str>;
98 fn email_verified(&self) -> bool;
99 fn image(&self) -> Option<&str>;
100 fn created_at(&self) -> DateTime<Utc>;
101 fn updated_at(&self) -> DateTime<Utc>;
102 fn username(&self) -> Option<&str>;
103 fn display_username(&self) -> Option<&str>;
104 fn two_factor_enabled(&self) -> bool;
105 fn two_factor_enabled_value(&self) -> Option<bool> {
107 Some(self.two_factor_enabled())
108 }
109 fn role(&self) -> Option<&str>;
110 fn banned(&self) -> bool;
111 fn banned_value(&self) -> Option<bool> {
113 Some(self.banned())
114 }
115 fn ban_reason(&self) -> Option<&str>;
116 fn ban_expires(&self) -> Option<DateTime<Utc>>;
117 fn metadata(&self) -> &serde_json::Value;
118 fn is_anonymous(&self) -> Option<bool> {
120 None
121 }
122 fn phone_number(&self) -> Option<&str> {
123 None
124 }
125 fn phone_number_verified(&self) -> Option<bool> {
126 None
127 }
128 fn last_login_method(&self) -> Option<&str> {
129 None
130 }
131}
132
133pub trait AuthSession: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
135 fn secondary_snapshot(&self) -> AuthResult<serde_json::Value> {
138 Err(AuthError::NotImplemented(
139 "Secondary model encoding is unsupported".into(),
140 ))
141 }
142 fn from_secondary_snapshot(_snapshot: serde_json::Value) -> AuthResult<Self> {
144 Err(AuthError::NotImplemented(
145 "Secondary model decoding is unsupported".into(),
146 ))
147 }
148
149 fn adapter_snapshot(&self) -> Option<&AdapterOutput> {
150 None
151 }
152 fn retained_session_view(&self) -> Option<&crate::SessionView> {
153 None
154 }
155 fn additional_fields(&self) -> serde_json::Map<String, serde_json::Value> {
156 serde_json::Map::new()
157 }
158 fn id(&self) -> Cow<'_, str>;
159 fn expires_at(&self) -> DateTime<Utc>;
160 fn token(&self) -> &str;
161 fn created_at(&self) -> DateTime<Utc>;
162 fn updated_at(&self) -> DateTime<Utc>;
163 fn ip_address(&self) -> Option<&str>;
164 fn user_agent(&self) -> Option<&str>;
165 fn user_id(&self) -> Cow<'_, str>;
166 fn impersonated_by(&self) -> Option<&str>;
167 fn active_organization_id(&self) -> Option<&str>;
168 fn active_team_id(&self) -> Option<&str> {
169 None
170 }
171}
172
173pub trait AuthAccount: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
175 fn adapter_snapshot(&self) -> Option<&AdapterOutput> {
176 None
177 }
178 fn additional_fields(&self) -> crate::field_policy::FieldOutput {
179 crate::field_policy::FieldOutput::new()
180 }
181 fn id(&self) -> Cow<'_, str>;
182 fn account_id(&self) -> &str;
183 fn provider_id(&self) -> &str;
184 fn user_id(&self) -> Cow<'_, str>;
185 fn access_token(&self) -> Option<&str>;
186 fn refresh_token(&self) -> Option<&str>;
187 fn id_token(&self) -> Option<&str>;
188 fn access_token_expires_at(&self) -> Option<DateTime<Utc>>;
189 fn refresh_token_expires_at(&self) -> Option<DateTime<Utc>>;
190 fn scope(&self) -> Option<&str>;
191 fn password(&self) -> Option<&str>;
192 fn created_at(&self) -> DateTime<Utc>;
193 fn updated_at(&self) -> DateTime<Utc>;
194}
195
196pub trait AuthOrganization: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
198 fn additional_fields(&self) -> std::collections::BTreeMap<String, serde_json::Value> {
199 std::collections::BTreeMap::default()
200 }
201 fn id(&self) -> Cow<'_, str>;
202 fn name(&self) -> &str;
203 fn slug(&self) -> &str;
204 fn logo(&self) -> Option<&str>;
205 fn metadata(&self) -> Option<&serde_json::Value>;
206 fn created_at(&self) -> DateTime<Utc>;
207}
208
209pub trait AuthMember: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
211 fn id(&self) -> Cow<'_, str>;
212 fn organization_id(&self) -> Cow<'_, str>;
213 fn user_id(&self) -> Cow<'_, str>;
214 fn role(&self) -> &str;
215 fn created_at(&self) -> DateTime<Utc>;
216}
217
218pub trait AuthInvitation: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
220 fn id(&self) -> Cow<'_, str>;
221 fn organization_id(&self) -> Cow<'_, str>;
222 fn email(&self) -> &str;
223 fn role(&self) -> &str;
224 fn optional_role(&self) -> Option<&str> {
225 Some(self.role())
226 }
227 fn team_id(&self) -> Option<&str> {
228 None
229 }
230 fn status(&self) -> &InvitationStatus;
231 fn inviter_id(&self) -> Cow<'_, str>;
232 fn expires_at(&self) -> DateTime<Utc>;
233 fn created_at(&self) -> DateTime<Utc>;
234
235 fn is_pending(&self) -> bool {
237 *self.status() == InvitationStatus::Pending
238 }
239
240 fn is_expired(&self) -> bool {
242 self.expires_at() < Utc::now()
243 }
244}
245
246pub trait AuthVerification: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
248 fn id(&self) -> Cow<'_, str>;
249 fn identifier(&self) -> &str;
250 fn value(&self) -> &str;
251 fn expires_at(&self) -> DateTime<Utc>;
252 fn created_at(&self) -> DateTime<Utc>;
253 fn updated_at(&self) -> DateTime<Utc>;
254}
255
256pub trait AuthTwoFactor: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
258 fn id(&self) -> Cow<'_, str>;
259 fn secret(&self) -> &str;
260 fn backup_codes(&self) -> &str;
261 fn user_id(&self) -> Cow<'_, str>;
262 fn verified(&self) -> Option<bool> {
264 None
265 }
266 fn failed_verification_count(&self) -> Option<f64> {
267 None
268 }
269 fn locked_until(&self) -> Option<DateTime<Utc>> {
270 None
271 }
272}
273
274pub trait AuthApiKey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
276 fn id(&self) -> Cow<'_, str>;
277 fn name(&self) -> Option<&str>;
278 fn start(&self) -> Option<&str>;
279 fn prefix(&self) -> Option<&str>;
280 fn key_hash(&self) -> &str;
281 fn reference_id(&self) -> Cow<'_, str>;
284 fn config_id(&self) -> Cow<'_, str>;
287 fn refill_interval(&self) -> Option<f64>;
288 fn refill_amount(&self) -> Option<f64>;
289 fn last_refill_at(&self) -> Option<&str>;
290 fn enabled(&self) -> bool;
291 fn rate_limit_enabled(&self) -> bool;
292 fn rate_limit_time_window(&self) -> Option<f64>;
293 fn rate_limit_max(&self) -> Option<f64>;
294 fn request_count(&self) -> Option<f64>;
295 fn remaining(&self) -> Option<f64>;
296 fn last_request(&self) -> Option<&str>;
297 fn expires_at(&self) -> Option<&str>;
298 fn created_at(&self) -> &str;
299 fn updated_at(&self) -> &str;
300 fn permissions(&self) -> Option<&str>;
301 fn metadata(&self) -> Option<&str>;
302}
303
304pub trait AuthPasskey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
306 fn id(&self) -> Cow<'_, str>;
307 fn name(&self) -> Option<&str>;
308 fn public_key(&self) -> &str;
309 fn user_id(&self) -> Cow<'_, str>;
310 fn credential_id(&self) -> &str;
311 fn counter(&self) -> u64;
312 fn device_type(&self) -> &str;
313 fn backed_up(&self) -> bool;
314 fn transports(&self) -> Option<&str>;
315 fn created_at(&self) -> Option<DateTime<Utc>>;
316 fn aaguid(&self) -> Option<&str>;
317}
318
319#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct MemberUserView {
325 pub id: String,
326 pub email: Option<String>,
327 pub name: Option<String>,
328 pub image: Option<String>,
329}
330
331impl MemberUserView {
332 #[must_use]
334 pub fn from_user(user: &impl AuthUser) -> Self {
335 Self {
336 id: user.id().to_string(),
337 email: user.email().map(ToOwned::to_owned),
338 name: user.name().map(ToOwned::to_owned),
339 image: user.image().map(ToOwned::to_owned),
340 }
341 }
342}