116 lines
3.2 KiB
Rust

use super::AlterableField::{self, Login, Name, Pass};
use crate::{change_state, prelude::*};
use cryptography::account::Cipher;
use tokio::task::spawn_blocking;
#[inline]
async fn update_account(
user_id: u64,
db: &Pool,
name: String,
field: AlterableField,
field_value: String,
master_pass: String,
) -> crate::Result<bool> {
if field == Name {
return Account::update_name(user_id, &name, &field_value, db)
.await
.map_err(Into::into);
}
let Some(salt) = Account::get_salt(user_id, &name, db).await? else {
return Ok(false);
};
let field_value = spawn_blocking(move || {
let cipher = Cipher::new(master_pass.as_bytes(), &salt);
let mut field = field_value.into_bytes();
cipher.encrypt(&mut field);
field
})
.await?;
let updated = match field {
Login => Account::update_login(user_id, &name, field_value, db).await?,
Pass => Account::update_password(user_id, &name, field_value, db).await?,
Name => unreachable!(),
};
Ok(updated)
}
#[inline]
#[allow(clippy::too_many_arguments)]
async fn get_master_pass(
bot: Throttle<Bot>,
msg: Message,
db: Pool,
dialogue: MainDialogue,
mut ids: MessageIds,
locale: LocaleRef,
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;
let text = match update_account(user_id, &db, name, field, field_value, master_pass).await {
Ok(true) => locale.success.as_str(),
Ok(false) => &locale.account_not_found,
Err(err) => {
log::error!("{err:?}");
&locale.something_went_wrong
}
};
ids.alter_message(&bot, text, deletion_markup(locale), None)
.await?;
Ok(())
}
handler!(get_field(name:String, field:AlterableField, field_value:String),send_master_password, State::GetMasterPass, get_master_pass);
#[inline]
pub async fn alter(
bot: Throttle<Bot>,
q: CallbackQuery,
db: Pool,
dialogue: MainDialogue,
locale: LocaleRef,
(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) = Account::get_name_by_hash(user_id, &hash, &db).await? else {
bot.send_message(ids.0, &locale.account_not_found)
.reply_markup(deletion_markup(locale))
.await?;
bot.answer_callback_query(q.id).await?;
return Ok(());
};
let text: &str = match field {
Name => {
change_state!(dialogue, ids, (name, field), State::GetNewName, get_field);
&locale.send_new_name
}
Login => {
change_state!(dialogue, ids, (name, field), State::GetLogin, get_field);
&locale.send_new_login
}
Pass => {
change_state!(dialogue, ids, (name, field), State::GetPassword, get_field);
&locale.send_new_password
}
};
ids.alter_message(&bot, text, None, None).await?;
bot.answer_callback_query(q.id).await?;
Ok(())
}