//! Server configuration module use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ServerConfig { pub host: String, pub port: u16, pub stripe_secret_key: String, pub stripe_publishable_key: String, pub stripe_webhook_secret: Option, pub identify_api_key: String, pub identify_api_url: String, pub identify_webhook_secret: Option, pub cors_origins: Vec, pub api_keys: Vec, } impl Default for ServerConfig { fn default() -> Self { Self { host: "127.0.0.1".to_string(), port: 3001, stripe_secret_key: String::new(), stripe_publishable_key: String::new(), stripe_webhook_secret: None, identify_api_key: String::new(), identify_api_url: "https://api.identify.com".to_string(), identify_webhook_secret: None, cors_origins: vec!["*".to_string()], api_keys: vec![], } } } impl ServerConfig { pub fn from_env() -> anyhow::Result { // Note: .env file loading is now handled by the CLI before calling this function let config = Self { host: std::env::var("HOST").unwrap_or_else(|_| "127.0.0.1".to_string()), port: std::env::var("PORT") .unwrap_or_else(|_| "3001".to_string()) .parse() .unwrap_or(3001), stripe_secret_key: std::env::var("STRIPE_SECRET_KEY") .map_err(|_| anyhow::anyhow!("STRIPE_SECRET_KEY environment variable is required"))?, stripe_publishable_key: std::env::var("STRIPE_PUBLISHABLE_KEY") .map_err(|_| anyhow::anyhow!("STRIPE_PUBLISHABLE_KEY environment variable is required"))?, stripe_webhook_secret: std::env::var("STRIPE_WEBHOOK_SECRET").ok(), identify_api_key: std::env::var("IDENTIFY_API_KEY") .map_err(|_| anyhow::anyhow!("IDENTIFY_API_KEY environment variable is required"))?, identify_api_url: std::env::var("IDENTIFY_API_URL") .unwrap_or_else(|_| "https://api.identify.com".to_string()), identify_webhook_secret: std::env::var("IDENTIFY_WEBHOOK_SECRET").ok(), cors_origins: std::env::var("CORS_ORIGINS") .unwrap_or_else(|_| "*".to_string()) .split(',') .map(|s| s.trim().to_string()) .collect(), api_keys: std::env::var("API_KEYS") .unwrap_or_else(|_| String::new()) .split(',') .filter(|s| !s.trim().is_empty()) .map(|s| s.trim().to_string()) .collect(), }; Ok(config) } pub fn address(&self) -> String { format!("{}:{}", self.host, self.port) } /// Validate an API key against the configured keys pub fn validate_api_key(&self, api_key: &str) -> bool { if self.api_keys.is_empty() { // If no API keys are configured, allow all requests (development mode) true } else { self.api_keys.contains(&api_key.to_string()) } } }