use std::collections::HashMap; use std::fs; use rust_util::{debugging, opt_result, simple_error, XResult}; use rust_util::util_file::resolve_file_path; use serde::{Deserialize, Serialize}; use crate::spec::TinyEncryptEnvelopType; /// Config file sample: /// ~/.tinyencrypt/config-rs.json /// { /// "envelops": [ /// { /// "type": "pgp", /// "kid": "KID-1", /// "desc": "this is key 001", /// "public_key": "----- BEGIN OPENPGP ..." /// }, /// { /// "type": "ecdh", /// "kid": "KID-2", /// "desc": "this is key 002", /// "publicPart": "04..." /// } /// ], /// "profiles": { /// "default": ["KID-1", "KID-2", "type:pgp"], /// "leve2": ["KID-2"] /// } /// } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TinyEncryptConfig { pub envelops: Vec, pub profiles: HashMap>, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TinyEncryptConfigEnvelop { pub r#type: TinyEncryptEnvelopType, pub kid: String, pub desc: Option, pub public_part: String, } impl TinyEncryptConfig { pub fn load(file: &str) -> XResult { let resolved_file = resolve_file_path(file); let config_contents = opt_result!(fs::read_to_string(&resolved_file), "Read file: {}, failed: {}", file); // TODO replace with Human JSON Ok(opt_result!(serde_json::from_str(&config_contents), "Parse file: {}, failed: {}", file)) } pub fn find_envelops(&self, profile: &Option) -> XResult> { let profile = profile.as_ref().map(String::as_str).unwrap_or("default"); debugging!("Profile: {}", profile); let mut matched_envelops_map = HashMap::new(); if let Some(key_ids) = self.profiles.get(profile) { if key_ids.is_empty() { return simple_error!("Profile: {} contains no valid envelopes", profile); } for key_id in key_ids { self.envelops.iter().for_each(|envelop| { let is_matched = (&envelop.kid == key_id) || key_id == &format!("type:{}", &envelop.r#type.get_name()); if is_matched { matched_envelops_map.insert(&envelop.kid, envelop); } }); } } let envelops: Vec<_> = matched_envelops_map.values().map(|envelop| *envelop).collect(); if envelops.is_empty() { return simple_error!("Profile: {} has no valid envelopes found", profile); } debugging!("Found envelopes: {:#?}", envelops); Ok(envelops) } }