deadbolt_parser/
config.rs

1use std::{
2    env,
3    error::Error,
4    fs::{self, OpenOptions},
5    io::{Read, Write},
6    path::Path,
7};
8
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
12pub struct KdfObject {
13    pub algorithm: String,
14    pub parameters: Option<KdfParams>,
15}
16
17#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
18pub struct KdfParams {
19    pub iterations: u8,
20    pub threads: u8,
21    pub memory: u32,
22}
23
24impl Default for KdfParams {
25    fn default() -> Self {
26        // Default Argon2 params
27        // According to rfc9106 Sect. 4 - 2nd recommendation
28        // https://www.rfc-editor.org/rfc/rfc9106.html#section-4
29        KdfParams {
30            iterations: 3,
31            threads: 4,
32            memory: 64 * 1024,
33        }
34    }
35}
36
37#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
38pub struct GeneratorConfig {
39    pub length: u8,
40    pub punctuation: bool,
41}
42
43impl Default for GeneratorConfig {
44    fn default() -> Self {
45        GeneratorConfig {
46            length: 18,
47            punctuation: true,
48        }
49    }
50}
51
52#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
53pub struct AlgorithmConfig {
54    pub encryption: String,
55    pub hash: String,
56    pub kdf: KdfObject,
57    pub compression: bool,
58}
59
60#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
61pub struct Config {
62    pub db_path: String,
63    pub algorithms: AlgorithmConfig,
64    pub generator: GeneratorConfig,
65    pub lock_timeout: u32,
66    pub debug_mode: bool,
67}
68
69pub fn default_config() -> Config {
70    let mut default_path = home::home_dir().unwrap_or_else(env::temp_dir);
71    default_path.push(".deadbolt");
72    default_path.push("database.dblt");
73
74    Config {
75        db_path: default_path.to_string_lossy().to_string(),
76        algorithms: AlgorithmConfig {
77            encryption: "aes-gcm".to_string(),
78            hash: "sha-256".to_string(),
79            kdf: KdfObject {
80                algorithm: "argon2d".to_string(),
81                parameters: Some(KdfParams::default()),
82            },
83            compression: true,
84        },
85        generator: GeneratorConfig::default(),
86        lock_timeout: 600,
87        debug_mode: false,
88    }
89}
90
91pub fn get_config(path: &str) -> Result<Config, Box<dyn Error>> {
92    let mut file = OpenOptions::new().read(true).open(path)?;
93    let mut buf: String = Default::default();
94    file.read_to_string(&mut buf)?;
95
96    let value: Config = serde_yaml::from_str(&buf)?;
97    Ok(value)
98}
99
100pub fn set_config(path: &str, config: &Config) -> Result<(), Box<dyn Error>> {
101    let yaml = serde_yaml::to_string(&config)?;
102    // Create parent folder(s) if not exist
103    let parent = Path::new(path).parent();
104    if let Some(parent_dir) = parent {
105        fs::create_dir_all(parent_dir)?;
106    }
107
108    let mut file = OpenOptions::new()
109        .write(true)
110        .create(true)
111        .truncate(true)
112        .open(path)?;
113
114    file.write_all(yaml.as_bytes())?;
115    Ok(())
116}