From f6aaecb9cf43d7dfa3ef653ff0cd117b3197308b Mon Sep 17 00:00:00 2001 From: Awiteb Date: Sun, 17 Mar 2024 11:35:47 +0300 Subject: [PATCH 1/4] refactor: Rename `Password`s `Vault`s --- src/cli/add_command.rs | 10 +- src/cli/clean_command.rs | 4 +- src/cli/edit_command.rs | 42 ++++---- src/cli/export_command.rs | 6 +- src/cli/gen_command.rs | 4 +- src/cli/import_command.rs | 30 +++--- src/cli/list_command.rs | 22 ++-- src/cli/mod.rs | 27 +++-- src/cli/remove_command.rs | 4 +- src/macros.rs | 4 +- src/password/bitwarden.rs | 12 +-- src/password/mod.rs | 29 +++--- src/password/validator.rs | 4 +- src/traits.rs | 4 +- src/vault/mod.rs | 209 ++++++++++++++++++++++++++++++++++++++ 15 files changed, 302 insertions(+), 109 deletions(-) create mode 100644 src/vault/mod.rs diff --git a/src/cli/add_command.rs b/src/cli/add_command.rs index cdc2557..46b836b 100644 --- a/src/cli/add_command.rs +++ b/src/cli/add_command.rs @@ -17,7 +17,7 @@ use clap::Args; use crate::{ - password::{Password, Passwords}, + password::{Vault, Vaults}, LprsResult, RunCommand, }; @@ -25,12 +25,12 @@ use crate::{ #[command(author, version, about, long_about = None)] pub struct Add { #[command(flatten)] - password_info: Password, + vault_info: Vault, } impl RunCommand for Add { - fn run(&self, mut password_manager: Passwords) -> LprsResult<()> { - password_manager.add_password(self.password_info.clone()); - password_manager.try_export() + fn run(&self, mut vault_manager: Vaults) -> LprsResult<()> { + vault_manager.add_vault(self.vault_info.clone()); + vault_manager.try_export() } } diff --git a/src/cli/clean_command.rs b/src/cli/clean_command.rs index 8c91892..ca49ee7 100644 --- a/src/cli/clean_command.rs +++ b/src/cli/clean_command.rs @@ -18,14 +18,14 @@ use std::fs; use clap::Args; -use crate::{password::Passwords, LprsError, LprsResult, RunCommand}; +use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] pub struct Clean {} impl RunCommand for Clean { - fn run(&self, password_manager: Passwords) -> LprsResult<()> { + fn run(&self, password_manager: Vaults) -> LprsResult<()> { fs::write(password_manager.passwords_file, "[]").map_err(LprsError::Io) } } diff --git a/src/cli/edit_command.rs b/src/cli/edit_command.rs index 6b2885e..4336a10 100644 --- a/src/cli/edit_command.rs +++ b/src/cli/edit_command.rs @@ -19,7 +19,7 @@ use std::num::NonZeroU64; use clap::Args; use crate::{ - password::{Password, Passwords}, + password::{Vault, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -30,27 +30,27 @@ pub struct Edit { index: NonZeroU64, #[arg(short, long)] - /// The new password name + /// The new vault name name: Option, #[arg(short, long)] - /// The new password username + /// The new vault username username: Option, #[arg(short, long)] /// The new password password: Option, #[arg(short, long)] - /// The new password service + /// The new vault service service: Option, #[arg(short = 'o', long)] - /// The new password note + /// The new vault note note: Option, } impl RunCommand for Edit { - fn run(&self, mut password_manager: Passwords) -> LprsResult<()> { + fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { let index = self.index.get() as usize; - if let Some(password) = password_manager.passwords.get_mut(index - 1) { + if let Some(vault) = vault_manager.vaults.get_mut(index - 1) { if self.name.is_none() && self.username.is_none() && self.password.is_none() @@ -61,26 +61,18 @@ impl RunCommand for Edit { "You must edit one option at least".to_owned(), )) } else { - *password = Password { - name: self.name.as_ref().unwrap_or(&password.name).to_string(), - username: self - .username - .as_ref() - .unwrap_or(&password.username) - .to_string(), - password: self - .password - .as_ref() - .unwrap_or(&password.password) - .to_string(), - service: self.service.as_ref().or(password.service.as_ref()).cloned(), - note: self.note.as_ref().or(password.note.as_ref()).cloned(), - }; - password_manager.try_export() + *vault = Vault::::new( + self.name.as_ref().unwrap_or(&vault.name), + self.username.as_ref().unwrap_or(&vault.username), + self.password.as_ref().unwrap_or(&vault.password), + self.service.as_ref().or(vault.service.as_ref()), + self.note.as_ref().or(vault.note.as_ref()), + ); + vault_manager.try_export() } } else { - Err(LprsError::InvalidPasswordIndex(format!( - "The index `{}` is greater than the passwords count {}", + Err(LprsError::InvalidVaultIndex(format!( + "The index `{}` is greater than the vaults count {}", self.index, password_manager.passwords.len() ))) diff --git a/src/cli/export_command.rs b/src/cli/export_command.rs index 475b8b5..8c5fb31 100644 --- a/src/cli/export_command.rs +++ b/src/cli/export_command.rs @@ -19,7 +19,7 @@ use std::{fs, io::Error as IoError, io::ErrorKind as IoErrorKind, path::PathBuf} use clap::Args; use crate::{ - password::{BitWardenPasswords, Format, Passwords}, + password::{BitWardenPasswords, Format, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -28,13 +28,13 @@ use crate::{ pub struct Export { /// The path to export to path: PathBuf, - /// Format to export passwords in + /// Format to export vaults in #[arg(short, long, value_name = "FORMAT", default_value_t= Format::Lprs)] format: Format, } impl RunCommand for Export { - fn run(&self, password_manager: Passwords) -> LprsResult<()> { + fn run(&self, password_manager: Vaults) -> LprsResult<()> { if self .path .extension() diff --git a/src/cli/gen_command.rs b/src/cli/gen_command.rs index afb31d5..7dd7c96 100644 --- a/src/cli/gen_command.rs +++ b/src/cli/gen_command.rs @@ -18,7 +18,7 @@ use std::num::NonZeroU64; use clap::Args; -use crate::{password::Passwords, LprsError, LprsResult, RunCommand}; +use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] @@ -42,7 +42,7 @@ pub struct Gen { } impl RunCommand for Gen { - fn run(&self, _password_manager: Passwords) -> LprsResult<()> { + fn run(&self, _password_manager: Vaults) -> LprsResult<()> { if self.uppercase || self.lowercase || self.numbers || self.symbols { println!( "{}", diff --git a/src/cli/import_command.rs b/src/cli/import_command.rs index aa02bc3..04a54d0 100644 --- a/src/cli/import_command.rs +++ b/src/cli/import_command.rs @@ -19,7 +19,7 @@ use std::{fs::File, io::Error as IoError, io::ErrorKind as IoErrorKind, path::Pa use clap::Args; use crate::{ - password::{BitWardenPasswords, Format, Password, Passwords}, + password::{BitWardenPasswords, Format, Vault, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -35,7 +35,7 @@ pub struct Import { } impl RunCommand for Import { - fn run(&self, mut password_manager: Passwords) -> LprsResult<()> { + fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { if self.path.exists() { if self .path @@ -44,30 +44,30 @@ impl RunCommand for Import { { let imported_passwords_len = match self.format { Format::Lprs => { - let passwords = Passwords::try_reload( + let vaults = Vaults::try_reload( self.path.to_path_buf(), password_manager.master_password.to_vec(), )?; - let passwords_len = passwords.passwords.len(); + let vaults_len = vaults.vaults.len(); - password_manager.passwords.extend(passwords.passwords); - password_manager.try_export()?; - passwords_len + vault_manager.vaults.extend(vaults.vaults); + vault_manager.try_export()?; + vaults_len } Format::BitWarden => { - let passwords: BitWardenPasswords = + let vaults: BitWardenPasswords = serde_json::from_reader(File::open(&self.path)?)?; - let passwords_len = passwords.items.len(); + let vaults_len = vaults.items.len(); - password_manager - .passwords - .extend(passwords.items.into_iter().map(Password::from)); - password_manager.try_export()?; - passwords_len + vault_manager + .vaults + .extend(vaults.items.into_iter().map(Vault::from)); + vault_manager.try_export()?; + vaults_len } }; println!( - "{imported_passwords_len} password{s} were imported successfully", + "{imported_passwords_len} vault{s} were imported successfully", s = if imported_passwords_len >= 2 { "s" } else { "" } ); diff --git a/src/cli/list_command.rs b/src/cli/list_command.rs index 32b47e9..3015a04 100644 --- a/src/cli/list_command.rs +++ b/src/cli/list_command.rs @@ -20,7 +20,7 @@ use clap::Args; use comfy_table::Table; use regex::Regex; -use crate::{password::Passwords, LprsError, LprsResult, RunCommand}; +use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] @@ -49,7 +49,7 @@ pub struct List { } impl RunCommand for List { - fn run(&self, password_manager: Passwords) -> LprsResult<()> { + fn run(&self, password_manager: Vaults) -> LprsResult<()> { if password_manager.passwords.is_empty() { Err(LprsError::Other( "Looks like there is no passwords to list".to_owned(), @@ -77,8 +77,8 @@ impl RunCommand for List { let re = Regex::new(self.search.as_deref().unwrap_or("."))?; table.set_header(header); - let passwords = password_manager - .passwords + let vaults = vault_manager + .vaults .iter() .enumerate() .filter(|(idx, pass)| { @@ -112,24 +112,24 @@ impl RunCommand for List { true }); - for (idx, password) in passwords { - let hide_password = "*".repeat(password.password.chars().count()); + for (idx, vault) in vaults { + let hide_password = "*".repeat(vault.password.chars().count()); let idx = (idx + 1).to_string(); let mut row = vec![ idx.as_str(), - password.name.as_str(), - password.username.as_str(), + vault.name.as_str(), + vault.username.as_str(), if self.unhide_password { - password.password.as_str() + vault.password.as_str() } else { hide_password.as_str() }, ]; if self.with_service { - row.push(password.service.as_deref().unwrap_or("Not Set")) + row.push(vault.service.as_deref().unwrap_or("Not Set")) } if self.with_note { - row.push(password.note.as_deref().unwrap_or("Not Set")) + row.push(vault.note.as_deref().unwrap_or("Not Set")) } table.add_row(row); } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index f4459e0..29b1bd4 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -19,7 +19,7 @@ use std::path::PathBuf; use clap::Parser; use crate::{ - password::{self, Passwords}, + password::{self, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -47,7 +47,7 @@ crate::create_commands!( #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] pub struct Cli { - /// The passwords json file, default: $HOME/.local/share/lprs/passwords.json + /// The vaults json file #[arg(short, long)] passwords_file: Option, @@ -64,33 +64,30 @@ impl Cli { } else { crate::utils::passwords_file()? }; - log::debug!( - "Getting password file: {}", - passwords_file.to_string_lossy() - ); - let password_manager = if matches!(self.command, Commands::Clean(..) | Commands::Gen(..)) { - Passwords { + log::debug!("Getting the vaults file: {}", vaults_file.to_string_lossy()); + let vault_manager = if matches!(self.command, Commands::Clean(..) | Commands::Gen(..)) { + Vaults { passwords_file, ..Default::default() } } else { - let password = scanpw::scanpw!("Master Password: "); + let master_password = scanpw::scanpw!("Master Password: "); - if password::is_new_password_file(&passwords_file)? { - let analyzed = passwords::analyzer::analyze(&password); + if vault::is_new_vaults_file(&vaults_file)? { + let analyzed = passwords::analyzer::analyze(&master_password); if analyzed.length() < 15 { return Err(LprsError::WeakPassword( - "The password length must be beggier then 15".to_owned(), + "The master password length must be beggier then 15".to_owned(), )); } else if passwords::scorer::score(&analyzed) < 80.0 { return Err(LprsError::WeakPassword( - "Your password is not stronge enough".to_owned(), + "Your master password is not stronge enough".to_owned(), )); } } - let master_password = sha256::digest(password); - Passwords::try_reload( + let master_password = sha256::digest(master_password); + Vaults::try_reload( passwords_file, master_password.into_bytes().into_iter().take(32).collect(), )? diff --git a/src/cli/remove_command.rs b/src/cli/remove_command.rs index ac12597..6c9151b 100644 --- a/src/cli/remove_command.rs +++ b/src/cli/remove_command.rs @@ -18,7 +18,7 @@ use std::num::NonZeroU64; use clap::Args; -use crate::{password::Passwords, LprsError, LprsResult, RunCommand}; +use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] @@ -32,7 +32,7 @@ pub struct Remove { } impl RunCommand for Remove { - fn run(&self, mut password_manager: Passwords) -> LprsResult<()> { + fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { let index = (self.index.get() - 1) as usize; if index > password_manager.passwords.len() { if !self.force { diff --git a/src/macros.rs b/src/macros.rs index 80ba849..1819671 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -40,7 +40,7 @@ /// impl crate::RunCommand for TestCommands { /// fn run( /// &self, -/// password_manager: crate::password::Passwords, +/// vault_manager: crate::vault::Vaults, /// ) -> crate::LprsResult<()> { /// match self { /// Self::Test(command) => command.run(password_manager), @@ -63,7 +63,7 @@ macro_rules! create_commands { #[automatically_derived] impl $crate::RunCommand for $enum_name{ - fn run(&self, password_manager: $crate::password::Passwords) -> $crate::LprsResult<()> { + fn run(&self, password_manager: $crate::password::Vaults) -> $crate::LprsResult<()> { match self { $( Self::$varint(command) => command.run(password_manager), diff --git a/src/password/bitwarden.rs b/src/password/bitwarden.rs index b1ab0a9..c31fd8f 100644 --- a/src/password/bitwarden.rs +++ b/src/password/bitwarden.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use super::{Password, Passwords}; +use super::{Vault, Vaults}; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct BitWardenLoginData { @@ -39,7 +39,7 @@ pub struct BitWardenPasswords { pub items: Vec, } -impl From for Password { +impl From for Vault { fn from(value: BitWardenPassword) -> Self { Self { name: value.name, @@ -59,8 +59,8 @@ impl From for Password { } } -impl From for BitWardenPassword { - fn from(value: Password) -> Self { +impl From for BitWardenPassword { + fn from(value: Vault) -> Self { Self { ty: 1, name: value.name, @@ -76,8 +76,8 @@ impl From for BitWardenPassword { } } -impl From for BitWardenPasswords { - fn from(value: Passwords) -> Self { +impl From for BitWardenPasswords { + fn from(value: Vaults) -> Self { Self { encrypted: false, folders: Vec::new(), diff --git a/src/password/mod.rs b/src/password/mod.rs index a13fbe7..86ad388 100644 --- a/src/password/mod.rs +++ b/src/password/mod.rs @@ -38,7 +38,7 @@ pub enum Format { /// The password struct #[serde_with_macros::skip_serializing_none] #[derive(Clone, Debug, Deserialize, Serialize, Parser)] -pub struct Password { +pub struct Vault { /// The name of the password #[arg(short, long)] pub name: String, @@ -58,16 +58,16 @@ pub struct Password { /// The passwords manager #[derive(Default)] -pub struct Passwords { +pub struct Vaults { /// Hash of the master password pub master_password: Vec, /// The json passwords file pub passwords_file: PathBuf, /// The passwords - pub passwords: Vec, + pub passwords: Vec, } -impl Password { +impl Vault { /// Encrypt the password data pub fn encrypt(self, master_password: &[u8]) -> LprsResult { Ok(Self { @@ -103,13 +103,9 @@ impl Password { } } -impl Passwords { +impl Vaults { /// Create new Passwords instnce - pub fn new( - master_password: Vec, - passwords_file: PathBuf, - passwords: Vec, - ) -> Self { + pub fn new(master_password: Vec, passwords_file: PathBuf, passwords: Vec) -> Self { Self { master_password, passwords_file, @@ -124,18 +120,17 @@ impl Passwords { .passwords .into_iter() .map(|p| p.encrypt(&self.master_password)) - .collect::>>()?, + .collect::>>()?, ..self }) } /// Reload the passwords from the file pub fn try_reload(passwords_file: PathBuf, master_password: Vec) -> LprsResult { - let passwords = - serde_json::from_str::>(&fs::read_to_string(&passwords_file)?)? - .into_iter() - .map(|p| p.decrypt(master_password.as_slice())) - .collect::>>()?; + let passwords = serde_json::from_str::>(&fs::read_to_string(&passwords_file)?)? + .into_iter() + .map(|p| p.decrypt(master_password.as_slice())) + .collect::>>()?; Ok(Self::new(master_password, passwords_file, passwords)) } @@ -147,7 +142,7 @@ impl Passwords { } /// Add new password - pub fn add_password(&mut self, password: Password) { + pub fn add_password(&mut self, password: Vault) { self.passwords.push(password) } } diff --git a/src/password/validator.rs b/src/password/validator.rs index fb9bbf6..1fc015c 100644 --- a/src/password/validator.rs +++ b/src/password/validator.rs @@ -18,7 +18,7 @@ use std::{fs, path::Path}; use crate::LprsResult; -use super::Password; +use super::Vault; /// Return if the password file new file or not pub fn is_new_password_file(path: &Path) -> LprsResult { @@ -26,7 +26,7 @@ pub fn is_new_password_file(path: &Path) -> LprsResult { let file_content = fs::read_to_string(path)?; if !file_content.is_empty() && file_content.trim() != "[]" - && serde_json::from_str::>(&file_content).is_ok() + && serde_json::from_str::>(&file_content).is_ok() { return Ok(false); } diff --git a/src/traits.rs b/src/traits.rs index 05da877..e12a415 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -14,9 +14,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{password::Passwords, LprsResult}; +use crate::{password::Vaults, LprsResult}; /// Trait to run the command pub trait RunCommand { - fn run(&self, password_manager: Passwords) -> LprsResult<()>; + fn run(&self, password_manager: Vaults) -> LprsResult<()>; } diff --git a/src/vault/mod.rs b/src/vault/mod.rs new file mode 100644 index 0000000..2e4bacd --- /dev/null +++ b/src/vault/mod.rs @@ -0,0 +1,209 @@ +// Lprs - A local CLI vault manager +// Copyright (C) 2024 Awiteb +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +use std::{fs, marker::PhantomData, path::PathBuf}; + +use clap::{Parser, ValueEnum}; +use serde::{Deserialize, Serialize}; + +use crate::{LprsError, LprsResult}; +use vault_state::*; + +pub mod cipher; + +mod bitwarden; +mod validator; + +pub use bitwarden::*; +pub use validator::*; + +#[derive(Clone, Debug, ValueEnum)] +pub enum Format { + Lprs, + BitWarden, +} + +/// The states of the vaults +pub mod vault_state { + /// Means the vault is encrypted + #[derive(Clone, Debug, Default)] + pub struct Encrypted; + /// Means the vault is not encrypted + #[derive(Clone, Debug, Default)] + pub struct Plain; +} + +/// The vault struct +#[serde_with_macros::skip_serializing_none] +#[derive(Clone, Debug, Deserialize, Serialize, Parser)] +pub struct Vault +where + T: std::fmt::Debug + Clone, +{ + /// The name of the vault + #[arg(short, long)] + pub name: String, + /// The username + #[arg(short, long)] + pub username: String, + /// The password + #[arg(short, long)] + pub password: String, + /// The service name. e.g the website url + #[arg(short, long)] + pub service: Option, + /// Add a note to the vault + #[arg(short = 'o', long)] + pub note: Option, + + /// State phantom + #[serde(skip)] + #[arg(skip)] + phantom: PhantomData, +} + +/// The vaults manager +#[derive(Default)] +pub struct Vaults +where + T: std::fmt::Debug + Clone, +{ + /// Hash of the master password + pub master_password: Vec, + /// The json vaults file + pub vaults_file: PathBuf, + /// The vaults + pub vaults: Vec>, +} + +impl Vault +where + T: std::fmt::Debug + Clone, +{ + /// Create new [`Vault`] instance + pub fn new( + name: impl Into, + username: impl Into, + password: impl Into, + service: Option>, + note: Option>, + ) -> Self { + Self { + name: name.into(), + username: username.into(), + password: password.into(), + service: service.map(|s| s.into()), + note: note.map(|s| s.into()), + phantom: std::marker::PhantomData, + } + } +} + +impl Vault { + /// Decrypt the vault + pub fn decrypt(&self, master_password: &[u8]) -> LprsResult> { + Ok(Vault::::new( + cipher::decrypt(master_password, &self.name)?, + cipher::decrypt(master_password, &self.username)?, + cipher::decrypt(master_password, &self.password)?, + self.service + .as_ref() + .map(|url| cipher::decrypt(master_password, url)) + .transpose()?, + self.note + .as_ref() + .map(|note| cipher::decrypt(master_password, note)) + .transpose()?, + )) + } +} + +impl Vault { + /// Encrypt the vault + pub fn encrypt(&self, master_password: &[u8]) -> LprsResult> { + Ok(Vault::::new( + cipher::encrypt(master_password, &self.name)?, + cipher::encrypt(master_password, &self.username)?, + cipher::encrypt(master_password, &self.password)?, + self.service + .as_ref() + .map(|url| cipher::encrypt(master_password, url)) + .transpose()?, + self.note + .as_ref() + .map(|note| cipher::encrypt(master_password, note)) + .transpose()?, + )) + } +} + +impl Vaults +where + T: std::fmt::Debug + Clone, +{ + /// Create new [`Vaults`] instnce + pub fn new(master_password: Vec, vaults_file: PathBuf, vaults: Vec>) -> Self { + Self { + master_password, + vaults_file, + vaults, + } + } +} + +impl Vaults { + /// Encrypt the vaults + pub fn encrypt_vaults(&self) -> LprsResult>> { + self.vaults + .iter() + .map(|p| p.encrypt(&self.master_password)) + .collect() + } + + /// Reload the vaults from the file then decrypt it + pub fn try_reload(vaults_file: PathBuf, master_password: Vec) -> LprsResult { + let vaults = + serde_json::from_str::>>(&fs::read_to_string(&vaults_file)?)? + .into_iter() + .map(|p| p.decrypt(master_password.as_slice())) + .collect::>>>()?; + + Ok(Self::new(master_password, vaults_file, vaults)) + } + + /// Encrypt the vaults then export it to the file + pub fn try_export(self) -> LprsResult<()> { + fs::write( + &self.vaults_file, + serde_json::to_string(&self.encrypt_vaults()?)?, + ) + .map_err(LprsError::Io) + } + + /// Add new vault + pub fn add_vault(&mut self, vault: Vault) { + self.vaults.push(vault) + } +} + +impl ToString for Format { + fn to_string(&self) -> String { + self.to_possible_value() + .expect("There is no skiped values") + .get_name() + .to_owned() + } +} -- 2.45.2 From dc24d355690c2b476819adc3ca5da5f1f927e98e Mon Sep 17 00:00:00 2001 From: Awiteb Date: Mon, 18 Mar 2024 23:32:48 +0300 Subject: [PATCH 2/4] refactor: Add a ecryption state to the vault Also - Rename `password`somthing to `vault`somthing - Rename the `password` mod to `vault` BREACKING-CHANGE: Moving from password to vault ISSUE: https://git.4rs.nl/awiteb/lprs/issues/4 --- src/cli/add_command.rs | 2 +- src/cli/clean_command.rs | 9 +- src/cli/edit_command.rs | 6 +- src/cli/export_command.rs | 8 +- src/cli/gen_command.rs | 7 +- src/cli/import_command.rs | 4 +- src/cli/list_command.rs | 9 +- src/cli/mod.rs | 28 ++--- src/cli/remove_command.rs | 11 +- src/errors.rs | 5 +- src/macros.rs | 2 +- src/main.rs | 4 +- src/password/mod.rs | 157 --------------------------- src/traits.rs | 7 +- src/utils.rs | 12 +- src/{password => vault}/bitwarden.rs | 28 ++--- src/{password => vault}/cipher.rs | 0 src/{password => vault}/validator.rs | 8 +- 18 files changed, 84 insertions(+), 223 deletions(-) delete mode 100644 src/password/mod.rs rename src/{password => vault}/bitwarden.rs (82%) rename src/{password => vault}/cipher.rs (100%) rename src/{password => vault}/validator.rs (81%) diff --git a/src/cli/add_command.rs b/src/cli/add_command.rs index 46b836b..8bd052f 100644 --- a/src/cli/add_command.rs +++ b/src/cli/add_command.rs @@ -17,7 +17,7 @@ use clap::Args; use crate::{ - password::{Vault, Vaults}, + vault::{vault_state::*, Vault, Vaults}, LprsResult, RunCommand, }; diff --git a/src/cli/clean_command.rs b/src/cli/clean_command.rs index ca49ee7..683fa9d 100644 --- a/src/cli/clean_command.rs +++ b/src/cli/clean_command.rs @@ -18,14 +18,17 @@ use std::fs; use clap::Args; -use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; +use crate::{ + vault::{vault_state::*, Vaults}, + LprsError, LprsResult, RunCommand, +}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] pub struct Clean {} impl RunCommand for Clean { - fn run(&self, password_manager: Vaults) -> LprsResult<()> { - fs::write(password_manager.passwords_file, "[]").map_err(LprsError::Io) + fn run(&self, password_manager: Vaults) -> LprsResult<()> { + fs::write(password_manager.vaults_file, "[]").map_err(LprsError::Io) } } diff --git a/src/cli/edit_command.rs b/src/cli/edit_command.rs index 4336a10..df99815 100644 --- a/src/cli/edit_command.rs +++ b/src/cli/edit_command.rs @@ -19,7 +19,7 @@ use std::num::NonZeroU64; use clap::Args; use crate::{ - password::{Vault, Vaults}, + vault::{vault_state::*, Vault, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -47,7 +47,7 @@ pub struct Edit { } impl RunCommand for Edit { - fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { + fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { let index = self.index.get() as usize; if let Some(vault) = vault_manager.vaults.get_mut(index - 1) { @@ -74,7 +74,7 @@ impl RunCommand for Edit { Err(LprsError::InvalidVaultIndex(format!( "The index `{}` is greater than the vaults count {}", self.index, - password_manager.passwords.len() + password_manager.vaults.len() ))) } } diff --git a/src/cli/export_command.rs b/src/cli/export_command.rs index 8c5fb31..555b214 100644 --- a/src/cli/export_command.rs +++ b/src/cli/export_command.rs @@ -19,7 +19,7 @@ use std::{fs, io::Error as IoError, io::ErrorKind as IoErrorKind, path::PathBuf} use clap::Args; use crate::{ - password::{BitWardenPasswords, Format, Vaults}, + vault::{vault_state::*, BitWardenPasswords, Format, Vault, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -34,7 +34,7 @@ pub struct Export { } impl RunCommand for Export { - fn run(&self, password_manager: Vaults) -> LprsResult<()> { + fn run(&self, password_manager: Vaults) -> LprsResult<()> { if self .path .extension() @@ -42,7 +42,9 @@ impl RunCommand for Export { { if !self.path.exists() { let exported_data = match self.format { - Format::Lprs => serde_json::to_string(&password_manager.encrypt()?.passwords), + Format::Lprs => serde_json::to_string::>>( + &password_manager.encrypt_vaults()?, + ), Format::BitWarden => { serde_json::to_string(&BitWardenPasswords::from(password_manager)) } diff --git a/src/cli/gen_command.rs b/src/cli/gen_command.rs index 7dd7c96..41b5c54 100644 --- a/src/cli/gen_command.rs +++ b/src/cli/gen_command.rs @@ -18,7 +18,10 @@ use std::num::NonZeroU64; use clap::Args; -use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; +use crate::{ + vault::{vault_state::*, Vaults}, + LprsError, LprsResult, RunCommand, +}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] @@ -42,7 +45,7 @@ pub struct Gen { } impl RunCommand for Gen { - fn run(&self, _password_manager: Vaults) -> LprsResult<()> { + fn run(&self, _password_manager: Vaults) -> LprsResult<()> { if self.uppercase || self.lowercase || self.numbers || self.symbols { println!( "{}", diff --git a/src/cli/import_command.rs b/src/cli/import_command.rs index 04a54d0..4e559dd 100644 --- a/src/cli/import_command.rs +++ b/src/cli/import_command.rs @@ -19,7 +19,7 @@ use std::{fs::File, io::Error as IoError, io::ErrorKind as IoErrorKind, path::Pa use clap::Args; use crate::{ - password::{BitWardenPasswords, Format, Vault, Vaults}, + vault::{vault_state::*, BitWardenPasswords, Format, Vault, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -35,7 +35,7 @@ pub struct Import { } impl RunCommand for Import { - fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { + fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { if self.path.exists() { if self .path diff --git a/src/cli/list_command.rs b/src/cli/list_command.rs index 3015a04..e36609f 100644 --- a/src/cli/list_command.rs +++ b/src/cli/list_command.rs @@ -20,7 +20,10 @@ use clap::Args; use comfy_table::Table; use regex::Regex; -use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; +use crate::{ + vault::{vault_state::*, Vaults}, + LprsError, LprsResult, RunCommand, +}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] @@ -49,8 +52,8 @@ pub struct List { } impl RunCommand for List { - fn run(&self, password_manager: Vaults) -> LprsResult<()> { - if password_manager.passwords.is_empty() { + fn run(&self, password_manager: Vaults) -> LprsResult<()> { + if password_manager.vaults.is_empty() { Err(LprsError::Other( "Looks like there is no passwords to list".to_owned(), )) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 29b1bd4..1221ebb 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -19,7 +19,7 @@ use std::path::PathBuf; use clap::Parser; use crate::{ - password::{self, Vaults}, + vault::{self, Vaults}, LprsError, LprsResult, RunCommand, }; @@ -34,14 +34,14 @@ pub mod remove_command; crate::create_commands!( enum Commands - "Add new password", Add => add_command::Add - "Remove password", Remove => remove_command::Remove - "List your password and search", List => list_command::List - "Clean the password file", Clean => clean_command::Clean - "Edit the password content", Edit => edit_command::Edit - "Generate password", Gen => gen_command::Gen - "Export the passwords", Export => export_command::Export - "Import passwords", Import => import_command::Import + "Add new vault", Add => add_command::Add + "Remove vault", Remove => remove_command::Remove + "List your vaults and search", List => list_command::List + "Clean the vaults file", Clean => clean_command::Clean + "Edit the vault content", Edit => edit_command::Edit + "Generate a password", Gen => gen_command::Gen + "Export the vaults", Export => export_command::Export + "Import vaults", Import => import_command::Import ); #[derive(Parser, Debug)] @@ -49,7 +49,7 @@ crate::create_commands!( pub struct Cli { /// The vaults json file #[arg(short, long)] - passwords_file: Option, + vaults_file: Option, // TODO: verbose flag #[command(subcommand)] @@ -59,15 +59,15 @@ pub struct Cli { impl Cli { /// Run the cli pub fn run(self) -> LprsResult<()> { - let passwords_file = if let Some(ref path) = self.passwords_file { + let vaults_file = if let Some(ref path) = self.vaults_file { path.clone() } else { - crate::utils::passwords_file()? + crate::utils::vaults_file()? }; log::debug!("Getting the vaults file: {}", vaults_file.to_string_lossy()); let vault_manager = if matches!(self.command, Commands::Clean(..) | Commands::Gen(..)) { Vaults { - passwords_file, + vaults_file, ..Default::default() } } else { @@ -88,7 +88,7 @@ impl Cli { let master_password = sha256::digest(master_password); Vaults::try_reload( - passwords_file, + vaults_file, master_password.into_bytes().into_iter().take(32).collect(), )? }; diff --git a/src/cli/remove_command.rs b/src/cli/remove_command.rs index 6c9151b..331cd21 100644 --- a/src/cli/remove_command.rs +++ b/src/cli/remove_command.rs @@ -18,7 +18,10 @@ use std::num::NonZeroU64; use clap::Args; -use crate::{password::Vaults, LprsError, LprsResult, RunCommand}; +use crate::{ + vault::{vault_state::*, Vaults}, + LprsError, LprsResult, RunCommand, +}; #[derive(Debug, Args)] #[command(author, version, about, long_about = None)] @@ -32,16 +35,16 @@ pub struct Remove { } impl RunCommand for Remove { - fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { + fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { let index = (self.index.get() - 1) as usize; - if index > password_manager.passwords.len() { + if index > password_manager.vaults.len() { if !self.force { return Err(LprsError::Other( "The index is greater than the passwords counts".to_owned(), )); } } else { - password_manager.passwords.remove(index); + password_manager.vaults.remove(index); password_manager.try_export()?; } Ok(()) diff --git a/src/errors.rs b/src/errors.rs index 6be1c8f..50d44e6 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -34,8 +34,8 @@ pub enum Error { WeakPassword(String), #[error("Args Conflict Error: {0}")] ArgsConflict(String), - #[error("Invalid Password Index Error: {0}")] - InvalidPasswordIndex(String), + #[error("Invalid Vault Index Error: {0}")] + InvalidVaultIndex(String), #[error("{0}")] Other(String), @@ -56,6 +56,7 @@ pub enum Error { impl Error { /// Return the exit code of the error pub fn exit_code(&self) -> ExitCode { + // TODO: Exit with more specific exit code ExitCode::FAILURE } } diff --git a/src/macros.rs b/src/macros.rs index 1819671..f31d85a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -63,7 +63,7 @@ macro_rules! create_commands { #[automatically_derived] impl $crate::RunCommand for $enum_name{ - fn run(&self, password_manager: $crate::password::Vaults) -> $crate::LprsResult<()> { + fn run(&self, password_manager: $crate::vault::Vaults<$crate::vault::vault_state::Plain>) -> $crate::LprsResult<()> { match self { $( Self::$varint(command) => command.run(password_manager), diff --git a/src/main.rs b/src/main.rs index 04ba220..c3186cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,8 +24,8 @@ use clap::Parser; pub mod cli; pub mod errors; -pub mod password; pub mod utils; +pub mod vault; mod macros; mod traits; @@ -34,7 +34,7 @@ pub use errors::{Error as LprsError, Result as LprsResult}; pub use traits::*; pub const STANDARDBASE: GeneralPurpose = GeneralPurpose::new(&alphabet::STANDARD, PAD); -pub const DEFAULT_PASSWORD_FILE: &str = "passwords.json"; +pub const DEFAULT_VAULTS_FILE: &str = "vaults.json"; #[cfg(feature = "update-notify")] pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/src/password/mod.rs b/src/password/mod.rs deleted file mode 100644 index 86ad388..0000000 --- a/src/password/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -// Lprs - A local CLI password manager -// Copyright (C) 2024 Awiteb -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -use std::{fs, path::PathBuf}; - -use clap::{Parser, ValueEnum}; -use serde::{Deserialize, Serialize}; - -use crate::{LprsError, LprsResult}; - -pub mod cipher; - -mod bitwarden; -mod validator; - -pub use bitwarden::*; -pub use validator::*; - -#[derive(Clone, Debug, ValueEnum)] -pub enum Format { - Lprs, - BitWarden, -} - -/// The password struct -#[serde_with_macros::skip_serializing_none] -#[derive(Clone, Debug, Deserialize, Serialize, Parser)] -pub struct Vault { - /// The name of the password - #[arg(short, long)] - pub name: String, - /// The username - #[arg(short, long)] - pub username: String, - /// The password - #[arg(short, long)] - pub password: String, - /// The service name. e.g the website url - #[arg(short, long)] - pub service: Option, - /// The note of the password - #[arg(short = 'o', long)] - pub note: Option, -} - -/// The passwords manager -#[derive(Default)] -pub struct Vaults { - /// Hash of the master password - pub master_password: Vec, - /// The json passwords file - pub passwords_file: PathBuf, - /// The passwords - pub passwords: Vec, -} - -impl Vault { - /// Encrypt the password data - pub fn encrypt(self, master_password: &[u8]) -> LprsResult { - Ok(Self { - name: cipher::encrypt(master_password, &self.name)?, - username: cipher::encrypt(master_password, &self.username)?, - password: cipher::encrypt(master_password, &self.password)?, - service: self - .service - .map(|url| cipher::encrypt(master_password, &url)) - .transpose()?, - note: self - .note - .map(|note| cipher::encrypt(master_password, ¬e)) - .transpose()?, - }) - } - - /// Decrypt the password data - pub fn decrypt(self, master_password: &[u8]) -> LprsResult { - Ok(Self { - name: cipher::decrypt(master_password, &self.name)?, - username: cipher::decrypt(master_password, &self.username)?, - password: cipher::decrypt(master_password, &self.password)?, - service: self - .service - .map(|url| cipher::decrypt(master_password, &url)) - .transpose()?, - note: self - .note - .map(|note| cipher::decrypt(master_password, ¬e)) - .transpose()?, - }) - } -} - -impl Vaults { - /// Create new Passwords instnce - pub fn new(master_password: Vec, passwords_file: PathBuf, passwords: Vec) -> Self { - Self { - master_password, - passwords_file, - passwords, - } - } - - /// Encrypt the passwords - pub fn encrypt(self) -> LprsResult { - Ok(Self { - passwords: self - .passwords - .into_iter() - .map(|p| p.encrypt(&self.master_password)) - .collect::>>()?, - ..self - }) - } - - /// Reload the passwords from the file - pub fn try_reload(passwords_file: PathBuf, master_password: Vec) -> LprsResult { - let passwords = serde_json::from_str::>(&fs::read_to_string(&passwords_file)?)? - .into_iter() - .map(|p| p.decrypt(master_password.as_slice())) - .collect::>>()?; - - Ok(Self::new(master_password, passwords_file, passwords)) - } - - /// Export the passwords to the file - pub fn try_export(self) -> LprsResult<()> { - let path = self.passwords_file.to_path_buf(); - fs::write(path, serde_json::to_string(&self.encrypt()?.passwords)?).map_err(LprsError::Io) - } - - /// Add new password - pub fn add_password(&mut self, password: Vault) { - self.passwords.push(password) - } -} - -impl ToString for Format { - fn to_string(&self) -> String { - self.to_possible_value() - .expect("There is no skiped values") - .get_name() - .to_owned() - } -} diff --git a/src/traits.rs b/src/traits.rs index e12a415..5be273b 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -14,9 +14,12 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{password::Vaults, LprsResult}; +use crate::{ + vault::{vault_state::*, Vaults}, + LprsResult, +}; /// Trait to run the command pub trait RunCommand { - fn run(&self, password_manager: Vaults) -> LprsResult<()>; + fn run(&self, password_manager: Vaults) -> LprsResult<()>; } diff --git a/src/utils.rs b/src/utils.rs index 37adda3..ef1dd7d 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -31,13 +31,13 @@ pub fn local_project_file(filename: &str) -> LprsResult { Ok(local_dir.join(filename)) } -/// Returns the default passwords json file -pub fn passwords_file() -> LprsResult { - let password_file = local_project_file(crate::DEFAULT_PASSWORD_FILE)?; - if !password_file.exists() { - fs::write(&password_file, "[]")?; +/// Returns the default vaults json file +pub fn vaults_file() -> LprsResult { + let vaults_file = local_project_file(crate::DEFAULT_VAULTS_FILE)?; + if !vaults_file.exists() { + fs::write(&vaults_file, "[]")?; } - Ok(password_file) + Ok(vaults_file) } /// Retuns the current lprs version from `crates.io` diff --git a/src/password/bitwarden.rs b/src/vault/bitwarden.rs similarity index 82% rename from src/password/bitwarden.rs rename to src/vault/bitwarden.rs index c31fd8f..7c4670c 100644 --- a/src/password/bitwarden.rs +++ b/src/vault/bitwarden.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -use super::{Vault, Vaults}; +use super::{vault_state::*, Vault, Vaults}; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct BitWardenLoginData { @@ -39,28 +39,28 @@ pub struct BitWardenPasswords { pub items: Vec, } -impl From for Vault { +impl From for Vault { fn from(value: BitWardenPassword) -> Self { - Self { - name: value.name, - username: value + Self::new( + value.name, + value .login .as_ref() .map_or_else(String::new, |l| l.username.to_owned().unwrap_or_default()), - password: value + value .login .as_ref() .map_or_else(String::new, |l| l.password.to_owned().unwrap_or_default()), - service: value + value .login .and_then(|l| l.uris.and_then(|p| p.first().map(|u| u.uri.clone()))), - note: value.notes, - } + value.notes, + ) } } -impl From for BitWardenPassword { - fn from(value: Vault) -> Self { +impl From> for BitWardenPassword { + fn from(value: Vault) -> Self { Self { ty: 1, name: value.name, @@ -76,13 +76,13 @@ impl From for BitWardenPassword { } } -impl From for BitWardenPasswords { - fn from(value: Vaults) -> Self { +impl From> for BitWardenPasswords { + fn from(value: Vaults) -> Self { Self { encrypted: false, folders: Vec::new(), items: value - .passwords + .vaults .into_iter() .map(BitWardenPassword::from) .collect(), diff --git a/src/password/cipher.rs b/src/vault/cipher.rs similarity index 100% rename from src/password/cipher.rs rename to src/vault/cipher.rs diff --git a/src/password/validator.rs b/src/vault/validator.rs similarity index 81% rename from src/password/validator.rs rename to src/vault/validator.rs index 1fc015c..f27e37c 100644 --- a/src/password/validator.rs +++ b/src/vault/validator.rs @@ -18,15 +18,15 @@ use std::{fs, path::Path}; use crate::LprsResult; -use super::Vault; +use super::{vault_state::*, Vault}; -/// Return if the password file new file or not -pub fn is_new_password_file(path: &Path) -> LprsResult { +/// Return if the vaults file new file or not +pub fn is_new_vaults_file(path: &Path) -> LprsResult { if path.exists() { let file_content = fs::read_to_string(path)?; if !file_content.is_empty() && file_content.trim() != "[]" - && serde_json::from_str::>(&file_content).is_ok() + && serde_json::from_str::>>(&file_content).is_ok() { return Ok(false); } -- 2.45.2 From 078b047e04c5c2d6aafcb4e07cc9c96cdd72bcf0 Mon Sep 17 00:00:00 2001 From: Awiteb Date: Mon, 18 Mar 2024 23:45:39 +0300 Subject: [PATCH 3/4] change: Change 'password manager' to 'vault manager' --- src/cli/add_command.rs | 2 +- src/cli/clean_command.rs | 6 +++--- src/cli/edit_command.rs | 6 +++--- src/cli/export_command.rs | 8 ++++---- src/cli/gen_command.rs | 4 ++-- src/cli/import_command.rs | 6 +++--- src/cli/list_command.rs | 6 +++--- src/cli/mod.rs | 4 ++-- src/cli/remove_command.rs | 10 +++++----- src/errors.rs | 2 +- src/macros.rs | 10 +++++----- src/main.rs | 2 +- src/traits.rs | 4 ++-- src/utils.rs | 2 +- src/vault/cipher.rs | 2 +- src/vault/validator.rs | 2 +- 16 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/cli/add_command.rs b/src/cli/add_command.rs index 8bd052f..7b5a5c9 100644 --- a/src/cli/add_command.rs +++ b/src/cli/add_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify diff --git a/src/cli/clean_command.rs b/src/cli/clean_command.rs index 683fa9d..2efeed3 100644 --- a/src/cli/clean_command.rs +++ b/src/cli/clean_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -28,7 +28,7 @@ use crate::{ pub struct Clean {} impl RunCommand for Clean { - fn run(&self, password_manager: Vaults) -> LprsResult<()> { - fs::write(password_manager.vaults_file, "[]").map_err(LprsError::Io) + fn run(&self, vault_manager: Vaults) -> LprsResult<()> { + fs::write(vault_manager.vaults_file, "[]").map_err(LprsError::Io) } } diff --git a/src/cli/edit_command.rs b/src/cli/edit_command.rs index df99815..d8cdd88 100644 --- a/src/cli/edit_command.rs +++ b/src/cli/edit_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -47,7 +47,7 @@ pub struct Edit { } impl RunCommand for Edit { - fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { + fn run(&self, mut vault_manager: Vaults) -> LprsResult<()> { let index = self.index.get() as usize; if let Some(vault) = vault_manager.vaults.get_mut(index - 1) { @@ -74,7 +74,7 @@ impl RunCommand for Edit { Err(LprsError::InvalidVaultIndex(format!( "The index `{}` is greater than the vaults count {}", self.index, - password_manager.vaults.len() + vault_manager.vaults.len() ))) } } diff --git a/src/cli/export_command.rs b/src/cli/export_command.rs index 555b214..1375ebb 100644 --- a/src/cli/export_command.rs +++ b/src/cli/export_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -34,7 +34,7 @@ pub struct Export { } impl RunCommand for Export { - fn run(&self, password_manager: Vaults) -> LprsResult<()> { + fn run(&self, vault_manager: Vaults) -> LprsResult<()> { if self .path .extension() @@ -43,10 +43,10 @@ impl RunCommand for Export { if !self.path.exists() { let exported_data = match self.format { Format::Lprs => serde_json::to_string::>>( - &password_manager.encrypt_vaults()?, + &vault_manager.encrypt_vaults()?, ), Format::BitWarden => { - serde_json::to_string(&BitWardenPasswords::from(password_manager)) + serde_json::to_string(&BitWardenPasswords::from(vault_manager)) } }?; diff --git a/src/cli/gen_command.rs b/src/cli/gen_command.rs index 41b5c54..d5dacac 100644 --- a/src/cli/gen_command.rs +++ b/src/cli/gen_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -45,7 +45,7 @@ pub struct Gen { } impl RunCommand for Gen { - fn run(&self, _password_manager: Vaults) -> LprsResult<()> { + fn run(&self, _vault_manager: Vaults) -> LprsResult<()> { if self.uppercase || self.lowercase || self.numbers || self.symbols { println!( "{}", diff --git a/src/cli/import_command.rs b/src/cli/import_command.rs index 4e559dd..cbc080a 100644 --- a/src/cli/import_command.rs +++ b/src/cli/import_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -35,7 +35,7 @@ pub struct Import { } impl RunCommand for Import { - fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { + fn run(&self, mut vault_manager: Vaults) -> LprsResult<()> { if self.path.exists() { if self .path @@ -46,7 +46,7 @@ impl RunCommand for Import { Format::Lprs => { let vaults = Vaults::try_reload( self.path.to_path_buf(), - password_manager.master_password.to_vec(), + vault_manager.master_password.to_vec(), )?; let vaults_len = vaults.vaults.len(); diff --git a/src/cli/list_command.rs b/src/cli/list_command.rs index e36609f..a7550c9 100644 --- a/src/cli/list_command.rs +++ b/src/cli/list_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -52,8 +52,8 @@ pub struct List { } impl RunCommand for List { - fn run(&self, password_manager: Vaults) -> LprsResult<()> { - if password_manager.vaults.is_empty() { + fn run(&self, vault_manager: Vaults) -> LprsResult<()> { + if vault_manager.vaults.is_empty() { Err(LprsError::Other( "Looks like there is no passwords to list".to_owned(), )) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 1221ebb..d76a89d 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -92,7 +92,7 @@ impl Cli { master_password.into_bytes().into_iter().take(32).collect(), )? }; - self.command.run(password_manager)?; + self.command.run(vault_manager)?; Ok(()) } diff --git a/src/cli/remove_command.rs b/src/cli/remove_command.rs index 331cd21..29ac6b6 100644 --- a/src/cli/remove_command.rs +++ b/src/cli/remove_command.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -35,17 +35,17 @@ pub struct Remove { } impl RunCommand for Remove { - fn run(&self, mut password_manager: Vaults) -> LprsResult<()> { + fn run(&self, mut vault_manager: Vaults) -> LprsResult<()> { let index = (self.index.get() - 1) as usize; - if index > password_manager.vaults.len() { + if index > vault_manager.vaults.len() { if !self.force { return Err(LprsError::Other( "The index is greater than the passwords counts".to_owned(), )); } } else { - password_manager.vaults.remove(index); - password_manager.try_export()?; + vault_manager.vaults.remove(index); + vault_manager.try_export()?; } Ok(()) } diff --git a/src/errors.rs b/src/errors.rs index 50d44e6..52ac749 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify diff --git a/src/macros.rs b/src/macros.rs index f31d85a..454b8ed 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -43,8 +43,8 @@ /// vault_manager: crate::vault::Vaults, /// ) -> crate::LprsResult<()> { /// match self { -/// Self::Test(command) => command.run(password_manager), -/// Self::Some(command) => command.run(password_manager), +/// Self::Test(command) => command.run(vault_manager), +/// Self::Some(command) => command.run(vault_manager), /// } /// } /// } @@ -63,10 +63,10 @@ macro_rules! create_commands { #[automatically_derived] impl $crate::RunCommand for $enum_name{ - fn run(&self, password_manager: $crate::vault::Vaults<$crate::vault::vault_state::Plain>) -> $crate::LprsResult<()> { + fn run(&self, vault_manager: $crate::vault::Vaults<$crate::vault::vault_state::Plain>) -> $crate::LprsResult<()> { match self { $( - Self::$varint(command) => command.run(password_manager), + Self::$varint(command) => command.run(vault_manager), )+ } } diff --git a/src/main.rs b/src/main.rs index c3186cf..bfe7443 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify diff --git a/src/traits.rs b/src/traits.rs index 5be273b..dd8e9c4 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify @@ -21,5 +21,5 @@ use crate::{ /// Trait to run the command pub trait RunCommand { - fn run(&self, password_manager: Vaults) -> LprsResult<()>; + fn run(&self, vault_manager: Vaults) -> LprsResult<()>; } diff --git a/src/utils.rs b/src/utils.rs index ef1dd7d..4e21c24 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify diff --git a/src/vault/cipher.rs b/src/vault/cipher.rs index 0b34b0b..8e66c71 100644 --- a/src/vault/cipher.rs +++ b/src/vault/cipher.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify diff --git a/src/vault/validator.rs b/src/vault/validator.rs index f27e37c..784a84b 100644 --- a/src/vault/validator.rs +++ b/src/vault/validator.rs @@ -1,4 +1,4 @@ -// Lprs - A local CLI password manager +// Lprs - A local CLI vault manager // Copyright (C) 2024 Awiteb // // This program is free software: you can redistribute it and/or modify -- 2.45.2 From f4bf05ea71c947c90ab016a9e58a3415fb227516 Mon Sep 17 00:00:00 2001 From: Awiteb Date: Tue, 19 Mar 2024 10:12:55 +0300 Subject: [PATCH 4/4] chore: Update README.md --- README.md | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d12b666..b3c331f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Lprs -Lprs is a local password manager designed to securely store and manage your passwords. +Lprs is a local vault manager designed to securely store and manage your vaults. ### MSRV The Minimum Supported Rust Version (MSRV) is `1.70.0`. @@ -31,7 +31,7 @@ cargo uninstall lprs ## Usage -Lprs provides a command-line interface for managing your passwords. The following commands are available: +Lprs provides a command-line interface for managing your vaults. The following commands are available: ``` A local CLI password manager @@ -39,23 +39,20 @@ A local CLI password manager Usage: lprs [OPTIONS] Commands: - add Add new password - remove Remove password - list List your password and search - clean Clean the password file - edit Edit the password content - gen Generate password - export Export the passwords - import Import passwords + add Add new vault + remove Remove vault + list List your vaults and search + clean Clean the vaults file + edit Edit the vault content + gen Generate a password + export Export the vaults + import Import vaults help Print this message or the help of the given subcommand(s) Options: - -p, --passwords-file - The passwords json file, default: $HOME/.local/share/lprs/passwords.json - -h, --help - Print help - -V, --version - Print version + -v, --vaults-file The vaults json file + -h, --help Print help + -V, --version Print version ``` ### Example @@ -78,7 +75,7 @@ Master Password: *************** ### Backup -It is important to regularly backup your passwords to prevent data loss. Lprs does not provide an automatic backup feature. To backup your passwords, you can use the `export` command provided by Lprs. This command allows you to export your encrypted passwords to a json file, which you can then manually backup to a secure location. +It is important to regularly backup your vaults to prevent data loss. Lprs does not provide an automatic backup feature. To backup your vaults, you can use the `export` command provided by Lprs. This command allows you to export your encrypted vaults to a json file, which you can then manually backup to a secure location. #### Formats The format of the exported file can be specified using the `--format` option. The following formats are supported: @@ -104,4 +101,4 @@ Lprs is licensed under the GPL-3.0 License. This means that you are free to use, --- -[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/awiteb) \ No newline at end of file +[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/awiteb) -- 2.45.2