chore: Use inquire to get user password #14
5 changed files with 127 additions and 63 deletions
111
Cargo.lock
generated
111
Cargo.lock
generated
|
@ -139,6 +139,12 @@ version = "3.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -245,9 +251,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossterm"
|
name = "crossterm"
|
||||||
version = "0.26.1"
|
version = "0.25.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13"
|
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"crossterm_winapi",
|
"crossterm_winapi",
|
||||||
|
@ -357,6 +363,12 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dyn-clone"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.33"
|
version = "0.8.33"
|
||||||
|
@ -479,6 +491,24 @@ dependencies = [
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fuzzy-matcher"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94"
|
||||||
|
dependencies = [
|
||||||
|
"thread_local",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxhash"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
|
@ -652,6 +682,23 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inquire"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fe95f33091b9b7b517a5849bce4dce1b550b430fc20d58059fcaa319ed895d8b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"crossterm 0.25.0",
|
||||||
|
"dyn-clone",
|
||||||
|
"fuzzy-matcher",
|
||||||
|
"fxhash",
|
||||||
|
"newline-converter",
|
||||||
|
"once_cell",
|
||||||
|
"unicode-segmentation",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.9.0"
|
version = "2.9.0"
|
||||||
|
@ -737,12 +784,12 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"comfy-table",
|
"comfy-table",
|
||||||
"directories",
|
"directories",
|
||||||
|
"inquire",
|
||||||
"log",
|
"log",
|
||||||
"passwords",
|
"passwords",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"scanpw",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_with_macros",
|
"serde_with_macros",
|
||||||
|
@ -758,15 +805,6 @@ version = "2.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memoffset"
|
|
||||||
version = "0.7.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
|
@ -813,16 +851,12 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "newline-converter"
|
||||||
version = "0.26.4"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
|
checksum = "47b6b097ecb1cbfed438542d16e84fd7ad9b0c76c8a65b7f9039212a3d14dc7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"unicode-segmentation",
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"memoffset",
|
|
||||||
"pin-utils",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1175,18 +1209,6 @@ version = "1.0.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scanpw"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6196197a27d908a0b1cb44606d5a4f358c73d04dd1e9ba0ddc034841fa043a03"
|
|
||||||
dependencies = [
|
|
||||||
"crossterm 0.26.1",
|
|
||||||
"nix",
|
|
||||||
"thiserror",
|
|
||||||
"windows",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.23"
|
version = "0.1.23"
|
||||||
|
@ -1463,6 +1485,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thread_local"
|
||||||
|
version = "1.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinyvec"
|
name = "tinyvec"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -1576,6 +1608,12 @@ dependencies = [
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.11"
|
version = "0.1.11"
|
||||||
|
@ -1734,15 +1772,6 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows"
|
|
||||||
version = "0.48.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets 0.48.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
|
|
|
@ -20,7 +20,6 @@ log = "0.4.20"
|
||||||
passwords = { version = "3.1.16", features = ["common-password"] }
|
passwords = { version = "3.1.16", features = ["common-password"] }
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger = "0.5.0"
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
scanpw = "1.0.0"
|
|
||||||
serde = { version = "1.0.193", features = ["derive"] }
|
serde = { version = "1.0.193", features = ["derive"] }
|
||||||
serde_json = "1.0.108"
|
serde_json = "1.0.108"
|
||||||
serde_with_macros = "3.4.0"
|
serde_with_macros = "3.4.0"
|
||||||
|
@ -29,6 +28,7 @@ soft-aes = "0.1.0"
|
||||||
thiserror = "1.0.51"
|
thiserror = "1.0.51"
|
||||||
url = { version = "2.5.0", features = ["serde"] }
|
url = { version = "2.5.0", features = ["serde"] }
|
||||||
reqwest = {version = "0.11.23", optional = true}
|
reqwest = {version = "0.11.23", optional = true}
|
||||||
|
inquire = "0.7.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["update-notify"]
|
default = ["update-notify"]
|
||||||
|
|
|
@ -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