use std::sync::Arc; use crate::db::Environment; use crate::db::AllocAdapter; use crate::db::DB; use crate::db::RawDB; use crate::db::{DatabaseFlags, WriteFlags}; use crate::db::Result; use crate::db::Transaction; use argon2; type Adapter = AllocAdapter; #[derive(Clone, Debug)] pub struct PassDB { env: Arc, db: DB, } impl PassDB { pub unsafe fn new(env: Arc, db: RawDB) -> Self { let db = DB::new_unchecked(db); Self { env, db } } pub unsafe fn open(env: Arc) -> Result { let db = RawDB::open(&env, Some("pass"))?; Ok(Self::new(env, db)) } pub unsafe fn create(env: Arc) -> Result { let flags = DatabaseFlags::empty(); let db = RawDB::create(&env, Some("pass"), flags)?; Ok(Self::new(env, db)) } pub fn check_pw>(&self, uid: &str, inpass: P) -> Result> { let txn = self.env.begin_ro_txn()?; if let Some(pass) = self.db.get(&txn, &uid.as_bytes())? { Ok(argon2::verify_encoded(pass.as_str(), inpass.as_ref()) .ok()) } else { Ok(None) } } pub fn set_password>(&self, uid: &str, password: P) -> Result<()> { let cfg = argon2::Config::default(); let salt: [u8; 10] = rand::random(); let enc = argon2::hash_encoded(password.as_ref(), &salt, &cfg) .expect("Hashing password failed for static valid config"); let flags = WriteFlags::empty(); let mut txn = self.env.begin_rw_txn()?; self.db.put(&mut txn, &uid.as_bytes(), &enc, flags)?; txn.commit()?; Ok(()) } pub fn get_all(&self) -> Result> { let txn = self.env.begin_ro_txn()?; let mut cursor = self.db.open_ro_cursor(&txn)?; let iter = cursor.iter_start(); let mut out = Vec::new(); for pass in iter { let (uid, pass) = pass?; let uid = unsafe { std::str::from_utf8_unchecked(uid).to_string() }; let pass = pass.as_str().to_string(); out.push((uid, pass)); } Ok(out) } }