feat: Support entering custom keys value via STDIN

This for adding new key, and editing keys (Change the key value)

Fixes: #56
Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
Awiteb 2024-08-17 14:52:14 +00:00
parent 2f0531fbc9
commit 4028607cb5
Signed by: awiteb
GPG key ID: 3F6B55640AA6682F
2 changed files with 28 additions and 16 deletions

View file

@ -39,9 +39,11 @@ pub struct Add {
#[allow(clippy::option_option)] #[allow(clippy::option_option)]
totp_secret: Option<Option<String>>, totp_secret: Option<Option<String>>,
/// Add a custom field to the vault /// Add a custom field to the vault
#[arg(name = "KEY=VALUE", short = 'c', long = "custom")] ///
/// If there is no value, you will enter it through a prompt
#[arg(name = "KEY(=VALUE)?", short = 'c', long = "custom")]
#[arg(value_parser = clap_parsers::kv_parser)] #[arg(value_parser = clap_parsers::kv_parser)]
custom_fields: Vec<(String, String)>, custom_fields: Vec<(String, Option<String>)>,
/// Force add, will not return error if there is a problem with the args. /// Force add, will not return error if there is a problem with the args.
/// ///
/// For example, duplication in the custom fields and try to adding empty /// For example, duplication in the custom fields and try to adding empty
@ -73,7 +75,9 @@ impl LprsCommand for Add {
self.vault_info.name = self.vault_info.name.trim().to_string(); self.vault_info.name = self.vault_info.name.trim().to_string();
self.vault_info.password = utils::user_secret(self.password, "Vault password:", false)?; self.vault_info.password = utils::user_secret(self.password, "Vault password:", false)?;
self.vault_info.custom_fields = self.custom_fields.into_iter().collect(); self.vault_info.custom_fields = utils::prompt_custom(self.custom_fields)?
.into_iter()
.collect();
vault_manager.add_vault(self.vault_info); vault_manager.add_vault(self.vault_info);
vault_manager.try_export()?; vault_manager.try_export()?;
} }
@ -95,23 +99,23 @@ impl LprsCommand for Add {
if self if self
.password .password
.as_ref() .as_ref()
.is_some_and(|p| p.as_ref().is_some_and(|p| p.is_empty())) .is_some_and(|p| p.as_ref().is_some_and(String::is_empty))
|| self.vault_info.name.is_empty() || self.vault_info.name.is_empty()
|| self || self
.vault_info .vault_info
.username .username
.as_ref() .as_ref()
.is_some_and(|u| u.is_empty()) .is_some_and(String::is_empty)
|| self || self
.vault_info .vault_info
.service .service
.as_ref() .as_ref()
.is_some_and(|s| s.is_empty()) .is_some_and(String::is_empty)
|| self.vault_info.note.as_ref().is_some_and(|n| n.is_empty()) || self.vault_info.note.as_ref().is_some_and(String::is_empty)
|| self || self
.custom_fields .custom_fields
.iter() .iter()
.any(|(k, v)| k.is_empty() || v.is_empty()) .any(|(k, v)| k.is_empty() || v.as_ref().is_some_and(String::is_empty))
{ {
return Err(LprsError::EmptyValue); return Err(LprsError::EmptyValue);
} }

View file

@ -36,28 +36,33 @@ pub struct Edit {
/// The new vault name /// The new vault name
name: Option<String>, name: Option<String>,
#[arg(short, long)] #[arg(short, long)]
/// The new vault username /// The new vault username, make it empty string to delete it
username: Option<String>, username: Option<String>,
#[arg(short, long)] #[arg(short, long)]
/// The new password, if there is no value for it you will prompt it /// The new password, make it empty string to delete it
///
/// If there is no value for it you will prompt it
#[allow(clippy::option_option)] #[allow(clippy::option_option)]
password: Option<Option<String>>, password: Option<Option<String>>,
#[arg(short, long)] #[arg(short, long)]
/// The new vault service /// The new vault service, make it empty string to delete it
service: Option<String>, service: Option<String>,
#[arg(short = 'o', long)] #[arg(short = 'o', long)]
/// The new vault note /// The new vault note
note: Option<String>, note: Option<String>,
/// The TOTP secret, if there is no value you will prompt it /// The TOTP secret, make it empty string to delete it
///
/// If there is no value you will prompt it
#[arg(short, long)] #[arg(short, long)]
#[allow(clippy::option_option)] #[allow(clippy::option_option)]
totp_secret: Option<Option<String>>, totp_secret: Option<Option<String>>,
/// The custom field, make its value empty to delete it /// The custom field, make it empty string to delete it
/// ///
/// If the custom field not exist will created it, if it's will update it /// If the custom field not exist will created it, if it's will update it,
/// if there is no value, you will enter it through a prompt (e.g `-c key`)
#[arg(name = "KEY=VALUE", short = 'c', long = "custom")] #[arg(name = "KEY=VALUE", short = 'c', long = "custom")]
#[arg(value_parser = clap_parsers::kv_parser)] #[arg(value_parser = clap_parsers::kv_parser)]
custom_fields: Vec<(String, String)>, custom_fields: Vec<(String, Option<String>)>,
/// Force edit, will not return error if there is a problem with the args. /// Force edit, will not return error if there is a problem with the args.
/// ///
/// For example, duplication in the custom fields and try to editing nothing /// For example, duplication in the custom fields and try to editing nothing
@ -120,7 +125,10 @@ impl LprsCommand for Edit {
vault.note = Some(new_note); vault.note = Some(new_note);
} }
} }
utils::apply_custom_fields(&mut vault.custom_fields, self.custom_fields); utils::apply_custom_fields(
&mut vault.custom_fields,
utils::prompt_custom(self.custom_fields)?,
);
vault_manager.try_export() vault_manager.try_export()
} }