few code cleanup

This commit is contained in:
Bilal Elmoussaoui 2020-12-07 15:51:09 +01:00
parent b07804368b
commit 9b5d4a4d0b
5 changed files with 47 additions and 33 deletions

View file

@ -1,5 +1,4 @@
use super::{Backupable, Restorable};
use crate::helpers::Keyring;
use crate::models::{Account, Algorithm, HOTPAlgorithm, Provider, ProvidersModel};
use anyhow::Result;
use gio::{FileExt, ListModelExt};
@ -123,15 +122,9 @@ impl Restorable for AndOTP {
}
};
match Keyring::store(&item.label, &item.secret) {
Ok(token_id) => {
let account = Account::create(&item.label, &token_id, &provider).unwrap();
provider.add_account(&account);
}
Err(e) => {
warn!("Failed to restore account {}", e);
}
};
if let Ok(account) = Account::create(&item.label, &item.secret, &provider) {
provider.add_account(&account);
}
});
Ok(())
}

View file

@ -195,10 +195,13 @@ glib_wrapper! {
}
impl Account {
pub fn create(name: &str, token_id: &str, provider: &Provider) -> Result<Account> {
pub fn create(name: &str, token: &str, provider: &Provider) -> Result<Account> {
let db = database::connection();
let conn = db.get()?;
let token_id = Keyring::store(&format!("{} - {}", provider.name(), name), &token)
.expect("Failed to save token");
diesel::insert_into(accounts::table)
.values(NewAccount {
name: name.to_string(),
@ -308,17 +311,12 @@ impl Account {
Algorithm::Steam => 1,
};
// Modified version of an implementation from otpauth crate
let key = hmac::Key::new(provider.hmac_algorithm().into(), self.token().as_bytes());
let wtr = counter.to_be_bytes().to_vec();
let result = hmac::sign(&key, &wtr);
let digest = result.as_ref();
let ob = digest[19];
let pos = (ob & 15) as usize;
let mut rdr = std::io::Cursor::new(digest[pos..pos + 4].to_vec());
let base = rdr.read_u32::<BigEndian>().unwrap() & 0x7fff_ffff;
let otp = base % 10_u32.pow(provider.digits() as u32);
let otp = generate_otp(
&self.token(),
counter,
provider.hmac_algorithm().into(),
provider.digits() as u32,
);
self.set_property("otp", &otp.to_string()).unwrap();
}
@ -343,6 +341,11 @@ impl Account {
let clipboard = display.get_clipboard();
let priv_ = AccountPriv::from_instance(self);
clipboard.set_text(&priv_.otp.borrow());
// Indirectly increment the counter once the token was copied
if self.provider().algorithm() == Algorithm::HOTP {
self.generate_otp();
}
}
pub fn id(&self) -> i32 {
@ -354,6 +357,7 @@ impl Account {
let provider = self.get_property("provider").unwrap();
provider.get::<Provider>().unwrap().unwrap()
}
pub fn counter(&self) -> i32 {
let priv_ = AccountPriv::from_instance(self);
priv_.counter.get()
@ -396,3 +400,22 @@ impl Account {
Ok(())
}
}
pub(crate) fn generate_otp(
token: &str,
counter: u64,
algorithm: hmac::Algorithm,
digits: u32,
) -> u32 {
// Modified version of an implementation from otpauth crate
let key = hmac::Key::new(algorithm, token.as_bytes());
let wtr = counter.to_be_bytes().to_vec();
let result = hmac::sign(&key, &wtr);
let digest = result.as_ref();
let ob = digest[19];
let pos = (ob & 15) as usize;
let mut rdr = std::io::Cursor::new(digest[pos..pos + 4].to_vec());
let base = rdr.read_u32::<BigEndian>().unwrap() & 0x7fff_ffff;
base % 10_u32.pow(digits)
}

View file

@ -112,7 +112,7 @@ static PROPERTIES: [subclass::Property; 11] = [
"default_counter",
"default_counter",
0,
1000,
i32::MAX,
1,
glib::ParamFlags::READWRITE,
)
@ -505,7 +505,7 @@ impl Provider {
&priv_.filter_model
}
pub fn search_accounts(&self, text: String) {
pub fn filter(&self, text: String) {
let priv_ = ProviderPriv::from_instance(self);
let filter = gtk::CustomFilter::new(Some(Box::new(move |obj| {
let account = obj.downcast_ref::<Account>().unwrap();

View file

@ -1,5 +1,5 @@
use crate::application::Action;
use crate::helpers::{qrcode, Keyring};
use crate::helpers::qrcode;
use crate::models::{Account, Algorithm, Provider, ProvidersModel};
use crate::widgets::{ProviderImage, ProviderImageSize};
use anyhow::Result;
@ -200,13 +200,11 @@ impl AccountAddDialog {
let username = self_.username_entry.get().get_text().unwrap();
let token = self_.token_entry.get().get_text().unwrap();
if let Ok(token_id) = Keyring::store(&username, &token) {
let account = Account::create(&username, &token_id, provider)?;
send!(
self_.global_sender.get().unwrap(),
Action::AccountCreated(account, provider.clone())
);
}
let account = Account::create(&username, &token, provider)?;
send!(
self_.global_sender.get().unwrap(),
Action::AccountCreated(account, provider.clone())
);
// TODO: display an error message saying there was an error form keyring
}
Ok(())

View file

@ -89,7 +89,7 @@ impl ProvidersList {
let accounts_filter = gtk::CustomFilter::new(Some(Box::new(move |object| {
let provider = object.downcast_ref::<Provider>().unwrap();
provider.search_accounts(text.clone());
provider.filter(text.clone());
provider.accounts().get_n_items() != 0
})));
self_.filter_model.set_filter(Some(&accounts_filter));