2023-11-19 14:45:46 +03:00

124 lines
3.2 KiB
Rust

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]
async fn update_account(
user_id: u64,
db: &DatabaseConnection,
name: String,
field: AlterableField,
field_value: String,
master_pass: String,
) -> crate::Result<()> {
if field == Name {
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 field_value = spawn_blocking(move || {
let cipher = Cipher::new(master_pass.as_bytes(), &salt);
cipher.encrypt(field_value.as_bytes()).unwrap()
})
.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),
Name => unreachable!(),
}
model.update(db).await?;
Ok(())
}
#[inline]
#[allow(clippy::too_many_arguments)]
async fn get_master_pass(
bot: Throttle<Bot>,
msg: Message,
db: DatabaseConnection,
dialogue: MainDialogue,
mut ids: MessageIds,
name: String,
field: AlterableField,
field_value: String,
master_pass: String,
) -> crate::Result<()> {
dialogue.exit().await?;
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
update_account(user_id, &db, name, field, field_value, master_pass).await?;
ids.alter_message(
&bot,
"Success. Choose the account to view",
menu_markup("get", user_id, &db).await?,
None,
)
.await?;
Ok(())
}
handler!(get_field(name:String, field:AlterableField, field_value:String), "Send the master password", State::GetMasterPass, get_master_pass);
#[inline]
pub async fn alter(
bot: Throttle<Bot>,
q: CallbackQuery,
db: DatabaseConnection,
dialogue: MainDialogue,
(hash, field): (super::NameHash, AlterableField),
) -> crate::Result<()> {
let user_id = q.from.id.0;
let mut ids: MessageIds = q.message.as_ref().unwrap().into();
let Some(name) = name_from_hash(&db, user_id, &hash).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()
)?;
return Ok(());
};
let text = match field {
Name => {
change_state!(dialogue, ids, (name, field), State::GetNewName, get_field);
"Send new account name"
}
Login => {
change_state!(dialogue, ids, (name, field), State::GetLogin, get_field);
"Send new account login"
}
Pass => {
change_state!(dialogue, ids, (name, field), State::GetPassword, get_field);
"Send new account password"
}
};
try_join!(
ids.alter_message(&bot, text, None, None),
bot.answer_callback_query(q.id).send().err_into()
)?;
Ok(())
}