From 3db99a3626f9b3aec9fdad0476308e39a47c3b96 Mon Sep 17 00:00:00 2001 From: StNicolay Date: Tue, 9 May 2023 20:27:58 +0300 Subject: [PATCH] Added comments to the funtions --- src/entity/account.rs | 3 +++ src/entity/master_pass.rs | 1 + src/handlers/callbacks/delete_message.rs | 2 ++ src/handlers/callbacks/mod.rs | 2 ++ src/handlers/commands/add_account.rs | 5 +++++ src/handlers/commands/cancel.rs | 1 + src/handlers/commands/default.rs | 10 +++++++--- src/handlers/commands/delete.rs | 4 ++++ src/handlers/commands/delete_all.rs | 3 +++ src/handlers/commands/export.rs | 2 ++ src/handlers/commands/gen_password.rs | 11 +++++++---- src/handlers/commands/get_account.rs | 3 +++ src/handlers/commands/get_accounts.rs | 1 + src/handlers/commands/help.rs | 1 + src/handlers/commands/import.rs | 3 +++ src/handlers/commands/mod.rs | 2 ++ src/handlers/commands/set_master_pass.rs | 2 ++ src/handlers/commands/start.rs | 1 + src/handlers/markups.rs | 3 +++ src/handlers/master_password_check.rs | 7 +++++++ src/handlers/mod.rs | 1 + src/handlers/state/generic.rs | 1 + src/handlers/state/get_account_name.rs | 1 + src/handlers/state/get_document.rs | 1 + src/handlers/state/get_login.rs | 1 + src/handlers/state/get_master_pass.rs | 1 + src/handlers/state/get_password.rs | 1 + src/handlers/state/mod.rs | 2 ++ src/handlers/utils.rs | 3 +++ src/models.rs | 4 +++- 30 files changed, 75 insertions(+), 8 deletions(-) diff --git a/src/entity/account.rs b/src/entity/account.rs index a79047f..504f569 100644 --- a/src/entity/account.rs +++ b/src/entity/account.rs @@ -88,6 +88,7 @@ impl Model { } impl Entity { + /// Gets all user's account from DB pub async fn get_all( user_id: u64, db: &DatabaseConnection, @@ -116,6 +117,7 @@ impl Entity { Ok(result.err_into()) } + /// Checks if the account exists pub async fn exists( user_id: u64, account_name: impl Into, @@ -130,6 +132,7 @@ impl Entity { Ok(result.is_some()) } + /// Gets the account from the DB pub async fn get( user_id: u64, account_name: impl Into, diff --git a/src/entity/master_pass.rs b/src/entity/master_pass.rs index 16ba11c..e6a7253 100644 --- a/src/entity/master_pass.rs +++ b/src/entity/master_pass.rs @@ -42,6 +42,7 @@ impl ActiveModel { } impl Entity { + /// Verifies the provided master password against the one from DB pub async fn verify_master_pass( user_id: u64, master_pass: String, diff --git a/src/handlers/callbacks/delete_message.rs b/src/handlers/callbacks/delete_message.rs index 0f81284..8945586 100644 --- a/src/handlers/callbacks/delete_message.rs +++ b/src/handlers/callbacks/delete_message.rs @@ -1,5 +1,6 @@ use teloxide::{adaptors::Throttle, prelude::*}; +/// Deletes the message from the callback pub async fn run(bot: Throttle, q: CallbackQuery) -> crate::Result<()> { match q.message { Some(msg) => { @@ -10,6 +11,7 @@ pub async fn run(bot: Throttle, q: CallbackQuery) -> crate::Result<()> { } } +/// Filters the delete_message callbacks pub fn filter(q: CallbackQuery) -> bool { matches!(q.data.as_deref(), Some("delete_message")) } diff --git a/src/handlers/callbacks/mod.rs b/src/handlers/callbacks/mod.rs index dec9066..ec58fab 100644 --- a/src/handlers/callbacks/mod.rs +++ b/src/handlers/callbacks/mod.rs @@ -1 +1,3 @@ +//! This module consists of endpoints to handle callbacks + pub mod delete_message; diff --git a/src/handlers/commands/add_account.rs b/src/handlers/commands/add_account.rs index 1eefacb..ce731ab 100644 --- a/src/handlers/commands/add_account.rs +++ b/src/handlers/commands/add_account.rs @@ -8,6 +8,7 @@ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; use tokio::task::spawn_blocking; +/// Gets the name of the master password, encryptes the account and adds it to the DB async fn get_master_pass( bot: Throttle, msg: Message, @@ -26,6 +27,7 @@ async fn get_master_pass( Ok(()) } +/// Gets the password of the account to add async fn get_password( bot: Throttle, msg: Message, @@ -54,6 +56,7 @@ async fn get_password( Ok(()) } +/// Gets the login of the account to add async fn get_login( bot: Throttle, msg: Message, @@ -74,6 +77,7 @@ async fn get_login( Ok(()) } +/// Gets the name of the account to add and checks that there're no accounts with the same name async fn get_account_name( bot: Throttle, msg: Message, @@ -98,6 +102,7 @@ async fn get_account_name( Ok(()) } +/// Handles /add_account pub async fn add_account( bot: Throttle, msg: Message, diff --git a/src/handlers/commands/cancel.rs b/src/handlers/commands/cancel.rs index 1f0283e..e3445ad 100644 --- a/src/handlers/commands/cancel.rs +++ b/src/handlers/commands/cancel.rs @@ -1,5 +1,6 @@ use teloxide::{adaptors::Throttle, prelude::*}; +/// Handles /cancel command when there's no active state pub async fn cancel(bot: Throttle, msg: Message) -> crate::Result<()> { bot.send_message(msg.chat.id, "Nothing to cancel").await?; Ok(()) diff --git a/src/handlers/commands/default.rs b/src/handlers/commands/default.rs index 179ca34..e6ab59d 100644 --- a/src/handlers/commands/default.rs +++ b/src/handlers/commands/default.rs @@ -1,9 +1,13 @@ use crate::handlers::markups::deletion_markup; use teloxide::{adaptors::Throttle, prelude::*}; +/// Handles the messages which weren't matched by any commands or states pub async fn default(bot: Throttle, msg: Message) -> crate::Result<()> { - bot.send_message(msg.chat.id, "Unknown command") - .reply_markup(deletion_markup()) - .await?; + bot.send_message( + msg.chat.id, + "Unknown command. Use /help command to get the list of commands", + ) + .reply_markup(deletion_markup()) + .await?; Ok(()) } diff --git a/src/handlers/commands/delete.rs b/src/handlers/commands/delete.rs index 75f7ef4..27b2780 100644 --- a/src/handlers/commands/delete.rs +++ b/src/handlers/commands/delete.rs @@ -10,6 +10,8 @@ use crate::{ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; +/// Gets the master password and deletes the account. +/// Although it doesn't use the master password, we get it to be sure that it's the user who used that command async fn get_master_pass( bot: Throttle, msg: Message, @@ -26,6 +28,7 @@ async fn get_master_pass( Ok(()) } +/// Gets the name of the account to delete async fn get_account_name( bot: Throttle, msg: Message, @@ -52,6 +55,7 @@ async fn get_account_name( Ok(()) } +/// Handles /delete command pub async fn delete( bot: Throttle, msg: Message, diff --git a/src/handlers/commands/delete_all.rs b/src/handlers/commands/delete_all.rs index 37184cc..8957418 100644 --- a/src/handlers/commands/delete_all.rs +++ b/src/handlers/commands/delete_all.rs @@ -6,6 +6,8 @@ use crate::{ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; +/// Gets the master password, deletes the accounts and the master password from DB. +/// Although it doesn't use the master password, we get it to be sure that it's the user who used that command async fn get_master_pass( bot: Throttle, msg: Message, @@ -26,6 +28,7 @@ async fn get_master_pass( Ok(()) } +/// Handles /delete_all command pub async fn delete_all( bot: Throttle, msg: Message, diff --git a/src/handlers/commands/export.rs b/src/handlers/commands/export.rs index 1f2d203..a8b31c3 100644 --- a/src/handlers/commands/export.rs +++ b/src/handlers/commands/export.rs @@ -11,6 +11,7 @@ use std::sync::Arc; use teloxide::{adaptors::Throttle, prelude::*, types::InputFile}; use tokio::{sync::Mutex, task::spawn_blocking}; +/// Gets the master password, decryptes the account and sends the json file to the user async fn get_master_pass( bot: Throttle, msg: Message, @@ -54,6 +55,7 @@ async fn get_master_pass( Ok(()) } +/// Handles /export command pub async fn export(bot: Throttle, msg: Message, dialogue: MainDialogue) -> crate::Result<()> { let previous = bot .send_message(msg.chat.id, "Send a master password to export the accounts") diff --git a/src/handlers/commands/gen_password.rs b/src/handlers/commands/gen_password.rs index 2f5012e..23d9274 100644 --- a/src/handlers/commands/gen_password.rs +++ b/src/handlers/commands/gen_password.rs @@ -1,13 +1,14 @@ +use crate::handlers::markups::deletion_markup; use arrayvec::{ArrayString, ArrayVec}; use rand::{rngs::OsRng, seq::SliceRandom}; use std::{iter, str::from_utf8_unchecked}; use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode}; use tokio::task::JoinSet; -use crate::handlers::markups::deletion_markup; - -const CHARS: &'static [u8] = br##"!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~"##; +const CHARS: &[u8] = br##"!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~"##; +/// Returns true if the generated master password is valid. +/// It checks that it has at least one lowercase, one lowercase and one punctuation char #[inline] fn check_generated_password(password: &[u8]) -> bool { let mut flags: u8 = 0; @@ -26,6 +27,7 @@ fn check_generated_password(password: &[u8]) -> bool { false } +/// Continuously generates the password until it passes the checks fn generete_password() -> ArrayString<34> { loop { let password: ArrayVec = iter::repeat_with(|| *CHARS.choose(&mut OsRng).unwrap()) @@ -41,12 +43,13 @@ fn generete_password() -> ArrayString<34> { } } +/// Handles /gen_password command by generating 10 copyable passwords and sending them to the user pub async fn gen_password(bot: Throttle, msg: Message) -> crate::Result<()> { let mut message = ArrayString::<{ 11 + 35 * 10 }>::new(); message.push_str("Passwords:\n"); let mut join_set = JoinSet::new(); for _ in 0..10 { - join_set.spawn_blocking(|| generete_password()); + join_set.spawn_blocking(generete_password); } while let Some(password) = join_set.join_next().await { message.push_str(password?.as_str()); diff --git a/src/handlers/commands/get_account.rs b/src/handlers/commands/get_account.rs index 1969e16..0146749 100644 --- a/src/handlers/commands/get_account.rs +++ b/src/handlers/commands/get_account.rs @@ -11,6 +11,7 @@ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode}; use tokio::task::spawn_blocking; +/// Gets the master password, decryptes the account and sends it to the user with copyable fields async fn get_master_pass( bot: Throttle, msg: Message, @@ -39,6 +40,7 @@ async fn get_master_pass( Ok(()) } +/// Gets the account name to get async fn get_account_name( bot: Throttle, msg: Message, @@ -67,6 +69,7 @@ async fn get_account_name( Ok(()) } +/// Handles /get_account command pub async fn get_account( bot: Throttle, msg: Message, diff --git a/src/handlers/commands/get_accounts.rs b/src/handlers/commands/get_accounts.rs index 3ab0258..12ffef1 100644 --- a/src/handlers/commands/get_accounts.rs +++ b/src/handlers/commands/get_accounts.rs @@ -3,6 +3,7 @@ use futures::TryStreamExt; use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode}; +/// Handles /get_accounts command by sending the list of copyable account names to the user pub async fn get_accounts( bot: Throttle, msg: Message, diff --git a/src/handlers/commands/help.rs b/src/handlers/commands/help.rs index 7ffc1e6..90d3f46 100644 --- a/src/handlers/commands/help.rs +++ b/src/handlers/commands/help.rs @@ -1,6 +1,7 @@ use crate::handlers::{markups::deletion_markup, Command}; use teloxide::{adaptors::Throttle, prelude::*, utils::command::BotCommands}; +/// Handles the help command by sending the passwords descryptions pub async fn help(bot: Throttle, msg: Message) -> crate::Result<()> { bot.send_message(msg.chat.id, Command::descriptions().to_string()) .reply_markup(deletion_markup()) diff --git a/src/handlers/commands/import.rs b/src/handlers/commands/import.rs index 5e5d109..e5d73de 100644 --- a/src/handlers/commands/import.rs +++ b/src/handlers/commands/import.rs @@ -11,6 +11,7 @@ use std::sync::Arc; use teloxide::{adaptors::Throttle, net::Download, prelude::*}; use tokio::{sync::Mutex, task::spawn_blocking}; +/// Gets the master password, encryptes and adds the accounts to the DB async fn get_master_pass( bot: Throttle, msg: Message, @@ -70,6 +71,7 @@ async fn get_master_pass( Ok(()) } +/// Downloads and parses the json and asks for the master password async fn get_document( bot: Throttle, msg: Message, @@ -129,6 +131,7 @@ async fn get_document( Ok(()) } +/// Handles /import command pub async fn import(bot: Throttle, msg: Message, dialogue: MainDialogue) -> crate::Result<()> { let previous = bot .send_message( diff --git a/src/handlers/commands/mod.rs b/src/handlers/commands/mod.rs index f3007cd..feee469 100644 --- a/src/handlers/commands/mod.rs +++ b/src/handlers/commands/mod.rs @@ -1,3 +1,5 @@ +//! This module consists of endpoints to handle commands + mod add_account; mod cancel; mod default; diff --git a/src/handlers/commands/set_master_pass.rs b/src/handlers/commands/set_master_pass.rs index f99f0d1..69c7ad2 100644 --- a/src/handlers/commands/set_master_pass.rs +++ b/src/handlers/commands/set_master_pass.rs @@ -7,6 +7,7 @@ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; use tokio::task; +/// Actually sets the master password async fn get_master_pass( bot: Throttle, msg: Message, @@ -27,6 +28,7 @@ async fn get_master_pass( Ok(()) } +/// Handles /set_master_pass command pub async fn set_master_pass( bot: Throttle, msg: Message, diff --git a/src/handlers/commands/start.rs b/src/handlers/commands/start.rs index b5fd991..78e8f16 100644 --- a/src/handlers/commands/start.rs +++ b/src/handlers/commands/start.rs @@ -1,5 +1,6 @@ use teloxide::{adaptors::Throttle, prelude::*}; +/// Handles /start command by sending the greeting message pub async fn start(bot: Throttle, msg: Message) -> crate::Result<()> { bot.send_message( msg.chat.id, diff --git a/src/handlers/markups.rs b/src/handlers/markups.rs index 296037e..20af21d 100644 --- a/src/handlers/markups.rs +++ b/src/handlers/markups.rs @@ -3,6 +3,7 @@ use futures::TryStreamExt; use sea_orm::prelude::*; use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, KeyboardMarkup}; +/// Creates a markup of all user's account names #[inline] pub async fn account_markup( user_id: u64, @@ -20,6 +21,8 @@ pub async fn account_markup( Ok(markup) } +/// Creates a markup with a "Delete message" button. +/// This markup should be added for all messages that won't be deleted afterwards #[inline] pub fn deletion_markup() -> InlineKeyboardMarkup { let button = InlineKeyboardButton::callback("Delete message", "delete_message"); diff --git a/src/handlers/master_password_check.rs b/src/handlers/master_password_check.rs index cfea4fd..2c2228e 100644 --- a/src/handlers/master_password_check.rs +++ b/src/handlers/master_password_check.rs @@ -4,6 +4,12 @@ use teloxide::{adaptors::Throttle, dispatching::DpHandlerDescription, prelude::* use super::markups::deletion_markup; +/// A wierd filter that checks for the existance of a master password. +/// +/// # Returns +/// +/// Returns None if account exists, Some(None) if there's an account and Some(Some(String)) if an error occures. +/// The String represents the error that occured async fn master_pass_exists(msg: Message, db: DatabaseConnection) -> Option> { let user_id = match msg.from() { Some(user) => user.id.0, @@ -30,6 +36,7 @@ async fn notify_about_no_master_pass( Ok(()) } +/// Gets a handler that filters out the messages of users that don't have a master password set pub fn get_handler() -> Handler<'static, DependencyMap, crate::Result<()>, DpHandlerDescription> { dptree::filter_map_async(master_pass_exists).endpoint(notify_about_no_master_pass) } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index db664a1..95aa62b 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -94,6 +94,7 @@ pub fn get_dispatcher( .branch(case![Command::SetMasterPass].endpoint(commands::set_master_pass)) .branch(case![Command::GenPassword].endpoint(commands::gen_password)) .branch(case![Command::Cancel].endpoint(commands::cancel)) + // This branch filters out the users that don't have a master password set .branch(master_password_check::get_handler()) .branch(case![Command::AddAccount].endpoint(commands::add_account)) .branch(case![Command::GetAccount].endpoint(commands::get_account)) diff --git a/src/handlers/state/generic.rs b/src/handlers/state/generic.rs index 161d7c3..a8ce012 100644 --- a/src/handlers/state/generic.rs +++ b/src/handlers/state/generic.rs @@ -6,6 +6,7 @@ use crate::{ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; +/// A generic state handler. It checks for "/cancel" messages and runs the provided validation function pub async fn generic( bot: Throttle, text: String, diff --git a/src/handlers/state/get_account_name.rs b/src/handlers/state/get_account_name.rs index 2eae066..aff5c92 100644 --- a/src/handlers/state/get_account_name.rs +++ b/src/handlers/state/get_account_name.rs @@ -6,6 +6,7 @@ use crate::{ handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler}, }; +/// Function to handle GetAccountName state pub async fn get_account_name( bot: Throttle, msg: Message, diff --git a/src/handlers/state/get_document.rs b/src/handlers/state/get_document.rs index 373f162..8141add 100644 --- a/src/handlers/state/get_document.rs +++ b/src/handlers/state/get_document.rs @@ -5,6 +5,7 @@ use crate::{ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; +/// Function to handle get_document state. It doesn't actually validate anything pub async fn get_document( bot: Throttle, msg: Message, diff --git a/src/handlers/state/get_login.rs b/src/handlers/state/get_login.rs index 8804f73..e55b07a 100644 --- a/src/handlers/state/get_login.rs +++ b/src/handlers/state/get_login.rs @@ -6,6 +6,7 @@ use crate::{ handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler}, }; +/// Function to handle GetLogin state pub async fn get_login( bot: Throttle, msg: Message, diff --git a/src/handlers/state/get_master_pass.rs b/src/handlers/state/get_master_pass.rs index aeb693d..5415856 100644 --- a/src/handlers/state/get_master_pass.rs +++ b/src/handlers/state/get_master_pass.rs @@ -6,6 +6,7 @@ use crate::{ use sea_orm::prelude::*; use teloxide::{adaptors::Throttle, prelude::*}; +/// Returns true if the provided master password is valid #[inline] pub async fn check_master_pass<'a>( bot: &'a Throttle, diff --git a/src/handlers/state/get_password.rs b/src/handlers/state/get_password.rs index dec8ba3..708908b 100644 --- a/src/handlers/state/get_password.rs +++ b/src/handlers/state/get_password.rs @@ -6,6 +6,7 @@ use crate::{ handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler}, }; +/// Function to handle GetPassword state pub async fn get_password( bot: Throttle, msg: Message, diff --git a/src/handlers/state/mod.rs b/src/handlers/state/mod.rs index db0e503..eb54e0c 100644 --- a/src/handlers/state/mod.rs +++ b/src/handlers/state/mod.rs @@ -1,3 +1,5 @@ +//! This module consists of endpoints to handle the state + mod generic; mod get_account_name; mod get_document; diff --git a/src/handlers/utils.rs b/src/handlers/utils.rs index 2ff722a..2bb2c6d 100644 --- a/src/handlers/utils.rs +++ b/src/handlers/utils.rs @@ -4,6 +4,7 @@ use std::{future::Future, sync::Arc}; use teloxide::{adaptors::Throttle, prelude::*}; use tokio::sync::Mutex; +/// Convinience method to convert a simple async function and a previous message into PackagedHandler #[inline] pub fn package_handler(f: H, previous: impl Into>) -> PackagedHandler where @@ -21,10 +22,12 @@ where }))) } +/// Deletes the message ignoring the errors pub async fn delete_message(bot: Throttle, msg: Message) { let _ = bot.delete_message(msg.chat.id, msg.id).await; } +/// Deletes the message if there is one ignoring the errors #[inline] pub async fn delete_optional(bot: &Throttle, msg: &Option) { if let Some(msg) = msg { diff --git a/src/models.rs b/src/models.rs index 4f61758..0ce80a4 100644 --- a/src/models.rs +++ b/src/models.rs @@ -9,6 +9,7 @@ pub struct DecryptedAccount { } impl DecryptedAccount { + /// Constructs DecryptedAccount by decrypting the provided account pub fn from_account(account: account::Model, master_pass: &str) -> crate::Result { let name = account.name.clone(); let (login, password) = account.decrypt(master_pass)?; @@ -19,6 +20,7 @@ impl DecryptedAccount { }) } + /// Constructs ActiveModel with eath field Set by encrypting `self` pub fn into_account( self, user_id: u64, @@ -28,7 +30,7 @@ impl DecryptedAccount { account::ActiveModel::from_unencrypted(user_id, name, &login, &password, master_pass) } - /// Returns true if the account is valid + /// Returns true if the account's fields are valid #[inline] pub fn validate(&self) -> bool { for string in [&self.name, &self.login, &self.password] {