Compare commits
4 commits
9b39da877f
...
dbaa518855
Author | SHA1 | Date | |
---|---|---|---|
dbaa518855 | |||
e033971665 | |||
aee33f819c | |||
ad3dc025a9 |
4 changed files with 45 additions and 34 deletions
|
@ -75,7 +75,7 @@ pub struct Edit {
|
||||||
|
|
||||||
impl LprsCommand for Edit {
|
impl LprsCommand for Edit {
|
||||||
fn run(self, mut vault_manager: Vaults) -> LprsResult<()> {
|
fn run(self, mut vault_manager: Vaults) -> LprsResult<()> {
|
||||||
let vault = match utils::vault_by_index_or_name(self.location, &mut vault_manager.vaults) {
|
let vault = match utils::vault_by_index_or_name(&self.location, &mut vault_manager.vaults) {
|
||||||
Ok((_, v)) => v,
|
Ok((_, v)) => v,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
if self.force {
|
if self.force {
|
||||||
|
|
|
@ -112,7 +112,7 @@ pub struct Get {
|
||||||
impl LprsCommand for Get {
|
impl LprsCommand for Get {
|
||||||
fn run(self, mut vault_manager: Vaults) -> LprsResult<()> {
|
fn run(self, mut vault_manager: Vaults) -> LprsResult<()> {
|
||||||
let (index, vault) =
|
let (index, vault) =
|
||||||
utils::vault_by_index_or_name(self.location, &mut vault_manager.vaults)?;
|
utils::vault_by_index_or_name(&self.location, &mut vault_manager.vaults)?;
|
||||||
|
|
||||||
if let Some(field) = self.field {
|
if let Some(field) = self.field {
|
||||||
if field == VaultGetField::Index {
|
if field == VaultGetField::Index {
|
||||||
|
|
73
src/utils.rs
73
src/utils.rs
|
@ -19,7 +19,11 @@ use std::num::NonZeroUsize;
|
||||||
use std::{fs, path::PathBuf};
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use inquire::{validator::Validation, Password, PasswordDisplayMode};
|
use inquire::{
|
||||||
|
validator::{StringValidator, Validation},
|
||||||
|
Password,
|
||||||
|
PasswordDisplayMode,
|
||||||
|
};
|
||||||
use passwords::{analyzer, scorer};
|
use passwords::{analyzer, scorer};
|
||||||
#[cfg(feature = "update-notify")]
|
#[cfg(feature = "update-notify")]
|
||||||
use reqwest::blocking::Client as BlockingClient;
|
use reqwest::blocking::Client as BlockingClient;
|
||||||
|
@ -47,6 +51,26 @@ pub fn local_project_file(filename: &str) -> LprsResult<PathBuf> {
|
||||||
Ok(local_dir.join(filename))
|
Ok(local_dir.join(filename))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ask the user for a secret in the stdin
|
||||||
|
///
|
||||||
|
/// ## Errors
|
||||||
|
/// - If can't read the user input
|
||||||
|
fn secret_prompt(
|
||||||
|
prompt_message: &str,
|
||||||
|
confirmation: bool,
|
||||||
|
validators: Option<Vec<Box<dyn StringValidator>>>,
|
||||||
|
) -> LprsResult<String> {
|
||||||
|
Password {
|
||||||
|
validators: validators.unwrap_or_default(),
|
||||||
|
enable_confirmation: confirmation,
|
||||||
|
..Password::new(prompt_message)
|
||||||
|
.with_formatter(&|p| "*".repeat(p.chars().count()))
|
||||||
|
.with_display_mode(PasswordDisplayMode::Masked)
|
||||||
|
}
|
||||||
|
.prompt()
|
||||||
|
.map_err(LprsError::Inquire)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the user secret if any
|
/// Returns the user secret if any
|
||||||
///
|
///
|
||||||
/// - If the `secret` is `None` will return `None`
|
/// - If the `secret` is `None` will return `None`
|
||||||
|
@ -66,15 +90,7 @@ pub fn user_secret(
|
||||||
Some(Some(p)) => Some(p),
|
Some(Some(p)) => Some(p),
|
||||||
Some(None) => {
|
Some(None) => {
|
||||||
log::debug!("User didn't provide a secret, prompting it");
|
log::debug!("User didn't provide a secret, prompting it");
|
||||||
Some(
|
Some(secret_prompt(prompt_message, confirmation, None)?)
|
||||||
Password {
|
|
||||||
enable_confirmation: confirmation,
|
|
||||||
..Password::new(prompt_message)
|
|
||||||
.with_formatter(&|p| "*".repeat(p.chars().count()))
|
|
||||||
.with_display_mode(PasswordDisplayMode::Masked)
|
|
||||||
}
|
|
||||||
.prompt()?,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -119,21 +135,12 @@ pub fn password_validator(password: &str) -> Result<Validation, inquire::CustomU
|
||||||
///
|
///
|
||||||
/// Return's the password as 32 bytes after hash it (256 bit)
|
/// Return's the password as 32 bytes after hash it (256 bit)
|
||||||
pub fn master_password_prompt(is_new_vaults_file: bool) -> LprsResult<[u8; 32]> {
|
pub fn master_password_prompt(is_new_vaults_file: bool) -> LprsResult<[u8; 32]> {
|
||||||
inquire::Password {
|
secret_prompt(
|
||||||
message: "Master Password:",
|
"Master Password:",
|
||||||
enable_confirmation: is_new_vaults_file,
|
is_new_vaults_file,
|
||||||
validators: if is_new_vaults_file {
|
Some(vec![Box::new(password_validator)]),
|
||||||
vec![Box::new(password_validator)]
|
)
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
},
|
|
||||||
..inquire::Password::new("")
|
|
||||||
}
|
|
||||||
.with_formatter(&|p| "*".repeat(p.chars().count()))
|
|
||||||
.with_display_mode(PasswordDisplayMode::Masked)
|
|
||||||
.prompt()
|
|
||||||
.map(|p| sha2::Sha256::digest(p).into())
|
.map(|p| sha2::Sha256::digest(p).into())
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retuns the current lprs version from `crates.io`
|
/// Retuns the current lprs version from `crates.io`
|
||||||
|
@ -225,7 +232,7 @@ pub fn prompt_custom(
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
new_fields.push((key, value));
|
new_fields.push((key, value));
|
||||||
} else {
|
} else {
|
||||||
let value = inquire::Text::new(&format!("Value of `{key}`:")).prompt()?;
|
let value = secret_prompt(&format!("Value of `{key}`:"), false, None)?;
|
||||||
new_fields.push((key, value));
|
new_fields.push((key, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,16 +244,17 @@ pub fn prompt_custom(
|
||||||
///
|
///
|
||||||
/// ## Errors
|
/// ## Errors
|
||||||
/// - If there is no vault with the given index or name
|
/// - If there is no vault with the given index or name
|
||||||
pub fn vault_by_index_or_name(
|
pub fn vault_by_index_or_name<'v>(
|
||||||
location: Either<NonZeroUsize, String>,
|
location: &Either<NonZeroUsize, String>,
|
||||||
vaults: &mut [Vault],
|
vaults: &'v mut [Vault],
|
||||||
) -> LprsResult<(usize, &mut Vault)> {
|
) -> LprsResult<(usize, &'v mut Vault)> {
|
||||||
let idx = location
|
let idx = location
|
||||||
|
.as_ref()
|
||||||
.map_right(|name| {
|
.map_right(|name| {
|
||||||
vaults
|
vaults
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find_map(|(idx, v)| (v.name == name).then_some(idx))
|
.find_map(|(idx, v)| (&v.name == name).then_some(idx))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
LprsError::Other(format!("There is no vault with the given name `{name}`"))
|
LprsError::Other(format!("There is no vault with the given name `{name}`"))
|
||||||
})
|
})
|
||||||
|
@ -257,7 +265,10 @@ pub fn vault_by_index_or_name(
|
||||||
Ok((
|
Ok((
|
||||||
idx,
|
idx,
|
||||||
vaults.get_mut(idx).ok_or_else(|| {
|
vaults.get_mut(idx).ok_or_else(|| {
|
||||||
LprsError::Other(format!("There is no vault with the given index `{idx}`"))
|
LprsError::Other(format!(
|
||||||
|
"There is no vault with the given index `{}`",
|
||||||
|
idx + 1
|
||||||
|
))
|
||||||
})?,
|
})?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub enum Format {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The vault struct
|
/// The vault struct
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, Parser)]
|
#[derive(Clone, Debug, Deserialize, Serialize, Parser, Eq, PartialEq)]
|
||||||
pub struct Vault {
|
pub struct Vault {
|
||||||
/// The name of the vault
|
/// The name of the vault
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
Loading…
Reference in a new issue