better_auth_core/
entity.rs1use std::borrow::Cow;
11
12use chrono::Utc;
13use serde::Serialize;
14
15use crate::{SchemaValue, types::InvitationStatus};
16
17pub trait AuthRecordFields {
19 fn field_values(&self) -> crate::AuthResult<crate::FieldMap>;
20
21 fn structured_clone(
23 &self,
24 context: &mut crate::StructuredCloneContext,
25 ) -> crate::AuthResult<Self>
26 where
27 Self: FromFieldMap,
28 {
29 Self::from_field_values(context.clone_map(&self.field_values()?))
30 }
31}
32
33pub trait FromFieldMap: Sized {
35 fn from_field_values(fields: crate::FieldMap) -> crate::AuthResult<Self>;
36}
37
38impl AuthRecordFields for crate::FieldMap {
39 fn field_values(&self) -> crate::AuthResult<Self> {
40 Ok(self.clone())
41 }
42
43 fn structured_clone(
44 &self,
45 context: &mut crate::StructuredCloneContext,
46 ) -> crate::AuthResult<Self> {
47 Ok(context.clone_map(self))
48 }
49}
50
51impl FromFieldMap for crate::FieldMap {
52 fn from_field_values(fields: Self) -> crate::AuthResult<Self> {
53 Ok(fields)
54 }
55}
56
57pub trait AuthUser:
65 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
66{
67 fn field_presence(&self) -> Option<&std::collections::BTreeSet<String>> {
70 None
71 }
72 fn projected_fields(&self) -> Option<&crate::FieldMap> {
75 None
76 }
77 const PLUGIN_FIELDS: &'static [&'static str] = &[];
82
83 fn require_plugin_fields(plugin: &str, required: &[&str]) -> crate::AuthResult<()> {
85 require_plugin_fields(plugin, "user", Self::PLUGIN_FIELDS, required)
86 }
87
88 fn serialized_field_name(name: &str) -> &str {
90 name
91 }
92
93 fn id(&self) -> SchemaValue<Cow<'_, str>>;
94 fn email(&self) -> Option<&str>;
95 fn email_verified(&self) -> bool;
96 fn created_at(&self) -> crate::FieldDate;
97 fn updated_at(&self) -> crate::FieldDate;
98 fn is_anonymous(&self) -> Option<bool> {
99 None
100 }
101 fn phone_number(&self) -> Option<&str> {
102 None
103 }
104 fn phone_number_verified(&self) -> Option<bool> {
105 None
106 }
107 fn username(&self) -> Option<&str>;
108 fn display_username(&self) -> Option<&str>;
109 fn two_factor_enabled(&self) -> bool;
110 fn role(&self) -> Option<&str>;
111 fn banned(&self) -> bool;
112 fn ban_reason(&self) -> Option<&str>;
113 fn ban_expires(&self) -> Option<crate::FieldDate>;
114}
115
116pub trait AuthSession:
118 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
119{
120 fn field_presence(&self) -> Option<&std::collections::BTreeSet<String>> {
122 None
123 }
124 fn serialized_field_name(name: &str) -> &str {
126 name
127 }
128 fn projected_fields(&self) -> Option<&crate::FieldMap> {
130 None
131 }
132
133 const PLUGIN_FIELDS: &'static [&'static str] = &[];
138
139 fn require_plugin_fields(plugin: &str, required: &[&str]) -> crate::AuthResult<()> {
141 require_plugin_fields(plugin, "session", Self::PLUGIN_FIELDS, required)
142 }
143
144 fn id(&self) -> SchemaValue<Cow<'_, str>>;
145 fn expires_at(&self) -> crate::FieldDate;
146 fn token(&self) -> &str;
147 fn created_at(&self) -> crate::FieldDate;
148 fn updated_at(&self) -> crate::FieldDate;
149 fn ip_address(&self) -> Option<&str>;
150 fn user_agent(&self) -> Option<&str>;
151 fn user_id(&self) -> SchemaValue<Cow<'_, str>>;
152 fn impersonated_by(&self) -> Option<&str>;
153 fn active_organization_id(&self) -> Option<&str>;
154 fn active_team_id(&self) -> Option<&str> {
156 None
157 }
158 fn active(&self) -> bool;
159}
160
161fn require_plugin_fields(
162 plugin: &str,
163 entity: &str,
164 available: &[&str],
165 required: &[&str],
166) -> crate::AuthResult<()> {
167 for field in required {
168 if !available.contains(field) {
169 return Err(crate::AuthError::config(format!(
170 "Plugin `{plugin}` requires {entity} field `{field}`; add the field and migrate the database"
171 )));
172 }
173 }
174 Ok(())
175}
176
177pub trait AuthAccount:
179 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
180{
181 fn field_presence(&self) -> Option<&std::collections::BTreeSet<String>> {
183 None
184 }
185 fn id(&self) -> Cow<'_, str>;
186 fn account_id(&self) -> &str;
187 fn provider_id(&self) -> &str;
188 fn user_id(&self) -> Cow<'_, str>;
189 fn access_token(&self) -> Option<&str>;
190 fn refresh_token(&self) -> Option<&str>;
191 fn id_token(&self) -> Option<&str>;
192 fn access_token_expires_at(&self) -> Option<crate::FieldDate>;
193 fn refresh_token_expires_at(&self) -> Option<crate::FieldDate>;
194 fn scope(&self) -> Option<&str>;
195 fn password(&self) -> Option<&str>;
196 fn created_at(&self) -> crate::FieldDate;
197 fn updated_at(&self) -> crate::FieldDate;
198}
199
200pub trait AuthOrganization:
202 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
203{
204 fn projected_fields(&self) -> Option<&crate::FieldMap> {
206 None
207 }
208
209 fn id(&self) -> SchemaValue<Cow<'_, str>>;
210 fn name(&self) -> &SchemaValue<String>;
211 fn slug(&self) -> &SchemaValue<String>;
212 fn logo(&self) -> &SchemaValue<Option<String>>;
213 fn metadata(&self) -> &SchemaValue<Option<crate::FieldValue>>;
214 fn created_at(&self) -> &SchemaValue<crate::FieldDate>;
215}
216
217pub trait AuthMember:
219 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
220{
221 fn projected_fields(&self) -> Option<&crate::FieldMap> {
223 None
224 }
225
226 fn id(&self) -> SchemaValue<Cow<'_, str>>;
227 fn organization_id(&self) -> &SchemaValue<String>;
228 fn user_id(&self) -> &SchemaValue<String>;
229 fn role(&self) -> &SchemaValue<String>;
230 fn created_at(&self) -> &SchemaValue<crate::FieldDate>;
231}
232
233pub trait AuthInvitation:
235 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
236{
237 fn projected_fields(&self) -> Option<&crate::FieldMap> {
239 None
240 }
241
242 fn id(&self) -> SchemaValue<Cow<'_, str>>;
243 fn organization_id(&self) -> &SchemaValue<String>;
244 fn email(&self) -> &SchemaValue<String>;
245 fn role(&self) -> &SchemaValue<String>;
246 fn status(&self) -> &SchemaValue<InvitationStatus>;
247 fn inviter_id(&self) -> &SchemaValue<String>;
248 fn expires_at(&self) -> &SchemaValue<crate::FieldDate>;
249 fn created_at(&self) -> &SchemaValue<crate::FieldDate>;
250
251 fn is_pending(&self) -> bool {
253 self.status() == &SchemaValue::Typed(InvitationStatus::Pending)
254 }
255
256 fn is_expired(&self) -> crate::AuthResult<bool> {
258 self.expires_at().is_before(Utc::now())
259 }
260 fn team_id(&self) -> &SchemaValue<Option<String>>;
262}
263
264pub trait AuthVerification:
266 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
267{
268 fn id(&self) -> Cow<'_, str>;
269 fn identifier(&self) -> &str;
270 fn value(&self) -> &str;
271 fn expires_at(&self) -> crate::FieldDate;
272 fn created_at(&self) -> crate::FieldDate;
273 fn updated_at(&self) -> crate::FieldDate;
274}
275
276pub trait AuthTwoFactor:
278 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
279{
280 fn additional_fields(&self) -> Option<&crate::FieldMap> {
282 None
283 }
284 fn id(&self) -> SchemaValue<Cow<'_, str>>;
285 fn secret(&self) -> &str;
286 fn backup_codes(&self) -> &str;
287 fn user_id(&self) -> SchemaValue<Cow<'_, str>>;
288 fn verified(&self) -> Option<bool>;
289 fn failed_verification_count(&self) -> Option<i64>;
290 fn locked_until(&self) -> Option<crate::FieldDate>;
291 fn created_at(&self) -> &SchemaValue<crate::FieldDate>;
292 fn updated_at(&self) -> &SchemaValue<crate::FieldDate>;
293}
294
295pub trait AuthApiKey:
297 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
298{
299 fn additional_fields(&self) -> Option<&crate::FieldMap> {
301 None
302 }
303 fn id(&self) -> SchemaValue<Cow<'_, str>>;
304 fn name(&self) -> &SchemaValue<Option<String>>;
305 fn start(&self) -> Option<Cow<'_, crate::ApiKeyStart>>;
306 fn prefix(&self) -> Option<&str>;
307 fn key_hash(&self) -> &str;
308 fn reference_id(&self) -> Cow<'_, str>;
311 fn config_id(&self) -> Cow<'_, str>;
314 fn refill_interval(&self) -> Option<f64>;
315 fn refill_amount(&self) -> Option<f64>;
316 fn last_refill_at(&self) -> Option<crate::FieldDate>;
317 fn enabled(&self) -> &SchemaValue<bool>;
318 fn rate_limit_enabled(&self) -> &SchemaValue<bool>;
319 fn rate_limit_time_window(&self) -> Option<f64>;
320 fn rate_limit_max(&self) -> Option<f64>;
321 fn request_count(&self) -> Option<f64>;
322 fn remaining(&self) -> Option<f64>;
323 fn last_request(&self) -> Option<crate::FieldDate>;
324 fn expires_at(&self) -> Option<crate::FieldDate>;
325 fn created_at(&self) -> crate::FieldDate;
326 fn updated_at(&self) -> crate::FieldDate;
327 fn permissions(&self) -> Option<&str>;
328 fn metadata(&self) -> Option<&str>;
329}
330
331pub trait AuthPasskey:
333 AuthRecordFields + Clone + Send + Sync + Serialize + std::fmt::Debug + 'static
334{
335 fn additional_fields(&self) -> Option<&crate::FieldMap> {
337 None
338 }
339 fn id(&self) -> SchemaValue<Cow<'_, str>>;
340 fn name(&self) -> &SchemaValue<Option<String>>;
341 fn public_key(&self) -> &str;
342 fn user_id(&self) -> SchemaValue<Cow<'_, str>>;
343 fn credential_id(&self) -> &str;
344 fn counter(&self) -> u64;
345 fn device_type(&self) -> &str;
346 fn backed_up(&self) -> bool;
347 fn transports(&self) -> Option<&str>;
348 fn created_at(&self) -> &SchemaValue<Option<crate::FieldDate>>;
349 fn updated_at(&self) -> &SchemaValue<crate::FieldDate>;
350 fn aaguid(&self) -> &SchemaValue<Option<String>>;
351 fn credential(&self) -> &SchemaValue<String>;
352}
353
354#[derive(Debug, Clone, Default)]
359pub struct MemberUserView {
360 pub id: SchemaValue<String>,
361 pub email: SchemaValue<Option<String>>,
362 pub name: SchemaValue<Option<String>>,
363 pub image: SchemaValue<Option<String>>,
364}
365
366mod member_user_view;
367mod record_fields;
368
369impl MemberUserView {
370 pub fn from_user(user: &crate::UserView) -> Self {
372 Self {
373 id: SchemaValue::from_field(user.native_field_value("id").unwrap_or_default()),
374 email: SchemaValue::from_field(user.native_field_value("email").unwrap_or_default()),
375 name: SchemaValue::from_field(user.native_field_value("name").unwrap_or_default()),
376 image: SchemaValue::from_field(user.native_field_value("image").unwrap_or_default()),
377 }
378 }
379}