use rocket::config::{ Config as RocketConfig, ConfigBuilder as RocketConfigBuilder, Environment as RocketEnvironment, }; const DEFAULT_ENVIRONMENT: Environment = Environment::Development; const DEFAULT_ADDRESS: &str = "127.0.0.1"; const DEFAULT_PORT: u16 = 8000; const DEFAULT_DATABASE_URL: &str = "postgres://fedihub_website_development:fedihub_website_development@localhost:5432/fedihub_website_development"; #[derive(Debug)] pub enum Environment { Development, Test, Production, } #[derive(Debug)] pub struct Config { pub root: String, pub environment: Environment, pub address: String, pub port: u16, pub database_url: String, pub secret_key: Option, } impl Environment { pub fn from_string(value: String) -> Self { match value.to_lowercase().as_str() { "development" | "dev" => Self::Development, "test" => Self::Test, "production" | "prod" => Self::Production, _ => Self::Development, } } pub fn to_rocket_environment(&self) -> RocketEnvironment { match self { Environment::Development => RocketEnvironment::Development, Environment::Test => RocketEnvironment::Development, Environment::Production => RocketEnvironment::Production, } } } impl Config { pub fn default() -> Result { let default_root = match Self::default_root() { Err(_) => return Err(()), Ok(value) => value, }; Ok( Config { root: default_root, environment: DEFAULT_ENVIRONMENT, address: DEFAULT_ADDRESS.to_string(), port: DEFAULT_PORT, database_url: DEFAULT_DATABASE_URL.to_string(), secret_key: None, } ) } pub fn from_env() -> Result { let mut result = Self::default()?; result.use_env(); Ok(result) } pub fn default_root() -> Result { let root_path_buf = match std::env::current_dir() { Err(_) => return Err(()), Ok(value) => value, }; let root_str = match root_path_buf.to_str() { None => return Err(()), Some(value) => value, }; Ok(root_str.to_string()) } pub fn use_env(&mut self) { self.use_env_for_root(); self.use_env_for_environment(); self.use_env_for_address(); self.use_env_for_port(); self.use_env_for_database_url(); self.use_env_for_secret_key(); } pub fn to_rocket_config(&self) -> Result { match self.to_rocket_config_builder().finalize() { Err(_) => Err(()), Ok(rocket_config) => Ok(rocket_config), } } pub fn to_rocket_config_builder(&self) -> RocketConfigBuilder { let mut value = RocketConfig::build(self.environment.to_rocket_environment()) .root(self.root.to_string()) .address(self.address.to_string()) .port(self.port); if let Some(secret_key) = &self.secret_key { value = value.secret_key(secret_key); } value } pub fn public_path(&self) -> Result { let mut result_path_buf = std::path::PathBuf::new(); result_path_buf.push(self.root.to_string()); result_path_buf.push("public"); let result_str = match result_path_buf.to_str() { None => return Err(()), Some(value) => value, }; Ok(result_str.to_string()) } pub fn locales_path(&self) -> Result { let mut result_path_buf = std::path::PathBuf::new(); result_path_buf.push(self.root.to_string()); result_path_buf.push("locales"); let result_str = match result_path_buf.to_str() { None => return Err(()), Some(value) => value, }; Ok(result_str.to_string()) } pub fn use_env_for_root(&mut self) { self.root = match std::env::var("ROOT") { Err(_) => return, Ok(value) => if value.is_empty() { return } else { value }, }; } pub fn use_env_for_environment(&mut self) { self.environment = match std::env::var("ENVIRONMENT") { Err(_) => return, Ok(value) => if value.is_empty() { return } else { Environment::from_string(value) }, }; } pub fn use_env_for_address(&mut self) { self.address = match std::env::var("ADDRESS") { Err(_) => return, Ok(value) => if value.is_empty() { return } else { value }, }; } pub fn use_env_for_port(&mut self) { self.port = match std::env::var("PORT") { Err(_) => return, Ok(value) => match value.parse::() { Err(_) => return, Ok(value) => value, }, }; } pub fn use_env_for_database_url(&mut self) { self.database_url = match std::env::var("DATABASE_URL") { Err(_) => return, Ok(value) => if value.is_empty() { return } else { value }, }; } pub fn use_env_for_secret_key(&mut self) { self.secret_key = match std::env::var("SECRET_KEY") { Err(_) => return, Ok(value) => if value.is_empty() { return } else { Some(value) }, } } }