use serde::Deserialize; #[derive(Debug, Clone, Deserialize)] pub struct AppConfig { pub server: ServerConfig, pub database: DatabaseConfig, pub redis: RedisConfig, pub jwt: JwtConfig, pub auth: AuthConfig, pub log: LogConfig, pub cors: CorsConfig, } #[derive(Debug, Clone, Deserialize)] pub struct ServerConfig { pub host: String, pub port: u16, } #[derive(Debug, Clone, Deserialize)] pub struct DatabaseConfig { pub url: String, pub max_connections: u32, pub min_connections: u32, } #[derive(Debug, Clone, Deserialize)] pub struct RedisConfig { pub url: String, } #[derive(Debug, Clone, Deserialize)] pub struct JwtConfig { pub secret: String, pub access_token_ttl: String, pub refresh_token_ttl: String, } #[derive(Debug, Clone, Deserialize)] pub struct LogConfig { pub level: String, } #[derive(Debug, Clone, Deserialize)] pub struct AuthConfig { pub super_admin_password: String, } #[derive(Debug, Clone, Deserialize)] pub struct CorsConfig { /// Comma-separated list of allowed origins. /// Use "*" to allow all origins (development only). pub allowed_origins: String, } impl AppConfig { pub fn load() -> anyhow::Result { let config = config::Config::builder() .add_source(config::File::with_name("config/default")) .add_source(config::Environment::with_prefix("ERP").separator("__")) .build()?; let app_config: Self = config.try_deserialize()?; // 安全检查:禁止在生产使用默认 JWT 密钥 if app_config.jwt.secret == "change-me-in-production" { tracing::warn!("⚠️ JWT 密钥使用默认值,请通过 ERP__JWT__SECRET 环境变量设置安全密钥"); } Ok(app_config) } }