Code cleanup

This commit is contained in:
StNicolay 2024-02-22 12:44:02 +03:00
parent 8979cc5b25
commit b526eb0c12
Signed by: StNicolay
GPG Key ID: 9693D04DCD962B0D
18 changed files with 124 additions and 148 deletions

92
Cargo.lock generated
View File

@ -29,9 +29,9 @@ dependencies = [
[[package]]
name = "ahash"
version = "0.8.8"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff"
checksum = "d713b3834d76b85304d4d525563c1276e2e30dc97cc67bfb4585a4a29fc2c89f"
dependencies = [
"cfg-if",
"getrandom",
@ -57,9 +57,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "anyhow"
version = "1.0.79"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
[[package]]
name = "aquamarine"
@ -158,9 +158,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.14.0"
version = "3.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
checksum = "a3b1be7772ee4501dba05acbe66bb1e8760f6a6c474a36035631638e4415f130"
[[package]]
name = "byteorder"
@ -176,12 +176,9 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
version = "1.0.83"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
[[package]]
name = "cfg-if"
@ -603,7 +600,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
]
[[package]]
@ -712,9 +709,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.3.5"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3"
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
[[package]]
name = "hex"
@ -845,9 +842,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.2.2"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
dependencies = [
"equivalent",
"hashbrown",
@ -1236,7 +1233,7 @@ checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
]
[[package]]
@ -1274,9 +1271,9 @@ dependencies = [
[[package]]
name = "pkg-config"
version = "0.3.29"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
[[package]]
name = "poly1305"
@ -1470,16 +1467,17 @@ dependencies = [
[[package]]
name = "ring"
version = "0.17.7"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74"
checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
dependencies = [
"cc",
"cfg-if",
"getrandom",
"libc",
"spin 0.9.8",
"untrusted",
"windows-sys 0.48.0",
"windows-sys 0.52.0",
]
[[package]]
@ -1563,9 +1561,9 @@ dependencies = [
[[package]]
name = "ryu"
version = "1.0.16"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
[[package]]
name = "salsa20"
@ -1606,35 +1604,35 @@ dependencies = [
[[package]]
name = "semver"
version = "1.0.21"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]]
name = "serde"
version = "1.0.196"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.196"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
]
[[package]]
name = "serde_json"
version = "1.0.113"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
dependencies = [
"itoa",
"ryu",
@ -2000,9 +1998,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.48"
version = "2.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
dependencies = [
"proc-macro2",
"quote",
@ -2141,22 +2139,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.56"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
]
[[package]]
@ -2200,7 +2198,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
]
[[package]]
@ -2264,7 +2262,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
]
[[package]]
@ -2317,9 +2315,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
dependencies = [
"tinyvec",
]
@ -2433,7 +2431,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
"wasm-bindgen-shared",
]
@ -2467,7 +2465,7 @@ checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -2703,7 +2701,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
"syn 2.0.50",
]
[[package]]

View File

@ -140,9 +140,9 @@ mod tests {
#[test]
fn account_encryption() -> crate::Result<()> {
let original = Decrypted {
name: "Account Name".into(),
login: "StrongLogin@mail.com".into(),
password: "StrongP@$$word!".into(),
name: "Account Name".to_owned(),
login: "StrongLogin@mail.com".to_owned(),
password: "StrongP@$$word!".to_owned(),
};
let account = original.clone().into_account(1, TESTING_MASTER_PASSWORD);
let decrypted = Decrypted::from_account(account, TESTING_MASTER_PASSWORD)?;

View File

@ -73,3 +73,21 @@ impl From<MasterPass> for HashedBytes<Vec<u8>, Vec<u8>> {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn params_valid() {
#[allow(clippy::no_effect_underscore_binding)]
let _params: &Params = &PARAMS; // Initializes the PARAMS, which might panic if the passed in values are invalid
}
#[test]
fn hashing_test() {
const ORIGINAL: &[u8] = b"Important data";
assert!(HashedBytes::new(ORIGINAL).verify(ORIGINAL));
}
}

View File

@ -39,7 +39,7 @@ impl Account {
/// Streams the names of the user accounts
#[inline]
pub fn get_names(user_id: u64, pool: &Pool) -> impl Stream<Item = crate::Result<String>> + '_ {
query_as::<_, (String,)>("SELECT name FROM account WHERE user_id = ?")
query_as::<_, (String,)>("SELECT name FROM account WHERE user_id = ? ORDER BY name")
.bind(user_id)
.fetch(pool)
.map_ok(|(name,)| name)

View File

@ -1,8 +1,7 @@
use super::AlterableField::{self, Login, Name, Pass};
use crate::{change_state, prelude::*};
use cryptography::account::Cipher;
use futures::TryFutureExt;
use tokio::{task::spawn_blocking, try_join};
use tokio::task::spawn_blocking;
#[inline]
async fn update_account(
@ -81,13 +80,10 @@ pub async fn alter(
let mut ids: MessageIds = q.message.as_ref().unwrap().into();
let Some(name) = Account::get_name_by_hash(user_id, &hash, &db).await? else {
try_join!(
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.send(),
bot.answer_callback_query(q.id).send()
)?;
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.await?;
bot.answer_callback_query(q.id).await?;
return Ok(());
};
@ -106,10 +102,8 @@ pub async fn alter(
}
};
try_join!(
ids.alter_message(&bot, text, None, None),
bot.answer_callback_query(q.id).send().err_into()
)?;
ids.alter_message(&bot, text, None, None).await?;
bot.answer_callback_query(q.id).await?;
Ok(())
}

View File

@ -1,6 +1,6 @@
use crate::{change_state, prelude::*};
use teloxide::types::ParseMode;
use tokio::{task::spawn_blocking, try_join};
use tokio::task::spawn_blocking;
#[inline]
async fn get_master_pass(
@ -53,13 +53,10 @@ pub async fn decrypt(
let user_id = q.from.id.0;
let Some(name) = Account::get_name_by_hash(user_id, &hash, &db).await? else {
try_join!(
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.send(),
bot.answer_callback_query(q.id).send()
)?;
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.await?;
bot.answer_callback_query(q.id).await?;
return Ok(());
};

View File

@ -1,6 +1,3 @@
use futures::TryFutureExt;
use tokio::try_join;
use crate::{change_state, prelude::*};
#[inline]
@ -37,35 +34,28 @@ pub async fn delete(
dialogue: MainDialogue,
(hash, is_command): (super::NameHash, bool),
) -> crate::Result<()> {
const TEXT: &str = "Send master password. \
Once you send the master password the account is unrecoverable";
let mut ids: MessageIds = q.message.as_ref().unwrap().into();
let user_id = q.from.id.0;
let Some(name) = Account::get_name_by_hash(user_id, &hash, &db).await? else {
try_join!(
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.send(),
bot.answer_callback_query(q.id).send()
)?;
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.await?;
bot.answer_callback_query(q.id).await?;
return Ok(());
};
let response = async {
const TEXT: &str = "Send master password. \
Once you send the master password the account is unrecoverable";
if is_command {
ids.alter_message(&bot, TEXT, None, None).await?;
} else {
let msg = bot.send_message(ids.0, TEXT).await?;
ids = MessageIds::from(&msg);
};
Ok::<_, crate::Error>(())
if is_command {
ids.alter_message(&bot, TEXT, None, None).await?;
} else {
let msg = bot.send_message(ids.0, TEXT).await?;
ids = MessageIds::from(&msg);
};
try_join!(response, bot.answer_callback_query(q.id).send().err_into())?;
bot.answer_callback_query(q.id).await?;
change_state!(dialogue, ids, (name), State::GetMasterPass, get_master_pass);

View File

@ -1,5 +1,4 @@
use crate::prelude::*;
use futures::try_join;
use teloxide::types::ParseMode;
#[inline]
@ -13,12 +12,10 @@ pub async fn get(
let mut ids: MessageIds = q.message.as_ref().unwrap().into();
let Some(name) = Account::get_name_by_hash(user_id, &hash, &db).await? else {
try_join!(
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.send(),
bot.answer_callback_query(q.id).send()
)?;
bot.send_message(ids.0, "Account wasn't found")
.reply_markup(deletion_markup())
.await?;
bot.answer_callback_query(q.id).await?;
return Ok(());
};

View File

@ -1,20 +1,18 @@
use crate::prelude::*;
use tokio::task::spawn_blocking;
#[inline]
pub async fn delete(bot: Throttle<Bot>, msg: Message, db: Pool) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let names: Vec<String> = Account::get_names(user_id, &db).try_collect().await?;
let markup = menu_markup("get", user_id, &db).await?;
if names.is_empty() {
if markup.inline_keyboard.is_empty() {
bot.send_message(msg.chat.id, "You don't have any accounts")
.reply_markup(deletion_markup())
.await?;
return Ok(());
}
let markup = spawn_blocking(|| menu_markup_sync("delete1", names)).await?;
bot.send_message(msg.chat.id, "Choose the account to delete")
.reply_markup(markup)
.await?;

View File

@ -14,6 +14,7 @@ async fn get_master_pass(
) -> crate::Result<()> {
dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let mut txn = db.begin().await?;
let result = (
Account::delete_all(user_id, &mut *txn).await,

View File

@ -1,20 +1,18 @@
use crate::prelude::*;
use tokio::task::spawn_blocking;
#[inline]
pub async fn get_account(bot: Throttle<Bot>, msg: Message, db: Pool) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let names: Vec<String> = Account::get_names(user_id, &db).try_collect().await?;
let markup = menu_markup("decrypt", user_id, &db).await?;
if names.is_empty() {
if markup.inline_keyboard.is_empty() {
bot.send_message(msg.chat.id, "You don't have any accounts")
.reply_markup(deletion_markup())
.await?;
return Ok(());
}
let markup = spawn_blocking(|| menu_markup_sync("decrypt", names)).await?;
bot.send_message(msg.chat.id, "Choose the account to get")
.reply_markup(markup)
.await?;

View File

@ -1,5 +1,4 @@
use crate::prelude::*;
use futures::future;
use std::fmt::Write;
use teloxide::types::ParseMode;
@ -18,13 +17,9 @@ pub async fn get_accounts(bot: Throttle<Bot>, msg: Message, db: Pool) -> crate::
return Ok(());
};
account_names
.map_err(crate::Error::from)
.try_for_each(|name| {
let result = write!(text, "\n`{name}`").map_err(Into::into);
future::ready(result)
})
.await?;
while let Some(name) = account_names.try_next().await? {
write!(text, "\n`{name}`")?;
}
bot.send_message(msg.chat.id, text)
.parse_mode(ParseMode::MarkdownV2)

View File

@ -1,20 +1,18 @@
use crate::prelude::*;
use tokio::task::spawn_blocking;
#[inline]
pub async fn menu(bot: Throttle<Bot>, msg: Message, db: Pool) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let names: Vec<String> = Account::get_names(user_id, &db).try_collect().await?;
let markup = menu_markup("get", user_id, &db).await?;
if names.is_empty() {
if markup.inline_keyboard.is_empty() {
bot.send_message(msg.chat.id, "You don't have any accounts")
.reply_markup(deletion_markup())
.await?;
return Ok(());
}
let markup = spawn_blocking(|| menu_markup_sync("get", names)).await?;
bot.send_message(msg.chat.id, "Choose your account")
.reply_markup(markup)
.await?;

View File

@ -40,7 +40,6 @@ async fn get_master_pass2(
Ok(())
}
/// Actually sets the master password
#[inline]
async fn get_master_pass(
bot: Throttle<Bot>,

View File

@ -6,7 +6,7 @@ pub async fn start(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
bot.send_message(
msg.chat.id,
"Hi! This bot can be used to store the passwords securely. \
Use /help command to get the list of commands",
Use /help command to get the list of commands",
)
.await?;
Ok(())

View File

@ -11,7 +11,7 @@ type DynError = Arc<dyn std::error::Error + Send + Sync>;
///
/// # Returns
///
/// Returns None if account exists, Some(None) if there's an account and Some(Some(String)) if an error occures.
/// Returns None if account exists, Some(None) if there's an account and Some(Some(DynError)) if an error occures.
/// The String represents the error that occured
#[inline]
async fn master_pass_exists(update: Update, db: Pool) -> Option<Option<DynError>> {

View File

@ -20,8 +20,8 @@ async fn check_master_pass(
let is_valid = {
let hash = HashedBytes::from(model);
let master_pass = master_pass.to_owned();
spawn_blocking(move || hash.verify(master_pass.as_bytes())).await?
let master_pass: Box<[u8]> = master_pass.as_bytes().into();
spawn_blocking(move || hash.verify(&master_pass)).await?
};
if !is_valid {

View File

@ -31,16 +31,14 @@ fn validate_document(document: Option<&Document>) -> Result<&Document, &'static
}
#[inline]
async fn download_file(bot: &Throttle<Bot>, file: &FileMeta) -> crate::Result<Vec<u8>> {
let path = bot.get_file(file.id.as_str()).await?.path;
async fn download_file(bot: &Throttle<Bot>, file: &FileMeta) -> crate::Result<Box<[u8]>> {
let path = bot.get_file(&file.id).await?.path;
let mut data = Vec::with_capacity(file.size as usize);
bot.download_file_stream(&path)
.try_for_each(|bytes| {
data.extend_from_slice(&bytes);
async { Ok(()) }
})
.await?;
Ok(data)
let mut stream = bot.download_file_stream(&path);
while let Some(bytes) = stream.try_next().await? {
data.extend_from_slice(&bytes);
}
Ok(data.into_boxed_slice())
}
#[inline]
@ -116,12 +114,12 @@ fn process_accounts(
}
#[inline]
fn user_from_vec(
vector: Vec<u8>,
fn user_from_bytes(
bytes: impl AsRef<[u8]>,
existing_names: ahash::HashSet<String>,
) -> crate::Result<Result<User, String>> {
let mut user: User = serde_json::from_slice(&vector)?;
drop(vector);
let mut user: User = serde_json::from_slice(bytes.as_ref())?;
drop(bytes);
match process_accounts(&mut user.accounts, existing_names)? {
Ok(()) => Ok(Ok(user)),
Err(error_text) => Ok(Err(error_text)),
@ -136,11 +134,7 @@ async fn user_from_document(
user_id: u64,
) -> Result<User, Cow<'static, str>> {
let (data, existing_names) = {
let file = match validate_document(document) {
Ok(document) => &document.file,
Err(text) => return Err(Cow::Borrowed(text)),
};
let file = &validate_document(document)?.file;
let data = download_file(bot, file).map_err(|_| "Error downloading the file. Try again");
let existing_names = Account::get_names(user_id, db)
@ -150,9 +144,8 @@ async fn user_from_document(
try_join!(data, existing_names)?
};
match spawn_blocking(|| user_from_vec(data, existing_names)).await {
Ok(Ok(Ok(user))) => Ok(user),
Ok(Ok(Err(error_text))) => Err(Cow::Owned(error_text)),
match spawn_blocking(|| user_from_bytes(data, existing_names)).await {
Ok(Ok(user)) => user.map_err(Cow::Owned),
_ => Err(Cow::Borrowed("Error parsing the json file. Try again")),
}
}