use std::{net::SocketAddr, path::PathBuf}; /// Runtime configuration, read from the environment (see `.env.example`). #[derive(Debug, Clone)] pub struct Config { pub bind: SocketAddr, pub frontend: PathBuf, pub templates: PathBuf, pub data_dir: PathBuf, pub database_url: String, pub default_domain: String, pub xmpp_whitelist: Vec, pub max_sessions: usize, pub disable_registration: bool, pub default_locale: String, pub banner: Option, pub info: Option, pub debug_xmpp: bool, /// Development only: connect without TLS to this host:port pub xmpp_plaintext: Option, /// Disconnect the XMPP sessions without any browser activity for this long pub session_timeout_hours: u64, /// Allow the picture proxy and link previews to reach private networks (development) pub allow_private_urls: bool, /// Delete the cached messages older than this many days (0: keep them), /// to follow the XMPP server's archive expiry pub message_retention_days: u32, } fn env(key: &str) -> Option { std::env::var(key).ok().filter(|v| !v.is_empty()) } impl Config { pub fn from_env() -> Self { let root = env("MOVIM_ROOT") .map(PathBuf::from) .unwrap_or_else(|| PathBuf::from(env!("CARGO_MANIFEST_DIR"))); let data_dir = env("MOVIM_DATA_DIR") .map(PathBuf::from) .unwrap_or_else(|| root.join("data")); Config { bind: env("MOVIM_BIND") .unwrap_or_else(|| "127.0.0.1:8080".into()) .parse() .expect("invalid MOVIM_BIND"), frontend: root.join("frontend"), templates: root.join("templates"), database_url: env("MOVIM_DATABASE_URL").unwrap_or_else(|| { format!("sqlite://{}?mode=rwc", data_dir.join("movim.sqlite").display()) }), data_dir, default_domain: env("MOVIM_DOMAIN").unwrap_or_else(|| "movim.eu".into()), xmpp_whitelist: env("MOVIM_XMPP_WHITELIST") .map(|s| { s.split(',') .map(|d| d.trim().to_string()) .filter(|d| !d.is_empty()) .collect() }) .unwrap_or_default(), max_sessions: env("MOVIM_MAX_SESSIONS") .and_then(|s| s.parse().ok()) .unwrap_or(0), disable_registration: env("MOVIM_DISABLE_REGISTRATION").is_some_and(|v| v == "1" || v == "true"), default_locale: env("MOVIM_LOCALE").unwrap_or_else(|| "en".into()), banner: env("MOVIM_BANNER"), info: env("MOVIM_INFO"), debug_xmpp: env("MOVIM_DEBUG_XMPP").is_some_and(|v| v == "1" || v == "true"), xmpp_plaintext: env("MOVIM_XMPP_PLAINTEXT"), session_timeout_hours: env("MOVIM_SESSION_TIMEOUT_HOURS").and_then(|s| s.parse().ok()).unwrap_or(24 * 7), allow_private_urls: env("MOVIM_ALLOW_PRIVATE_URLS").is_some_and(|v| v == "1" || v == "true"), message_retention_days: env("MOVIM_MESSAGE_RETENTION_DAYS").and_then(|s| s.parse().ok()).unwrap_or(0), } } }