Split up MasterPass::verify into 2 functions: MasterPass::get and master_pass::Model::verify, refactored check_master_pass
This commit is contained in:
parent
1fb004f949
commit
e39762916d
@ -1,7 +1,6 @@
|
|||||||
use rand::{rngs::OsRng, RngCore};
|
use rand::{rngs::OsRng, RngCore};
|
||||||
use scrypt::{scrypt, Params};
|
use scrypt::{scrypt, Params};
|
||||||
use sea_orm::{entity::prelude::*, ActiveValue::Set, QuerySelect};
|
use sea_orm::{entity::prelude::*, ActiveValue::Set, QuerySelect};
|
||||||
use tokio::task::spawn_blocking;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "master_pass")]
|
#[sea_orm(table_name = "master_pass")]
|
||||||
@ -28,6 +27,14 @@ fn hash_password(password: &[u8], salt: &[u8]) -> crate::Result<Vec<u8>> {
|
|||||||
Ok(password_hash)
|
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<bool> {
|
||||||
|
let hashed = hash_password(password.as_bytes(), &self.salt)?;
|
||||||
|
Ok(hashed == self.password_hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ActiveModel {
|
impl ActiveModel {
|
||||||
/// Hashes the password and creates an ActiveModel with all fields set to Set variant
|
/// Hashes the password and creates an ActiveModel with all fields set to Set variant
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -44,21 +51,10 @@ impl ActiveModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Entity {
|
impl Entity {
|
||||||
/// Verifies the provided master password against the one from DB
|
/// Gets the master password from the database
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn verify_master_pass(
|
pub async fn get(user_id: u64, db: &DatabaseConnection) -> crate::Result<Option<Model>> {
|
||||||
user_id: u64,
|
Self::find_by_id(user_id).one(db).await.map_err(Into::into)
|
||||||
master_pass: String,
|
|
||||||
db: &DatabaseConnection,
|
|
||||||
) -> crate::Result<Option<bool>> {
|
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the master password for the user exists
|
/// 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
|
/// Removes a master password of the user from the database
|
||||||
pub async fn remove(user_id: u64, db: &DatabaseConnection) -> crate::Result<()> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use sea_orm::prelude::*;
|
use sea_orm::prelude::*;
|
||||||
use teloxide::{adaptors::Throttle, prelude::*};
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
/// Returns true if the provided master password is valid
|
/// Returns true if the provided master password is valid
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -15,23 +16,25 @@ pub async fn check_master_pass<'a>(
|
|||||||
master_pass: &'a str,
|
master_pass: &'a str,
|
||||||
) -> crate::Result<bool> {
|
) -> crate::Result<bool> {
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let result = MasterPass::verify_master_pass(user_id, master_pass.to_owned(), db).await;
|
let model = MasterPass::get(user_id, db).await?;
|
||||||
match result {
|
let is_valid = match model {
|
||||||
Ok(Some(true)) => Ok(true),
|
Some(model) => {
|
||||||
Ok(Some(false)) => {
|
let master_pass = master_pass.to_owned();
|
||||||
bot.send_message(msg.chat.id, "Wrong master password")
|
spawn_blocking(move || model.verify(&master_pass)).await??
|
||||||
.reply_markup(deletion_markup())
|
|
||||||
.await?;
|
|
||||||
Ok(false)
|
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
None => {
|
||||||
bot.send_message(msg.chat.id, "No master password set")
|
bot.send_message(msg.chat.id, "No master password set")
|
||||||
.reply_markup(deletion_markup())
|
.reply_markup(deletion_markup())
|
||||||
.await?;
|
.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(
|
pub async fn get_master_pass(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user