chore: Use inquire to get user password #14
3 changed files with 56 additions and 21 deletions
|
@ -17,10 +17,12 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use inquire::validator::Validation;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
utils,
|
||||||
vault::{self, Vaults},
|
vault::{self, Vaults},
|
||||||
LprsError, LprsResult, RunCommand,
|
LprsResult, RunCommand,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod add_command;
|
pub mod add_command;
|
||||||
|
@ -65,35 +67,21 @@ impl Cli {
|
||||||
crate::utils::vaults_file()?
|
crate::utils::vaults_file()?
|
||||||
};
|
};
|
||||||
log::debug!("Getting the vaults file: {}", vaults_file.to_string_lossy());
|
log::debug!("Getting the vaults file: {}", vaults_file.to_string_lossy());
|
||||||
|
|
||||||
let vault_manager = if matches!(self.command, Commands::Clean(..) | Commands::Gen(..)) {
|
let vault_manager = if matches!(self.command, Commands::Clean(..) | Commands::Gen(..)) {
|
||||||
|
// Returns empty vault manager for those commands don't need it
|
||||||
Vaults {
|
Vaults {
|
||||||
vaults_file,
|
vaults_file,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let master_password = scanpw::scanpw!("Master Password: ");
|
let master_password = utils::master_password_prompt(&vaults_file)?;
|
||||||
|
|
||||||
if vault::is_new_vaults_file(&vaults_file)? {
|
|
||||||
let analyzed = passwords::analyzer::analyze(&master_password);
|
|
||||||
if analyzed.length() < 15 {
|
|
||||||
return Err(LprsError::WeakPassword(
|
|
||||||
"The master password length must be beggier then 15".to_owned(),
|
|
||||||
));
|
|
||||||
} else if passwords::scorer::score(&analyzed) < 80.0 {
|
|
||||||
return Err(LprsError::WeakPassword(
|
|
||||||
"Your master password is not stronge enough".to_owned(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let master_password = sha256::digest(master_password);
|
|
||||||
Vaults::try_reload(
|
Vaults::try_reload(
|
||||||
vaults_file,
|
vaults_file,
|
||||||
master_password.into_bytes().into_iter().take(32).collect(),
|
master_password.into_bytes().into_iter().take(32).collect(),
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
self.command.run(vault_manager)?;
|
|
||||||
|
|
||||||
Ok(())
|
self.command.run(vault_manager)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ pub enum Error {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Other(String),
|
Other(String),
|
||||||
|
|
||||||
|
#[error("CLI error: {0}")]
|
||||||
|
Inquire(#[from] inquire::InquireError),
|
||||||
#[error("Invalid Regex: {0}")]
|
#[error("Invalid Regex: {0}")]
|
||||||
InvalidRegex(#[from] regex::Error),
|
InvalidRegex(#[from] regex::Error),
|
||||||
#[error("UTF8 Error: {0}")]
|
#[error("UTF8 Error: {0}")]
|
||||||
|
|
49
src/utils.rs
49
src/utils.rs
|
@ -14,9 +14,14 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
|
||||||
|
|
||||||
use std::{fs, path::PathBuf};
|
use std::{
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{LprsError, LprsResult};
|
use inquire::{ui::RenderConfig, validator::Validation};
|
||||||
|
|
||||||
|
use crate::{vault, LprsError, LprsResult};
|
||||||
|
|
||||||
/// Returns the local project dir joined with the given file name
|
/// Returns the local project dir joined with the given file name
|
||||||
pub fn local_project_file(filename: &str) -> LprsResult<PathBuf> {
|
pub fn local_project_file(filename: &str) -> LprsResult<PathBuf> {
|
||||||
|
@ -40,6 +45,46 @@ pub fn vaults_file() -> LprsResult<PathBuf> {
|
||||||
Ok(vaults_file)
|
Ok(vaults_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Validate the password
|
||||||
|
///
|
||||||
|
/// ## To pass
|
||||||
|
/// - The length must be higher than 14 (>=15)
|
||||||
|
/// - Its score must be greater than 80.0
|
||||||
|
pub fn password_validator(password: &str) -> Result<Validation, inquire::CustomUserError> {
|
||||||
|
let analyzed = passwords::analyzer::analyze(password);
|
||||||
|
if analyzed.length() < 15 {
|
||||||
|
return Ok(Validation::Invalid(
|
||||||
|
"The master password length must be beggier then 15".into(),
|
||||||
|
));
|
||||||
|
} else if passwords::scorer::score(&analyzed) < 80.0 {
|
||||||
|
return Ok(Validation::Invalid(
|
||||||
|
"Your master password is not stronge enough".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(Validation::Valid)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ask the user for the master password, then returns it
|
||||||
|
pub fn master_password_prompt(vaults_file: &Path) -> LprsResult<String> {
|
||||||
|
let is_new_vaults_file = vault::is_new_vaults_file(vaults_file)?;
|
||||||
|
|
||||||
|
inquire::Password {
|
||||||
|
message: "Master Password:",
|
||||||
|
enable_confirmation: is_new_vaults_file,
|
||||||
|
validators: if is_new_vaults_file {
|
||||||
|
vec![Box::new(password_validator)]
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
},
|
||||||
|
..inquire::Password::new("")
|
||||||
|
}
|
||||||
|
.with_formatter(&|p| "*".repeat(p.chars().count()))
|
||||||
|
.with_display_mode(inquire::PasswordDisplayMode::Masked)
|
||||||
|
.prompt()
|
||||||
|
.map(sha256::digest)
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
/// Retuns the current lprs version from `crates.io`
|
/// Retuns the current lprs version from `crates.io`
|
||||||
#[cfg(feature = "update-notify")]
|
#[cfg(feature = "update-notify")]
|
||||||
pub fn lprs_version() -> LprsResult<Option<String>> {
|
pub fn lprs_version() -> LprsResult<Option<String>> {
|
||||||
|
|
Loading…
Reference in a new issue