Switched from sea-orm to sqlx

This commit is contained in:
2023-11-25 19:29:06 +03:00
parent e4e33f52b1
commit 9f967e82d5
40 changed files with 434 additions and 1110 deletions

View File

@ -1,9 +1,7 @@
use super::AlterableField::{self, Login, Name, Pass};
use crate::{change_state, prelude::*};
use account::ActiveModel;
use cryptography::account::Cipher;
use futures::TryFutureExt;
use sea_orm::ActiveValue::Set;
use tokio::{task::spawn_blocking, try_join};
#[inline]
@ -16,12 +14,12 @@ async fn update_account(
master_pass: String,
) -> crate::Result<()> {
if field == Name {
Account::update_name(user_id, name, field_value, db).await?;
Account::update_name(user_id, &name, &field_value, db).await?;
return Ok(());
}
let salt = Account::get_salt(user_id, name.clone(), db).await?.unwrap();
let salt = Account::get_salt(user_id, &name, db).await?.unwrap();
let field_value = spawn_blocking(move || {
let cipher = Cipher::new(master_pass.as_bytes(), &salt);
@ -31,20 +29,12 @@ async fn update_account(
})
.await?;
let mut model = ActiveModel {
user_id: Set(user_id),
name: Set(name),
..Default::default()
};
match field {
Login => model.enc_login = Set(field_value),
Pass => model.enc_password = Set(field_value),
Login => Account::update_login(user_id, &name, field_value, db).await?,
Pass => Account::update_password(user_id, &name, field_value, db).await?,
Name => unreachable!(),
}
model.update(db).await?;
Ok(())
}

View File

@ -16,7 +16,7 @@ async fn get_master_pass(
dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
Account::delete_by_id((user_id, name)).exec(&db).await?;
Account::delete(user_id, &name, &db).await?;
ids.alter_message(
&bot,

View File

@ -5,10 +5,7 @@ use tokio::task::spawn_blocking;
pub async fn delete(bot: Throttle<Bot>, msg: Message, db: DatabaseConnection) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let names: Vec<String> = Account::get_names(user_id, &db)
.await?
.try_collect()
.await?;
let names: Vec<String> = Account::get_names(user_id, &db).try_collect().await?;
if names.is_empty() {
bot.send_message(msg.chat.id, "You don't have any accounts")

View File

@ -1,7 +1,5 @@
use crate::prelude::*;
use log::error;
use sea_orm::TransactionTrait;
use tokio::try_join;
/// 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
@ -16,17 +14,17 @@ async fn get_master_pass(
) -> crate::Result<()> {
dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let txn = db.begin().await?;
let result = try_join!(
Account::delete_all(user_id, &txn),
MasterPass::remove(user_id, &txn),
let mut txn = db.begin().await?;
let result = (
Account::delete_all(user_id, &mut *txn).await,
MasterPass::remove(user_id, &mut *txn).await,
);
let text = match result {
Ok(_) => {
(Ok(()), Ok(())) => {
txn.commit().await?;
"Everything was deleted"
}
Err(err) => {
(Err(err), _) | (_, Err(err)) => {
error!("{}", crate::Error::from(err));
txn.rollback().await?;
"Something went wrong. Try again later"

View File

@ -7,7 +7,7 @@ use tokio::task::spawn_blocking;
/// Decryptes the account on a worker thread and adds it to the accounts vector
#[inline]
async fn decrypt_account(
account: account::Model,
account: Account,
master_pass: Arc<str>,
accounts: &Mutex<&mut Vec<DecryptedAccount>>,
) -> crate::Result<()> {
@ -38,7 +38,6 @@ async fn get_master_pass(
let master_pass: Arc<str> = master_pass.into();
Account::get_all(user_id, &db)
.await?
.err_into::<crate::Error>()
.try_for_each_concurrent(3, |account| {
decrypt_account(account, master_pass.clone(), &accounts)

View File

@ -9,10 +9,7 @@ pub async fn get_account(
) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let names: Vec<String> = Account::get_names(user_id, &db)
.await?
.try_collect()
.await?;
let names: Vec<String> = Account::get_names(user_id, &db).try_collect().await?;
if names.is_empty() {
bot.send_message(msg.chat.id, "You don't have any accounts")

View File

@ -11,7 +11,7 @@ pub async fn get_accounts(
db: DatabaseConnection,
) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let mut account_names = Account::get_names(user_id, &db).await?;
let mut account_names = Account::get_names(user_id, &db);
let mut text = if let Some(name) = account_names.try_next().await? {
format!("Accounts:\n`{name}`")

View File

@ -18,7 +18,7 @@ async fn encrypt_account(
let name = account.name.clone();
match spawn_blocking(move || account.into_account(user_id, &master_pass)).await {
Ok(account) => match account.insert(db).await {
Ok(_) => (),
Ok(()) => (),
Err(_) => failed.lock().push(name),
},
_ => failed.lock().push(name),

View File

@ -5,10 +5,7 @@ use tokio::task::spawn_blocking;
pub async fn menu(bot: Throttle<Bot>, msg: Message, db: DatabaseConnection) -> crate::Result<()> {
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
let names: Vec<String> = Account::get_names(user_id, &db)
.await?
.try_collect()
.await?;
let names: Vec<String> = Account::get_names(user_id, &db).try_collect().await?;
if names.is_empty() {
bot.send_message(msg.chat.id, "You don't have any accounts")

View File

@ -1,6 +1,5 @@
use crate::{change_state, prelude::*};
use cryptography::hashing::HashedBytes;
use sea_orm::ActiveValue::Set;
use tokio::task::spawn_blocking;
#[inline]
@ -14,7 +13,7 @@ async fn get_master_pass2(
master_pass: String,
) -> crate::Result<()> {
dialogue.exit().await?;
let user_id = Set(msg.from().ok_or(NoUserInfo)?.id.0);
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
if !hash.verify(master_pass.as_bytes()) {
ids.alter_message(
@ -28,10 +27,10 @@ async fn get_master_pass2(
return Ok(());
}
let model = master_pass::ActiveModel {
let model = MasterPass {
user_id,
password_hash: Set(hash.hash.to_vec()),
salt: Set(hash.salt.to_vec()),
password_hash: hash.hash.to_vec(),
salt: hash.salt.to_vec(),
};
model.insert(&db).await?;

View File

@ -1,6 +1,3 @@
// #![warn(clippy::pedantic, clippy::all, clippy::nursery)]
// #![allow(clippy::single_match_else)]
mod callbacks;
mod commands;
mod default;
@ -16,9 +13,7 @@ mod utils;
use anyhow::{Error, Result};
use dotenvy::dotenv;
use migration::{Migrator, MigratorTrait};
use prelude::*;
use sea_orm::Database;
use std::env;
use teloxide::{adaptors::throttle::Limits, dispatching::dialogue::InMemStorage, filter_command};
@ -92,8 +87,10 @@ async fn main() -> Result<()> {
let token = env::var("TOKEN").expect("expected TOKEN in the enviroment");
let database_url = env::var("DATABASE_URL").expect("expected DATABASE_URL in the enviroment");
let db = Database::connect(database_url).await?;
Migrator::up(&db, None).await?;
get_dispatcher(token, db).dispatch().await;
let pool = sqlx::mysql::MySqlPool::connect(&database_url).await?;
sqlx::migrate!().run(&pool).await?;
get_dispatcher(token, pool).dispatch().await;
Ok(())
}

View File

@ -32,7 +32,7 @@ pub async fn menu_markup(
db: &DatabaseConnection,
) -> crate::Result<InlineKeyboardMarkup> {
let command: String = command.into();
let names: Vec<String> = Account::get_names(user_id, db).await?.try_collect().await?;
let names: Vec<String> = Account::get_names(user_id, db).try_collect().await?;
spawn_blocking(move || menu_markup_sync(&command, names))
.await

View File

@ -8,7 +8,6 @@ pub use crate::{
utils::*,
};
pub use cryptography::prelude::*;
pub use entity::prelude::*;
pub use entity::{prelude::*, Pool as DatabaseConnection};
pub use futures::{StreamExt, TryStreamExt};
pub use sea_orm::prelude::*;
pub use teloxide::{adaptors::Throttle, prelude::*};

View File

@ -165,7 +165,6 @@ pub async fn get_user(
let existing_names = async {
Account::get_names(user_id, &db)
.await?
.try_collect()
.await
.map_err(Into::into)