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 fn active(&self) -> bool;
172}
173
174pub trait AuthAccount: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
176 fn adapter_snapshot(&self) -> Option<&AdapterOutput> {
177 None
178 }
179 fn additional_fields(&self) -> crate::field_policy::FieldOutput {
180 crate::field_policy::FieldOutput::new()
181 }
182 fn id(&self) -> Cow<'_, str>;
183 fn account_id(&self) -> &str;
184 fn provider_id(&self) -> &str;
185 fn user_id(&self) -> Cow<'_, str>;
186 fn access_token(&self) -> Option<&str>;
187 fn refresh_token(&self) -> Option<&str>;
188 fn id_token(&self) -> Option<&str>;
189 fn access_token_expires_at(&self) -> Option<DateTime<Utc>>;
190 fn refresh_token_expires_at(&self) -> Option<DateTime<Utc>>;
191 fn scope(&self) -> Option<&str>;
192 fn password(&self) -> Option<&str>;
193 fn created_at(&self) -> DateTime<Utc>;
194 fn updated_at(&self) -> DateTime<Utc>;
195}
196
197pub trait AuthOrganization: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
199 fn additional_fields(&self) -> std::collections::BTreeMap<String, serde_json::Value> {
200 std::collections::BTreeMap::default()
201 }
202 fn id(&self) -> Cow<'_, str>;
203 fn name(&self) -> &str;
204 fn slug(&self) -> &str;
205 fn logo(&self) -> Option<&str>;
206 fn metadata(&self) -> Option<&serde_json::Value>;
207 fn created_at(&self) -> DateTime<Utc>;
208 fn updated_at(&self) -> DateTime<Utc>;
209}
210
211pub trait AuthMember: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
213 fn id(&self) -> Cow<'_, str>;
214 fn organization_id(&self) -> Cow<'_, str>;
215 fn user_id(&self) -> Cow<'_, str>;
216 fn role(&self) -> &str;
217 fn created_at(&self) -> DateTime<Utc>;
218}
219
220pub trait AuthInvitation: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
222 fn id(&self) -> Cow<'_, str>;
223 fn organization_id(&self) -> Cow<'_, str>;
224 fn email(&self) -> &str;
225 fn role(&self) -> &str;
226 fn optional_role(&self) -> Option<&str> {
227 Some(self.role())
228 }
229 fn team_id(&self) -> Option<&str> {
230 None
231 }
232 fn status(&self) -> &InvitationStatus;
233 fn inviter_id(&self) -> Cow<'_, str>;
234 fn expires_at(&self) -> DateTime<Utc>;
235 fn created_at(&self) -> DateTime<Utc>;
236
237 fn is_pending(&self) -> bool {
239 *self.status() == InvitationStatus::Pending
240 }
241
242 fn is_expired(&self) -> bool {
244 self.expires_at() < Utc::now()
245 }
246}
247
248pub trait AuthVerification: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
250 fn id(&self) -> Cow<'_, str>;
251 fn identifier(&self) -> &str;
252 fn value(&self) -> &str;
253 fn expires_at(&self) -> DateTime<Utc>;
254 fn created_at(&self) -> DateTime<Utc>;
255 fn updated_at(&self) -> DateTime<Utc>;
256}
257
258pub trait AuthTwoFactor: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
260 fn id(&self) -> Cow<'_, str>;
261 fn secret(&self) -> &str;
262 fn backup_codes(&self) -> &str;
263 fn user_id(&self) -> Cow<'_, str>;
264 fn created_at(&self) -> DateTime<Utc>;
265 fn updated_at(&self) -> DateTime<Utc>;
266 fn verified(&self) -> Option<bool> {
268 None
269 }
270 fn failed_verification_count(&self) -> Option<f64> {
271 None
272 }
273 fn locked_until(&self) -> Option<DateTime<Utc>> {
274 None
275 }
276}
277
278pub trait AuthApiKey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
280 fn id(&self) -> Cow<'_, str>;
281 fn name(&self) -> Option<&str>;
282 fn start(&self) -> Option<&str>;
283 fn prefix(&self) -> Option<&str>;
284 fn key_hash(&self) -> &str;
285 fn reference_id(&self) -> Cow<'_, str>;
288 fn config_id(&self) -> Cow<'_, str>;
291 fn refill_interval(&self) -> Option<f64>;
292 fn refill_amount(&self) -> Option<f64>;
293 fn last_refill_at(&self) -> Option<&str>;
294 fn enabled(&self) -> bool;
295 fn rate_limit_enabled(&self) -> bool;
296 fn rate_limit_time_window(&self) -> Option<f64>;
297 fn rate_limit_max(&self) -> Option<f64>;
298 fn request_count(&self) -> Option<f64>;
299 fn remaining(&self) -> Option<f64>;
300 fn last_request(&self) -> Option<&str>;
301 fn expires_at(&self) -> Option<&str>;
302 fn created_at(&self) -> &str;
303 fn updated_at(&self) -> &str;
304 fn permissions(&self) -> Option<&str>;
305 fn metadata(&self) -> Option<&str>;
306}
307
308pub trait AuthPasskey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
310 fn id(&self) -> Cow<'_, str>;
311 fn name(&self) -> Option<&str>;
312 fn public_key(&self) -> &str;
313 fn user_id(&self) -> Cow<'_, str>;
314 fn credential_id(&self) -> &str;
315 fn counter(&self) -> u64;
316 fn device_type(&self) -> &str;
317 fn backed_up(&self) -> bool;
318 fn transports(&self) -> Option<&str>;
319 fn created_at(&self) -> DateTime<Utc>;
320 fn updated_at(&self) -> DateTime<Utc>;
321 fn aaguid(&self) -> Option<&str>;
322 fn credential(&self) -> &str;
323}
324
325#[derive(Debug, Clone, Serialize, Deserialize)]
330pub struct MemberUserView {
331 pub id: String,
332 pub email: Option<String>,
333 pub name: Option<String>,
334 pub image: Option<String>,
335}
336
337impl MemberUserView {
338 #[must_use]
340 pub fn from_user(user: &impl AuthUser) -> Self {
341 Self {
342 id: user.id().to_string(),
343 email: user.email().map(ToOwned::to_owned),
344 name: user.name().map(ToOwned::to_owned),
345 image: user.image().map(ToOwned::to_owned),
346 }
347 }
348}