240 lines
8.5 KiB
Rust
240 lines
8.5 KiB
Rust
//! Interfaces for writing and reading PeachCloud configurations, stored in yaml.
|
|
//!
|
|
//! Different PeachCloud microservices import peach-lib, so that they can share
|
|
//! this interface.
|
|
//!
|
|
//! Config values are looked up from three locations in this order by key name:
|
|
//! 1. from environmental variables
|
|
//! 2. from a configuration file
|
|
//! 3. from default values
|
|
//!
|
|
//! The configuration file is located at: "/var/lib/peachcloud/config.yml"
|
|
//! unless its path is configured by setting PEACH_CONFIG_PATH env variable.
|
|
|
|
use std::{env, fs};
|
|
use std::collections::HashMap;
|
|
|
|
use fslock::LockFile;
|
|
use lazy_static::lazy_static;
|
|
|
|
use crate::error::PeachError;
|
|
|
|
// load path to main configuration file
|
|
// from PEACH_CONFIG_PATH if that environment variable is set
|
|
// or using the default value if not set
|
|
pub const DEFAULT_YAML_PATH: &str = "/var/lib/peachcloud/config.yml";
|
|
lazy_static! {
|
|
static ref CONFIG_PATH: String = {
|
|
if let Ok(val) = env::var("PEACH_CONFIG_PATH") {
|
|
val
|
|
}
|
|
else {
|
|
DEFAULT_YAML_PATH.to_string()
|
|
}
|
|
};
|
|
// lock file (used to avoid race conditions during config reading & writing)
|
|
// the lock file path is the config file path + ".lock"
|
|
static ref LOCK_FILE_PATH: String = format!("{}.lock", *CONFIG_PATH);
|
|
}
|
|
|
|
// primary interface for getting config values
|
|
pub fn get_config_value(key: &str) -> Result<String, PeachError> {
|
|
// first check if it is an environmental variable
|
|
if let Ok(val) = env::var(key) {
|
|
Ok(val)
|
|
} else {
|
|
// then check disc
|
|
let peach_config_on_disc = load_peach_config_from_disc()?;
|
|
let val = peach_config_on_disc.get(key);
|
|
// then check defaults
|
|
match val {
|
|
Some(v) => Ok(v.to_string()),
|
|
None => {
|
|
match get_peach_config_defaults().get(key) {
|
|
Some(v) => Ok(v.to_string()),
|
|
None => {
|
|
Err(PeachError::InvalidKey { msg: format!("No default config value set for key: {}", key) })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Default values for PeachCloud configs which are used for any key which is not set
|
|
// via an environment variable or in a saved configuration file.
|
|
pub fn get_peach_config_defaults() -> HashMap<String, String> {
|
|
let peach_config_defaults: HashMap<String, String> = HashMap::from([
|
|
("STANDALONE_MODE".to_string(), "true".to_string()),
|
|
("DISABLE_AUTH".to_string(), "false".to_string()),
|
|
("ADDR".to_string(), "127.0.0.1".to_string()),
|
|
("PORT".to_string(), "8000".to_string()),
|
|
("EXTERNAL_DOMAIN".to_string(), "".to_string()),
|
|
("DYN_DOMAIN".to_string(), "".to_string()),
|
|
("DYN_DNS_SERVER_ADDRESS".to_string(), "http://dynserver.dyn.peachcloud.org".to_string()),
|
|
("DYN_USE_CUSTOM_SERVER".to_string(), "true".to_string()),
|
|
("DYN_TSIG_KEY_PATH".to_string(), "".to_string()),
|
|
("DYN_NAMESERVER".to_string(), "ns.peachcloud.org".to_string()),
|
|
("DYN_ENABLED".to_string(), "false".to_string()),
|
|
("SSB_ADMIN_IDS".to_string(), "[]".to_string()),
|
|
("ADMIN_PASSWORD_HASH".to_string(), "146".to_string()),
|
|
("TEMPORARY_PASSWORD_HASH".to_string(), "".to_string()),
|
|
("GO_SBOT_DATADIR".to_string(), "".to_string()),
|
|
("PEACH_CONFIGDIR".to_string(), "/var/lib/peachcloud".to_string()),
|
|
]);
|
|
peach_config_defaults
|
|
}
|
|
|
|
|
|
// helper function to load PeachCloud configuration files saved to disc
|
|
pub fn load_peach_config_from_disc() -> Result<HashMap<String, String>, PeachError> {
|
|
let peach_config : HashMap<String, String> = HashMap::new();
|
|
// TODO: implement
|
|
Ok(peach_config)
|
|
}
|
|
|
|
pub fn save_peach_config_to_disc(peach_config: HashMap<String, String>) -> Result<HashMap<String, String>, PeachError> {
|
|
|
|
// use a file lock to avoid race conditions while saving config
|
|
let mut lock = LockFile::open(&*LOCK_FILE_PATH)?;
|
|
lock.lock()?;
|
|
|
|
// convert HashMap to yaml
|
|
let yaml_str = serde_yaml::to_string(&peach_config)?;
|
|
|
|
// write yaml to file
|
|
fs::write(CONFIG_PATH.as_str(), yaml_str).map_err(|source| PeachError::Write {
|
|
source,
|
|
path: CONFIG_PATH.to_string(),
|
|
})?;
|
|
|
|
// unlock file lock
|
|
lock.unlock()?;
|
|
|
|
// return modified HashMap
|
|
Ok(peach_config)
|
|
}
|
|
|
|
// helper functions for serializing and deserializing PeachConfig from disc
|
|
pub fn save_peach_config_value(key: &str, value: String) -> Result<HashMap<String, String>, PeachError> {
|
|
|
|
// get current config from disc
|
|
let mut peach_config = load_peach_config_from_disc()?;
|
|
|
|
// insert new key/value
|
|
peach_config.insert(key.to_string(), value);
|
|
|
|
// save hte modified hashmap to disc
|
|
save_peach_config_to_disc(peach_config)
|
|
}
|
|
|
|
|
|
// set all dyn configuration values at once
|
|
pub fn set_peach_dyndns_config(
|
|
dyn_domain: &str,
|
|
dyn_dns_server_address: &str,
|
|
dyn_tsig_key_path: &str,
|
|
dyn_enabled: bool,
|
|
) -> Result<HashMap<String, String>, PeachError> {
|
|
let mut peach_config = load_peach_config_from_disc()?;
|
|
let dyn_enabled_str = match dyn_enabled {
|
|
true => "true",
|
|
false => "false"
|
|
};
|
|
peach_config.insert("DYN_DOMAIN".to_string(), dyn_domain.to_string());
|
|
peach_config.insert("DYN_DNS_SERVER_ADDRESS".to_string(), dyn_dns_server_address.to_string());
|
|
peach_config.insert("DYN_TSIG_KEY_PATH".to_string(), dyn_tsig_key_path.to_string());
|
|
peach_config.insert("DYN_ENABLED".to_string(), dyn_enabled_str.to_string());
|
|
save_peach_config_to_disc(peach_config)
|
|
}
|
|
|
|
pub fn set_external_domain(new_external_domain: &str) -> Result<HashMap<String, String>, PeachError> {
|
|
save_peach_config_value("EXTERNAL_DOMAIN", new_external_domain.to_string())
|
|
}
|
|
|
|
pub fn get_peachcloud_domain() -> Result<Option<String>, PeachError> {
|
|
let external_domain = get_config_value("EXTERNAL_DOMAIN")?;
|
|
let dyn_domain = get_config_value("DYN_DOMAIN")?;
|
|
if !external_domain.is_empty() {
|
|
Ok(Some(external_domain.to_string()))
|
|
} else if !dyn_domain.is_empty() {
|
|
Ok(Some(dyn_domain.to_string()))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
pub fn get_dyndns_server_address() -> Result<String, PeachError> {
|
|
get_config_value("DYN_DNS_SERVER_ADDRESS")
|
|
}
|
|
|
|
pub fn set_dyndns_enabled_value(enabled_value: bool) -> Result<HashMap<String, String>, PeachError> {
|
|
match enabled_value {
|
|
true => save_peach_config_value("DYN_ENABLED", "true".to_string()),
|
|
false => save_peach_config_value("DYN_ENABLED", "false".to_string())
|
|
}
|
|
}
|
|
|
|
pub fn get_dyndns_enabled_value() -> Result<bool, PeachError> {
|
|
let val = get_config_value("DYN_ENABLED")?;
|
|
return Ok(val == "true")
|
|
}
|
|
|
|
pub fn add_ssb_admin_id(ssb_id: &str) -> Result<Vec<String>, PeachError> {
|
|
let mut ssb_admin_ids = get_ssb_admin_ids()?;
|
|
ssb_admin_ids.push(ssb_id.to_string());
|
|
save_ssb_admin_ids(ssb_admin_ids)
|
|
}
|
|
|
|
pub fn delete_ssb_admin_id(ssb_id: &str) -> Result<Vec<String>, PeachError> {
|
|
let mut ssb_admin_ids = get_ssb_admin_ids()?;
|
|
let index_result = ssb_admin_ids.iter().position(|x| *x == ssb_id);
|
|
match index_result {
|
|
Some(index) => {
|
|
ssb_admin_ids.remove(index);
|
|
save_ssb_admin_ids(ssb_admin_ids)
|
|
}
|
|
None => Err(PeachError::SsbAdminIdNotFound {
|
|
id: ssb_id.to_string(),
|
|
}),
|
|
}
|
|
}
|
|
|
|
pub fn save_ssb_admin_ids(ssb_admin_ids: Vec<String>) -> Result<Vec<String>, PeachError> {
|
|
// save_peach_config_value("SSB_ADMIN_IDS", ssb_admin_ids.to_string())
|
|
// TODO: implement
|
|
Ok(ssb_admin_ids)
|
|
}
|
|
|
|
pub fn set_admin_password_hash(password_hash: String) -> Result<HashMap<String, String>, PeachError> {
|
|
save_peach_config_value("ADMIN_PASSWORD_HASH", password_hash)
|
|
}
|
|
|
|
pub fn get_admin_password_hash() -> Result<String, PeachError> {
|
|
let admin_password_hash = get_config_value("ADMIN_PASSWORD_HASH")?;
|
|
if !admin_password_hash.is_empty() {
|
|
Ok(admin_password_hash.to_string())
|
|
} else {
|
|
Err(PeachError::PasswordNotSet)
|
|
}
|
|
}
|
|
|
|
pub fn set_temporary_password_hash(password_hash: String) -> Result<HashMap<String, String>, PeachError> {
|
|
save_peach_config_value("TEMPORARY_PASSWORD_HASH", password_hash)
|
|
}
|
|
|
|
pub fn get_temporary_password_hash() -> Result<String, PeachError> {
|
|
let admin_password_hash = get_config_value("TEMPORARY_PASSWORD_HASH")?;
|
|
if !admin_password_hash.is_empty() {
|
|
Ok(admin_password_hash.to_string())
|
|
} else {
|
|
Err(PeachError::PasswordNotSet)
|
|
}
|
|
}
|
|
|
|
pub fn get_ssb_admin_ids() -> Result<Vec<String>, PeachError> {
|
|
let mut ssb_admin_ids = vec!["x".to_string(), "y".to_string(), "z".to_string()];
|
|
Ok(ssb_admin_ids)
|
|
}
|