use crate::config::{ConfigPatch, SecretConfigPatch};
use crate::encrypt_utils::Encrypter;
use serde::{de::DeserializeOwned, Serialize};
use std::collections::HashMap;
pub trait Source {
type Value: Serialize + DeserializeOwned;
type Map: IntoIterator<Item = (String, Self::Value)>;
fn collect(&self) -> Result<Self::Map, Box<dyn std::error::Error>>;
fn upgrade(&self, key: impl AsRef<str>, new_value: &Self::Value) -> ConfigPatch {
let key = key.as_ref().to_owned();
let serded = serde_json::to_vec(&new_value).unwrap();
let func = Box::new(move || Ok((key, serded)));
ConfigPatch::new(func)
}
}
pub trait PersistSource {
type Value: Serialize + DeserializeOwned;
#[cfg(feature = "default_config_dir")]
fn source_name(&self) -> String;
#[cfg(feature = "default_config_dir")]
fn path(&self) -> std::path::PathBuf {
dirs_next::config_dir()
.expect("Default config dir unknown, please turn off feature `default_config_dir`")
.join(self.source_name())
}
fn default(&self) -> HashMap<String, Self::Value> {
HashMap::new()
}
#[cfg(not(feature = "default_config_dir"))]
fn path(&self) -> std::path::PathBuf;
fn collect(&self) -> HashMap<String, Vec<u8>> {
match std::fs::read(self.path()) {
Ok(serded) => serde_json::from_slice(&serded).unwrap(),
Err(_) => self
.default()
.into_iter()
.map(|(k, v)| (k, serde_json::to_vec(&v).unwrap()))
.collect(),
}
}
fn upgrade(&self, key: impl AsRef<str>, new_value: &Self::Value) -> ConfigPatch {
let key = key.as_ref().to_owned();
let path = self.path();
let serded = serde_json::to_vec(new_value).unwrap();
let mut config = self.collect();
let func = Box::new(move || {
config.insert(key.clone(), serded.clone());
std::fs::write(path, serde_json::to_vec(&config).unwrap())?;
Ok((key, serded))
});
ConfigPatch::new(func)
}
}
pub trait SecretSource {
type Value: Serialize + DeserializeOwned;
#[cfg(feature = "default_config_dir")]
fn source_name(&self) -> String;
#[cfg(feature = "default_config_dir")]
fn path(&self) -> std::path::PathBuf {
dirs_next::config_dir()
.expect("Default config dir unknown, please turn off feature `default_config_dir`")
.join(self.source_name())
}
#[cfg(not(feature = "default_config_dir"))]
fn path(&self) -> std::path::PathBuf;
#[cfg(not(feature = "default_config"))]
fn default(&self) -> HashMap<String, Self::Value> {
HashMap::new()
}
fn collect(&self, encrypter: &Encrypter) -> HashMap<String, Vec<u8>> {
match std::fs::read(self.path()) {
Ok(encrypted) => {
serde_json::from_slice(&encrypter.decrypt(&encrypted).unwrap()).unwrap()
}
Err(_) => self
.default()
.into_iter()
.map(|(k, v)| (k, serde_json::to_vec(&v).unwrap()))
.collect(),
}
}
fn upgrade(&self, key: impl AsRef<str>, new_value: &Self::Value) -> SecretConfigPatch {
let key = key.as_ref().to_owned();
let path = self.path();
let serded = serde_json::to_vec(new_value).unwrap();
let func = Box::new(move |encrypter: &Encrypter| {
let mut decrtpted: HashMap<String, Vec<u8>> = match std::fs::read(&path) {
Ok(encrypted) => serde_json::from_slice(&encrypter.decrypt(&encrypted)?).unwrap(),
Err(_) => HashMap::new(),
};
decrtpted.insert(key.clone(), serded.clone());
let encrypted = encrypter.encrypt(&decrtpted)?;
std::fs::write(path, encrypted)?;
Ok((key, serded))
});
SecretConfigPatch::new(func)
}
}