code cleanup

mostly rename hmac_alogrithm -> algorithm
algorithm -> method
This commit is contained in:
Bilal Elmoussaoui 2020-12-09 03:04:55 +01:00
parent 29bada492f
commit 4223fcf10e
18 changed files with 313 additions and 313 deletions

View File

@ -71,6 +71,7 @@
<object class="HdyActionRow">
<property name="activatable_widget">provider_entry</property>
<property name="title" translatable="yes">Provider</property>
<property name="subtitle" translatable="yes">The service provider</property>
<child>
<object class="GtkEntry" id="provider_entry">
<property name="halign">end</property>
@ -164,10 +165,10 @@
</object>
</child>
<child>
<object class="HdyActionRow" id="digits_row">
<property name="title" translatable="yes">Digits</property>
<object class="HdyActionRow" id="algorithm_row">
<property name="title" translatable="yes">Algorithm</property>
<child>
<object class="GtkLabel" id="digits_label">
<object class="GtkLabel" id="algorithm_label">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
@ -176,10 +177,10 @@
</object>
</child>
<child>
<object class="HdyActionRow" id="hmac_algorithm_row">
<property name="title" translatable="yes">HMAC Algorithm</property>
<object class="HdyActionRow" id="method_row">
<property name="title" translatable="yes">Computing Method</property>
<child>
<object class="GtkLabel" id="hmac_algorithm_label">
<object class="GtkLabel" id="method_label">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
@ -200,10 +201,10 @@
</object>
</child>
<child>
<object class="HdyActionRow" id="algorithm_row">
<property name="title" translatable="yes">Algorithm</property>
<object class="HdyActionRow" id="digits_row">
<property name="title" translatable="yes">Digits</property>
<child>
<object class="GtkLabel" id="algorithm_label">
<object class="GtkLabel" id="digits_label">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>

View File

@ -21,7 +21,7 @@
<object class="HdyActionRow">
<property name="title" translatable="yes">Dark Theme</property>
<property name="activatable_widget">dark_theme_switch</property>
<property name="subtitle" translatable="yes">Whether the application should use a dark theme.</property>
<property name="subtitle" translatable="yes">Whether the application should use a dark theme</property>
<child>
<object class="GtkSwitch" id="dark_theme_switch">
<property name="valign">center</property>
@ -37,7 +37,7 @@
<child>
<object class="HdyActionRow">
<property name="title" translatable="yes">Password</property>
<property name="subtitle" translatable="yes">Setup a password to lock the application with.</property>
<property name="subtitle" translatable="yes">Setup a password to lock the application with</property>
<property name="activatable">True</property>
<property name="action-name">preferences.show_password_page</property>
<child>
@ -51,7 +51,7 @@
<object class="HdyActionRow">
<property name="title" translatable="yes">Auto Lock the application</property>
<property name="activatable_widget">auto_lock_switch</property>
<property name="subtitle" translatable="yes">Whether to automatically lock the application.</property>
<property name="subtitle" translatable="yes">Whether to automatically lock the application</property>
<child>
<object class="GtkSwitch" id="auto_lock_switch">
<property name="valign">center</property>
@ -62,7 +62,7 @@
<child>
<object class="HdyActionRow">
<property name="title" translatable="yes">Auto lock timeout</property>
<property name="subtitle" translatable="yes">The time in minutes.</property>
<property name="subtitle" translatable="yes">The time in minutes</property>
<property name="activatable_widget">lock_timeout_spin_btn</property>
<child>
<object class="GtkSpinButton" id="lock_timeout_spin_btn">

View File

@ -96,6 +96,7 @@
<object class="HdyActionRow">
<property name="activatable_widget">provider_website_entry</property>
<property name="title" translatable="yes">Website</property>
<property name="subtitle" translatable="yes">Used to fetch the website icon if possible</property>
<child>
<object class="GtkEntry" id="provider_website_entry">
<property name="halign">end</property>
@ -106,6 +107,77 @@
</child>
</object>
</child>
<child>
<object class="HdyComboRow" id="method_comborow">
<property name="title" translatable="yes">Computing Method</property>
<property name="expression">
<lookup type="HdyEnumValueObject" name="name"/>
</property>
</object>
</child>
<child>
<object class="HdyComboRow" id="algorithm_comborow">
<property name="title" translatable="yes">Algorithm</property>
<property name="expression">
<lookup type="HdyEnumValueObject" name="name"/>
</property>
</object>
</child>
<style>
<class name="content"/>
</style>
<child>
<object class="HdyActionRow" id="period_row">
<property name="activatable_widget">period_spinbutton</property>
<property name="title" translatable="yes">Period</property>
<property name="subtitle" translatable="yes">The duration in seconds. The recommended value is 30</property>
<child>
<object class="GtkSpinButton" id="period_spinbutton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="text">0</property>
<property name="adjustment">period_adjustment</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="HdyActionRow" id="default_counter_row">
<property name="activatable_widget">default_counter_spinbutton</property>
<property name="title" translatable="yes">Counter</property>
<property name="subtitle" translatable="yes">The by default value for counter-based computing method</property>
<child>
<object class="GtkSpinButton" id="default_counter_spinbutton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="text">0</property>
<property name="adjustment">default_counter_adjustment</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="HdyActionRow" id="digits_row">
<property name="activatable_widget">digits_spinbutton</property>
<property name="title" translatable="yes">Digits</property>
<property name="subtitle" translatable="yes">Length of the generated code, recommended value is 6</property>
<child>
<object class="GtkSpinButton" id="digits_spinbutton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="value">6</property>
<property name="text">0</property>
<property name="adjustment">digits_adjustment</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="HdyActionRow">
<property name="activatable_widget">provider_help_entry</property>
@ -121,82 +193,6 @@
</child>
</object>
</child>
<child>
<object class="HdyComboRow" id="algorithm_comborow">
<property name="title" translatable="yes">Algorithm</property>
<property name="expression">
<lookup type="HdyEnumValueObject" name="name"/>
</property>
</object>
</child>
<style>
<class name="content"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox">
<property name="selection_mode">none</property>
<style>
<class name="content"/>
</style>
<child>
<object class="HdyActionRow" id="period_row">
<property name="activatable_widget">period_spinbutton</property>
<property name="title" translatable="yes">Period</property>
<child>
<object class="GtkSpinButton" id="period_spinbutton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="text">0</property>
<property name="adjustment">period_adjustment</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="HdyComboRow" id="hmac_algorithm_comborow">
<property name="title" translatable="yes">HMAC Algorithm</property>
<property name="expression">
<lookup type="HdyEnumValueObject" name="name"/>
</property>
</object>
</child>
<child>
<object class="HdyActionRow" id="default_counter_row">
<property name="activatable_widget">default_counter_spinbutton</property>
<property name="title" translatable="yes">Default Counter</property>
<child>
<object class="GtkSpinButton" id="default_counter_spinbutton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="text">0</property>
<property name="adjustment">default_counter_adjustment</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="HdyActionRow" id="digits_row">
<property name="activatable_widget">digits_spinbutton</property>
<property name="title" translatable="yes">Digits</property>
<property name="subtitle" translatable="yes">Defaults to 6</property>
<child>
<object class="GtkSpinButton" id="digits_spinbutton">
<property name="halign">end</property>
<property name="valign">center</property>
<property name="hexpand">True</property>
<property name="text">0</property>
<property name="adjustment">digits_adjustment</property>
<property name="numeric">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>

View File

@ -8,6 +8,6 @@ CREATE TABLE "providers" (
"digits" INTEGER NULL DEFAULT 6,
"period" INTEGER NULL DEFAULT 30,
"default_counter" INTEGER NULL DEFAULT 1,
"hmac_algorithm" VARCHAR NULL DEFAULT "SHA1",
"algorithm" VARCHAR DEFAULT "TOTP"
"algorithm" VARCHAR NULL DEFAULT "SHA1",
"method" VARCHAR DEFAULT "TOTP"
);

View File

@ -1,5 +1,5 @@
use super::{Backupable, Restorable};
use crate::models::{Account, Algorithm, HOTPAlgorithm, Provider, ProvidersModel};
use crate::models::{Account, Algorithm, OTPMethod, Provider, ProvidersModel};
use anyhow::Result;
use gettextrs::gettext;
use gio::{FileExt, ListModelExt};
@ -13,8 +13,8 @@ pub struct AndOTP {
pub label: String,
pub digits: i32,
#[serde(rename = "type")]
pub type_field: Algorithm,
pub algorithm: HOTPAlgorithm,
pub method: OTPMethod,
pub algorithm: Algorithm,
pub thumbnail: String,
pub last_used: i64,
pub used_frequency: i32,
@ -55,8 +55,8 @@ impl Backupable for AndOTP {
issuer: provider.name(),
label: account.name(),
digits: provider.digits(),
type_field: provider.algorithm(),
algorithm: provider.hmac_algorithm(),
method: provider.method(),
algorithm: provider.algorithm(),
thumbnail: "".to_string(),
last_used: 0,
used_frequency: 0,
@ -108,7 +108,7 @@ impl Restorable for AndOTP {
let provider = model.find_or_create(
&item.issuer,
item.period.unwrap_or_else(|| 30),
item.type_field,
item.method,
None,
item.algorithm,
item.digits,

View File

@ -1,5 +1,5 @@
use super::{Backupable, Restorable};
use crate::models::{Account, OtpUri, Provider, ProvidersModel};
use crate::models::{Account, OTPUri, Provider, ProvidersModel};
use anyhow::Result;
use gettextrs::gettext;
use gio::prelude::*;
@ -75,13 +75,13 @@ impl Restorable for FreeOTP {
.into_iter()
.try_for_each(|uri| -> Result<()> {
println!("{:#?}", uri);
let otp_uri = OtpUri::from_str(uri)?;
let otp_uri = OTPUri::from_str(uri)?;
let provider = model.find_or_create(
&otp_uri.issuer,
otp_uri.period.unwrap_or_else(|| 30),
otp_uri.algorithm,
otp_uri.method,
None,
otp_uri.hmac_algorithm,
otp_uri.algorithm,
otp_uri.digits.unwrap_or_else(|| 6),
otp_uri.counter.unwrap_or_else(|| 1),
)?;

View File

@ -1,5 +1,5 @@
use super::Restorable;
use crate::models::{Account, Algorithm, HOTPAlgorithm, ProvidersModel};
use crate::models::{Account, Algorithm, OTPMethod, ProvidersModel};
use anyhow::Result;
use gettextrs::gettext;
use gio::FileExt;
@ -12,8 +12,8 @@ pub struct LegacyAuthenticator {
pub label: String,
pub digits: i32,
#[serde(rename = "type")]
pub type_field: Algorithm,
pub algorithm: HOTPAlgorithm,
pub method: OTPMethod,
pub algorithm: Algorithm,
pub thumbnail: String,
pub last_used: i64,
pub tags: Vec<String>,
@ -48,7 +48,7 @@ impl Restorable for LegacyAuthenticator {
let provider = model.find_or_create(
&issuer,
item.period,
item.type_field,
item.method,
None,
item.algorithm,
item.digits,

View File

@ -1,4 +1,4 @@
use crate::models::OtpUri;
use crate::models::OTPUri;
use anyhow::Result;
use ashpd::desktop::screenshot::{Screenshot, ScreenshotOptions, ScreenshotProxy};
use ashpd::{zbus, RequestProxy, Response, WindowIdentifier};
@ -7,7 +7,7 @@ use image::GenericImageView;
use std::str::FromStr;
use zbar_rust::ZBarImageScanner;
pub(crate) fn scan(screenshot: &gio::File) -> Result<OtpUri> {
pub(crate) fn scan(screenshot: &gio::File) -> Result<OTPUri> {
let (data, _) = screenshot.load_contents(gio::NONE_CANCELLABLE)?;
let img = image::load_from_memory(&data)?;
@ -23,7 +23,7 @@ pub(crate) fn scan(screenshot: &gio::File) -> Result<OtpUri> {
if let Some(ref result) = results.get(0) {
let uri = String::from_utf8(result.data.clone())?;
return Ok(OtpUri::from_str(&uri)?);
return Ok(OTPUri::from_str(&uri)?);
}
anyhow::bail!("Invalid QR code")
}

View File

@ -1,5 +1,7 @@
use super::provider::{DiProvider, Provider};
use super::{Algorithm, OtpUri};
use super::{
provider::{DiProvider, Provider},
OTPMethod, OTPUri,
};
use crate::helpers::Keyring;
use crate::models::database;
use crate::schema::accounts;
@ -275,8 +277,6 @@ impl Account {
let priv_ = AccountPriv::from_instance(&account);
priv_.token.set(token);
account.qr_code();
account.init();
account
}
@ -284,7 +284,7 @@ impl Account {
fn init(&self) {
self.generate_otp();
// Only trigger time-based callback after duration if it's a TOTP
if self.provider().algorithm() == Algorithm::TOTP {
if self.provider().method() == OTPMethod::TOTP {
glib::source::timeout_add_seconds_local(
self.provider().period() as u32,
clone!(@weak self as account => @default-return glib::Continue(false), move || {
@ -299,26 +299,26 @@ impl Account {
fn generate_otp(&self) {
let provider = self.provider();
let counter = match provider.algorithm() {
Algorithm::TOTP => {
let counter = match provider.method() {
OTPMethod::TOTP => {
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();
timestamp / (provider.period() as u64)
}
Algorithm::HOTP => {
OTPMethod::HOTP => {
let old_counter = self.counter();
self.increment_counter();
old_counter as u64
}
Algorithm::Steam => 1,
OTPMethod::Steam => 1,
};
let otp = generate_otp(
&self.token(),
counter,
provider.hmac_algorithm().into(),
provider.algorithm().into(),
provider.digits() as u32,
);
self.set_property("otp", &otp.to_string()).unwrap();
@ -347,7 +347,7 @@ impl Account {
clipboard.set_text(&priv_.otp.borrow());
// Indirectly increment the counter once the token was copied
if self.provider().algorithm() == Algorithm::HOTP {
if self.provider().method() == OTPMethod::HOTP {
self.generate_otp();
}
}
@ -382,7 +382,7 @@ impl Account {
priv_.token_id.borrow().clone()
}
pub fn otp_uri(&self) -> OtpUri {
pub fn otp_uri(&self) -> OTPUri {
self.into()
}

View File

@ -6,8 +6,8 @@ use std::string::ToString;
#[derive(Debug, Eq, PartialEq, Clone, Copy, GEnum)]
#[repr(u32)]
#[genum(type_name = "ProviderAlgorithm")]
pub enum Algorithm {
#[genum(type_name = "ProviderMethod")]
pub enum OTPMethod {
#[genum(name = "TOTP")]
TOTP = 0,
#[genum(name = "HOTP")]
@ -15,12 +15,91 @@ pub enum Algorithm {
Steam = 2,
}
impl Default for Algorithm {
impl Default for OTPMethod {
fn default() -> Self {
Self::TOTP
}
}
impl Serialize for OTPMethod {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for OTPMethod {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(OTPMethod::from_str(&String::deserialize(deserializer)?).unwrap())
}
}
impl From<u32> for OTPMethod {
fn from(u: u32) -> Self {
match u {
1 => OTPMethod::HOTP,
2 => OTPMethod::Steam,
_ => OTPMethod::default(),
}
}
}
impl OTPMethod {
pub fn to_locale_string(&self) -> String {
match *self {
OTPMethod::HOTP => gettext("Counter-based"),
OTPMethod::TOTP => gettext("Time-based"),
OTPMethod::Steam => gettext("Steam"),
}
}
}
impl FromStr for OTPMethod {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"totp" | "otp" => Ok(Self::TOTP),
"hotp" => Ok(Self::HOTP),
"steam" => Ok(Self::Steam),
_ => anyhow::bail!("Unsupported OTPMethod"),
}
}
}
impl ToString for OTPMethod {
fn to_string(&self) -> String {
match *self {
OTPMethod::TOTP => "totp",
OTPMethod::HOTP => "hotp",
OTPMethod::Steam => "steam",
}
.to_string()
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, GEnum)]
#[repr(u32)]
#[genum(type_name = "ProviderAlgorithm")]
pub enum Algorithm {
#[genum(name = "SHA1")]
SHA1 = 0,
#[genum(name = "SHA256")]
SHA256 = 1,
#[genum(name = "SHA512")]
SHA512 = 2,
}
impl Default for Algorithm {
fn default() -> Self {
Self::SHA1
}
}
impl Serialize for Algorithm {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -39,22 +118,12 @@ impl<'de> Deserialize<'de> for Algorithm {
}
}
impl From<u32> for Algorithm {
fn from(u: u32) -> Self {
match u {
1 => Algorithm::HOTP,
2 => Algorithm::Steam,
_ => Algorithm::default(),
}
}
}
impl Algorithm {
pub fn to_locale_string(&self) -> String {
match *self {
Algorithm::HOTP => gettext("HMAC-based"),
Algorithm::TOTP => gettext("Time-based"),
Algorithm::Steam => gettext("Steam"),
Algorithm::SHA1 => gettext("SHA-1"),
Algorithm::SHA256 => gettext("SHA-256"),
Algorithm::SHA512 => gettext("SHA-512"),
}
}
}
@ -63,10 +132,10 @@ impl FromStr for Algorithm {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"totp" | "otp" => Ok(Self::TOTP),
"hotp" => Ok(Self::HOTP),
"steam" => Ok(Self::Steam),
_ => anyhow::bail!("Unsupported algorithm"),
"sha1" | "otp" => Ok(Self::SHA1),
"sha256" => Ok(Self::SHA256),
"sha512" => Ok(Self::SHA512),
_ => anyhow::bail!("Unsupported HMAC-algorithm"),
}
}
}
@ -74,89 +143,20 @@ impl FromStr for Algorithm {
impl ToString for Algorithm {
fn to_string(&self) -> String {
match *self {
Algorithm::TOTP => "totp",
Algorithm::HOTP => "hotp",
Algorithm::Steam => "steam",
Algorithm::SHA1 => "sha1",
Algorithm::SHA256 => "sha256",
Algorithm::SHA512 => "sha512",
}
.to_string()
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy, GEnum)]
#[repr(u32)]
#[genum(type_name = "ProviderHOTPAlgorithm")]
pub enum HOTPAlgorithm {
#[genum(name = "SHA1")]
SHA1 = 0,
#[genum(name = "SHA256")]
SHA256 = 1,
#[genum(name = "SHA512")]
SHA512 = 2,
}
impl Default for HOTPAlgorithm {
fn default() -> Self {
Self::SHA1
}
}
impl Serialize for HOTPAlgorithm {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for HOTPAlgorithm {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(HOTPAlgorithm::from_str(&String::deserialize(deserializer)?).unwrap())
}
}
impl HOTPAlgorithm {
pub fn to_locale_string(&self) -> String {
match *self {
HOTPAlgorithm::SHA1 => gettext("SHA1"),
HOTPAlgorithm::SHA256 => gettext("SHA256"),
HOTPAlgorithm::SHA512 => gettext("SHA512"),
}
}
}
impl FromStr for HOTPAlgorithm {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"sha1" | "otp" => Ok(Self::SHA1),
"sha256" => Ok(Self::SHA256),
"sha512" => Ok(Self::SHA512),
_ => anyhow::bail!("Unsupported HMAC algorithm"),
}
}
}
impl ToString for HOTPAlgorithm {
fn to_string(&self) -> String {
match *self {
HOTPAlgorithm::SHA1 => "sha1",
HOTPAlgorithm::SHA256 => "sha256",
HOTPAlgorithm::SHA512 => "sha512",
}
.to_string()
}
}
impl From<HOTPAlgorithm> for hmac::Algorithm {
fn from(h: HOTPAlgorithm) -> Self {
impl From<Algorithm> for hmac::Algorithm {
fn from(h: Algorithm) -> Self {
match h {
HOTPAlgorithm::SHA1 => hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
HOTPAlgorithm::SHA256 => hmac::HMAC_SHA256,
HOTPAlgorithm::SHA512 => hmac::HMAC_SHA512,
Algorithm::SHA1 => hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
Algorithm::SHA256 => hmac::HMAC_SHA256,
Algorithm::SHA512 => hmac::HMAC_SHA512,
}
}
}

View File

@ -12,9 +12,9 @@ mod providers;
pub use self::account::Account;
pub use self::account_sorter::AccountSorter;
pub use self::accounts::AccountsModel;
pub use self::algorithm::{Algorithm, HOTPAlgorithm};
pub use self::algorithm::{Algorithm, OTPMethod};
pub use self::favicon::{FaviconError, FaviconScrapper};
pub use self::otp_uri::OtpUri;
pub use self::otp_uri::OTPUri;
pub use self::provider::Provider;
pub use self::provider_sorter::ProviderSorter;
pub use self::providers::ProvidersModel;

View File

@ -1,20 +1,20 @@
use crate::models::{Account, Algorithm, HOTPAlgorithm};
use crate::models::{Account, Algorithm, OTPMethod};
use percent_encoding::percent_decode_str;
use std::str::FromStr;
#[derive(Debug, Clone)]
pub struct OtpUri {
pub struct OTPUri {
pub algorithm: Algorithm,
pub label: String,
pub secret: String,
pub issuer: String,
pub hmac_algorithm: HOTPAlgorithm,
pub method: OTPMethod,
pub digits: Option<i32>,
pub period: Option<i32>,
pub counter: Option<i32>,
}
impl FromStr for OtpUri {
impl FromStr for OTPUri {
type Err = anyhow::Error;
fn from_str(uri: &str) -> Result<Self, Self::Err> {
let url = url::Url::parse(uri)?;
@ -26,11 +26,11 @@ impl FromStr for OtpUri {
let mut counter = None;
let mut digits = None;
let mut provider_name = None;
let mut hmac_algorithm = None;
let mut algorithm = None;
let mut secret = None;
let pairs = url.query_pairs();
let algorithm = Algorithm::from_str(url.host_str().unwrap())?;
let method = OTPMethod::from_str(url.host_str().unwrap())?;
let account_info = url
.path()
@ -60,7 +60,7 @@ impl FromStr for OtpUri {
provider_name = Some(value.to_string());
}
"algorithm" => {
hmac_algorithm = HOTPAlgorithm::from_str(&value).ok();
algorithm = Algorithm::from_str(&value).ok();
}
"secret" => {
secret = Some(value.to_string());
@ -80,11 +80,11 @@ impl FromStr for OtpUri {
};
Ok(Self {
algorithm,
method,
label,
secret: secret.unwrap(),
issuer,
hmac_algorithm: hmac_algorithm.unwrap_or_default(),
algorithm: algorithm.unwrap_or_default(),
digits,
period,
counter,
@ -92,29 +92,29 @@ impl FromStr for OtpUri {
}
}
impl Into<String> for OtpUri {
impl Into<String> for OTPUri {
fn into(self) -> String {
format!(
"otpauth://{}/{}?secret={}&issuer={}&algorithm={}&digits={}&counter={}",
self.algorithm.to_string(),
self.method.to_string(),
self.label,
self.secret,
self.issuer,
self.hmac_algorithm.to_string(),
self.algorithm.to_string(),
self.digits.unwrap_or_else(|| 6),
self.counter.unwrap_or_else(|| 1),
)
}
}
impl From<&Account> for OtpUri {
impl From<&Account> for OTPUri {
fn from(a: &Account) -> Self {
Self {
algorithm: a.provider().algorithm(),
method: a.provider().method(),
label: a.name(),
secret: a.token(),
issuer: a.provider().name(),
hmac_algorithm: a.provider().hmac_algorithm(),
algorithm: a.provider().algorithm(),
digits: Some(a.provider().digits()),
period: Some(a.provider().period()),
counter: Some(a.counter()),

View File

@ -1,4 +1,4 @@
use super::algorithm::{Algorithm, HOTPAlgorithm};
use super::algorithm::{Algorithm, OTPMethod};
use crate::diesel::ExpressionMethods;
use crate::models::{database, Account, AccountsModel, FaviconError, FaviconScrapper};
use crate::schema::providers;
@ -26,8 +26,8 @@ struct NewProvider {
pub period: i32,
pub digits: i32,
pub default_counter: i32,
pub hmac_algorithm: String,
pub algorithm: String,
pub method: String,
}
#[derive(Identifiable, Queryable, Associations, Hash, PartialEq, Eq, Debug, Clone)]
@ -41,17 +41,17 @@ pub struct DiProvider {
pub period: i32,
pub digits: i32,
pub default_counter: i32,
pub hmac_algorithm: String,
pub algorithm: String,
pub method: String,
}
pub struct ProviderPriv {
pub id: Cell<i32>,
pub name: RefCell<String>,
pub period: Cell<i32>,
pub algorithm: RefCell<String>,
pub method: RefCell<String>,
pub default_counter: Cell<i32>,
pub hmac_algorithm: RefCell<String>,
pub algorithm: RefCell<String>,
pub digits: Cell<i32>,
pub website: RefCell<Option<String>>,
pub help_url: RefCell<Option<String>>,
@ -117,15 +117,6 @@ static PROPERTIES: [subclass::Property; 11] = [
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("hmac-algorithm", |name| {
glib::ParamSpec::string(
name,
"hmac_algorithm",
"HMAC algorithm",
Some(&HOTPAlgorithm::default().to_string()),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("algorithm", |name| {
glib::ParamSpec::string(
name,
@ -135,6 +126,15 @@ static PROPERTIES: [subclass::Property; 11] = [
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("method", |name| {
glib::ParamSpec::string(
name,
"method",
"Method",
Some(&OTPMethod::default().to_string()),
glib::ParamFlags::READWRITE,
)
}),
subclass::Property("website", |name| {
glib::ParamSpec::string(
name,
@ -182,13 +182,13 @@ impl ObjectSubclass for ProviderPriv {
Self {
id: Cell::new(0),
default_counter: Cell::new(1),
hmac_algorithm: RefCell::new(HOTPAlgorithm::default().to_string()),
algorithm: RefCell::new(Algorithm::default().to_string()),
digits: Cell::new(6),
name: RefCell::new("".to_string()),
website: RefCell::new(None),
help_url: RefCell::new(None),
image_uri: RefCell::new(None),
algorithm: RefCell::new(Algorithm::default().to_string()),
method: RefCell::new(OTPMethod::default().to_string()),
period: Cell::new(30),
filter_model: gtk::FilterListModel::new(Some(&model), gtk::NONE_FILTER),
accounts: model,
@ -221,12 +221,12 @@ impl ObjectImpl for ProviderPriv {
.expect("type conformity checked by `Object::set_property`");
self.period.replace(period);
}
subclass::Property("algorithm", ..) => {
let algorithm = value
subclass::Property("method", ..) => {
let method = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.algorithm.replace(algorithm);
self.method.replace(method);
}
subclass::Property("digits", ..) => {
let digits = value
@ -234,12 +234,12 @@ impl ObjectImpl for ProviderPriv {
.expect("type conformity checked by `Object::set_property`");
self.digits.replace(digits);
}
subclass::Property("hmac-algorithm", ..) => {
let hmac_algorithm = value
subclass::Property("algorithm", ..) => {
let algorithm = value
.get()
.expect("type conformity checked by `Object::set_property`")
.unwrap();
self.hmac_algorithm.replace(hmac_algorithm);
self.algorithm.replace(algorithm);
}
subclass::Property("default-counter", ..) => {
let default_counter = value
@ -276,9 +276,9 @@ impl ObjectImpl for ProviderPriv {
subclass::Property("id", ..) => self.id.get().to_value(),
subclass::Property("name", ..) => self.name.borrow().to_value(),
subclass::Property("period", ..) => self.period.get().to_value(),
subclass::Property("algorithm", ..) => self.algorithm.borrow().to_value(),
subclass::Property("method", ..) => self.method.borrow().to_value(),
subclass::Property("digits", ..) => self.digits.get().to_value(),
subclass::Property("hmac-algorithm", ..) => self.hmac_algorithm.borrow().to_value(),
subclass::Property("algorithm", ..) => self.algorithm.borrow().to_value(),
subclass::Property("default-counter", ..) => self.default_counter.get().to_value(),
subclass::Property("website", ..) => self.website.borrow().to_value(),
subclass::Property("help-url", ..) => self.help_url.borrow().to_value(),
@ -298,7 +298,7 @@ impl Provider {
period: i32,
algorithm: Algorithm,
website: Option<String>,
hmac_algorithm: HOTPAlgorithm,
method: OTPMethod,
digits: i32,
default_counter: i32,
) -> Result<Self> {
@ -309,9 +309,9 @@ impl Provider {
.values(NewProvider {
name: name.to_string(),
period,
algorithm: algorithm.to_string(),
method: method.to_string(),
website,
hmac_algorithm: hmac_algorithm.to_string(),
algorithm: algorithm.to_string(),
digits,
default_counter,
help_url: None,
@ -355,8 +355,8 @@ impl Provider {
id: i32,
name: &str,
period: i32,
method: OTPMethod,
algorithm: Algorithm,
hmac_algorithm: HOTPAlgorithm,
digits: i32,
default_counter: i32,
website: Option<String>,
@ -372,8 +372,8 @@ impl Provider {
("help-url", &help_url),
("image-uri", &image_uri),
("period", &period),
("method", &method.to_string()),
("algorithm", &algorithm.to_string()),
("hmac-algorithm", &hmac_algorithm.to_string()),
("digits", &digits),
("default-counter", &default_counter),
],
@ -436,16 +436,16 @@ impl Provider {
priv_.period.get()
}
pub fn hmac_algorithm(&self) -> HOTPAlgorithm {
let priv_ = ProviderPriv::from_instance(self);
HOTPAlgorithm::from_str(&priv_.hmac_algorithm.borrow().clone()).unwrap()
}
pub fn algorithm(&self) -> Algorithm {
let priv_ = ProviderPriv::from_instance(self);
Algorithm::from_str(&priv_.algorithm.borrow().clone()).unwrap()
}
pub fn method(&self) -> OTPMethod {
let priv_ = ProviderPriv::from_instance(self);
OTPMethod::from_str(&priv_.method.borrow().clone()).unwrap()
}
pub fn website(&self) -> Option<String> {
let priv_ = ProviderPriv::from_instance(self);
priv_.website.borrow().clone()
@ -528,8 +528,8 @@ impl From<DiProvider> for Provider {
p.id,
&p.name,
p.period,
OTPMethod::from_str(&p.method).unwrap(),
Algorithm::from_str(&p.algorithm).unwrap(),
HOTPAlgorithm::from_str(&p.hmac_algorithm).unwrap(),
p.digits,
p.default_counter,
p.website,
@ -545,8 +545,8 @@ impl From<&Provider> for DiProvider {
id: p.id(),
name: p.name(),
period: p.period(),
method: p.method().to_string(),
algorithm: p.algorithm().to_string(),
hmac_algorithm: p.hmac_algorithm().to_string(),
digits: p.digits(),
default_counter: p.default_counter(),
website: p.website(),

View File

@ -1,4 +1,4 @@
use super::{Account, Algorithm, HOTPAlgorithm, Provider};
use super::{Account, Algorithm, OTPMethod, Provider};
use anyhow::Result;
use gio::prelude::*;
use gio::subclass::ObjectSubclass;
@ -68,9 +68,9 @@ impl ProvidersModel {
&self,
name: &str,
period: i32,
algorithm: Algorithm,
method: OTPMethod,
website: Option<String>,
hmac_algorithm: HOTPAlgorithm,
algorithm: Algorithm,
digits: i32,
default_counter: i32,
) -> Result<Provider> {
@ -82,7 +82,7 @@ impl ProvidersModel {
period,
algorithm,
website,
hmac_algorithm,
method,
digits,
default_counter,
)?;

View File

@ -18,8 +18,8 @@ table! {
period -> Integer,
digits -> Integer,
default_counter -> Integer,
hmac_algorithm -> Text,
algorithm -> Text,
method -> Text,
}
}

View File

@ -1,5 +1,5 @@
use crate::helpers::qrcode;
use crate::models::{Account, Algorithm, OtpUri, Provider, ProvidersModel};
use crate::models::{Account, OTPMethod, OTPUri, Provider, ProvidersModel};
use crate::widgets::{Action, ProviderImage, ProviderImageSize};
use anyhow::Result;
use gio::prelude::*;
@ -45,8 +45,8 @@ mod imp {
#[template_child(id = "provider_entry")]
pub provider_entry: TemplateChild<gtk::Entry>,
#[template_child(id = "algorithm_label")]
pub algorithm_label: TemplateChild<gtk::Label>,
#[template_child(id = "method_label")]
pub method_label: TemplateChild<gtk::Label>,
#[template_child(id = "provider_website_row")]
pub provider_website_row: TemplateChild<libhandy::ActionRow>,
@ -54,8 +54,8 @@ mod imp {
#[template_child(id = "provider_help_row")]
pub provider_help_row: TemplateChild<libhandy::ActionRow>,
#[template_child(id = "hmac_algorithm_row")]
pub hmac_algorithm_row: TemplateChild<libhandy::ActionRow>,
#[template_child(id = "algorithm_label")]
pub algorithm_label: TemplateChild<gtk::Label>,
#[template_child(id = "counter_row")]
pub counter_row: TemplateChild<libhandy::ActionRow>,
@ -92,11 +92,11 @@ mod imp {
period_label: TemplateChild::default(),
digits_label: TemplateChild::default(),
provider_entry: TemplateChild::default(),
algorithm_label: TemplateChild::default(),
method_label: TemplateChild::default(),
provider_website_row: TemplateChild::default(),
provider_help_row: TemplateChild::default(),
provider_completion: TemplateChild::default(),
hmac_algorithm_row: TemplateChild::default(),
algorithm_label: TemplateChild::default(),
counter_row: TemplateChild::default(),
period_row: TemplateChild::default(),
}
@ -181,7 +181,7 @@ impl AccountAddDialog {
Ok(())
}
fn set_from_otp_uri(&self, otp_uri: OtpUri) {
fn set_from_otp_uri(&self, otp_uri: OTPUri) {
let self_ = imp::AccountAddDialog::from_instance(self);
self_.token_entry.get().set_text(&otp_uri.secret);
@ -194,9 +194,9 @@ impl AccountAddDialog {
.find_or_create(
&otp_uri.issuer,
otp_uri.period.unwrap_or_else(|| 30),
otp_uri.algorithm,
otp_uri.method,
None,
otp_uri.hmac_algorithm,
otp_uri.algorithm,
otp_uri.digits.unwrap_or_else(|| 6),
otp_uri.counter.unwrap_or_else(|| 1),
)
@ -233,6 +233,11 @@ impl AccountAddDialog {
self_.image.set_provider(&provider);
self_
.method_label
.get()
.set_text(&provider.method().to_locale_string());
self_
.algorithm_label
.get()
@ -243,18 +248,16 @@ impl AccountAddDialog {
.get()
.set_text(&provider.digits().to_string());
match provider.algorithm() {
Algorithm::TOTP => {
self_.hmac_algorithm_row.get().hide();
match provider.method() {
OTPMethod::TOTP => {
self_.counter_row.get().hide();
self_.period_row.get().show();
}
Algorithm::HOTP => {
self_.hmac_algorithm_row.get().show();
OTPMethod::HOTP => {
self_.counter_row.get().show();
self_.period_row.get().hide();
}
Algorithm::Steam => {}
OTPMethod::Steam => {}
};
if let Some(ref website) = provider.website() {

View File

@ -1,4 +1,4 @@
use crate::models::{Algorithm, HOTPAlgorithm, Provider};
use crate::models::{Algorithm, OTPMethod, Provider};
use crate::widgets::{ProviderImage, ProviderImageSize};
use gio::subclass::ObjectSubclass;
use glib::subclass::prelude::*;
@ -13,6 +13,8 @@ pub enum ProviderPageMode {
}
mod imp {
use crate::models::OTPMethod;
use super::*;
use glib::subclass;
use gtk::subclass::prelude::*;
@ -34,10 +36,10 @@ mod imp {
pub provider_website_entry: TemplateChild<gtk::Entry>,
#[template_child(id = "provider_help_entry")]
pub provider_help_entry: TemplateChild<gtk::Entry>,
#[template_child(id = "method_comborow")]
pub method_comborow: TemplateChild<libhandy::ComboRow>,
#[template_child(id = "algorithm_comborow")]
pub algorithm_comborow: TemplateChild<libhandy::ComboRow>,
#[template_child(id = "hmac_algorithm_comborow")]
pub hmac_algorithm_comborow: TemplateChild<libhandy::ComboRow>,
#[template_child(id = "period_row")]
pub period_row: TemplateChild<libhandy::ActionRow>,
#[template_child(id = "digits_row")]
@ -46,8 +48,8 @@ mod imp {
pub default_counter_row: TemplateChild<libhandy::ActionRow>,
#[template_child(id = "title")]
pub title: TemplateChild<gtk::Label>,
pub methods_model: libhandy::EnumListModel,
pub algorithms_model: libhandy::EnumListModel,
pub hmac_algorithms_model: libhandy::EnumListModel,
}
impl ObjectSubclass for ProviderPage {
@ -60,8 +62,8 @@ mod imp {
glib_object_subclass!();
fn new() -> Self {
let methods_model = libhandy::EnumListModel::new(OTPMethod::static_type());
let algorithms_model = libhandy::EnumListModel::new(Algorithm::static_type());
let hmac_algorithms_model = libhandy::EnumListModel::new(HOTPAlgorithm::static_type());
Self {
image: ProviderImage::new(ProviderImageSize::Large),
@ -72,14 +74,14 @@ mod imp {
default_counter_spinbutton: TemplateChild::default(),
provider_website_entry: TemplateChild::default(),
provider_help_entry: TemplateChild::default(),
method_comborow: TemplateChild::default(),
algorithm_comborow: TemplateChild::default(),
hmac_algorithm_comborow: TemplateChild::default(),
period_row: TemplateChild::default(),
digits_row: TemplateChild::default(),
default_counter_row: TemplateChild::default(),
title: TemplateChild::default(),
methods_model,
algorithms_model,
hmac_algorithms_model,
}
}
@ -143,10 +145,10 @@ impl ProviderPage {
.get()
.set_value(provider.digits() as f64);
self_.hmac_algorithm_comborow.get().set_selected(
self_.method_comborow.get().set_selected(
self_
.hmac_algorithms_model
.find_position(provider.hmac_algorithm().to_glib()),
.methods_model
.find_position(provider.method().to_glib()),
);
self_.image.set_provider(&provider);
self_
@ -171,27 +173,25 @@ impl ProviderPage {
page.on_algorithm_changed();
}));
self_
.hmac_algorithm_comborow
.method_comborow
.get()
.set_model(Some(&self_.hmac_algorithms_model));
.set_model(Some(&self_.methods_model));
}
fn on_algorithm_changed(&self) {
let self_ = imp::ProviderPage::from_instance(self);
let selected = Algorithm::from(self_.algorithm_comborow.get().get_selected());
let selected = OTPMethod::from(self_.method_comborow.get().get_selected());
match selected {
Algorithm::TOTP => {
OTPMethod::TOTP => {
self_.default_counter_row.get().hide();
self_.hmac_algorithm_comborow.get().hide();
self_.period_row.get().show();
}
Algorithm::HOTP => {
OTPMethod::HOTP => {
self_.default_counter_row.get().show();
self_.hmac_algorithm_comborow.get().show();
self_.period_row.get().hide();
}
Algorithm::Steam => {}
OTPMethod::Steam => {}
}
}
@ -205,7 +205,7 @@ impl ProviderPage {
self_.provider_website_entry.get().set_text("");
self_.provider_help_entry.get().set_text("");
self_.algorithm_comborow.get().set_selected(0);
self_.method_comborow.get().set_selected(0);
}
ProviderPageMode::Edit => {}
}

View File

@ -1,4 +1,4 @@
use crate::models::{Account, AccountSorter, Algorithm, Provider};
use crate::models::{Account, AccountSorter, OTPMethod, Provider};
use crate::widgets::{accounts::AccountRow, ProviderImage, ProviderImageSize};
use gio::prelude::*;
use gio::subclass::ObjectSubclass;
@ -122,13 +122,13 @@ impl ProviderRow {
fn setup_widgets(&self) {
let self_ = imp::ProviderRow::from_instance(self);
self.add_css_class(&self.provider().algorithm().to_string());
self.add_css_class(&self.provider().method().to_string());
self_.header.get().prepend(&self_.image);
self_.image.set_provider(&self.provider());
let progress_bar = self_.progress.get();
if self.provider().algorithm() == Algorithm::TOTP {
if self.provider().method() == OTPMethod::TOTP {
progress_bar.set_fraction(1_f64);
let max = self.provider().period() as f64;
glib::timeout_add_local(