login: Simplify whole async decrypting process

This commit is contained in:
Christoph Heiss 2020-12-02 17:36:14 +01:00
parent c82ba73eba
commit 84f57b4493
Signed by: c8h4
GPG key ID: 8D9166DCF6A28E57
3 changed files with 30 additions and 66 deletions

View file

@ -17,6 +17,9 @@ fuzzy-matcher = "0.3.7"
serde_json = "1.0.59"
unicase = "2.6.0"
[dependencies.bitwarden]
path = "bitwarden"
[dependencies.cursive]
version = "0.15.0"
default-features = false
@ -28,6 +31,3 @@ git = "https://github.com/BonsaiDen/cursive_table_view.git"
[dependencies.serde]
version = "1.0.117"
features = ["derive"]
[dependencies.bitwarden]
path = "bitwarden"

View file

@ -29,4 +29,3 @@ features = ["derive"]
[dependencies.uuid]
version = "0.8.1"
features = ["v4", "serde"]

View file

@ -1,6 +1,5 @@
// SPDX-License-Identifier: MIT
use std::sync::mpsc;
use std::thread;
use cursive::direction::Orientation;
@ -14,16 +13,6 @@ use bitwarden::{self, ApiError, AuthData};
use crate::vault::{self, VaultData};
enum LoginProgress {
Decrypting,
Syncing,
Finished(VaultData),
Error(Option<VaultData>, ApiError),
}
type LoginProgressSink = mpsc::Sender<LoginProgress>;
type LoginProgressRecv = mpsc::Receiver<LoginProgress>;
pub fn create(siv: &mut Cursive) {
let email_edit = EditView::new().with_name("email");
let email_view = OnEventView::new(email_edit).on_event(Event::CtrlChar('u'), |siv| {
@ -66,89 +55,65 @@ fn on_login(siv: &mut Cursive) {
siv.add_layer(progress_dialog);
let vault_data = siv.take_user_data();
let (tx, rx) = mpsc::channel();
let sink = siv.cb_sink().clone();
thread::spawn(move || {
if let Some(data) = vault_data {
decrypt_cached(tx, data, &email, &password);
decrypt_cached(sink.clone(), progress_text, data, &email, &password);
} else {
sync_and_decrypt(tx, &email, &password);
sync_and_decrypt(sink.clone(), progress_text, &email, &password);
}
sink.send(Box::new(|siv| {
siv.set_autorefresh(false);
})).unwrap();
});
let cb_sink = siv.cb_sink().clone();
thread::spawn(move || {
process_login(cb_sink, rx, progress_text);
});
}
fn decrypt_cached(
sink: LoginProgressSink,
sink: CursiveSink,
progress: TextContent,
mut vault: VaultData,
email: &str,
master_password: &str
) {
sink.send(LoginProgress::Decrypting).unwrap();
progress.set_content("decrypting ...");
vault.auth.cipher = CipherSuite::from(&email, master_password, vault.auth.kdf_iterations);
if vault.auth.cipher.set_decrypt_key(&vault.sync.profile.key).is_err() {
sink.send(
LoginProgress::Error(Some(vault), ApiError::LoginFailed)
).unwrap();
handle_login_error(sink, Some(vault), ApiError::LoginFailed);
} else {
vault::decrypt(&mut vault);
sink.send(LoginProgress::Finished(vault)).unwrap();
sink.send(Box::new(|siv| {
siv.set_user_data(vault);
vault::create(siv);
})).unwrap();
}
}
fn sync_and_decrypt(sink: LoginProgressSink, email: &str, master_password: &str) {
fn sync_and_decrypt(sink: CursiveSink, progress: TextContent, email: &str, master_password: &str) {
match bitwarden::authenticate(&email, &master_password) {
Ok(auth) => {
sink.send(LoginProgress::Syncing).unwrap();
progress.set_content("syncing ...");
let vault = sync_vault_data(auth).unwrap();
decrypt_cached(sink, vault, email, master_password);
decrypt_cached(sink, progress, vault, email, master_password);
},
Err(err) => sink.send(LoginProgress::Error(None, err)).unwrap(),
Err(err) => handle_login_error(sink, None, err),
}
}
fn process_login(sink: CursiveSink, recv: LoginProgressRecv, progress_text: TextContent) {
for progress in recv.iter() {
match progress {
LoginProgress::Decrypting => {
progress_text.set_content("decrypting ...");
},
fn handle_login_error(sink: CursiveSink, vault: Option<VaultData>, error: ApiError) {
sink.send(Box::new(move |siv| {
siv.pop_layer();
siv.find_name::<EditView>("master_password").unwrap().set_content("")(siv);
LoginProgress::Syncing => {
progress_text.set_content("syncing ...");
},
LoginProgress::Finished(vault) => {
sink.send(Box::new(|siv| {
siv.set_user_data(vault);
vault::create(siv);
})).unwrap();
break;
},
LoginProgress::Error(vault, err) => {
sink.send(Box::new(move |siv| {
siv.pop_layer();
siv.find_name::<EditView>("master_password").unwrap().set_content("")(siv);
if let Some(vault) = vault {
siv.set_user_data(vault);
}
siv.add_layer(Dialog::info(err.to_string()));
})).unwrap();
break;
},
if let Some(vault) = vault {
siv.set_user_data(vault);
}
}
sink.send(Box::new(|siv| {
siv.set_autorefresh(false);
siv.add_layer(Dialog::info(error.to_string()));
})).unwrap();
}