Skip to main content

better_auth_core/
entity.rs

1//! Entity traits for the Better Auth framework.
2//!
3//! These traits define the interface that entity types must implement.
4//! The framework accesses entity fields through these trait methods,
5//! allowing users to define their own entity structs with custom field names
6//! and extra fields.
7//!
8//! Implement these traits manually for any custom types used inside the auth
9//! runtime.
10
11use std::borrow::Cow;
12
13use chrono::{DateTime, Utc};
14use serde::Serialize;
15
16use crate::types::InvitationStatus;
17
18/// Trait representing a user entity.
19///
20/// The framework reads user fields through these getters. Custom types
21/// must provide all framework fields and may have additional fields.
22pub trait AuthUser: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
23    fn id(&self) -> Cow<'_, str>;
24    fn email(&self) -> Option<&str>;
25    fn name(&self) -> Option<&str>;
26    fn email_verified(&self) -> bool;
27    fn image(&self) -> Option<&str>;
28    fn created_at(&self) -> DateTime<Utc>;
29    fn updated_at(&self) -> DateTime<Utc>;
30    fn username(&self) -> Option<&str>;
31    fn display_username(&self) -> Option<&str>;
32    fn two_factor_enabled(&self) -> bool;
33    fn role(&self) -> Option<&str>;
34    fn banned(&self) -> bool;
35    fn ban_reason(&self) -> Option<&str>;
36    fn ban_expires(&self) -> Option<DateTime<Utc>>;
37    fn metadata(&self) -> &serde_json::Value;
38}
39
40/// Trait representing a session entity.
41pub trait AuthSession: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
42    fn id(&self) -> Cow<'_, str>;
43    fn expires_at(&self) -> DateTime<Utc>;
44    fn token(&self) -> &str;
45    fn created_at(&self) -> DateTime<Utc>;
46    fn updated_at(&self) -> DateTime<Utc>;
47    fn ip_address(&self) -> Option<&str>;
48    fn user_agent(&self) -> Option<&str>;
49    fn user_id(&self) -> Cow<'_, str>;
50    fn impersonated_by(&self) -> Option<&str>;
51    fn active_organization_id(&self) -> Option<&str>;
52    fn active(&self) -> bool;
53}
54
55/// Trait representing an account entity (OAuth provider linking).
56pub trait AuthAccount: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
57    fn id(&self) -> Cow<'_, str>;
58    fn account_id(&self) -> &str;
59    fn provider_id(&self) -> &str;
60    fn user_id(&self) -> Cow<'_, str>;
61    fn access_token(&self) -> Option<&str>;
62    fn refresh_token(&self) -> Option<&str>;
63    fn id_token(&self) -> Option<&str>;
64    fn access_token_expires_at(&self) -> Option<DateTime<Utc>>;
65    fn refresh_token_expires_at(&self) -> Option<DateTime<Utc>>;
66    fn scope(&self) -> Option<&str>;
67    fn password(&self) -> Option<&str>;
68    fn created_at(&self) -> DateTime<Utc>;
69    fn updated_at(&self) -> DateTime<Utc>;
70}
71
72/// Trait representing an organization entity.
73pub trait AuthOrganization: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
74    fn id(&self) -> Cow<'_, str>;
75    fn name(&self) -> &str;
76    fn slug(&self) -> &str;
77    fn logo(&self) -> Option<&str>;
78    fn metadata(&self) -> Option<&serde_json::Value>;
79    fn created_at(&self) -> DateTime<Utc>;
80    fn updated_at(&self) -> DateTime<Utc>;
81}
82
83/// Trait representing an organization member entity.
84pub trait AuthMember: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
85    fn id(&self) -> Cow<'_, str>;
86    fn organization_id(&self) -> Cow<'_, str>;
87    fn user_id(&self) -> Cow<'_, str>;
88    fn role(&self) -> &str;
89    fn created_at(&self) -> DateTime<Utc>;
90}
91
92/// Trait representing an invitation entity.
93pub trait AuthInvitation: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
94    fn id(&self) -> Cow<'_, str>;
95    fn organization_id(&self) -> Cow<'_, str>;
96    fn email(&self) -> &str;
97    fn role(&self) -> &str;
98    fn status(&self) -> &InvitationStatus;
99    fn inviter_id(&self) -> Cow<'_, str>;
100    fn expires_at(&self) -> DateTime<Utc>;
101    fn created_at(&self) -> DateTime<Utc>;
102
103    /// Check if the invitation is still pending.
104    fn is_pending(&self) -> bool {
105        *self.status() == InvitationStatus::Pending
106    }
107
108    /// Check if the invitation has expired.
109    fn is_expired(&self) -> bool {
110        self.expires_at() < Utc::now()
111    }
112}
113
114/// Trait representing a verification token entity.
115pub trait AuthVerification: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
116    fn id(&self) -> Cow<'_, str>;
117    fn identifier(&self) -> &str;
118    fn value(&self) -> &str;
119    fn expires_at(&self) -> DateTime<Utc>;
120    fn created_at(&self) -> DateTime<Utc>;
121    fn updated_at(&self) -> DateTime<Utc>;
122}
123
124/// Trait representing a two-factor authentication entity.
125pub trait AuthTwoFactor: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
126    fn id(&self) -> Cow<'_, str>;
127    fn secret(&self) -> &str;
128    fn backup_codes(&self) -> &str;
129    fn user_id(&self) -> Cow<'_, str>;
130    fn created_at(&self) -> DateTime<Utc>;
131    fn updated_at(&self) -> DateTime<Utc>;
132}
133
134/// Trait representing an API key entity.
135pub trait AuthApiKey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
136    fn id(&self) -> Cow<'_, str>;
137    fn name(&self) -> Option<&str>;
138    fn start(&self) -> Option<&str>;
139    fn prefix(&self) -> Option<&str>;
140    fn key_hash(&self) -> &str;
141    fn user_id(&self) -> Cow<'_, str>;
142    fn refill_interval(&self) -> Option<i64>;
143    fn refill_amount(&self) -> Option<i64>;
144    fn last_refill_at(&self) -> Option<&str>;
145    fn enabled(&self) -> bool;
146    fn rate_limit_enabled(&self) -> bool;
147    fn rate_limit_time_window(&self) -> Option<i64>;
148    fn rate_limit_max(&self) -> Option<i64>;
149    fn request_count(&self) -> Option<i64>;
150    fn remaining(&self) -> Option<i64>;
151    fn last_request(&self) -> Option<&str>;
152    fn expires_at(&self) -> Option<&str>;
153    fn created_at(&self) -> &str;
154    fn updated_at(&self) -> &str;
155    fn permissions(&self) -> Option<&str>;
156    fn metadata(&self) -> Option<&str>;
157}
158
159/// Trait representing a passkey entity.
160pub trait AuthPasskey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
161    fn id(&self) -> Cow<'_, str>;
162    fn name(&self) -> Option<&str>;
163    fn public_key(&self) -> &str;
164    fn user_id(&self) -> Cow<'_, str>;
165    fn credential_id(&self) -> &str;
166    fn counter(&self) -> u64;
167    fn device_type(&self) -> &str;
168    fn backed_up(&self) -> bool;
169    fn transports(&self) -> Option<&str>;
170    fn created_at(&self) -> DateTime<Utc>;
171    fn updated_at(&self) -> DateTime<Utc>;
172    fn aaguid(&self) -> Option<&str>;
173    fn credential(&self) -> &str;
174}
175
176/// Minimal user info for member-related API responses.
177///
178/// This is a concrete framework type (not generic) used to project
179/// user fields into member responses.
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct MemberUserView {
182    pub id: String,
183    pub email: Option<String>,
184    pub name: Option<String>,
185    pub image: Option<String>,
186}
187
188impl MemberUserView {
189    /// Construct from any type implementing [`AuthUser`].
190    pub fn from_user(user: &impl AuthUser) -> Self {
191        Self {
192            id: user.id().to_string(),
193            email: user.email().map(|s| s.to_string()),
194            name: user.name().map(|s| s.to_string()),
195            image: user.image().map(|s| s.to_string()),
196        }
197    }
198}
199
200use serde::Deserialize;