Added comments to the funtions

This commit is contained in:
StNicolay 2023-05-09 20:27:58 +03:00
parent 207832be43
commit 3db99a3626
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
30 changed files with 75 additions and 8 deletions

View File

@ -88,6 +88,7 @@ impl Model {
} }
impl Entity { impl Entity {
/// Gets all user's account from DB
pub async fn get_all( pub async fn get_all(
user_id: u64, user_id: u64,
db: &DatabaseConnection, db: &DatabaseConnection,
@ -116,6 +117,7 @@ impl Entity {
Ok(result.err_into()) Ok(result.err_into())
} }
/// Checks if the account exists
pub async fn exists( pub async fn exists(
user_id: u64, user_id: u64,
account_name: impl Into<String>, account_name: impl Into<String>,
@ -130,6 +132,7 @@ impl Entity {
Ok(result.is_some()) Ok(result.is_some())
} }
/// Gets the account from the DB
pub async fn get( pub async fn get(
user_id: u64, user_id: u64,
account_name: impl Into<String>, account_name: impl Into<String>,

View File

@ -42,6 +42,7 @@ impl ActiveModel {
} }
impl Entity { impl Entity {
/// Verifies the provided master password against the one from DB
pub async fn verify_master_pass( pub async fn verify_master_pass(
user_id: u64, user_id: u64,
master_pass: String, master_pass: String,

View File

@ -1,5 +1,6 @@
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
/// Deletes the message from the callback
pub async fn run(bot: Throttle<Bot>, q: CallbackQuery) -> crate::Result<()> { pub async fn run(bot: Throttle<Bot>, q: CallbackQuery) -> crate::Result<()> {
match q.message { match q.message {
Some(msg) => { Some(msg) => {
@ -10,6 +11,7 @@ pub async fn run(bot: Throttle<Bot>, q: CallbackQuery) -> crate::Result<()> {
} }
} }
/// Filters the delete_message callbacks
pub fn filter(q: CallbackQuery) -> bool { pub fn filter(q: CallbackQuery) -> bool {
matches!(q.data.as_deref(), Some("delete_message")) matches!(q.data.as_deref(), Some("delete_message"))
} }

View File

@ -1 +1,3 @@
//! This module consists of endpoints to handle callbacks
pub mod delete_message; pub mod delete_message;

View File

@ -8,6 +8,7 @@ use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
use tokio::task::spawn_blocking; 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( async fn get_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -26,6 +27,7 @@ async fn get_master_pass(
Ok(()) Ok(())
} }
/// Gets the password of the account to add
async fn get_password( async fn get_password(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -54,6 +56,7 @@ async fn get_password(
Ok(()) Ok(())
} }
/// Gets the login of the account to add
async fn get_login( async fn get_login(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -74,6 +77,7 @@ async fn get_login(
Ok(()) 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( async fn get_account_name(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -98,6 +102,7 @@ async fn get_account_name(
Ok(()) Ok(())
} }
/// Handles /add_account
pub async fn add_account( pub async fn add_account(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -1,5 +1,6 @@
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
/// Handles /cancel command when there's no active state
pub async fn cancel(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> { pub async fn cancel(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
bot.send_message(msg.chat.id, "Nothing to cancel").await?; bot.send_message(msg.chat.id, "Nothing to cancel").await?;
Ok(()) Ok(())

View File

@ -1,8 +1,12 @@
use crate::handlers::markups::deletion_markup; use crate::handlers::markups::deletion_markup;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
/// Handles the messages which weren't matched by any commands or states
pub async fn default(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> { pub async fn default(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
bot.send_message(msg.chat.id, "Unknown command") bot.send_message(
msg.chat.id,
"Unknown command. Use /help command to get the list of commands",
)
.reply_markup(deletion_markup()) .reply_markup(deletion_markup())
.await?; .await?;
Ok(()) Ok(())

View File

@ -10,6 +10,8 @@ use crate::{
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, 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( async fn get_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -26,6 +28,7 @@ async fn get_master_pass(
Ok(()) Ok(())
} }
/// Gets the name of the account to delete
async fn get_account_name( async fn get_account_name(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -52,6 +55,7 @@ async fn get_account_name(
Ok(()) Ok(())
} }
/// Handles /delete command
pub async fn delete( pub async fn delete(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -6,6 +6,8 @@ use crate::{
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, 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( async fn get_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -26,6 +28,7 @@ async fn get_master_pass(
Ok(()) Ok(())
} }
/// Handles /delete_all command
pub async fn delete_all( pub async fn delete_all(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -11,6 +11,7 @@ use std::sync::Arc;
use teloxide::{adaptors::Throttle, prelude::*, types::InputFile}; use teloxide::{adaptors::Throttle, prelude::*, types::InputFile};
use tokio::{sync::Mutex, task::spawn_blocking}; 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( async fn get_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -54,6 +55,7 @@ async fn get_master_pass(
Ok(()) Ok(())
} }
/// Handles /export command
pub async fn export(bot: Throttle<Bot>, msg: Message, dialogue: MainDialogue) -> crate::Result<()> { pub async fn export(bot: Throttle<Bot>, msg: Message, dialogue: MainDialogue) -> crate::Result<()> {
let previous = bot let previous = bot
.send_message(msg.chat.id, "Send a master password to export the accounts") .send_message(msg.chat.id, "Send a master password to export the accounts")

View File

@ -1,13 +1,14 @@
use crate::handlers::markups::deletion_markup;
use arrayvec::{ArrayString, ArrayVec}; use arrayvec::{ArrayString, ArrayVec};
use rand::{rngs::OsRng, seq::SliceRandom}; use rand::{rngs::OsRng, seq::SliceRandom};
use std::{iter, str::from_utf8_unchecked}; use std::{iter, str::from_utf8_unchecked};
use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode}; use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode};
use tokio::task::JoinSet; use tokio::task::JoinSet;
use crate::handlers::markups::deletion_markup; const CHARS: &[u8] = br##"!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~"##;
const CHARS: &'static [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] #[inline]
fn check_generated_password(password: &[u8]) -> bool { fn check_generated_password(password: &[u8]) -> bool {
let mut flags: u8 = 0; let mut flags: u8 = 0;
@ -26,6 +27,7 @@ fn check_generated_password(password: &[u8]) -> bool {
false false
} }
/// Continuously generates the password until it passes the checks
fn generete_password() -> ArrayString<34> { fn generete_password() -> ArrayString<34> {
loop { loop {
let password: ArrayVec<u8, 32> = iter::repeat_with(|| *CHARS.choose(&mut OsRng).unwrap()) let password: ArrayVec<u8, 32> = 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<Bot>, msg: Message) -> crate::Result<()> { pub async fn gen_password(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
let mut message = ArrayString::<{ 11 + 35 * 10 }>::new(); let mut message = ArrayString::<{ 11 + 35 * 10 }>::new();
message.push_str("Passwords:\n"); message.push_str("Passwords:\n");
let mut join_set = JoinSet::new(); let mut join_set = JoinSet::new();
for _ in 0..10 { 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 { while let Some(password) = join_set.join_next().await {
message.push_str(password?.as_str()); message.push_str(password?.as_str());

View File

@ -11,6 +11,7 @@ use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode}; use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode};
use tokio::task::spawn_blocking; 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( async fn get_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -39,6 +40,7 @@ async fn get_master_pass(
Ok(()) Ok(())
} }
/// Gets the account name to get
async fn get_account_name( async fn get_account_name(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -67,6 +69,7 @@ async fn get_account_name(
Ok(()) Ok(())
} }
/// Handles /get_account command
pub async fn get_account( pub async fn get_account(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -3,6 +3,7 @@ use futures::TryStreamExt;
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode}; 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( pub async fn get_accounts(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -1,6 +1,7 @@
use crate::handlers::{markups::deletion_markup, Command}; use crate::handlers::{markups::deletion_markup, Command};
use teloxide::{adaptors::Throttle, prelude::*, utils::command::BotCommands}; use teloxide::{adaptors::Throttle, prelude::*, utils::command::BotCommands};
/// Handles the help command by sending the passwords descryptions
pub async fn help(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> { pub async fn help(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
bot.send_message(msg.chat.id, Command::descriptions().to_string()) bot.send_message(msg.chat.id, Command::descriptions().to_string())
.reply_markup(deletion_markup()) .reply_markup(deletion_markup())

View File

@ -11,6 +11,7 @@ use std::sync::Arc;
use teloxide::{adaptors::Throttle, net::Download, prelude::*}; use teloxide::{adaptors::Throttle, net::Download, prelude::*};
use tokio::{sync::Mutex, task::spawn_blocking}; use tokio::{sync::Mutex, task::spawn_blocking};
/// Gets the master password, encryptes and adds the accounts to the DB
async fn get_master_pass( async fn get_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -70,6 +71,7 @@ async fn get_master_pass(
Ok(()) Ok(())
} }
/// Downloads and parses the json and asks for the master password
async fn get_document( async fn get_document(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -129,6 +131,7 @@ async fn get_document(
Ok(()) Ok(())
} }
/// Handles /import command
pub async fn import(bot: Throttle<Bot>, msg: Message, dialogue: MainDialogue) -> crate::Result<()> { pub async fn import(bot: Throttle<Bot>, msg: Message, dialogue: MainDialogue) -> crate::Result<()> {
let previous = bot let previous = bot
.send_message( .send_message(

View File

@ -1,3 +1,5 @@
//! This module consists of endpoints to handle commands
mod add_account; mod add_account;
mod cancel; mod cancel;
mod default; mod default;

View File

@ -7,6 +7,7 @@ use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
use tokio::task; use tokio::task;
/// Actually sets the master password
async fn get_master_pass( async fn get_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,
@ -27,6 +28,7 @@ async fn get_master_pass(
Ok(()) Ok(())
} }
/// Handles /set_master_pass command
pub async fn set_master_pass( pub async fn set_master_pass(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -1,5 +1,6 @@
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
/// Handles /start command by sending the greeting message
pub async fn start(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> { pub async fn start(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
bot.send_message( bot.send_message(
msg.chat.id, msg.chat.id,

View File

@ -3,6 +3,7 @@ use futures::TryStreamExt;
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, KeyboardMarkup}; use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, KeyboardMarkup};
/// Creates a markup of all user's account names
#[inline] #[inline]
pub async fn account_markup( pub async fn account_markup(
user_id: u64, user_id: u64,
@ -20,6 +21,8 @@ pub async fn account_markup(
Ok(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] #[inline]
pub fn deletion_markup() -> InlineKeyboardMarkup { pub fn deletion_markup() -> InlineKeyboardMarkup {
let button = InlineKeyboardButton::callback("Delete message", "delete_message"); let button = InlineKeyboardButton::callback("Delete message", "delete_message");

View File

@ -4,6 +4,12 @@ use teloxide::{adaptors::Throttle, dispatching::DpHandlerDescription, prelude::*
use super::markups::deletion_markup; 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<Option<String>> { async fn master_pass_exists(msg: Message, db: DatabaseConnection) -> Option<Option<String>> {
let user_id = match msg.from() { let user_id = match msg.from() {
Some(user) => user.id.0, Some(user) => user.id.0,
@ -30,6 +36,7 @@ async fn notify_about_no_master_pass(
Ok(()) 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> { pub fn get_handler() -> Handler<'static, DependencyMap, crate::Result<()>, DpHandlerDescription> {
dptree::filter_map_async(master_pass_exists).endpoint(notify_about_no_master_pass) dptree::filter_map_async(master_pass_exists).endpoint(notify_about_no_master_pass)
} }

View File

@ -94,6 +94,7 @@ pub fn get_dispatcher(
.branch(case![Command::SetMasterPass].endpoint(commands::set_master_pass)) .branch(case![Command::SetMasterPass].endpoint(commands::set_master_pass))
.branch(case![Command::GenPassword].endpoint(commands::gen_password)) .branch(case![Command::GenPassword].endpoint(commands::gen_password))
.branch(case![Command::Cancel].endpoint(commands::cancel)) .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(master_password_check::get_handler())
.branch(case![Command::AddAccount].endpoint(commands::add_account)) .branch(case![Command::AddAccount].endpoint(commands::add_account))
.branch(case![Command::GetAccount].endpoint(commands::get_account)) .branch(case![Command::GetAccount].endpoint(commands::get_account))

View File

@ -6,6 +6,7 @@ use crate::{
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, 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<F>( pub async fn generic<F>(
bot: Throttle<Bot>, bot: Throttle<Bot>,
text: String, text: String,

View File

@ -6,6 +6,7 @@ use crate::{
handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler}, handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler},
}; };
/// Function to handle GetAccountName state
pub async fn get_account_name( pub async fn get_account_name(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -5,6 +5,7 @@ use crate::{
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
/// Function to handle get_document state. It doesn't actually validate anything
pub async fn get_document( pub async fn get_document(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -6,6 +6,7 @@ use crate::{
handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler}, handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler},
}; };
/// Function to handle GetLogin state
pub async fn get_login( pub async fn get_login(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -6,6 +6,7 @@ use crate::{
use sea_orm::prelude::*; use sea_orm::prelude::*;
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
/// Returns true if the provided master password is valid
#[inline] #[inline]
pub async fn check_master_pass<'a>( pub async fn check_master_pass<'a>(
bot: &'a Throttle<Bot>, bot: &'a Throttle<Bot>,

View File

@ -6,6 +6,7 @@ use crate::{
handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler}, handlers::{markups::deletion_markup, utils::validate_field, MainDialogue, PackagedHandler},
}; };
/// Function to handle GetPassword state
pub async fn get_password( pub async fn get_password(
bot: Throttle<Bot>, bot: Throttle<Bot>,
msg: Message, msg: Message,

View File

@ -1,3 +1,5 @@
//! This module consists of endpoints to handle the state
mod generic; mod generic;
mod get_account_name; mod get_account_name;
mod get_document; mod get_document;

View File

@ -4,6 +4,7 @@ use std::{future::Future, sync::Arc};
use teloxide::{adaptors::Throttle, prelude::*}; use teloxide::{adaptors::Throttle, prelude::*};
use tokio::sync::Mutex; use tokio::sync::Mutex;
/// Convinience method to convert a simple async function and a previous message into PackagedHandler
#[inline] #[inline]
pub fn package_handler<H, F, T>(f: H, previous: impl Into<Option<Message>>) -> PackagedHandler<T> pub fn package_handler<H, F, T>(f: H, previous: impl Into<Option<Message>>) -> PackagedHandler<T>
where where
@ -21,10 +22,12 @@ where
}))) })))
} }
/// Deletes the message ignoring the errors
pub async fn delete_message(bot: Throttle<Bot>, msg: Message) { pub async fn delete_message(bot: Throttle<Bot>, msg: Message) {
let _ = bot.delete_message(msg.chat.id, msg.id).await; let _ = bot.delete_message(msg.chat.id, msg.id).await;
} }
/// Deletes the message if there is one ignoring the errors
#[inline] #[inline]
pub async fn delete_optional(bot: &Throttle<Bot>, msg: &Option<Message>) { pub async fn delete_optional(bot: &Throttle<Bot>, msg: &Option<Message>) {
if let Some(msg) = msg { if let Some(msg) = msg {

View File

@ -9,6 +9,7 @@ pub struct DecryptedAccount {
} }
impl DecryptedAccount { impl DecryptedAccount {
/// Constructs DecryptedAccount by decrypting the provided account
pub fn from_account(account: account::Model, master_pass: &str) -> crate::Result<Self> { pub fn from_account(account: account::Model, master_pass: &str) -> crate::Result<Self> {
let name = account.name.clone(); let name = account.name.clone();
let (login, password) = account.decrypt(master_pass)?; 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( pub fn into_account(
self, self,
user_id: u64, user_id: u64,
@ -28,7 +30,7 @@ impl DecryptedAccount {
account::ActiveModel::from_unencrypted(user_id, name, &login, &password, master_pass) 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] #[inline]
pub fn validate(&self) -> bool { pub fn validate(&self) -> bool {
for string in [&self.name, &self.login, &self.password] { for string in [&self.name, &self.login, &self.password] {