Merge pull request 'Update config_manager to check from three sources of configuration' (#105) from config into main
Reviewed-on: #105
This commit is contained in:
commit
810a97db8a
|
@ -2430,6 +2430,7 @@ dependencies = [
|
|||
"jsonrpc-client-core",
|
||||
"jsonrpc-client-http",
|
||||
"jsonrpc-core 8.0.1",
|
||||
"lazy_static",
|
||||
"log 0.4.16",
|
||||
"nanorand",
|
||||
"regex",
|
||||
|
|
|
@ -21,3 +21,4 @@ serde_json = "1.0"
|
|||
serde_yaml = "0.8"
|
||||
toml = "0.5"
|
||||
sha3 = "0.10"
|
||||
lazy_static = "1.4.0"
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
objcopy = { path ="aarch64-linux-gnu-objcopy" }
|
||||
strip = { path ="aarch64-linux-gnu-strip" }
|
|
@ -1,12 +0,0 @@
|
|||
[package]
|
||||
name = "debug"
|
||||
version = "0.1.0"
|
||||
authors = ["notplants <mfowler.email@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
peach-lib = { path = "../" }
|
||||
env_logger = "0.6"
|
||||
chrono = "0.4.19"
|
|
@ -1,65 +0,0 @@
|
|||
use peach_lib::dyndns_client::{dyndns_update_ip, register_domain, is_dns_updater_online, log_successful_nsupdate, get_num_seconds_since_successful_dns_update };
|
||||
use peach_lib::password_utils::{verify_password, set_new_password, verify_temporary_password, set_new_temporary_password, send_password_reset};
|
||||
use peach_lib::config_manager::{add_ssb_admin_id, delete_ssb_admin_id};
|
||||
use peach_lib::sbot_client;
|
||||
use std::process;
|
||||
use chrono::prelude::*;
|
||||
|
||||
|
||||
fn main() {
|
||||
// initalize the logger
|
||||
env_logger::init();
|
||||
//
|
||||
// println!("Hello, world its debug!");
|
||||
// let result = set_new_password("password3");
|
||||
// println!("result: {:?}", result);
|
||||
//
|
||||
// let result = verify_password("password1");
|
||||
// println!("result should be error: {:?}", result);
|
||||
//
|
||||
// let result = verify_password("password3");
|
||||
// println!("result should be ok: {:?}", result);
|
||||
//
|
||||
//
|
||||
// println!("Testing temporary passwords");
|
||||
// let result = set_new_temporary_password("abcd");
|
||||
// println!("result: {:?}", result);
|
||||
//
|
||||
// let result = verify_temporary_password("password1");
|
||||
// println!("result should be error: {:?}", result);
|
||||
//
|
||||
// let result = verify_temporary_password("abcd");
|
||||
// println!("result should be ok: {:?}", result);
|
||||
//
|
||||
let result = send_password_reset();
|
||||
println!("send password reset result should be ok: {:?}", result);
|
||||
|
||||
// sbot_client::post("hi cat");
|
||||
// let result = sbot_client::whoami();
|
||||
// let result = sbot_client::create_invite(50);
|
||||
// let result = sbot_client::post("is this working");
|
||||
// println!("result: {:?}", result);
|
||||
// let result = sbot_client::post("nice we have contact");
|
||||
// let result = sbot_client::update_pub_name("vermont-pub");
|
||||
// let result = sbot_client::private_message("this is a private message", "@LZx+HP6/fcjUm7vef2eaBKAQ9gAKfzmrMVGzzdJiQtA=.ed25519");
|
||||
// println!("result: {:?}", result);
|
||||
|
||||
// let result = send_password_reset();
|
||||
// let result = add_ssb_admin_id("xyzdab");
|
||||
// println!("result: {:?}", result);
|
||||
// let result = delete_ssb_admin_id("xyzdab");
|
||||
// println!("result: {:?}", result);
|
||||
// let result = delete_ssb_admin_id("ab");
|
||||
// println!("result: {:?}", result);
|
||||
|
||||
//// let result = log_successful_nsupdate();
|
||||
//// let result = get_num_seconds_since_successful_dns_update();
|
||||
// let is_online = is_dns_updater_online();
|
||||
// println!("is online: {:?}", is_online);
|
||||
//
|
||||
//// let result = get_last_successful_dns_update();
|
||||
//// println!("result: {:?}", result);
|
||||
//// register_domain("newquarter299.dyn.peachcloud.org");
|
||||
// let result = dyndns_update_ip();
|
||||
// println!("result: {:?}", result);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
use peach_lib::config_manager::{get_config_value, save_config_value};
|
||||
|
||||
fn main() {
|
||||
println!("Running example of PeachCloud configuration management");
|
||||
let v = get_config_value("ADDR").unwrap();
|
||||
println!("ADDR: {}", v);
|
||||
|
||||
save_config_value("ADDR", "1.1.1.1");
|
||||
let v = get_config_value("ADDR").unwrap();
|
||||
println!("ADDR: {}", v);
|
||||
}
|
|
@ -3,170 +3,273 @@
|
|||
//! 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::fs;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::{env, fs};
|
||||
|
||||
use fslock::LockFile;
|
||||
use lazy_static::lazy_static;
|
||||
use log::debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::PeachError;
|
||||
|
||||
// main configuration file
|
||||
pub const YAML_PATH: &str = "/var/lib/peachcloud/config.yml";
|
||||
|
||||
// lock file (used to avoid race conditions during config reading & writing)
|
||||
pub const LOCK_FILE_PATH: &str = "/var/lib/peachcloud/config.lock";
|
||||
|
||||
// default values
|
||||
pub const DEFAULT_DYN_SERVER_ADDRESS: &str = "http://dynserver.dyn.peachcloud.org";
|
||||
pub const DEFAULT_DYN_NAMESERVER: &str = "ns.peachcloud.org";
|
||||
|
||||
// we make use of Serde default values in order to make PeachCloud
|
||||
// robust and keep running even with a not fully complete config.yml
|
||||
// main type which represents all peachcloud configurations
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct PeachConfig {
|
||||
#[serde(default)]
|
||||
pub external_domain: String,
|
||||
#[serde(default)]
|
||||
pub dyn_domain: String,
|
||||
#[serde(default)]
|
||||
pub dyn_dns_server_address: String,
|
||||
#[serde(default)]
|
||||
pub dyn_use_custom_server: bool,
|
||||
#[serde(default)]
|
||||
pub dyn_nameserver: String,
|
||||
#[serde(default)]
|
||||
pub dyn_tsig_key_path: String,
|
||||
#[serde(default)] // default is false
|
||||
pub dyn_enabled: bool,
|
||||
#[serde(default)] // default is empty vector
|
||||
pub ssb_admin_ids: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub admin_password_hash: String,
|
||||
#[serde(default)]
|
||||
pub temporary_password_hash: String,
|
||||
// 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);
|
||||
}
|
||||
|
||||
// helper functions for serializing and deserializing PeachConfig from disc
|
||||
pub fn save_peach_config(peach_config: PeachConfig) -> Result<PeachConfig, PeachError> {
|
||||
// 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
|
||||
}
|
||||
|
||||
// primary interface for getting config values
|
||||
// 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
|
||||
pub fn get_config_value(key: &str) -> Result<String, PeachError> {
|
||||
// first check if there is an environmental variable set
|
||||
if let Ok(val) = env::var(key) {
|
||||
Ok(val)
|
||||
} else {
|
||||
// then check if a value is set in the config file
|
||||
let peach_config_on_disc = load_peach_config_from_disc()?;
|
||||
let val = peach_config_on_disc.get(key);
|
||||
// if no value is found in the config file, then get the default value
|
||||
match val {
|
||||
// return config value
|
||||
Some(v) => Ok(v.to_string()),
|
||||
// get default value
|
||||
None => {
|
||||
match get_peach_config_defaults().get(key) {
|
||||
Some(v) => Ok(v.to_string()),
|
||||
// if this key was not found in the defaults, then it was an invalid key
|
||||
None => Err(PeachError::InvalidKey {
|
||||
key: key.to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to load PeachCloud configuration file saved to disc
|
||||
pub fn load_peach_config_from_disc() -> Result<HashMap<String, String>, PeachError> {
|
||||
let peach_config_exists = std::path::Path::new(CONFIG_PATH.as_str()).exists();
|
||||
// if config file does not exist, return an emtpy HashMap
|
||||
if !peach_config_exists {
|
||||
let peach_config: HashMap<String, String> = HashMap::new();
|
||||
Ok(peach_config)
|
||||
}
|
||||
// otherwise we load peach config from disk
|
||||
else {
|
||||
debug!("Loading peach config: {} exists", CONFIG_PATH.as_str());
|
||||
let contents =
|
||||
fs::read_to_string(CONFIG_PATH.as_str()).map_err(|source| PeachError::Read {
|
||||
source,
|
||||
path: CONFIG_PATH.to_string(),
|
||||
})?;
|
||||
let peach_config: HashMap<String, String> = serde_yaml::from_str(&contents)?;
|
||||
Ok(peach_config)
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to save PeachCloud configuration file to disc
|
||||
// takes in a Hashmap<String, String> and saves the whole HashMap as a yaml file
|
||||
// with the keys in alphabetical order
|
||||
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)?;
|
||||
let mut lock = LockFile::open(&*LOCK_FILE_PATH)?;
|
||||
lock.lock()?;
|
||||
|
||||
let yaml_str = serde_yaml::to_string(&peach_config)?;
|
||||
// first convert Hashmap to BTreeMap (so that keys are saved in deterministic alphabetical order)
|
||||
let ordered: BTreeMap<_, _> = peach_config.iter().collect();
|
||||
// then serialize BTreeMap as yaml
|
||||
let yaml_str = serde_yaml::to_string(&ordered)?;
|
||||
|
||||
fs::write(YAML_PATH, yaml_str).map_err(|source| PeachError::Write {
|
||||
// write yaml to file
|
||||
fs::write(CONFIG_PATH.as_str(), yaml_str).map_err(|source| PeachError::Write {
|
||||
source,
|
||||
path: YAML_PATH.to_string(),
|
||||
path: CONFIG_PATH.to_string(),
|
||||
})?;
|
||||
|
||||
// unlock file lock
|
||||
lock.unlock()?;
|
||||
|
||||
// return peach_config
|
||||
// return modified HashMap
|
||||
Ok(peach_config)
|
||||
}
|
||||
|
||||
pub fn load_peach_config() -> Result<PeachConfig, PeachError> {
|
||||
let peach_config_exists = std::path::Path::new(YAML_PATH).exists();
|
||||
// helper functions for serializing and deserializing PeachConfig values from disc
|
||||
pub fn save_config_value(key: &str, value: &str) -> Result<HashMap<String, String>, PeachError> {
|
||||
// get current config from disc
|
||||
let mut peach_config = load_peach_config_from_disc()?;
|
||||
|
||||
let peach_config: PeachConfig = if !peach_config_exists {
|
||||
debug!("Loading peach config: {} does not exist", YAML_PATH);
|
||||
PeachConfig {
|
||||
external_domain: "".to_string(),
|
||||
dyn_domain: "".to_string(),
|
||||
dyn_dns_server_address: DEFAULT_DYN_SERVER_ADDRESS.to_string(),
|
||||
dyn_use_custom_server: false,
|
||||
dyn_nameserver: DEFAULT_DYN_NAMESERVER.to_string(),
|
||||
dyn_tsig_key_path: "".to_string(),
|
||||
dyn_enabled: false,
|
||||
ssb_admin_ids: Vec::new(),
|
||||
// default password is `peach`
|
||||
admin_password_hash: "146".to_string(),
|
||||
temporary_password_hash: "".to_string(),
|
||||
}
|
||||
}
|
||||
// otherwise we load peach config from disk
|
||||
else {
|
||||
debug!("Loading peach config: {} exists", YAML_PATH);
|
||||
let contents = fs::read_to_string(YAML_PATH).map_err(|source| PeachError::Read {
|
||||
source,
|
||||
path: YAML_PATH.to_string(),
|
||||
})?;
|
||||
serde_yaml::from_str(&contents)?
|
||||
};
|
||||
// insert new key/value
|
||||
peach_config.insert(key.to_string(), value.to_string());
|
||||
|
||||
Ok(peach_config)
|
||||
// save the modified hashmap to disc
|
||||
save_peach_config_to_disc(peach_config)
|
||||
}
|
||||
|
||||
// interfaces for setting specific config values
|
||||
// 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<PeachConfig, PeachError> {
|
||||
let mut peach_config = load_peach_config()?;
|
||||
peach_config.dyn_domain = dyn_domain.to_string();
|
||||
peach_config.dyn_dns_server_address = dyn_dns_server_address.to_string();
|
||||
peach_config.dyn_tsig_key_path = dyn_tsig_key_path.to_string();
|
||||
peach_config.dyn_enabled = dyn_enabled;
|
||||
save_peach_config(peach_config)
|
||||
) -> 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<PeachConfig, PeachError> {
|
||||
let mut peach_config = load_peach_config()?;
|
||||
peach_config.external_domain = new_external_domain.to_string();
|
||||
save_peach_config(peach_config)
|
||||
pub fn set_external_domain(
|
||||
new_external_domain: &str,
|
||||
) -> Result<HashMap<String, String>, PeachError> {
|
||||
save_config_value("EXTERNAL_DOMAIN", new_external_domain)
|
||||
}
|
||||
|
||||
pub fn get_peachcloud_domain() -> Result<Option<String>, PeachError> {
|
||||
let peach_config = load_peach_config()?;
|
||||
if !peach_config.external_domain.is_empty() {
|
||||
Ok(Some(peach_config.external_domain))
|
||||
} else if !peach_config.dyn_domain.is_empty() {
|
||||
Ok(Some(peach_config.dyn_domain))
|
||||
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))
|
||||
} else if !dyn_domain.is_empty() {
|
||||
Ok(Some(dyn_domain))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_dyndns_server_address() -> Result<String, PeachError> {
|
||||
let peach_config = load_peach_config()?;
|
||||
// if the user is using a custom dyn server then load the address from the config
|
||||
if peach_config.dyn_use_custom_server {
|
||||
Ok(peach_config.dyn_dns_server_address)
|
||||
}
|
||||
// otherwise hardcode the address
|
||||
else {
|
||||
Ok(DEFAULT_DYN_SERVER_ADDRESS.to_string())
|
||||
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_config_value("DYN_ENABLED", "true"),
|
||||
false => save_config_value("DYN_ENABLED", "false"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_dyndns_enabled_value(enabled_value: bool) -> Result<PeachConfig, PeachError> {
|
||||
let mut peach_config = load_peach_config()?;
|
||||
peach_config.dyn_enabled = enabled_value;
|
||||
save_peach_config(peach_config)
|
||||
pub fn get_dyndns_enabled_value() -> Result<bool, PeachError> {
|
||||
let val = get_config_value("DYN_ENABLED")?;
|
||||
Ok(val == "true")
|
||||
}
|
||||
|
||||
pub fn add_ssb_admin_id(ssb_id: &str) -> Result<PeachConfig, PeachError> {
|
||||
let mut peach_config = load_peach_config()?;
|
||||
peach_config.ssb_admin_ids.push(ssb_id.to_string());
|
||||
save_peach_config(peach_config)
|
||||
pub fn set_admin_password_hash(
|
||||
password_hash: String,
|
||||
) -> Result<HashMap<String, String>, PeachError> {
|
||||
save_config_value("ADMIN_PASSWORD_HASH", &password_hash)
|
||||
}
|
||||
|
||||
pub fn delete_ssb_admin_id(ssb_id: &str) -> Result<PeachConfig, PeachError> {
|
||||
let mut peach_config = load_peach_config()?;
|
||||
let mut ssb_admin_ids = peach_config.ssb_admin_ids;
|
||||
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)
|
||||
} else {
|
||||
Err(PeachError::PasswordNotSet)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_temporary_password_hash(
|
||||
password_hash: String,
|
||||
) -> Result<HashMap<String, String>, PeachError> {
|
||||
save_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)
|
||||
} else {
|
||||
Err(PeachError::PasswordNotSet)
|
||||
}
|
||||
}
|
||||
|
||||
// add ssb_id to vector of admin ids and save new value for SSB_ADMIN_IDS
|
||||
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)
|
||||
}
|
||||
|
||||
// remove ssb_id from vector of admin ids if found and save new value for SSB_ADMIN_IDS
|
||||
// if value is not found then return an error
|
||||
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);
|
||||
peach_config.ssb_admin_ids = ssb_admin_ids;
|
||||
save_peach_config(peach_config)
|
||||
save_ssb_admin_ids(ssb_admin_ids)
|
||||
}
|
||||
None => Err(PeachError::SsbAdminIdNotFound {
|
||||
id: ssb_id.to_string(),
|
||||
|
@ -174,32 +277,16 @@ pub fn delete_ssb_admin_id(ssb_id: &str) -> Result<PeachConfig, PeachError> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn set_admin_password_hash(password_hash: &str) -> Result<PeachConfig, PeachError> {
|
||||
let mut peach_config = load_peach_config()?;
|
||||
peach_config.admin_password_hash = password_hash.to_string();
|
||||
save_peach_config(peach_config)
|
||||
// looks up the String value for SSB_ADMIN_IDS and converts it into a Vec<String>
|
||||
pub fn get_ssb_admin_ids() -> Result<Vec<String>, PeachError> {
|
||||
let ssb_admin_ids_str = get_config_value("SSB_ADMIN_IDS")?;
|
||||
let ssb_admin_ids: Vec<String> = serde_json::from_str(&ssb_admin_ids_str)?;
|
||||
Ok(ssb_admin_ids)
|
||||
}
|
||||
|
||||
pub fn get_admin_password_hash() -> Result<String, PeachError> {
|
||||
let peach_config = load_peach_config()?;
|
||||
if !peach_config.admin_password_hash.is_empty() {
|
||||
Ok(peach_config.admin_password_hash)
|
||||
} else {
|
||||
Err(PeachError::PasswordNotSet)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_temporary_password_hash(password_hash: &str) -> Result<PeachConfig, PeachError> {
|
||||
let mut peach_config = load_peach_config()?;
|
||||
peach_config.temporary_password_hash = password_hash.to_string();
|
||||
save_peach_config(peach_config)
|
||||
}
|
||||
|
||||
pub fn get_temporary_password_hash() -> Result<String, PeachError> {
|
||||
let peach_config = load_peach_config()?;
|
||||
if !peach_config.temporary_password_hash.is_empty() {
|
||||
Ok(peach_config.temporary_password_hash)
|
||||
} else {
|
||||
Err(PeachError::PasswordNotSet)
|
||||
}
|
||||
// takes in a Vec<String> and saves SSB_ADMIN_IDS as a json string representation of this vec
|
||||
pub fn save_ssb_admin_ids(ssb_admin_ids: Vec<String>) -> Result<Vec<String>, PeachError> {
|
||||
let ssb_admin_ids_as_json_str = serde_json::to_string(&ssb_admin_ids)?;
|
||||
save_config_value("SSB_ADMIN_IDS", &ssb_admin_ids_as_json_str)?;
|
||||
Ok(ssb_admin_ids)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,9 @@ use jsonrpc_client_http::HttpTransport;
|
|||
use log::{debug, info};
|
||||
use regex::Regex;
|
||||
|
||||
use crate::config_manager::get_dyndns_server_address;
|
||||
use crate::config_manager::{
|
||||
get_config_value, get_dyndns_enabled_value, get_dyndns_server_address,
|
||||
};
|
||||
use crate::{config_manager, error::PeachError};
|
||||
|
||||
/// constants for dyndns configuration
|
||||
|
@ -107,7 +109,11 @@ fn get_public_ip_address() -> Result<String, PeachError> {
|
|||
/// Reads dyndns configurations from config.yml
|
||||
/// and then uses nsupdate to update the IP address for the configured domain
|
||||
pub fn dyndns_update_ip() -> Result<bool, PeachError> {
|
||||
let peach_config = config_manager::load_peach_config()?;
|
||||
let dyn_tsig_key_path = get_config_value("DYN_TSIG_KEY_PATH")?;
|
||||
let dyn_enabled = get_dyndns_enabled_value()?;
|
||||
let dyn_domain = get_config_value("DYN_DOMAIN")?;
|
||||
let dyn_dns_server_address = get_config_value("DYN_DNS_SERVER_ADDRESS")?;
|
||||
let dyn_nameserver = get_config_value("DYN_NAMESERVER")?;
|
||||
info!(
|
||||
"Using config:
|
||||
dyn_tsig_key_path: {:?}
|
||||
|
@ -116,22 +122,15 @@ pub fn dyndns_update_ip() -> Result<bool, PeachError> {
|
|||
dyn_enabled: {:?}
|
||||
dyn_nameserver: {:?}
|
||||
",
|
||||
peach_config.dyn_tsig_key_path,
|
||||
peach_config.dyn_domain,
|
||||
peach_config.dyn_dns_server_address,
|
||||
peach_config.dyn_enabled,
|
||||
peach_config.dyn_nameserver,
|
||||
dyn_tsig_key_path, dyn_domain, dyn_dns_server_address, dyn_enabled, dyn_nameserver,
|
||||
);
|
||||
if !peach_config.dyn_enabled {
|
||||
if !dyn_enabled {
|
||||
info!("dyndns is not enabled, not updating");
|
||||
Ok(false)
|
||||
} else {
|
||||
// call nsupdate passing appropriate configs
|
||||
let mut nsupdate_command = Command::new("nsupdate");
|
||||
nsupdate_command
|
||||
.arg("-k")
|
||||
.arg(&peach_config.dyn_tsig_key_path)
|
||||
.arg("-v");
|
||||
nsupdate_command.arg("-k").arg(&dyn_tsig_key_path).arg("-v");
|
||||
// pass nsupdate commands via stdin
|
||||
let public_ip_address = get_public_ip_address()?;
|
||||
info!("found public ip address: {}", public_ip_address);
|
||||
|
@ -142,9 +141,9 @@ pub fn dyndns_update_ip() -> Result<bool, PeachError> {
|
|||
update delete {DOMAIN} A
|
||||
update add {DOMAIN} 30 A {PUBLIC_IP_ADDRESS}
|
||||
send",
|
||||
NAMESERVER = peach_config.dyn_nameserver,
|
||||
ZONE = peach_config.dyn_domain,
|
||||
DOMAIN = peach_config.dyn_domain,
|
||||
NAMESERVER = dyn_nameserver,
|
||||
ZONE = dyn_domain,
|
||||
DOMAIN = dyn_domain,
|
||||
PUBLIC_IP_ADDRESS = public_ip_address,
|
||||
);
|
||||
info!("ns_commands: {:?}", ns_commands);
|
||||
|
@ -217,8 +216,7 @@ pub fn get_num_seconds_since_successful_dns_update() -> Result<Option<i64>, Peac
|
|||
/// and has successfully run recently (in the last six minutes)
|
||||
pub fn is_dns_updater_online() -> Result<bool, PeachError> {
|
||||
// first check if it is enabled in peach-config
|
||||
let peach_config = config_manager::load_peach_config()?;
|
||||
let is_enabled = peach_config.dyn_enabled;
|
||||
let is_enabled = get_dyndns_enabled_value()?;
|
||||
// then check if it has successfully run within the last 6 minutes (60*6 seconds)
|
||||
let num_seconds_since_successful_update = get_num_seconds_since_successful_dns_update()?;
|
||||
let ran_recently: bool = match num_seconds_since_successful_update {
|
||||
|
@ -248,8 +246,7 @@ pub fn get_dyndns_subdomain(dyndns_full_domain: &str) -> Option<String> {
|
|||
|
||||
// helper function which checks if a dyndns domain is new
|
||||
pub fn check_is_new_dyndns_domain(dyndns_full_domain: &str) -> Result<bool, PeachError> {
|
||||
let peach_config = config_manager::load_peach_config()?;
|
||||
let previous_dyndns_domain = peach_config.dyn_domain;
|
||||
let previous_dyndns_domain = get_config_value("DYN_DOMAIN")?;
|
||||
Ok(dyndns_full_domain != previous_dyndns_domain)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,12 @@ use std::{io, str, string};
|
|||
/// This type represents all possible errors that can occur when interacting with the PeachCloud library.
|
||||
#[derive(Debug)]
|
||||
pub enum PeachError {
|
||||
/// Represents looking up a Config value with a non-existent key
|
||||
InvalidKey {
|
||||
/// the key value which was invalid
|
||||
key: String,
|
||||
},
|
||||
|
||||
/// Represents a failure to determine the path of the user's home directory.
|
||||
HomeDir,
|
||||
|
||||
|
@ -102,6 +108,7 @@ impl std::error::Error for PeachError {
|
|||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match *self {
|
||||
PeachError::HomeDir => None,
|
||||
PeachError::InvalidKey { .. } => None,
|
||||
PeachError::Io(_) => None,
|
||||
PeachError::JsonRpcClientCore(_) => None,
|
||||
PeachError::JsonRpcCore(_) => None,
|
||||
|
@ -130,6 +137,9 @@ impl std::error::Error for PeachError {
|
|||
impl std::fmt::Display for PeachError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match *self {
|
||||
PeachError::InvalidKey { ref key } => {
|
||||
write!(f, "Invalid key in config lookup for key: {}", key)
|
||||
}
|
||||
PeachError::HomeDir => {
|
||||
write!(
|
||||
f,
|
||||
|
|
|
@ -33,7 +33,7 @@ pub fn validate_new_passwords(new_password1: &str, new_password2: &str) -> Resul
|
|||
/// Sets a new password for the admin user
|
||||
pub fn set_new_password(new_password: &str) -> Result<(), PeachError> {
|
||||
let new_password_hash = hash_password(new_password);
|
||||
config_manager::set_admin_password_hash(&new_password_hash)?;
|
||||
config_manager::set_admin_password_hash(new_password_hash)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ pub fn hash_password(password: &str) -> String {
|
|||
/// which can be used to reset the permanent password
|
||||
pub fn set_new_temporary_password(new_password: &str) -> Result<(), PeachError> {
|
||||
let new_password_hash = hash_password(new_password);
|
||||
config_manager::set_temporary_password_hash(&new_password_hash)?;
|
||||
config_manager::set_temporary_password_hash(new_password_hash)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -103,8 +103,8 @@ using this link: http://peach.local/auth/reset",
|
|||
};
|
||||
msg += &remote_link;
|
||||
// finally send the message to the admins
|
||||
let peach_config = config_manager::load_peach_config()?;
|
||||
for ssb_admin_id in peach_config.ssb_admin_ids {
|
||||
let ssb_admin_ids = config_manager::get_ssb_admin_ids()?;
|
||||
for ssb_admin_id in ssb_admin_ids {
|
||||
// use golgi to send a private message on scuttlebutt
|
||||
match task::block_on(publish_private_msg(&msg, &ssb_admin_id)) {
|
||||
Ok(_) => (),
|
||||
|
|
|
@ -26,8 +26,7 @@ use std::{
|
|||
};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use log::{debug, info};
|
||||
use peach_lib::{config_manager, config_manager::YAML_PATH as PEACH_CONFIG};
|
||||
use log::info;
|
||||
|
||||
// crate-local dependencies
|
||||
use config::Config;
|
||||
|
@ -50,18 +49,6 @@ fn main() {
|
|||
// initialize logger
|
||||
env_logger::init();
|
||||
|
||||
// check if /var/lib/peachcloud/config.yml exists
|
||||
if !std::path::Path::new(PEACH_CONFIG).exists() {
|
||||
debug!("PeachCloud configuration file not found; loading default values");
|
||||
// since we're in the intialisation phase, panic if the loading fails
|
||||
let config =
|
||||
config_manager::load_peach_config().expect("peachcloud configuration loading failed");
|
||||
|
||||
debug!("Saving default PeachCloud configuration values to file");
|
||||
// this ensures a config file is created if it does not already exist
|
||||
config_manager::save_peach_config(config).expect("peachcloud configuration saving failed");
|
||||
}
|
||||
|
||||
// set ip address / hostname and port for the webserver
|
||||
// defaults to "127.0.0.1:8000"
|
||||
let addr_and_port = format!("{}:{}", CONFIG.addr, CONFIG.port);
|
||||
|
|
|
@ -13,8 +13,8 @@ pub fn build_template(request: &Request) -> PreEscaped<String> {
|
|||
let (mut flash_name, mut flash_msg) = request.retrieve_flash();
|
||||
|
||||
// attempt to load peachcloud config file
|
||||
let ssb_admins = match config_manager::load_peach_config() {
|
||||
Ok(config) => Some(config.ssb_admin_ids),
|
||||
let ssb_admins = match config_manager::get_ssb_admin_ids() {
|
||||
Ok(ssb_admin_ids) => Some(ssb_admin_ids),
|
||||
// note: this will overwrite any received flash cookie values
|
||||
// TODO: find a way to include the `err` in the flash_msg
|
||||
// currently produces an error because we end up with Some(String)
|
||||
|
|
Loading…
Reference in New Issue