feat: Support export and import with different password #30
3 changed files with 33 additions and 39 deletions
|
@ -15,9 +15,9 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||
|
||||
use clap::Args;
|
||||
use inquire::{Password, PasswordDisplayMode};
|
||||
|
||||
use crate::{
|
||||
utils,
|
||||
vault::{Vault, Vaults},
|
||||
LprsCommand,
|
||||
LprsError,
|
||||
|
@ -32,31 +32,13 @@ pub struct Add {
|
|||
vault_info: Vault,
|
||||
/// The password, if there is no value for it you will prompt it
|
||||
#[arg(short, long)]
|
||||
// FIXME: I think replacing `Option<Option<String>>` with custom type will be better
|
||||
#[allow(clippy::option_option)]
|
||||
password: Option<Option<String>>,
|
||||
}
|
||||
|
||||
impl LprsCommand for Add {
|
||||
fn run(mut self, mut vault_manager: Vaults) -> LprsResult<()> {
|
||||
match self.password {
|
||||
Some(Some(password)) => {
|
||||
log::debug!("User provided a password");
|
||||
self.vault_info.password = Some(password);
|
||||
}
|
||||
Some(None) => {
|
||||
log::debug!("User didn't provide a password, prompting it");
|
||||
self.vault_info.password = Some(
|
||||
Password::new("Vault password:")
|
||||
.without_confirmation()
|
||||
.with_formatter(&|p| "*".repeat(p.chars().count()))
|
||||
.with_display_mode(PasswordDisplayMode::Masked)
|
||||
.prompt()?,
|
||||
);
|
||||
}
|
||||
None => {}
|
||||
};
|
||||
|
||||
self.vault_info.password = utils::user_password(self.password)?;
|
||||
vault_manager.add_vault(self.vault_info);
|
||||
vault_manager.try_export()
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
use std::num::NonZeroU64;
|
||||
|
||||
use clap::Args;
|
||||
use inquire::{Password, PasswordDisplayMode};
|
||||
|
||||
use crate::{
|
||||
utils,
|
||||
vault::{Vault, Vaults},
|
||||
LprsCommand,
|
||||
LprsError,
|
||||
|
@ -41,7 +41,6 @@ pub struct Edit {
|
|||
username: Option<String>,
|
||||
#[arg(short, long)]
|
||||
/// The new password, if there is no value for it you will prompt it
|
||||
// FIXME: I think replacing `Option<Option<String>>` with custom type will be better
|
||||
#[allow(clippy::option_option)]
|
||||
password: Option<Option<String>>,
|
||||
#[arg(short, long)]
|
||||
|
@ -65,26 +64,13 @@ impl LprsCommand for Edit {
|
|||
)));
|
||||
};
|
||||
|
||||
// Get the password from stdin or from its value if provided
|
||||
let password = match self.password {
|
||||
Some(Some(password)) => Some(password),
|
||||
Some(None) => {
|
||||
Some(
|
||||
Password::new("New vault password:")
|
||||
.without_confirmation()
|
||||
.with_formatter(&|p| "*".repeat(p.chars().count()))
|
||||
.with_display_mode(PasswordDisplayMode::Masked)
|
||||
.prompt()?,
|
||||
)
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
log::info!("Applying the new values to the vault");
|
||||
*vault = Vault::new(
|
||||
self.name.as_ref().unwrap_or(&vault.name),
|
||||
self.username.as_ref().or(vault.username.as_ref()),
|
||||
password.as_ref().or(vault.password.as_ref()),
|
||||
utils::user_password(self.password)?
|
||||
.as_ref()
|
||||
.or(vault.password.as_ref()),
|
||||
self.service.as_ref().or(vault.service.as_ref()),
|
||||
self.note.as_ref().or(vault.note.as_ref()),
|
||||
);
|
||||
|
|
28
src/utils.rs
28
src/utils.rs
|
@ -16,7 +16,7 @@
|
|||
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
use inquire::{validator::Validation, PasswordDisplayMode};
|
||||
use inquire::{validator::Validation, Password, PasswordDisplayMode};
|
||||
use passwords::{analyzer, scorer};
|
||||
#[cfg(feature = "update-notify")]
|
||||
use reqwest::blocking::Client as BlockingClient;
|
||||
|
@ -43,6 +43,32 @@ pub fn local_project_file(filename: &str) -> LprsResult<PathBuf> {
|
|||
Ok(local_dir.join(filename))
|
||||
}
|
||||
|
||||
/// Returns the user password if any
|
||||
///
|
||||
/// - If the `password` is `None` will return `None`
|
||||
/// - If the `password` is `Some(None)` will ask the user for a password in the
|
||||
/// stdin and return it
|
||||
/// - If the `password` is `Some(Some(password))` will return `Some(password)`
|
||||
///
|
||||
/// ## Errors
|
||||
/// - When failed to get the password from stdin
|
||||
pub fn user_password(password: Option<Option<String>>) -> LprsResult<Option<String>> {
|
||||
Ok(match password {
|
||||
None => None,
|
||||
Some(Some(p)) => Some(p),
|
||||
Some(None) => {
|
||||
log::debug!("User didn't provide a password, prompting it");
|
||||
Some(
|
||||
Password::new("Vault password:")
|
||||
.without_confirmation()
|
||||
.with_formatter(&|p| "*".repeat(p.chars().count()))
|
||||
.with_display_mode(PasswordDisplayMode::Masked)
|
||||
.prompt()?,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the default vaults json file
|
||||
///
|
||||
/// ## Errors
|
||||
|
|
Loading…
Reference in a new issue