Browse Source

storage & git begin

fix-typo
Coin de Gamma 3 months ago
parent
commit
4190c93e9e
  1. 1
      Cargo.toml
  2. 12
      README.md
  3. 35
      src/main.rs
  4. 69
      src/storage.rs

1
Cargo.toml

@ -9,7 +9,6 @@ edition = "2021"
aes-gcm = "0.10.3" aes-gcm = "0.10.3"
clap = { version = "4.5.16", features = ["derive"] } clap = { version = "4.5.16", features = ["derive"] }
hex = "0.4.3" hex = "0.4.3"
once_cell = "1.19.0"
rpassword = "7.3.1" rpassword = "7.3.1"
tempfile = "3.12.0" tempfile = "3.12.0"

12
README.md

@ -1,3 +1,13 @@
# mps # MPS
A small tool for storing passwords locally with git sync A small tool for storing passwords locally with git sync
## Installation
1. Create empty repository for storing your passwords on gitlab or somewhere you prefer
2. Clone to your home folder ~/.mps/storage
3. Set variable $MPS_HOME="~/.mps/"
4. Add to your $PATH:<path_to_msp> where you installed your mps
5. Run ./mps init

35
src/main.rs

@ -78,20 +78,41 @@ impl MPS {
MPS { storage: None } MPS { storage: None }
} }
fn init() -> io::Result<()> {
if Storage::is_inited() { fn prompt_new_password() -> io::Result<String> {
return Err(io::Error::new(io::ErrorKind::AlreadyExists, "Reinitialization attempted"));
}
print!("Enter passphrase for storage: "); print!("Enter passphrase for storage: ");
io::stdout().flush()?; io::stdout().flush()?;
let ps = rpassword::read_password()?; let ps = rpassword::read_password()?;
if ps.len() < 8 {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "Passphrase must be longet that 8 letters"));
}
if ps.len() > 32 {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "Passphrase must be shorted that 32 letters"));
}
print!("Reenter passphrase: "); print!("Reenter passphrase: ");
io::stdout().flush()?; io::stdout().flush()?;
let ps2 = rpassword::read_password()?; let ps2 = rpassword::read_password()?;
if ps != ps2 { if ps != ps2 {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "Passphrases must be equal")); return Err(io::Error::new(io::ErrorKind::InvalidInput, "Passphrases must be equal"));
} }
Storage::init(ps)?; Ok(ps)
}
fn init() -> io::Result<()> {
if Storage::is_inited()? {
return Err(io::Error::new(io::ErrorKind::AlreadyExists, "Reinitialization attempted"));
}
let mut passphrase = String::from("");
loop {
match MPS::prompt_new_password() {
Ok(ps) => {
passphrase = ps;
break;
},
Err(_) => continue
}
}
Storage::init(passphrase)?;
Ok(()) Ok(())
} }
@ -200,10 +221,10 @@ fn run_command() -> io::Result<()> {
mps.edit(id)? mps.edit(id)?
} }
None => { None => {
if !Storage::is_inited() { if !Storage::is_inited()? {
match get_prompt("Do you want to init your storage?")? { match get_prompt("Do you want to init your storage?")? {
PROMPT::YES => MPS::init()?, PROMPT::YES => MPS::init()?,
PROMPT::NO => Storage::print_init_hint(), PROMPT::NO => Storage::print_init_hint()?,
} }
} else { } else {
let mut mps = MPS::new(); let mut mps = MPS::new();

69
src/storage.rs

@ -2,11 +2,10 @@ use crate::encoder;
use encoder::Encoder; use encoder::Encoder;
use once_cell::sync::Lazy;
use std::collections::HashSet; use std::collections::HashSet;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::env;
use std::fs; use std::fs;
use std::path::Path; use std::path::Path;
use std::io::{self, Write, BufRead}; use std::io::{self, Write, BufRead};
@ -14,10 +13,10 @@ use std::fmt;
use std::cmp::{PartialEq, Ordering}; use std::cmp::{PartialEq, Ordering};
static STORAGE_FOLDER: Lazy<String> = Lazy::new(|| "storage".to_string() ); static ENV_MPS_HOME: &str = "MPS_HOME";
static STORAGE_PATH: Lazy<String> = Lazy::new(|| {
format!("{}/db.mps", &*STORAGE_FOLDER) static PATH_STORAGE: &str = "storage"; // should be under git
}); static PATH_DB: &str = "db.mps";
#[derive(Clone)] #[derive(Clone)]
@ -82,15 +81,30 @@ impl Storage {
encoder: Encoder::from(&passphrase) encoder: Encoder::from(&passphrase)
} }
} }
fn get_storage_path() -> io::Result<String> {
let mps_home = env::var(ENV_MPS_HOME).map_err(|err| {
io::Error::new(io::ErrorKind::NotFound, format!("{} error: {}", ENV_MPS_HOME, err))
})?;
let result = format!("{}/{}", mps_home, PATH_STORAGE);
Ok(result)
}
fn get_storage_db_path() -> io::Result<String> {
let st = Storage::get_storage_path()?;
let result = format!("{}/{}", st, PATH_DB);
Ok(result)
}
pub fn from_db(passphrase: String) -> io::Result<Storage> { pub fn from_db(passphrase: String) -> io::Result<Storage> {
if !Storage::is_inited() { if !Storage::is_inited()? {
return Err(io::Error::new( return Err(io::Error::new(
io::ErrorKind::Other, io::ErrorKind::Other,
"Storage is not initialized" "Storage is not initialized"
)); ));
} }
let encoder = Encoder::from(&passphrase); let encoder = Encoder::from(&passphrase);
let file = fs::File::open(&*STORAGE_PATH)?; let file = fs::File::open(Storage::get_storage_db_path()?)?;
let reader = io::BufReader::new(file); let reader = io::BufReader::new(file);
let mut items = HashSet::<Item>::new(); let mut items = HashSet::<Item>::new();
let mut id: Option<String> = None; let mut id: Option<String> = None;
@ -129,31 +143,36 @@ impl Storage {
} }
pub fn init(passphrase: String) -> io::Result<()> { pub fn init(passphrase: String) -> io::Result<()> {
fs::create_dir(&*STORAGE_FOLDER)?; // TODO: revrite all logic
println!("Storage folder created"); // Check if the folder exists and is a directory
fs::File::create(&*STORAGE_PATH)?; //if path.exists() && path.is_dir() {
let st = Storage::new(passphrase); // Err(io::Error::new(io::ErrorKind::NotFound, "Folder does not exist"))
st.dump()?; //}
println!("Storage db created."); //fs::File::create(&*STORAGE_PATH)?;
println!("Initialization complete."); //let st = Storage::new(passphrase);
println!(""); //st.dump()?;
println!("Now it's required to add folder `{}` under git manually.", &*STORAGE_FOLDER); //println!("Storage db created.");
println!("Don't worry it's going to be encrypted."); //println!("Initialization complete.");
//println!("");
//println!("Now it's required to add folder `{}` under git manually.", &*STORAGE_FOLDER);
//println!("Don't worry it's going to be encrypted.");
Ok(()) Ok(())
} }
pub fn print_init_hint() { pub fn print_init_hint() -> io::Result<()> {
println!("mps can work only when storage inited."); println!("mps can work only when storage inited.");
println!("Hint: you can restore your storage if you have it already:"); println!("Hint: you can restore your storage if you have it already:");
println!(" git clone <your_storage_git_url> {}", &*STORAGE_FOLDER); println!(" git clone <your_storage_git_url> {}", Storage::get_storage_path()?);
println!("to init manually your storage and config") println!("to init manually your storage and config");
Ok(())
} }
pub fn is_inited() -> bool { pub fn is_inited() -> io::Result<bool> {
// TODO: check db // TODO: check db
// TODO check git // TODO check git
let path = Path::new(&*STORAGE_FOLDER); //let path = Path::new(&*STORAGE_FOLDER);
return path.exists(); //return path.exists();
Ok(true)
} }
@ -189,7 +208,7 @@ impl Storage {
let mut file = fs::OpenOptions::new() let mut file = fs::OpenOptions::new()
.write(true) .write(true)
.append(false) .append(false)
.open(&*STORAGE_PATH)?; .open(Storage::get_storage_db_path()?)?;
writeln!(file, "{}", self.encoder.get_encoded_test_passphrase()?)?; writeln!(file, "{}", self.encoder.get_encoded_test_passphrase()?)?;
for item in self.items.iter() { for item in self.items.iter() {

Loading…
Cancel
Save