use crate::AuthError;
use crate::types::InvitationStatus;
use crate::{AdapterOutput, AuthResult};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
pub trait AuthTimestamp: Sized {
type UtcValue;
fn from_utc(value: Self::UtcValue) -> Self;
fn into_utc(self) -> Self::UtcValue;
}
impl AuthTimestamp for chrono::NaiveDateTime {
type UtcValue = DateTime<Utc>;
fn from_utc(value: Self::UtcValue) -> Self {
value.naive_utc()
}
fn into_utc(self) -> Self::UtcValue {
self.and_utc()
}
}
impl<Tz: chrono::TimeZone> AuthTimestamp for DateTime<Tz>
where
Self: From<DateTime<Utc>>,
{
type UtcValue = DateTime<Utc>;
fn from_utc(value: Self::UtcValue) -> Self {
value.into()
}
fn into_utc(self) -> Self::UtcValue {
self.with_timezone(&Utc)
}
}
impl<T: AuthTimestamp> AuthTimestamp for Option<T> {
type UtcValue = Option<T::UtcValue>;
fn from_utc(value: Self::UtcValue) -> Self {
value.map(T::from_utc)
}
fn into_utc(self) -> Self::UtcValue {
self.map(T::into_utc)
}
}
pub trait AuthUser: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn secondary_snapshot(&self) -> AuthResult<serde_json::Value> {
Err(AuthError::NotImplemented(
"Secondary model encoding is unsupported".into(),
))
}
fn from_secondary_snapshot(_snapshot: serde_json::Value) -> AuthResult<Self> {
Err(AuthError::NotImplemented(
"Secondary model decoding is unsupported".into(),
))
}
fn adapter_snapshot(&self) -> Option<&AdapterOutput> {
None
}
fn retained_user_view(&self) -> Option<&crate::UserView> {
None
}
fn additional_fields(&self) -> crate::field_policy::FieldOutput {
crate::field_policy::FieldOutput::new()
}
fn id(&self) -> Cow<'_, str>;
fn email(&self) -> Option<&str>;
fn name(&self) -> Option<&str>;
fn email_verified(&self) -> bool;
fn image(&self) -> Option<&str>;
fn created_at(&self) -> DateTime<Utc>;
fn updated_at(&self) -> DateTime<Utc>;
fn username(&self) -> Option<&str>;
fn display_username(&self) -> Option<&str>;
fn two_factor_enabled(&self) -> bool;
fn two_factor_enabled_value(&self) -> Option<bool> {
Some(self.two_factor_enabled())
}
fn role(&self) -> Option<&str>;
fn banned(&self) -> bool;
fn banned_value(&self) -> Option<bool> {
Some(self.banned())
}
fn ban_reason(&self) -> Option<&str>;
fn ban_expires(&self) -> Option<DateTime<Utc>>;
fn metadata(&self) -> &serde_json::Value;
fn is_anonymous(&self) -> Option<bool> {
None
}
fn phone_number(&self) -> Option<&str> {
None
}
fn phone_number_verified(&self) -> Option<bool> {
None
}
fn last_login_method(&self) -> Option<&str> {
None
}
}
pub trait AuthSession: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn secondary_snapshot(&self) -> AuthResult<serde_json::Value> {
Err(AuthError::NotImplemented(
"Secondary model encoding is unsupported".into(),
))
}
fn from_secondary_snapshot(_snapshot: serde_json::Value) -> AuthResult<Self> {
Err(AuthError::NotImplemented(
"Secondary model decoding is unsupported".into(),
))
}
fn adapter_snapshot(&self) -> Option<&AdapterOutput> {
None
}
fn retained_session_view(&self) -> Option<&crate::SessionView> {
None
}
fn additional_fields(&self) -> serde_json::Map<String, serde_json::Value> {
serde_json::Map::new()
}
fn id(&self) -> Cow<'_, str>;
fn expires_at(&self) -> DateTime<Utc>;
fn token(&self) -> &str;
fn created_at(&self) -> DateTime<Utc>;
fn updated_at(&self) -> DateTime<Utc>;
fn ip_address(&self) -> Option<&str>;
fn user_agent(&self) -> Option<&str>;
fn user_id(&self) -> Cow<'_, str>;
fn impersonated_by(&self) -> Option<&str>;
fn active_organization_id(&self) -> Option<&str>;
fn active_team_id(&self) -> Option<&str> {
None
}
}
pub trait AuthAccount: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn adapter_snapshot(&self) -> Option<&AdapterOutput> {
None
}
fn additional_fields(&self) -> crate::field_policy::FieldOutput {
crate::field_policy::FieldOutput::new()
}
fn id(&self) -> Cow<'_, str>;
fn account_id(&self) -> &str;
fn provider_id(&self) -> &str;
fn user_id(&self) -> Cow<'_, str>;
fn access_token(&self) -> Option<&str>;
fn refresh_token(&self) -> Option<&str>;
fn id_token(&self) -> Option<&str>;
fn access_token_expires_at(&self) -> Option<DateTime<Utc>>;
fn refresh_token_expires_at(&self) -> Option<DateTime<Utc>>;
fn scope(&self) -> Option<&str>;
fn password(&self) -> Option<&str>;
fn created_at(&self) -> DateTime<Utc>;
fn updated_at(&self) -> DateTime<Utc>;
}
pub trait AuthOrganization: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn additional_fields(&self) -> std::collections::BTreeMap<String, serde_json::Value> {
std::collections::BTreeMap::default()
}
fn id(&self) -> Cow<'_, str>;
fn name(&self) -> &str;
fn slug(&self) -> &str;
fn logo(&self) -> Option<&str>;
fn metadata(&self) -> Option<&serde_json::Value>;
fn created_at(&self) -> DateTime<Utc>;
}
pub trait AuthMember: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn id(&self) -> Cow<'_, str>;
fn organization_id(&self) -> Cow<'_, str>;
fn user_id(&self) -> Cow<'_, str>;
fn role(&self) -> &str;
fn created_at(&self) -> DateTime<Utc>;
}
pub trait AuthInvitation: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn id(&self) -> Cow<'_, str>;
fn organization_id(&self) -> Cow<'_, str>;
fn email(&self) -> &str;
fn role(&self) -> &str;
fn optional_role(&self) -> Option<&str> {
Some(self.role())
}
fn team_id(&self) -> Option<&str> {
None
}
fn status(&self) -> &InvitationStatus;
fn inviter_id(&self) -> Cow<'_, str>;
fn expires_at(&self) -> DateTime<Utc>;
fn created_at(&self) -> DateTime<Utc>;
fn is_pending(&self) -> bool {
*self.status() == InvitationStatus::Pending
}
fn is_expired(&self) -> bool {
self.expires_at() < Utc::now()
}
}
pub trait AuthVerification: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn id(&self) -> Cow<'_, str>;
fn identifier(&self) -> &str;
fn value(&self) -> &str;
fn expires_at(&self) -> DateTime<Utc>;
fn created_at(&self) -> DateTime<Utc>;
fn updated_at(&self) -> DateTime<Utc>;
}
pub trait AuthTwoFactor: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn id(&self) -> Cow<'_, str>;
fn secret(&self) -> &str;
fn backup_codes(&self) -> &str;
fn user_id(&self) -> Cow<'_, str>;
fn verified(&self) -> Option<bool> {
None
}
fn failed_verification_count(&self) -> Option<f64> {
None
}
fn locked_until(&self) -> Option<DateTime<Utc>> {
None
}
}
pub trait AuthApiKey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn id(&self) -> Cow<'_, str>;
fn name(&self) -> Option<&str>;
fn start(&self) -> Option<&str>;
fn prefix(&self) -> Option<&str>;
fn key_hash(&self) -> &str;
fn reference_id(&self) -> Cow<'_, str>;
fn config_id(&self) -> Cow<'_, str>;
fn refill_interval(&self) -> Option<f64>;
fn refill_amount(&self) -> Option<f64>;
fn last_refill_at(&self) -> Option<&str>;
fn enabled(&self) -> bool;
fn rate_limit_enabled(&self) -> bool;
fn rate_limit_time_window(&self) -> Option<f64>;
fn rate_limit_max(&self) -> Option<f64>;
fn request_count(&self) -> Option<f64>;
fn remaining(&self) -> Option<f64>;
fn last_request(&self) -> Option<&str>;
fn expires_at(&self) -> Option<&str>;
fn created_at(&self) -> &str;
fn updated_at(&self) -> &str;
fn permissions(&self) -> Option<&str>;
fn metadata(&self) -> Option<&str>;
}
pub trait AuthPasskey: Clone + Send + Sync + Serialize + std::fmt::Debug + 'static {
fn id(&self) -> Cow<'_, str>;
fn name(&self) -> Option<&str>;
fn public_key(&self) -> &str;
fn user_id(&self) -> Cow<'_, str>;
fn credential_id(&self) -> &str;
fn counter(&self) -> u64;
fn device_type(&self) -> &str;
fn backed_up(&self) -> bool;
fn transports(&self) -> Option<&str>;
fn created_at(&self) -> Option<DateTime<Utc>>;
fn aaguid(&self) -> Option<&str>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemberUserView {
pub id: String,
pub email: Option<String>,
pub name: Option<String>,
pub image: Option<String>,
}
impl MemberUserView {
#[must_use]
pub fn from_user(user: &impl AuthUser) -> Self {
Self {
id: user.id().to_string(),
email: user.email().map(ToOwned::to_owned),
name: user.name().map(ToOwned::to_owned),
image: user.image().map(ToOwned::to_owned),
}
}
}