use std::{
env,
error::Error,
fs::{self, OpenOptions},
io::{Read, Write},
path::Path,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct KdfObject {
pub algorithm: String,
pub parameters: Option<KdfParams>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct KdfParams {
pub iterations: u8,
pub threads: u8,
pub memory: u32,
}
impl Default for KdfParams {
fn default() -> Self {
KdfParams {
iterations: 3,
threads: 4,
memory: 64 * 1024,
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct GeneratorConfig {
pub length: u8,
pub punctuation: bool,
}
impl Default for GeneratorConfig {
fn default() -> Self {
GeneratorConfig {
length: 18,
punctuation: true,
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct AlgorithmConfig {
pub encryption: String,
pub hash: String,
pub kdf: KdfObject,
pub compression: bool,
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
pub struct Config {
pub db_path: String,
pub algorithms: AlgorithmConfig,
pub generator: GeneratorConfig,
pub lock_timeout: u32,
pub debug_mode: bool,
}
pub fn default_config() -> Config {
let mut default_path = home::home_dir().unwrap_or_else(env::temp_dir);
default_path.push(".deadbolt");
default_path.push("database.dblt");
Config {
db_path: default_path.to_string_lossy().to_string(),
algorithms: AlgorithmConfig {
encryption: "aes-gcm".to_string(),
hash: "sha-256".to_string(),
kdf: KdfObject {
algorithm: "argon2d".to_string(),
parameters: Some(KdfParams::default()),
},
compression: true,
},
generator: GeneratorConfig::default(),
lock_timeout: 600,
debug_mode: false,
}
}
pub fn get_config(path: &str) -> Result<Config, Box<dyn Error>> {
let mut file = OpenOptions::new().read(true).open(path)?;
let mut buf: String = Default::default();
file.read_to_string(&mut buf)?;
let value: Config = serde_yaml::from_str(&buf)?;
Ok(value)
}
pub fn set_config(path: &str, config: &Config) -> Result<(), Box<dyn Error>> {
let yaml = serde_yaml::to_string(&config)?;
let parent = Path::new(path).parent();
if let Some(parent_dir) = parent {
fs::create_dir_all(parent_dir)?;
}
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(path)?;
file.write_all(yaml.as_bytes())?;
Ok(())
}