diff --git a/src/entity/master_pass.rs b/src/entity/master_pass.rs index afa909f..e08c826 100644 --- a/src/entity/master_pass.rs +++ b/src/entity/master_pass.rs @@ -1,7 +1,6 @@ use rand::{rngs::OsRng, RngCore}; use scrypt::{scrypt, Params}; use sea_orm::{entity::prelude::*, ActiveValue::Set, QuerySelect}; -use tokio::task::spawn_blocking; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "master_pass")] @@ -28,6 +27,14 @@ fn hash_password(password: &[u8], salt: &[u8]) -> crate::Result> { Ok(password_hash) } +impl Model { + /// Checks that the given password hash matches the one of the model + pub fn verify(&self, password: &str) -> crate::Result { + let hashed = hash_password(password.as_bytes(), &self.salt)?; + Ok(hashed == self.password_hash) + } +} + impl ActiveModel { /// Hashes the password and creates an ActiveModel with all fields set to Set variant #[inline] @@ -44,21 +51,10 @@ impl ActiveModel { } impl Entity { - /// Verifies the provided master password against the one from DB + /// Gets the master password from the database #[inline] - pub async fn verify_master_pass( - user_id: u64, - master_pass: String, - db: &DatabaseConnection, - ) -> crate::Result> { - let model = match Self::find_by_id(user_id).one(db).await? { - Some(model) => model, - None => return Ok(None), - }; - let salt = model.salt; - let password_hash = - spawn_blocking(move || hash_password(master_pass.as_bytes(), &salt)).await??; - Ok(Some(password_hash == model.password_hash)) + pub async fn get(user_id: u64, db: &DatabaseConnection) -> crate::Result> { + Self::find_by_id(user_id).one(db).await.map_err(Into::into) } /// Checks if the master password for the user exists @@ -75,7 +71,7 @@ impl Entity { /// Removes a master password of the user from the database pub async fn remove(user_id: u64, db: &DatabaseConnection) -> crate::Result<()> { - Self::delete_by_id(user_id).exec(db)?; + Self::delete_by_id(user_id).exec(db).await?; Ok(()) } } diff --git a/src/handlers/state/get_master_pass.rs b/src/handlers/state/get_master_pass.rs index 23d7150..6891e13 100644 --- a/src/handlers/state/get_master_pass.rs +++ b/src/handlers/state/get_master_pass.rs @@ -5,6 +5,7 @@ use crate::{ }; use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; +use tokio::task::spawn_blocking; /// Returns true if the provided master password is valid #[inline] @@ -15,23 +16,25 @@ pub async fn check_master_pass<'a>( master_pass: &'a str, ) -> crate::Result { let user_id = msg.from().ok_or(NoUserInfo)?.id.0; - let result = MasterPass::verify_master_pass(user_id, master_pass.to_owned(), db).await; - match result { - Ok(Some(true)) => Ok(true), - Ok(Some(false)) => { - bot.send_message(msg.chat.id, "Wrong master password") - .reply_markup(deletion_markup()) - .await?; - Ok(false) + let model = MasterPass::get(user_id, db).await?; + let is_valid = match model { + Some(model) => { + let master_pass = master_pass.to_owned(); + spawn_blocking(move || model.verify(&master_pass)).await?? } - Ok(None) => { + None => { bot.send_message(msg.chat.id, "No master password set") .reply_markup(deletion_markup()) .await?; - Ok(false) + return Ok(false); } - Err(err) => Err(err), + }; + if !is_valid { + bot.send_message(msg.chat.id, "Wrong master password") + .reply_markup(deletion_markup()) + .await?; } + Ok(is_valid) } pub async fn get_master_pass(