use serde::{Deserialize, Serialize}; use std::path::Path; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Config { pub oidc: OidcConfig, pub server: ServerConfig, pub database: DatabaseConfig, pub session: SessionConfig, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct OidcConfig { pub client_id: String, pub client_secret: String, pub auth_url: String, pub token_url: String, pub redirect_url: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ServerConfig { pub host: String, pub port: u16, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DatabaseConfig { pub url: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SessionConfig { pub secret: String, } impl Config { /// Load configuration from a TOML file and environment variables /// config-rs merges file config with environment variables automatically pub fn load(path: &str) -> Result> { let mut builder = config::Config::builder(); // Add default values first let defaults = Self::defaults(); builder = builder.add_source( config::Config::try_from(&defaults) .map_err(|e| Box::new(e) as Box)?, ); // Load from file if it exists if Path::new(path).exists() { builder = builder.add_source(config::File::with_name(path).required(false)); } // Override with environment variables // Environment variables should be prefixed with the app name and use __ for nesting // e.g., WEIGHT_TRACKER_OIDC__CLIENT_ID for oidc.client_id builder = builder.add_source( config::Environment::with_prefix("WEIGHT_TRACKER") .try_parsing(true) .separator("__"), ); let config = builder.build()?; let result: Config = config.try_deserialize()?; Ok(result) } /// Get default configuration values fn defaults() -> Self { Config { oidc: OidcConfig { client_id: "your_client_id".to_string(), client_secret: "your_client_secret".to_string(), auth_url: "https://your-provider.com/auth".to_string(), token_url: "https://your-provider.com/token".to_string(), redirect_url: "http://localhost:3000/auth/callback".to_string(), }, server: ServerConfig { host: "127.0.0.1".to_string(), port: 3000, }, database: DatabaseConfig { url: "sqlite:weight_tracker.db".to_string(), }, session: SessionConfig { secret: "your_secret_key_that_is_long_enough_so_the_library_does_not_complain" .to_string(), }, } } }