use serde::Deserialize;
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct Settings {
pub database: DatabaseSettings,
pub secret_key: Option<String>,
pub admin: AdminSettings,
pub tenancy: TenancySettings,
pub cache: CacheSettings,
pub jobs: JobsSettings,
pub mail: MailSettings,
pub server: ServerSettings,
pub auth: AuthSettings,
pub brand: BrandSettings,
pub security: SecuritySettings,
pub routes: RoutesSettings,
pub audit: AuditSettings,
pub logging: LoggingSettings,
}
impl Settings {
#[must_use]
pub fn detected_features() -> Vec<&'static str> {
let mut out: Vec<&'static str> = Vec::new();
macro_rules! feat {
($name:literal) => {
#[cfg(feature = $name)]
out.push($name);
};
}
feat!("postgres");
feat!("mysql");
feat!("sqlite");
feat!("tenancy");
feat!("admin");
feat!("manage");
feat!("config");
feat!("forms");
feat!("serializer");
feat!("cache");
feat!("signals");
feat!("email");
feat!("storage");
feat!("storage-s3");
feat!("scheduler");
feat!("secrets");
feat!("totp");
feat!("webhook");
feat!("webhook-delivery");
feat!("api_keys");
feat!("passwords");
feat!("signed_url");
feat!("notifications");
feat!("jobs");
feat!("jobs-postgres");
feat!("auth_flows");
feat!("sse");
feat!("websocket");
feat!("oauth2");
feat!("http-client");
feat!("compression");
feat!("openapi");
feat!("csp-nonce");
feat!("sessions");
feat!("hmac-auth");
feat!("jwt");
feat!("uploads");
feat!("media");
feat!("runserver");
out
}
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct DatabaseSettings {
pub url: Option<String>,
pub pool_max_size: Option<u32>,
pub pool_min_size: Option<u32>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct AdminSettings {
pub allowed_tables: Vec<String>,
pub read_only_tables: Vec<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct TenancySettings {
pub apex_domain: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct CacheSettings {
pub backend: Option<String>,
pub redis_url: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct JobsSettings {
pub backend: Option<String>,
pub concurrency: Option<u32>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct MailSettings {
pub backend: Option<String>,
pub smtp_host: Option<String>,
pub from_address: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct ServerSettings {
pub bind: Option<String>,
pub request_timeout_secs: Option<u64>,
pub max_body_bytes: Option<u64>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct AuthSettings {
pub jwt: JwtSettings,
pub argon2_memory_kib: Option<u32>,
pub argon2_iterations: Option<u32>,
pub argon2_parallelism: Option<u32>,
pub lockout_threshold: Option<u32>,
pub lockout_duration_secs: Option<u64>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct JwtSettings {
pub access_ttl_secs: Option<u64>,
pub refresh_ttl_secs: Option<u64>,
pub issuer: Option<String>,
pub audience: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct BrandSettings {
pub name: Option<String>,
pub tagline: Option<String>,
pub logo_url: Option<String>,
pub primary_color: Option<String>,
pub theme_mode: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct SecuritySettings {
pub headers_preset: Option<String>,
pub csp: Option<String>,
pub hsts_max_age_secs: Option<u64>,
pub cors_allowed_origins: Vec<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct RoutesSettings {
pub legacy_preset: Option<bool>,
pub login_url: Option<String>,
pub logout_url: Option<String>,
pub admin_url: Option<String>,
pub audit_url: Option<String>,
pub static_url: Option<String>,
pub brand_url: Option<String>,
pub change_password_url: Option<String>,
pub impersonation_handoff_url: Option<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct AuditSettings {
pub retention_days: Option<u32>,
pub redact_query_params: Vec<String>,
}
#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
#[serde(default)]
pub struct LoggingSettings {
pub level: Option<String>,
pub format: Option<String>,
pub with_thread_ids: Option<bool>,
pub with_line_numbers: Option<bool>,
pub without_targets: Option<bool>,
pub file_dir: Option<String>,
pub file_prefix: Option<String>,
pub file_rotation: Option<String>,
pub file_only: Option<bool>,
}