diff --git a/src/providers/local.rs b/src/providers/local.rs index fd0128c..b7404d3 100644 --- a/src/providers/local.rs +++ b/src/providers/local.rs @@ -6,6 +6,7 @@ use zeroize::Zeroize; use crate::config::Config; use crate::providers::SecretProvider; +use crate::providers::git_sync::{SyncOpts, sync_and_push}; use crate::{ ARGON_M_COST_KIB, ARGON_P, ARGON_T_COST, HEADER, KDF, KEY_LEN, NONCE_LEN, SALT_LEN, VERSION, }; @@ -17,12 +18,11 @@ use chacha20poly1305::{ Key, XChaCha20Poly1305, XNonce, aead::{Aead, KeyInit, OsRng}, }; -use dialoguer::{theme, Input}; +use dialoguer::{Input, theme}; use log::{debug, error}; use serde::Deserialize; use theme::ColorfulTheme; use validator::Validate; -use crate::providers::git_sync::{sync_and_push, SyncOpts}; #[derive(Debug, Clone)] pub struct LocalProviderConfig { @@ -40,10 +40,14 @@ impl Default for LocalProviderConfig { } } -#[derive(Debug, Clone, Copy, Default, Deserialize)] +#[derive(Debug, Clone, Copy, Default, Deserialize, PartialEq, Eq)] pub struct LocalProvider; impl SecretProvider for LocalProvider { + fn name(&self) -> &'static str { + "LocalProvider" + } + fn get_secret(&self, config: &Config, key: &str) -> Result { let vault: HashMap = confy::load("gman", "vault").unwrap_or_default(); let envelope = vault @@ -72,8 +76,7 @@ impl SecretProvider for LocalProvider { vault.insert(key.to_string(), envelope); - confy::store("gman", "vault", vault) - .with_context(|| "failed to save secret to the vault") + confy::store("gman", "vault", vault).with_context(|| "failed to save secret to the vault") } fn update_secret(&self, config: &Config, key: &str, value: &str) -> Result<()> { @@ -90,7 +93,8 @@ impl SecretProvider for LocalProvider { .with_context(|| format!("key '{key}' not found in the vault"))?; *vault_entry = envelope; - return Ok(()); + return confy::store("gman", "vault", vault) + .with_context(|| "failed to save secret to the vault"); } vault.insert(key.to_string(), envelope); @@ -115,49 +119,55 @@ impl SecretProvider for LocalProvider { Ok(keys) } - fn sync(&self, config: &mut Config) -> Result<()> { - let mut config_changed = false; + fn sync(&self, config: &mut Config) -> Result<()> { + let mut config_changed = false; - if config.git_branch.is_none() { - config_changed = true; - debug!("Prompting user to set git_branch in config for sync"); - let branch: String = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Enter git branch to sync with") - .default("main".into()) - .interact_text()?; + if config.git_branch.is_none() { + config_changed = true; + debug!("Prompting user to set git_branch in config for sync"); + let branch: String = Input::with_theme(&ColorfulTheme::default()) + .with_prompt("Enter git branch to sync with") + .default("main".into()) + .interact_text()?; - config.git_branch = Some(branch); - } + config.git_branch = Some(branch); + } - if config.git_remote_url.is_none() { - config_changed = true; - debug!("Prompting user to set git_remote in config for sync"); - let remote: String = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Enter remote git URL to sync with") - .validate_with(|s: &String| { - Config { git_remote_url: Some(s.clone()), ..Config::default() }.validate().map(|_| ()) - .map_err(|e| e.to_string()) - }) - .interact_text()?; + if config.git_remote_url.is_none() { + config_changed = true; + debug!("Prompting user to set git_remote in config for sync"); + let remote: String = Input::with_theme(&ColorfulTheme::default()) + .with_prompt("Enter remote git URL to sync with") + .validate_with(|s: &String| { + Config { + git_remote_url: Some(s.clone()), + ..Config::default() + } + .validate() + .map(|_| ()) + .map_err(|e| e.to_string()) + }) + .interact_text()?; - config.git_remote_url = Some(remote); - } + config.git_remote_url = Some(remote); + } - if config_changed { - debug!("Saving updated config"); - confy::store("gman", "config", &config).with_context(|| "failed to save updated config")?; - } + if config_changed { + debug!("Saving updated config"); + confy::store("gman", "config", &config) + .with_context(|| "failed to save updated config")?; + } - let sync_opts = SyncOpts { - remote_url: &config.git_remote_url, - branch: &config.git_branch, - user_name: &config.git_user_name, - user_email: &config.git_user_email, - git_executable: &config.git_executable - }; + let sync_opts = SyncOpts { + remote_url: &config.git_remote_url, + branch: &config.git_branch, + user_name: &config.git_user_name, + user_email: &config.git_user_email, + git_executable: &config.git_executable, + }; - sync_and_push(&sync_opts) - } + sync_and_push(&sync_opts) + } } fn encrypt_string(password: &SecretString, plaintext: &str) -> Result { diff --git a/src/providers/mod.rs b/src/providers/mod.rs index 560d14a..96f9bf9 100644 --- a/src/providers/mod.rs +++ b/src/providers/mod.rs @@ -10,6 +10,7 @@ use std::str::FromStr; use thiserror::Error; pub trait SecretProvider { + fn name(&self) -> &'static str; fn get_secret(&self, config: &Config, key: &str) -> Result; fn set_secret(&self, config: &Config, key: &str, value: &str) -> Result<()>; fn update_secret(&self, config: &Config, key: &str, value: &str) -> Result<()>; @@ -24,7 +25,7 @@ pub enum ParseProviderError { Unsupported(String), } -#[derive(Debug, Clone, Copy, Deserialize)] +#[derive(Debug, Clone, Copy, Deserialize, Eq, PartialEq)] pub enum SupportedProvider { Local(LocalProvider), }