use rand::Rng;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
mod account;
mod branding;
mod captcha;
mod clients;
mod database;
mod email;
mod experimental;
mod http;
mod matrix;
mod passwords;
mod policy;
mod rate_limiting;
mod secrets;
mod telemetry;
mod templates;
mod upstream_oauth2;
pub use self::{
account::AccountConfig,
branding::BrandingConfig,
captcha::{CaptchaConfig, CaptchaServiceKind},
clients::{ClientAuthMethodConfig, ClientConfig, ClientsConfig},
database::{DatabaseConfig, PgSslMode},
email::{EmailConfig, EmailSmtpMode, EmailTransportKind},
experimental::ExperimentalConfig,
http::{
BindConfig as HttpBindConfig, HttpConfig, ListenerConfig as HttpListenerConfig,
Resource as HttpResource, TlsConfig as HttpTlsConfig, UnixOrTcp,
},
matrix::MatrixConfig,
passwords::{Algorithm as PasswordAlgorithm, PasswordsConfig},
policy::PolicyConfig,
rate_limiting::RateLimitingConfig,
secrets::SecretsConfig,
telemetry::{
MetricsConfig, MetricsExporterKind, Propagator, TelemetryConfig, TracingConfig,
TracingExporterKind,
},
templates::TemplatesConfig,
upstream_oauth2::{
ClaimsImports as UpstreamOAuth2ClaimsImports, DiscoveryMode as UpstreamOAuth2DiscoveryMode,
EmailImportPreference as UpstreamOAuth2EmailImportPreference,
ImportAction as UpstreamOAuth2ImportAction, PkceMethod as UpstreamOAuth2PkceMethod,
SetEmailVerification as UpstreamOAuth2SetEmailVerification, UpstreamOAuth2Config,
},
};
use crate::util::ConfigurationSection;
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct RootConfig {
#[serde(default, skip_serializing_if = "ClientsConfig::is_default")]
pub clients: ClientsConfig,
#[serde(default)]
pub http: HttpConfig,
#[serde(default)]
pub database: DatabaseConfig,
#[serde(default, skip_serializing_if = "TelemetryConfig::is_default")]
pub telemetry: TelemetryConfig,
#[serde(default, skip_serializing_if = "TemplatesConfig::is_default")]
pub templates: TemplatesConfig,
#[serde(default)]
pub email: EmailConfig,
pub secrets: SecretsConfig,
#[serde(default)]
pub passwords: PasswordsConfig,
pub matrix: MatrixConfig,
#[serde(default, skip_serializing_if = "PolicyConfig::is_default")]
pub policy: PolicyConfig,
#[serde(default, skip_serializing_if = "RateLimitingConfig::is_default")]
pub rate_limiting: RateLimitingConfig,
#[serde(default, skip_serializing_if = "UpstreamOAuth2Config::is_default")]
pub upstream_oauth2: UpstreamOAuth2Config,
#[serde(default, skip_serializing_if = "BrandingConfig::is_default")]
pub branding: BrandingConfig,
#[serde(default, skip_serializing_if = "CaptchaConfig::is_default")]
pub captcha: CaptchaConfig,
#[serde(default, skip_serializing_if = "AccountConfig::is_default")]
pub account: AccountConfig,
#[serde(default, skip_serializing_if = "ExperimentalConfig::is_default")]
pub experimental: ExperimentalConfig,
}
impl ConfigurationSection for RootConfig {
fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
self.clients.validate(figment)?;
self.http.validate(figment)?;
self.database.validate(figment)?;
self.telemetry.validate(figment)?;
self.templates.validate(figment)?;
self.email.validate(figment)?;
self.passwords.validate(figment)?;
self.secrets.validate(figment)?;
self.matrix.validate(figment)?;
self.policy.validate(figment)?;
self.rate_limiting.validate(figment)?;
self.upstream_oauth2.validate(figment)?;
self.branding.validate(figment)?;
self.captcha.validate(figment)?;
self.account.validate(figment)?;
self.experimental.validate(figment)?;
Ok(())
}
}
impl RootConfig {
pub async fn generate<R>(mut rng: R) -> anyhow::Result<Self>
where
R: Rng + Send,
{
Ok(Self {
clients: ClientsConfig::default(),
http: HttpConfig::default(),
database: DatabaseConfig::default(),
telemetry: TelemetryConfig::default(),
templates: TemplatesConfig::default(),
email: EmailConfig::default(),
passwords: PasswordsConfig::default(),
secrets: SecretsConfig::generate(&mut rng).await?,
matrix: MatrixConfig::generate(&mut rng),
policy: PolicyConfig::default(),
rate_limiting: RateLimitingConfig::default(),
upstream_oauth2: UpstreamOAuth2Config::default(),
branding: BrandingConfig::default(),
captcha: CaptchaConfig::default(),
account: AccountConfig::default(),
experimental: ExperimentalConfig::default(),
})
}
#[must_use]
pub fn test() -> Self {
Self {
clients: ClientsConfig::default(),
http: HttpConfig::default(),
database: DatabaseConfig::default(),
telemetry: TelemetryConfig::default(),
templates: TemplatesConfig::default(),
passwords: PasswordsConfig::default(),
email: EmailConfig::default(),
secrets: SecretsConfig::test(),
matrix: MatrixConfig::test(),
policy: PolicyConfig::default(),
rate_limiting: RateLimitingConfig::default(),
upstream_oauth2: UpstreamOAuth2Config::default(),
branding: BrandingConfig::default(),
captcha: CaptchaConfig::default(),
account: AccountConfig::default(),
experimental: ExperimentalConfig::default(),
}
}
}
#[allow(missing_docs)]
#[derive(Debug, Deserialize)]
pub struct AppConfig {
#[serde(default)]
pub http: HttpConfig,
#[serde(default)]
pub database: DatabaseConfig,
#[serde(default)]
pub templates: TemplatesConfig,
#[serde(default)]
pub email: EmailConfig,
pub secrets: SecretsConfig,
#[serde(default)]
pub passwords: PasswordsConfig,
pub matrix: MatrixConfig,
#[serde(default)]
pub policy: PolicyConfig,
#[serde(default)]
pub rate_limiting: RateLimitingConfig,
#[serde(default)]
pub branding: BrandingConfig,
#[serde(default)]
pub captcha: CaptchaConfig,
#[serde(default)]
pub account: AccountConfig,
#[serde(default)]
pub experimental: ExperimentalConfig,
}
impl ConfigurationSection for AppConfig {
fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
self.http.validate(figment)?;
self.database.validate(figment)?;
self.templates.validate(figment)?;
self.email.validate(figment)?;
self.passwords.validate(figment)?;
self.secrets.validate(figment)?;
self.matrix.validate(figment)?;
self.policy.validate(figment)?;
self.rate_limiting.validate(figment)?;
self.branding.validate(figment)?;
self.captcha.validate(figment)?;
self.account.validate(figment)?;
self.experimental.validate(figment)?;
Ok(())
}
}
#[allow(missing_docs)]
#[derive(Debug, Deserialize)]
pub struct SyncConfig {
#[serde(default)]
pub database: DatabaseConfig,
pub secrets: SecretsConfig,
#[serde(default)]
pub clients: ClientsConfig,
#[serde(default)]
pub upstream_oauth2: UpstreamOAuth2Config,
}
impl ConfigurationSection for SyncConfig {
fn validate(&self, figment: &figment::Figment) -> Result<(), figment::Error> {
self.database.validate(figment)?;
self.secrets.validate(figment)?;
self.clients.validate(figment)?;
self.upstream_oauth2.validate(figment)?;
Ok(())
}
}