163 lines
5.2 KiB
Rust
163 lines
5.2 KiB
Rust
use std::path::Path;
|
|
use std::{env, fs};
|
|
|
|
use config::builder::DefaultState;
|
|
use config::{Config, ConfigBuilder, ConfigError, File};
|
|
|
|
use serde::Deserialize;
|
|
use url::Url;
|
|
|
|
pub mod database;
|
|
pub mod forges;
|
|
pub mod server;
|
|
|
|
use database::{DBType, Database};
|
|
use forges::Forges;
|
|
use server::Server;
|
|
|
|
#[derive(Debug, Clone, Deserialize, Eq, PartialEq)]
|
|
pub struct Settings {
|
|
pub debug: bool,
|
|
pub log: String,
|
|
pub source_code: String,
|
|
pub allow_registration: bool,
|
|
pub database: Database,
|
|
pub forges: Forges,
|
|
pub server: Server,
|
|
// pub smtp: Option<Smtp>,
|
|
}
|
|
|
|
impl Settings {
|
|
fn env_override(mut s: ConfigBuilder<DefaultState>) -> ConfigBuilder<DefaultState> {
|
|
for (parameter, env_var_name) in [
|
|
("debug", "FORGEFLUX_debug"),
|
|
("source_code", "FORGEFLUX_source_code"),
|
|
("allow_registration", "FORGEFLUX_allow_registration"),
|
|
]
|
|
.iter()
|
|
{
|
|
if let Ok(val) = env::var(env_var_name) {
|
|
log::debug!("Overriding [{parameter}] with environment variable {env_var_name}");
|
|
s = s.set_override(parameter, val).unwrap();
|
|
}
|
|
}
|
|
|
|
s = Database::env_override(s);
|
|
s = Forges::env_override(s);
|
|
Server::env_override(s)
|
|
}
|
|
|
|
pub fn new() -> Result<Self, ConfigError> {
|
|
let mut s = Config::builder();
|
|
|
|
const CURRENT_DIR: &str = "./config/default.toml";
|
|
const ETC: &str = "/etc/forgeflux/config.toml";
|
|
|
|
// Will be overridden after config is parsed and loaded into Settings by
|
|
// Settings::set_database_type.
|
|
// This parameter is not ergonomic for users, but it is required and can be programatically
|
|
// inferred. But we need a default value for config lib to parse successfully, since it is
|
|
// DBType and not Option<DBType>
|
|
s = s
|
|
.set_default("database.database_type", DBType::Postgres.to_string())
|
|
.expect("unable to set database.database_type default config");
|
|
|
|
s = s
|
|
.set_default("log", "INFO")
|
|
.expect("unable to set log default config");
|
|
|
|
if let Ok(path) = env::var("FORGEFLUX_CONFIG") {
|
|
let absolute_path = Path::new(&path).canonicalize().unwrap();
|
|
log::info!(
|
|
"Loading config file from {}",
|
|
absolute_path.to_str().unwrap()
|
|
);
|
|
s = s.add_source(File::with_name(absolute_path.to_str().unwrap()));
|
|
} else if Path::new(CURRENT_DIR).exists() {
|
|
let absolute_path = fs::canonicalize(CURRENT_DIR).unwrap();
|
|
log::info!(
|
|
"Loading config file from {}",
|
|
absolute_path.to_str().unwrap()
|
|
);
|
|
// merging default config from file
|
|
s = s.add_source(File::with_name(absolute_path.to_str().unwrap()));
|
|
} else if Path::new(ETC).exists() {
|
|
log::info!("{}", format!("Loading config file from {}", ETC));
|
|
s = s.add_source(File::with_name(ETC));
|
|
} else {
|
|
log::warn!("Configuration file not found");
|
|
}
|
|
|
|
s = Self::env_override(s);
|
|
|
|
let mut settings = s.build()?.try_deserialize::<Settings>()?;
|
|
settings.check_url();
|
|
|
|
settings.database.set_database_type();
|
|
|
|
Ok(settings)
|
|
}
|
|
|
|
fn check_url(&self) {
|
|
Url::parse(&self.source_code).expect("Please enter a URL for source_code in settings");
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
pub mod tests {
|
|
use url::Url;
|
|
|
|
use super::Settings;
|
|
use crate::db::create_database::CreateDatabase;
|
|
use crate::db::delete_database::DeleteDatabase;
|
|
use crate::db::migrate::RunMigrations;
|
|
use crate::db::sqlx_postgres::Postgres;
|
|
use crate::utils::get_random;
|
|
|
|
#[macro_export]
|
|
macro_rules! env_helper {
|
|
($init_settings:ident, $env:expr, $val:expr, $val_typed:expr, $($param:ident).+) => {
|
|
println!("Setting env var {} to {} for test", $env, $val);
|
|
env::set_var($env, $val);
|
|
{
|
|
let new_settings = crate::settings::Settings::new().unwrap();
|
|
assert_eq!(new_settings.$($param).+, $val_typed, "should match");
|
|
assert_ne!(new_settings.$($param).+, $init_settings.$($param).+);
|
|
}
|
|
env::remove_var($env);
|
|
};
|
|
|
|
|
|
($init_settings:ident, $env:expr, $val:expr, $($param:ident).+) => {
|
|
env_helper!($init_settings, $env, $val.to_string(), $val, $($param).+);
|
|
};
|
|
}
|
|
|
|
pub async fn get_settings() -> Settings {
|
|
let mut settings = Settings::new().unwrap();
|
|
let mut db_url = Url::parse(&settings.database.url).unwrap();
|
|
db_url.set_path(&get_random(12));
|
|
settings.database.url = db_url.to_string();
|
|
|
|
crate::db::sqlx_postgres::PostgresDatabase
|
|
.create_database(&db_url)
|
|
.await;
|
|
let db = Postgres::new(
|
|
sqlx::postgres::PgPool::connect(&settings.database.url)
|
|
.await
|
|
.unwrap(),
|
|
);
|
|
db.migrate().await;
|
|
|
|
settings
|
|
}
|
|
|
|
impl Settings {
|
|
pub async fn drop_db(&self) {
|
|
crate::db::sqlx_postgres::PostgresDatabase
|
|
.delete_database(&Url::parse(&self.database.url).unwrap())
|
|
.await;
|
|
}
|
|
}
|
|
}
|