d5939db
use std::collections::BTreeMap;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PasswordPolicy {
pub min_length: usize,
#[serde(default = "default_true")]
pub require_upper: bool,
#[serde(default = "default_true")]
pub require_lower: bool,
#[serde(default = "default_true")]
pub require_digit: bool,
#[serde(default)]
pub require_symbol: bool,
}
fn default_true() -> bool {
true
}
impl Default for PasswordPolicy {
fn default() -> Self {
Self {
min_length: 8,
require_upper: true,
require_lower: true,
require_digit: true,
require_symbol: false,
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct OAuthProviderConfig {
#[serde(default)]
pub enabled: bool,
#[serde(default)]
pub client_id: String,
#[serde(default)]
pub client_secret: String,
#[serde(default)]
pub redirect_uri: String,
#[serde(default)]
pub scopes: Vec<String>,
#[serde(default)]
pub authorize_url: String,
#[serde(default)]
pub token_url: String,
#[serde(default)]
pub userinfo_url: String,
#[serde(default)]
pub emails_url: Option<String>,
#[serde(default)]
pub extra: BTreeMap<String, String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct OAuthConfig {
#[serde(default)]
pub google: Option<OAuthProviderConfig>,
#[serde(default)]
pub github: Option<OAuthProviderConfig>,
#[serde(default)]
pub apple: Option<OAuthProviderConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct AgreementDoc {
pub key: String,
pub version: String,
pub updated_at: String,
pub title: String,
pub content_md: String,
}
impl AgreementDoc {
pub fn placeholder(key: &str) -> Self {
Self {
key: key.to_string(),
version: "0.1.0".to_string(),
updated_at: "1970-01-01T00:00:00Z".to_string(),
title: format!("{} (placeholder)", key),
content_md: format!(
"# {}\n\nThis document is a placeholder. Please replace before production.",
key
),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgreementsConfig {
pub terms: AgreementDoc,
pub privacy: AgreementDoc,
}
impl Default for AgreementsConfig {
fn default() -> Self {
Self {
terms: AgreementDoc::placeholder("terms"),
privacy: AgreementDoc::placeholder("privacy"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthConfig {
#[serde(default)]
pub password_policy: PasswordPolicy,
#[serde(default = "default_verify_code_ttl")]
pub verify_code_ttl_secs: u64,
#[serde(default = "default_verify_code_len")]
pub verify_code_len: usize,
#[serde(default = "default_reset_token_ttl")]
pub reset_token_ttl_secs: u64,
#[serde(default = "default_reset_token_bytes")]
pub reset_token_bytes: usize,
#[serde(default = "default_cookie_prefix")]
pub cookie_name_prefix: String,
#[serde(default = "default_true_bool")]
pub cookie_secure: bool,
#[serde(default = "default_same_site")]
pub cookie_same_site: String,
#[serde(default)]
pub cookie_domain: Option<String>,
#[serde(default = "default_oauth_state_ttl")]
pub oauth_state_ttl_secs: u64,
#[serde(default = "default_email_rate_limit")]
pub email_code_rate_limit_secs: u64,
#[serde(default = "default_max_verify_attempts")]
pub max_verify_attempts: u32,
#[serde(default)]
pub auto_register_agreements: Vec<String>,
#[serde(default)]
pub oauth: OAuthConfig,
#[serde(default)]
pub agreements: AgreementsConfig,
}
fn default_verify_code_ttl() -> u64 {
600
}
fn default_verify_code_len() -> usize {
6
}
fn default_reset_token_ttl() -> u64 {
1800
}
fn default_reset_token_bytes() -> usize {
32
}
fn default_cookie_prefix() -> String {
"auth_".to_string()
}
fn default_true_bool() -> bool {
true
}
fn default_same_site() -> String {
"Strict".to_string()
}
fn default_oauth_state_ttl() -> u64 {
300
}
fn default_email_rate_limit() -> u64 {
60
}
fn default_max_verify_attempts() -> u32 {
5
}
impl Default for AuthConfig {
fn default() -> Self {
Self {
password_policy: PasswordPolicy::default(),
verify_code_ttl_secs: default_verify_code_ttl(),
verify_code_len: default_verify_code_len(),
reset_token_ttl_secs: default_reset_token_ttl(),
reset_token_bytes: default_reset_token_bytes(),
cookie_name_prefix: default_cookie_prefix(),
cookie_secure: default_true_bool(),
cookie_same_site: default_same_site(),
cookie_domain: None,
oauth_state_ttl_secs: default_oauth_state_ttl(),
email_code_rate_limit_secs: default_email_rate_limit(),
max_verify_attempts: default_max_verify_attempts(),
auto_register_agreements: Vec::new(),
oauth: OAuthConfig::default(),
agreements: AgreementsConfig::default(),
}
}
}
#[allow(dead_code)]
pub type SharedAuthConfig = Arc<AuthConfig>;