Added checks of the master password for /add_account and /get_account
This commit is contained in:
parent
3f8adb96f9
commit
8aadf96020
@ -86,19 +86,14 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, EnumIter, DeriveColumn, Debug)]
|
|
||||||
enum GetNamesQuery {
|
|
||||||
AccountName,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Entity {
|
impl Entity {
|
||||||
/// Gets a list of account names of a user
|
/// Gets a list of account names of a user
|
||||||
pub async fn get_names(user_id: u64, db: &DatabaseConnection) -> crate::Result<Vec<String>> {
|
pub async fn get_names(user_id: u64, db: &DatabaseConnection) -> crate::Result<Vec<String>> {
|
||||||
Self::find()
|
Self::find()
|
||||||
.select_only()
|
.select_only()
|
||||||
.column_as(Column::Name, GetNamesQuery::AccountName)
|
.column(Column::Name)
|
||||||
.filter(Column::UserId.eq(user_id))
|
.filter(Column::UserId.eq(user_id))
|
||||||
.into_values::<_, GetNamesQuery>()
|
.into_tuple()
|
||||||
.all(db)
|
.all(db)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| err.into())
|
.map_err(|err| err.into())
|
||||||
|
@ -20,22 +20,38 @@ pub enum Relation {}
|
|||||||
|
|
||||||
impl ActiveModelBehavior for ActiveModel {}
|
impl ActiveModelBehavior for ActiveModel {}
|
||||||
|
|
||||||
|
fn hash_password(password: &[u8], salt: &[u8]) -> crate::Result<Vec<u8>> {
|
||||||
|
let params = Params::new(14, Params::RECOMMENDED_R, Params::RECOMMENDED_P, 64)?;
|
||||||
|
let mut password_hash = vec![0; 64];
|
||||||
|
scrypt(password.as_ref(), &salt, ¶ms, &mut password_hash)?;
|
||||||
|
Ok(password_hash)
|
||||||
|
}
|
||||||
|
|
||||||
impl ActiveModel {
|
impl ActiveModel {
|
||||||
pub fn from_unencrypted(user_id: u64, password: &str) -> crate::Result<Self> {
|
pub fn from_unencrypted(user_id: u64, password: &str) -> crate::Result<Self> {
|
||||||
let mut salt = vec![0; 64];
|
let mut salt = vec![0; 64];
|
||||||
OsRng.fill_bytes(&mut salt);
|
OsRng.fill_bytes(&mut salt);
|
||||||
let params = Params::new(
|
let password_hash = Set(hash_password(password.as_ref(), &salt)?);
|
||||||
Params::RECOMMENDED_LOG_N,
|
|
||||||
Params::RECOMMENDED_R,
|
|
||||||
Params::RECOMMENDED_P,
|
|
||||||
64,
|
|
||||||
)?;
|
|
||||||
let mut password_hash = vec![0; 64];
|
|
||||||
scrypt(password.as_ref(), &salt, ¶ms, &mut password_hash)?;
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
user_id: Set(user_id),
|
user_id: Set(user_id),
|
||||||
salt: Set(salt),
|
salt: Set(salt),
|
||||||
password_hash: Set(password_hash),
|
password_hash,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Entity {
|
||||||
|
pub async fn verify_master_pass(
|
||||||
|
user_id: u64,
|
||||||
|
master_pass: &str,
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
) -> crate::Result<Option<bool>> {
|
||||||
|
let model = match Self::find_by_id(user_id).one(db).await {
|
||||||
|
Ok(Some(model)) => model,
|
||||||
|
Ok(None) => return Ok(None),
|
||||||
|
Err(err) => return Err(err.into()),
|
||||||
|
};
|
||||||
|
let password_hash = hash_password(master_pass.as_ref(), &model.salt)?;
|
||||||
|
Ok(Some(password_hash == model.password_hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
|
use crate::{entity::account, utils::handle_master_password_check};
|
||||||
use sea_orm::prelude::*;
|
use sea_orm::prelude::*;
|
||||||
use teloxide::{adaptors::Throttle, prelude::*};
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
use crate::entity::account;
|
|
||||||
|
|
||||||
pub async fn add_account(
|
pub async fn add_account(
|
||||||
bot: Throttle<Bot>,
|
bot: Throttle<Bot>,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
@ -10,6 +9,9 @@ pub async fn add_account(
|
|||||||
(name, login, password, master_pass): (String, String, String, String),
|
(name, login, password, master_pass): (String, String, String, String),
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let user_id = msg.from().unwrap().id.0;
|
let user_id = msg.from().unwrap().id.0;
|
||||||
|
if handle_master_password_check(&bot, &db, msg.chat.id, user_id, &master_pass).await? {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
let account =
|
let account =
|
||||||
account::ActiveModel::from_unencrypted(user_id, name, &login, &password, &master_pass)?;
|
account::ActiveModel::from_unencrypted(user_id, name, &login, &password, &master_pass)?;
|
||||||
account.insert(&db).await?;
|
account.insert(&db).await?;
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
use crate::entity::{account, prelude::Account};
|
use crate::{
|
||||||
|
entity::{account, prelude::Account},
|
||||||
|
utils::handle_master_password_check,
|
||||||
|
};
|
||||||
use sea_orm::prelude::*;
|
use sea_orm::prelude::*;
|
||||||
use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode};
|
use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode};
|
||||||
|
|
||||||
@ -8,10 +11,14 @@ pub async fn get_account(
|
|||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
(name, master_pass): (String, String),
|
(name, master_pass): (String, String),
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
let user_id = msg.from().unwrap().id.0;
|
||||||
|
if handle_master_password_check(&bot, &db, msg.chat.id, user_id, &master_pass).await? {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
let account = Account::find()
|
let account = Account::find()
|
||||||
.filter(
|
.filter(
|
||||||
account::Column::UserId
|
account::Column::UserId
|
||||||
.eq(msg.from().unwrap().id.0)
|
.eq(user_id)
|
||||||
.add(account::Column::Name.eq(&name)),
|
.add(account::Column::Name.eq(&name)),
|
||||||
)
|
)
|
||||||
.one(&db)
|
.one(&db)
|
||||||
|
@ -25,7 +25,7 @@ pub async fn get_accounts(
|
|||||||
result.reserve(name.len() + 3);
|
result.reserve(name.len() + 3);
|
||||||
result.push_str("\n`");
|
result.push_str("\n`");
|
||||||
result.push_str(&name);
|
result.push_str(&name);
|
||||||
result.push('\'')
|
result.push('`')
|
||||||
}
|
}
|
||||||
bot.send_message(msg.chat.id, result)
|
bot.send_message(msg.chat.id, result)
|
||||||
.parse_mode(ParseMode::MarkdownV2)
|
.parse_mode(ParseMode::MarkdownV2)
|
||||||
|
@ -10,10 +10,11 @@ pub async fn set_master_pass(
|
|||||||
master_pass: String,
|
master_pass: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
let user_id = msg.from().unwrap().id.0;
|
let user_id = msg.from().unwrap().id.0;
|
||||||
println!("User id: {user_id}");
|
|
||||||
let exists = MasterPass::find()
|
let exists = MasterPass::find()
|
||||||
|
.select_only()
|
||||||
|
.column(master_pass::Column::UserId)
|
||||||
.filter(master_pass::Column::UserId.eq(user_id))
|
.filter(master_pass::Column::UserId.eq(user_id))
|
||||||
.limit(1)
|
.into_tuple::<u64>()
|
||||||
.one(&db)
|
.one(&db)
|
||||||
.await?
|
.await?
|
||||||
.is_some();
|
.is_some();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
mod entity;
|
mod entity;
|
||||||
mod handlers;
|
mod handlers;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
34
src/utils.rs
Normal file
34
src/utils.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
use crate::entity::prelude::*;
|
||||||
|
use sea_orm::DatabaseConnection;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
|
/// Handles checking the master password
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
///
|
||||||
|
/// Returns Ok(true) if the master password wasn't right or if it wasn't set
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Returns an error if there was an error getting or hashing the master password
|
||||||
|
#[inline]
|
||||||
|
pub async fn handle_master_password_check(
|
||||||
|
bot: &Throttle<Bot>,
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
chat_id: ChatId,
|
||||||
|
user_id: u64,
|
||||||
|
master_pass: &str,
|
||||||
|
) -> crate::Result<bool> {
|
||||||
|
match MasterPass::verify_master_pass(user_id, &master_pass, db).await {
|
||||||
|
Ok(Some(true)) => Ok(false),
|
||||||
|
Ok(Some(false)) => {
|
||||||
|
bot.send_message(chat_id, "Wrong master password").await?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
bot.send_message(chat_id, "No master password set").await?;
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
Err(err) => Err(err.into()),
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user