Fixed a bug for updating secrets with the local provider

This commit is contained in:
2025-09-09 17:51:53 -06:00
parent 0514cc2c8d
commit 82e2e33608
2 changed files with 54 additions and 43 deletions
+52 -42
View File
@@ -6,6 +6,7 @@ use zeroize::Zeroize;
use crate::config::Config; use crate::config::Config;
use crate::providers::SecretProvider; use crate::providers::SecretProvider;
use crate::providers::git_sync::{SyncOpts, sync_and_push};
use crate::{ use crate::{
ARGON_M_COST_KIB, ARGON_P, ARGON_T_COST, HEADER, KDF, KEY_LEN, NONCE_LEN, SALT_LEN, VERSION, 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, Key, XChaCha20Poly1305, XNonce,
aead::{Aead, KeyInit, OsRng}, aead::{Aead, KeyInit, OsRng},
}; };
use dialoguer::{theme, Input}; use dialoguer::{Input, theme};
use log::{debug, error}; use log::{debug, error};
use serde::Deserialize; use serde::Deserialize;
use theme::ColorfulTheme; use theme::ColorfulTheme;
use validator::Validate; use validator::Validate;
use crate::providers::git_sync::{sync_and_push, SyncOpts};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LocalProviderConfig { 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; pub struct LocalProvider;
impl SecretProvider for LocalProvider { impl SecretProvider for LocalProvider {
fn name(&self) -> &'static str {
"LocalProvider"
}
fn get_secret(&self, config: &Config, key: &str) -> Result<String> { fn get_secret(&self, config: &Config, key: &str) -> Result<String> {
let vault: HashMap<String, String> = confy::load("gman", "vault").unwrap_or_default(); let vault: HashMap<String, String> = confy::load("gman", "vault").unwrap_or_default();
let envelope = vault let envelope = vault
@@ -72,8 +76,7 @@ impl SecretProvider for LocalProvider {
vault.insert(key.to_string(), envelope); vault.insert(key.to_string(), envelope);
confy::store("gman", "vault", vault) confy::store("gman", "vault", vault).with_context(|| "failed to save secret to the vault")
.with_context(|| "failed to save secret to the vault")
} }
fn update_secret(&self, config: &Config, key: &str, value: &str) -> Result<()> { 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"))?; .with_context(|| format!("key '{key}' not found in the vault"))?;
*vault_entry = envelope; *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); vault.insert(key.to_string(), envelope);
@@ -115,49 +119,55 @@ impl SecretProvider for LocalProvider {
Ok(keys) Ok(keys)
} }
fn sync(&self, config: &mut Config) -> Result<()> { fn sync(&self, config: &mut Config) -> Result<()> {
let mut config_changed = false; let mut config_changed = false;
if config.git_branch.is_none() { if config.git_branch.is_none() {
config_changed = true; config_changed = true;
debug!("Prompting user to set git_branch in config for sync"); debug!("Prompting user to set git_branch in config for sync");
let branch: String = Input::with_theme(&ColorfulTheme::default()) let branch: String = Input::with_theme(&ColorfulTheme::default())
.with_prompt("Enter git branch to sync with") .with_prompt("Enter git branch to sync with")
.default("main".into()) .default("main".into())
.interact_text()?; .interact_text()?;
config.git_branch = Some(branch); config.git_branch = Some(branch);
} }
if config.git_remote_url.is_none() { if config.git_remote_url.is_none() {
config_changed = true; config_changed = true;
debug!("Prompting user to set git_remote in config for sync"); debug!("Prompting user to set git_remote in config for sync");
let remote: String = Input::with_theme(&ColorfulTheme::default()) let remote: String = Input::with_theme(&ColorfulTheme::default())
.with_prompt("Enter remote git URL to sync with") .with_prompt("Enter remote git URL to sync with")
.validate_with(|s: &String| { .validate_with(|s: &String| {
Config { git_remote_url: Some(s.clone()), ..Config::default() }.validate().map(|_| ()) Config {
.map_err(|e| e.to_string()) git_remote_url: Some(s.clone()),
}) ..Config::default()
.interact_text()?; }
.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 { if config_changed {
debug!("Saving updated config"); debug!("Saving updated config");
confy::store("gman", "config", &config).with_context(|| "failed to save updated config")?; confy::store("gman", "config", &config)
} .with_context(|| "failed to save updated config")?;
}
let sync_opts = SyncOpts { let sync_opts = SyncOpts {
remote_url: &config.git_remote_url, remote_url: &config.git_remote_url,
branch: &config.git_branch, branch: &config.git_branch,
user_name: &config.git_user_name, user_name: &config.git_user_name,
user_email: &config.git_user_email, user_email: &config.git_user_email,
git_executable: &config.git_executable git_executable: &config.git_executable,
}; };
sync_and_push(&sync_opts) sync_and_push(&sync_opts)
} }
} }
fn encrypt_string(password: &SecretString, plaintext: &str) -> Result<String> { fn encrypt_string(password: &SecretString, plaintext: &str) -> Result<String> {
+2 -1
View File
@@ -10,6 +10,7 @@ use std::str::FromStr;
use thiserror::Error; use thiserror::Error;
pub trait SecretProvider { pub trait SecretProvider {
fn name(&self) -> &'static str;
fn get_secret(&self, config: &Config, key: &str) -> Result<String>; fn get_secret(&self, config: &Config, key: &str) -> Result<String>;
fn set_secret(&self, config: &Config, key: &str, value: &str) -> Result<()>; fn set_secret(&self, config: &Config, key: &str, value: &str) -> Result<()>;
fn update_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), Unsupported(String),
} }
#[derive(Debug, Clone, Copy, Deserialize)] #[derive(Debug, Clone, Copy, Deserialize, Eq, PartialEq)]
pub enum SupportedProvider { pub enum SupportedProvider {
Local(LocalProvider), Local(LocalProvider),
} }