better_auth_core/
entity.rs1use crate::types::InvitationStatus;
12use chrono::{DateTime, Utc};
13use serde::Deserialize;
14use serde::Serialize;
15use std::borrow::Cow;
16
17pub trait AuthTimestamp: Sized {
22 type UtcValue;
24 fn from_utc(value: Self::UtcValue) -> Self;
26 fn into_utc(self) -> Self::UtcValue;
28}
29
30impl AuthTimestamp for chrono::NaiveDateTime {
31 type UtcValue = DateTime<Utc>;
32 fn from_utc(value: Self::UtcValue) -> Self {
33 value.naive_utc()
34 }
35 fn into_utc(self) -> Self::UtcValue {
36 self.and_utc()
37 }
38}
39
40impl<Tz: chrono::TimeZone> AuthTimestamp for DateTime<Tz>
41where
42 DateTime<Tz>: From<DateTime<Utc>>,
43{
44 type UtcValue = DateTime<Utc>;
45 fn from_utc(value: Self::UtcValue) -> Self {
46 value.into()
47 }
48 fn into_utc(self) -> Self::UtcValue {
49 self.with_timezone(&Utc)
50 }
51}
52
53impl<T: AuthTimestamp> AuthTimestamp for Option<T> {
54 type UtcValue = Option<T::UtcValue>;
55 fn from_utc(value: Self::UtcValue) -> Self {
56 value.map(T::from_utc)
57 }
58 fn into_utc(self) -> Self::UtcValue {
59 self.map(T::into_utc)
60 }
61}
62
63pub trait AuthUser: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
68 fn secondary_snapshot(&self) -> crate::AuthResult<serde_json::Value> {
71 Err(crate::AuthError::NotImplemented(
72 "Secondary model encoding is unsupported".into(),
73 ))
74 }
75 fn from_secondary_snapshot(_snapshot: serde_json::Value) -> crate::AuthResult<Self> {
77 Err(crate::AuthError::NotImplemented(
78 "Secondary model decoding is unsupported".into(),
79 ))
80 }
81
82 fn adapter_snapshot(&self) -> Option<&crate::AdapterOutput> {
84 None
85 }
86 fn retained_user_view(&self) -> Option<&crate::UserView> {
88 None
89 }
90 fn additional_fields(&self) -> crate::field_policy::FieldOutput {
92 crate::field_policy::FieldOutput::new()
93 }
94 fn id(&self) -> Cow<'_, str>;
95 fn email(&self) -> Option<&str>;
96 fn name(&self) -> Option<&str>;
97 fn email_verified(&self) -> bool;
98 fn image(&self) -> Option<&str>;
99 fn created_at(&self) -> DateTime<Utc>;
100 fn updated_at(&self) -> DateTime<Utc>;
101 fn username(&self) -> Option<&str>;
102 fn display_username(&self) -> Option<&str>;
103 fn two_factor_enabled(&self) -> bool;
104 fn two_factor_enabled_value(&self) -> Option<bool> {
106 Some(self.two_factor_enabled())
107 }
108 fn role(&self) -> Option<&str>;
109 fn banned(&self) -> bool;
110 fn banned_value(&self) -> Option<bool> {
112 Some(self.banned())
113 }
114 fn ban_reason(&self) -> Option<&str>;
115 fn ban_expires(&self) -> Option<DateTime<Utc>>;
116 fn metadata(&self) -> &serde_json::Value;
117 fn is_anonymous(&self) -> Option<bool> {
119 None
120 }
121 fn phone_number(&self) -> Option<&str> {
122 None
123 }
124 fn phone_number_verified(&self) -> Option<bool> {
125 None
126 }
127 fn last_login_method(&self) -> Option<&str> {
128 None
129 }
130}
131
132pub trait AuthSession: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
134 fn secondary_snapshot(&self) -> crate::AuthResult<serde_json::Value> {
137 Err(crate::AuthError::NotImplemented(
138 "Secondary model encoding is unsupported".into(),
139 ))
140 }
141 fn from_secondary_snapshot(_snapshot: serde_json::Value) -> crate::AuthResult<Self> {
143 Err(crate::AuthError::NotImplemented(
144 "Secondary model decoding is unsupported".into(),
145 ))
146 }
147
148 fn adapter_snapshot(&self) -> Option<&crate::AdapterOutput> {
149 None
150 }
151 fn retained_session_view(&self) -> Option<&crate::SessionView> {
152 None
153 }
154 fn additional_fields(&self) -> serde_json::Map<String, serde_json::Value> {
155 serde_json::Map::new()
156 }
157 fn id(&self) -> Cow<'_, str>;
158 fn expires_at(&self) -> DateTime<Utc>;
159 fn token(&self) -> &str;
160 fn created_at(&self) -> DateTime<Utc>;
161 fn updated_at(&self) -> DateTime<Utc>;
162 fn ip_address(&self) -> Option<&str>;
163 fn user_agent(&self) -> Option<&str>;
164 fn user_id(&self) -> Cow<'_, str>;
165 fn impersonated_by(&self) -> Option<&str>;
166 fn active_organization_id(&self) -> Option<&str>;
167 fn active_team_id(&self) -> Option<&str> {
168 None
169 }
170 fn active(&self) -> bool;
171}
172
173pub trait AuthAccount: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
175 fn adapter_snapshot(&self) -> Option<&crate::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 Default::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 fn updated_at(&self) -> DateTime<Utc>;
208}
209
210pub trait AuthMember: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
212 fn id(&self) -> Cow<'_, str>;
213 fn organization_id(&self) -> Cow<'_, str>;
214 fn user_id(&self) -> Cow<'_, str>;
215 fn role(&self) -> &str;
216 fn created_at(&self) -> DateTime<Utc>;
217}
218
219pub trait AuthInvitation: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
221 fn id(&self) -> Cow<'_, str>;
222 fn organization_id(&self) -> Cow<'_, str>;
223 fn email(&self) -> &str;
224 fn role(&self) -> &str;
225 fn optional_role(&self) -> Option<&str> {
226 Some(self.role())
227 }
228 fn team_id(&self) -> Option<&str> {
229 None
230 }
231 fn status(&self) -> &InvitationStatus;
232 fn inviter_id(&self) -> Cow<'_, str>;
233 fn expires_at(&self) -> DateTime<Utc>;
234 fn created_at(&self) -> DateTime<Utc>;
235
236 fn is_pending(&self) -> bool {
238 *self.status() == InvitationStatus::Pending
239 }
240
241 fn is_expired(&self) -> bool {
243 self.expires_at() < Utc::now()
244 }
245}
246
247pub trait AuthVerification: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
249 fn id(&self) -> Cow<'_, str>;
250 fn identifier(&self) -> &str;
251 fn value(&self) -> &str;
252 fn expires_at(&self) -> DateTime<Utc>;
253 fn created_at(&self) -> DateTime<Utc>;
254 fn updated_at(&self) -> DateTime<Utc>;
255}
256
257pub trait AuthTwoFactor: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
259 fn id(&self) -> Cow<'_, str>;
260 fn secret(&self) -> &str;
261 fn backup_codes(&self) -> &str;
262 fn user_id(&self) -> Cow<'_, str>;
263 fn created_at(&self) -> DateTime<Utc>;
264 fn updated_at(&self) -> DateTime<Utc>;
265 fn verified(&self) -> Option<bool> {
267 None
268 }
269 fn failed_verification_count(&self) -> Option<f64> {
270 None
271 }
272 fn locked_until(&self) -> Option<DateTime<Utc>> {
273 None
274 }
275}
276
277pub trait AuthApiKey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
279 fn id(&self) -> Cow<'_, str>;
280 fn name(&self) -> Option<&str>;
281 fn start(&self) -> Option<&str>;
282 fn prefix(&self) -> Option<&str>;
283 fn key_hash(&self) -> &str;
284 fn reference_id(&self) -> Cow<'_, str>;
287 fn config_id(&self) -> Cow<'_, str>;
290 fn refill_interval(&self) -> Option<f64>;
291 fn refill_amount(&self) -> Option<f64>;
292 fn last_refill_at(&self) -> Option<&str>;
293 fn enabled(&self) -> bool;
294 fn rate_limit_enabled(&self) -> bool;
295 fn rate_limit_time_window(&self) -> Option<f64>;
296 fn rate_limit_max(&self) -> Option<f64>;
297 fn request_count(&self) -> Option<f64>;
298 fn remaining(&self) -> Option<f64>;
299 fn last_request(&self) -> Option<&str>;
300 fn expires_at(&self) -> Option<&str>;
301 fn created_at(&self) -> &str;
302 fn updated_at(&self) -> &str;
303 fn permissions(&self) -> Option<&str>;
304 fn metadata(&self) -> Option<&str>;
305}
306
307pub trait AuthPasskey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
309 fn id(&self) -> Cow<'_, str>;
310 fn name(&self) -> Option<&str>;
311 fn public_key(&self) -> &str;
312 fn user_id(&self) -> Cow<'_, str>;
313 fn credential_id(&self) -> &str;
314 fn counter(&self) -> u64;
315 fn device_type(&self) -> &str;
316 fn backed_up(&self) -> bool;
317 fn transports(&self) -> Option<&str>;
318 fn created_at(&self) -> DateTime<Utc>;
319 fn updated_at(&self) -> DateTime<Utc>;
320 fn aaguid(&self) -> Option<&str>;
321 fn credential(&self) -> &str;
322}
323
324#[derive(Debug, Clone, Serialize, Deserialize)]
329pub struct MemberUserView {
330 pub id: String,
331 pub email: Option<String>,
332 pub name: Option<String>,
333 pub image: Option<String>,
334}
335
336impl MemberUserView {
337 #[must_use]
339 pub fn from_user(user: &impl AuthUser) -> Self {
340 Self {
341 id: user.id().to_string(),
342 email: user.email().map(ToOwned::to_owned),
343 name: user.name().map(ToOwned::to_owned),
344 image: user.image().map(ToOwned::to_owned),
345 }
346 }
347}