use serde::Deserialize; use serde::de::DeserializeOwned; use crate::apihost::ApihostConfig as ApihostSection; use crate::auth::AuthConfig; use crate::chat::ChatConfig; use crate::database::DatabaseConfig; use crate::email::EmailConfig; use crate::error::ConfigError; use crate::git::GitConfig; use crate::githost::GithostConfig as GithostSection; use crate::issues::IssueConfig; use crate::livekit::LiveKitConfig; use crate::oauth::OAuthConfig; use crate::pow::PowConfig; use crate::push::PushConfig; use crate::quota::QuotaConfig; use crate::redis::RedisConfig; use crate::rocketmq::RocketMqConfig; use crate::s3::S3Config; use crate::space::SpaceConfig; use crate::user::UserConfig; use crate::web::WebConfig; use crate::{AppConfig, loader}; pub trait ScopedConfig: DeserializeOwned + Sized { fn validate_scoped(&self) -> Result<(), String>; fn load() -> Result { let cfg: Self = loader::figment().extract().map_err(ConfigError::from)?; cfg.validate_scoped().map_err(ConfigError::Validation)?; Ok(cfg) } } #[derive(Clone, Debug, Default, Deserialize)] #[serde(default)] pub struct MigrateConfig { pub database: DatabaseConfig, } impl ScopedConfig for MigrateConfig { fn validate_scoped(&self) -> Result<(), String> { self.database.validate() } } #[derive(Clone, Debug, Default, Deserialize)] #[serde(default)] pub struct GithostConfig { pub database: DatabaseConfig, pub redis: RedisConfig, pub s3: S3Config, pub email: EmailConfig, pub oauth: OAuthConfig, pub web: WebConfig, pub git: GitConfig, pub githost: GithostSection, } impl GithostConfig { pub fn into_app_config(self) -> AppConfig { AppConfig { database: self.database, redis: self.redis, s3: self.s3, email: self.email, oauth: self.oauth, web: self.web, git: self.git, githost: self.githost, ..Default::default() } } } impl ScopedConfig for GithostConfig { fn validate_scoped(&self) -> Result<(), String> { self.database.validate()?; self.redis.validate()?; self.githost.is_valid()?; self.oauth.is_valid()?; Ok(()) } } #[derive(Clone, Debug, Default, Deserialize)] #[serde(default)] pub struct ApihostConfig { pub s3: S3Config, pub redis: RedisConfig, pub chat: ChatConfig, pub database: DatabaseConfig, pub pow: PowConfig, pub auth: AuthConfig, pub web: WebConfig, pub user: UserConfig, pub quota: QuotaConfig, pub space: SpaceConfig, pub issues: IssueConfig, pub git: GitConfig, pub email: EmailConfig, pub oauth: OAuthConfig, pub apihost: ApihostSection, pub livekit: LiveKitConfig, pub rocketmq: RocketMqConfig, pub push: PushConfig, } impl ApihostConfig { pub fn into_app_config(self) -> AppConfig { AppConfig { s3: self.s3, redis: self.redis, chat: self.chat, database: self.database, pow: self.pow, auth: self.auth, web: self.web, user: self.user, quota: self.quota, space: self.space, issues: self.issues, git: self.git, email: self.email, oauth: self.oauth, apihost: self.apihost, livekit: self.livekit, rocketmq: self.rocketmq, push: self.push, ..Default::default() } } } impl ScopedConfig for ApihostConfig { fn validate_scoped(&self) -> Result<(), String> { self.redis.validate()?; self.database.validate()?; self.pow.validate()?; self.auth.validate()?; self.chat.is_valid()?; self.apihost.is_valid()?; self.livekit.is_valid()?; self.oauth.is_valid()?; self.rocketmq.is_valid()?; self.push.is_valid() } }