Make use of nightly rustfmt features

This commit is contained in:
Bilal Elmoussaoui 2022-06-10 21:10:52 +02:00
parent 99a4bd1efe
commit da507399ca
44 changed files with 316 additions and 212 deletions

View file

@ -1,5 +1,6 @@
use image::io::Reader as ImageReader;
use std::{fmt, io::Cursor, path::PathBuf};
use image::io::Reader as ImageReader;
use tokio::{io::AsyncWriteExt, sync::Mutex};
use url::Url;
@ -45,8 +46,8 @@ impl Favicon {
///
/// # Panics
///
/// If the favicon contains the data instead of a URL, you are supposed to check
/// it content using [`Favicon::is_url`]
/// If the favicon contains the data instead of a URL, you are supposed to
/// check it content using [`Favicon::is_url`]
pub fn url(&self) -> &Url {
match &self.url {
Some(url) => url,

View file

@ -1,7 +1,7 @@
use url::Url;
use std::{fmt, path::Path};
use url::Url;
/// Supported image formats.
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord)]
pub enum Format {
@ -11,11 +11,12 @@ pub enum Format {
}
impl Format {
/// Create a [`Format`] from a URL's path otherwise default to [`Format::Png`].
/// Create a [`Format`] from a URL's path otherwise default to
/// [`Format::Png`].
///
/// ```
/// use url::Url;
/// use favicon_scrapper::Format;
/// use url::Url;
///
/// let url = Url::parse("http://127.0.0.1:8000/favicon.ico").unwrap();
/// assert!(Format::from_url(&url).is_ico());
@ -38,7 +39,8 @@ impl Format {
}
}
/// Create a [`Format`] from a mimetype otherwise default to [`Format::Png`].
/// Create a [`Format`] from a mimetype otherwise default to
/// [`Format::Png`].
///
/// ```
/// use favicon_scrapper::Format;

View file

@ -16,9 +16,10 @@ pub use scrapper::Scrapper;
#[cfg(test)]
mod tests {
use super::*;
use url::Url;
use super::*;
#[tokio::test]
async fn parse_from_file() {
let base_url = Url::parse("https://github.com").unwrap();
@ -127,7 +128,8 @@ mod tests {
.await
.unwrap();
assert!(!scrapper.is_empty());
// There are 16 but we always add the favicon.ico to try in case it exists as well
// There are 16 but we always add the favicon.ico to try in case it exists as
// well
assert_eq!(scrapper.len(), 16 + 1);
assert_eq!(

View file

@ -1,6 +1,7 @@
use std::{fmt, path::PathBuf};
use percent_encoding::percent_decode_str;
use quick_xml::events::{attributes::Attribute, BytesStart, Event};
use std::{fmt, path::PathBuf};
use tracing::debug;
use url::Url;

7
rustfmt.toml Normal file
View file

@ -0,0 +1,7 @@
imports_granularity = "Crate"
format_code_in_doc_comments = true
group_imports = "StdExternalCrate"
newline_style = "Unix"
normalize_comments = true
normalize_doc_attributes = true
wrap_comments = true

View file

@ -1,3 +1,12 @@
use std::{collections::HashMap, str::FromStr};
use adw::prelude::*;
use gettextrs::gettext;
use glib::clone;
use gtk::{gio, glib, subclass::prelude::*};
use gtk_macros::{action, get_action};
use search_provider::{ResultID, ResultMeta, SearchProvider, SearchProviderImpl};
use crate::{
config,
models::{
@ -6,20 +15,15 @@ use crate::{
utils::spawn_tokio_blocking,
widgets::{PreferencesWindow, ProvidersDialog, Window},
};
use adw::prelude::*;
use gettextrs::gettext;
use glib::clone;
use gtk::{gio, glib, subclass::prelude::*};
use gtk_macros::{action, get_action};
use search_provider::{ResultID, ResultMeta, SearchProvider, SearchProviderImpl};
use std::{collections::HashMap, str::FromStr};
mod imp {
use super::*;
use std::cell::{Cell, RefCell};
use adw::subclass::prelude::*;
use glib::{ParamSpec, ParamSpecBoolean, Value, WeakRef};
use once_cell::sync::OnceCell;
use std::cell::{Cell, RefCell};
use super::*;
// The basic struct that holds our state and widgets
// (Ref)Cells are used for members which need to be mutable

View file

@ -3,24 +3,24 @@
//! See https://github.com/beemdevelopment/Aegis/blob/master/docs/vault.md for a description of the
//! aegis vault format.
//!
//! This module does not convert all information from aegis (note, icon, group are lost). When
//! exporting to the aegis json format the icon, url, help url, and tags are lost.
//! This module does not convert all information from aegis (note, icon, group
//! are lost). When exporting to the aegis json format the icon, url, help url,
//! and tags are lost.
//!
//! Exported files by this module cannot be decrypted by the python script provided in the aegis
//! repository (https://github.com/beemdevelopment/Aegis/blob/master/docs/decrypt.py). However,
//! Exported files by this module cannot be decrypted by the python script
//! provided in the aegis repository (https://github.com/beemdevelopment/Aegis/blob/master/docs/decrypt.py). However,
//! aegis android app is able to read the files! See line 173 for a discussion.
use super::{Backupable, Restorable, RestorableItem};
use crate::models::{Account, Algorithm, OTPMethod, Provider, ProvidersModel};
use aes_gcm::aead::Aead;
use aes_gcm::NewAead;
use anyhow::Context;
use anyhow::Result;
use aes_gcm::{aead::Aead, NewAead};
use anyhow::{Context, Result};
use gettextrs::gettext;
use gtk::{glib::Cast, prelude::*};
use rand::RngCore;
use serde::{Deserialize, Serialize};
use super::{Backupable, Restorable, RestorableItem};
use crate::models::{Account, Algorithm, OTPMethod, Provider, ProvidersModel};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Aegis {
@ -49,7 +49,8 @@ impl Default for AegisPlainText {
}
}
/// Encrypted version of the JSON format. `db` is simply a base64 encoded string with an encrypted AegisDatabase.
/// Encrypted version of the JSON format. `db` is simply a base64 encoded string
/// with an encrypted AegisDatabase.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AegisEncrypted {
version: u32,
@ -85,8 +86,8 @@ impl Aegis {
slots: Some(vec![HeaderSlot::default()]),
};
// We only support password encrypted database so far so we don't have to do any checks
// for the slot type
// We only support password encrypted database so far so we don't have to do any
// checks for the slot type
let mut password_slot = &mut header.slots.as_mut().unwrap().get_mut(0).unwrap();
// Derive key from given password
let mut derived_key: [u8; 32] = [0u8; 32];
@ -115,7 +116,8 @@ impl Aegis {
)
.map_err(|_| anyhow::anyhow!("Encrypter master key"))?;
// Add encrypted master key and tag to our password slot. If this assignment fails, we have a mistake in our logic, thus unwrap is okay.
// Add encrypted master key and tag to our password slot. If this assignment
// fails, we have a mistake in our logic, thus unwrap is okay.
password_slot.key_params.tag = ciphertext.split_off(32).try_into().unwrap();
password_slot.key = ciphertext.try_into().unwrap();
@ -153,7 +155,8 @@ impl Aegis {
/// Header of the Encrypted Aegis JSON File
///
/// Contains all necessary information for encrypting / decrypting the vault (db field).
/// Contains all necessary information for encrypting / decrypting the vault (db
/// field).
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Header {
#[serde(default)]
@ -177,9 +180,9 @@ pub struct HeaderSlot {
//
// TODO rename should be changed to `rename = 2`. However this does not work yet with serde,
// see: https://github.com/serde-rs/serde/issues/745. This allows decrypting the exported file
// with the python script provided in the aegis repository. The python script expects an integer
// but we provide a string. Thus, change the string in header / slots / password slot / `type = "1"`
// to `type = 1` to use the python script.
// with the python script provided in the aegis repository. The python script expects an
// integer but we provide a string. Thus, change the string in header / slots / password
// slot / `type = "1"` to `type = 1` to use the python script.
#[serde(rename = "type")]
pub type_: u32,
pub uuid: String,
@ -283,8 +286,8 @@ pub struct Item {
pub tags: Option<String>,
// Note is omitted
// Icon:
// TODO: Aegis encodes icons as JPEG's encoded in Base64 with padding. Does authenticator support
// this?
// TODO: Aegis encodes icons as JPEG's encoded in Base64 with padding. Does authenticator
// support this?
// TODO tags are not imported/exported right now.
#[serde(rename = "icon")]
pub thumbnail: Option<String>,
@ -482,8 +485,9 @@ impl Restorable for Aegis {
// Add the encryption tag
ciphertext.append(&mut encrypted.header.params.as_ref().unwrap().tag.into());
// Find slots with type password and derive the corresponding key. This key is used
// to decrypt the master key which in turn can be used to decrypt the database.
// Find slots with type password and derive the corresponding key. This key is
// used to decrypt the master key which in turn can be used to
// decrypt the database.
let master_keys: Vec<Vec<u8>> = encrypted
.header
.slots
@ -494,9 +498,11 @@ impl Restorable for Aegis {
.map(|slot| -> Result<Vec<u8>> {
tracing::info!("Found possible master key with UUID {}.", slot.uuid);
// Create parameters for scrypt function and derive decryption key for master key
// Create parameters for scrypt function and derive decryption key for
// master key
//
// Somehow, scrypt errors do not implement StdErr and cannot be converted to anyhow::Error. Should be possible but don't know why it doesn't work.
// Somehow, scrypt errors do not implement StdErr and cannot be converted to
// anyhow::Error. Should be possible but don't know why it doesn't work.
let params = scrypt::Params::new(
// TODO log2 for u64 is not stable yet. Change this in the future.
(slot.n() as f64).log2() as u8, // Defaults to 15 by aegis
@ -518,7 +524,8 @@ impl Restorable for Aegis {
let mut ciphertext: Vec<u8> = slot.key.to_vec();
ciphertext.append(&mut slot.key_params.tag.to_vec());
// Here we get the master key. The decrypt function does not return an error implementing std error. Thus, we have to convert it.
// Here we get the master key. The decrypt function does not return an error
// implementing std error. Thus, we have to convert it.
cipher
.decrypt(
aes_gcm::Nonce::from_slice(&slot.key_params.nonce),
@ -526,7 +533,9 @@ impl Restorable for Aegis {
)
.map_err(|_| anyhow::anyhow!("Cannot decrypt master key"))
})
// Here, we don't want to fail the whole function because one key slot failed to get the correct master key. Maybe there is another slot we were able to decrypt.
// Here, we don't want to fail the whole function because one key slot failed to
// get the correct master key. Maybe there is another slot we were able to
// decrypt.
.filter_map(|x| match x {
Ok(x) => Some(x),
Err(e) => {
@ -536,7 +545,8 @@ impl Restorable for Aegis {
})
.collect();
// Choose the first valid master key. I don't think there are aegis installations with two valid password slots.
// Choose the first valid master key. I don't think there are aegis
// installations with two valid password slots.
tracing::info!(
"Found {} valid password slots / master keys.",
master_keys.len()

View file

@ -1,10 +1,11 @@
use super::{Backupable, Restorable, RestorableItem};
use crate::models::{Account, Algorithm, OTPMethod, Provider, ProvidersModel};
use anyhow::Result;
use gettextrs::gettext;
use gtk::{glib::Cast, prelude::*};
use serde::{Deserialize, Serialize};
use super::{Backupable, Restorable, RestorableItem};
use crate::models::{Account, Algorithm, OTPMethod, Provider, ProvidersModel};
#[allow(clippy::upper_case_acronyms)]
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AndOTP {

View file

@ -1,9 +1,11 @@
use super::{Restorable, RestorableItem};
use crate::models::{Algorithm, OTPMethod, OTPUri};
use std::str::FromStr;
use anyhow::Result;
use gettextrs::gettext;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use super::{Restorable, RestorableItem};
use crate::models::{Algorithm, OTPMethod, OTPUri};
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Bitwarden {

View file

@ -1,10 +1,12 @@
use super::{Backupable, Restorable};
use crate::models::{Account, OTPUri, Provider, ProvidersModel};
use std::str::FromStr;
use anyhow::Result;
use gettextrs::gettext;
use gtk::prelude::*;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use super::{Backupable, Restorable};
use crate::models::{Account, OTPUri, Provider, ProvidersModel};
#[allow(clippy::upper_case_acronyms)]
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

View file

@ -1,12 +1,14 @@
use super::Restorable;
use crate::models::{Algorithm, OTPMethod, OTPUri};
use std::borrow::Cow;
use anyhow::Result;
use gettextrs::gettext;
use percent_encoding::percent_decode;
use prost::{Enumeration, Message};
use std::borrow::Cow;
use url::Url;
use super::Restorable;
use crate::models::{Algorithm, OTPMethod, OTPUri};
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Google;
@ -182,8 +184,7 @@ mod protobuf {
#[cfg(test)]
mod tests {
use super::super::RestorableItem;
use super::*;
use super::{super::RestorableItem, *};
#[test]
fn test_google_restore_otpauth() {

View file

@ -1,9 +1,10 @@
use super::{Restorable, RestorableItem};
use crate::models::{Algorithm, OTPMethod};
use anyhow::Result;
use gettextrs::gettext;
use serde::{Deserialize, Serialize};
use super::{Restorable, RestorableItem};
use crate::models::{Algorithm, OTPMethod};
// Same as andOTP except uses the first tag for the issuer
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LegacyAuthenticator {
@ -30,7 +31,8 @@ impl Restorable for LegacyAuthenticator {
}
fn title() -> String {
// Translators: this is for restoring a backup from the old Authenticator release
// Translators: this is for restoring a backup from the old Authenticator
// release
gettext("Au_thenticator (Legacy)")
}

View file

@ -1,9 +1,10 @@
use std::fmt::Debug;
use crate::models::{Account, Algorithm, OTPMethod, ProvidersModel};
use anyhow::Result;
use gtk::{gio, gio::prelude::*};
use crate::models::{Account, Algorithm, OTPMethod, ProvidersModel};
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub enum Operation {
Backup,
@ -23,16 +24,17 @@ pub trait Restorable: Sized {
fn subtitle() -> String;
fn identifier() -> String;
/// Restore many items from a slice of data, optionally using a key to unencrypt it.
/// Restore many items from a slice of data, optionally using a key to
/// unencrypt it.
///
/// If `key` is `None`, then the implementation should assume that the slice is unencrypted, and
/// error if it only supports encrypted slices.
/// If `key` is `None`, then the implementation should assume that the slice
/// is unencrypted, and error if it only supports encrypted slices.
fn restore_from_data(from: &[u8], key: Option<&str>) -> Result<Vec<Self::Item>>;
/// Restore many items from a file, optiontally using a key to unencrypt it.
///
/// If `key` is `None`, then the implementation should assume that the file is unencrypted, and
/// error if it only supports encrypted files.
/// If `key` is `None`, then the implementation should assume that the file
/// is unencrypted, and error if it only supports encrypted files.
///
/// By default, this method reads the file and passes the files content to
/// `Self::restore_from_data`.

View file

@ -1,3 +1,13 @@
use core::cmp::Ordering;
use std::cell::{Cell, RefCell};
use anyhow::{Context, Result};
use diesel::{BelongingToDsl, ExpressionMethods, QueryDsl, RunQueryDsl};
use glib::{clone, Cast, StaticType, ToValue};
use gtk::{glib, prelude::*, subclass::prelude::*};
use once_cell::sync::OnceCell;
use unicase::UniCase;
use super::{
provider::{DiProvider, Provider},
OTPMethod, OTPUri, RUNTIME,
@ -8,14 +18,6 @@ use crate::{
utils::spawn_tokio_blocking,
widgets::QRCodeData,
};
use anyhow::{Context, Result};
use core::cmp::Ordering;
use diesel::{BelongingToDsl, ExpressionMethods, QueryDsl, RunQueryDsl};
use glib::{clone, Cast, StaticType, ToValue};
use gtk::{glib, prelude::*, subclass::prelude::*};
use once_cell::sync::OnceCell;
use std::cell::{Cell, RefCell};
use unicase::UniCase;
#[derive(Insertable)]
#[table_name = "accounts"]
@ -39,9 +41,10 @@ pub struct DiAccount {
#[doc(hidden)]
mod imp {
use super::*;
use glib::{ParamSpec, ParamSpecObject, ParamSpecString, ParamSpecUInt, Value};
use super::*;
pub struct Account {
pub id: Cell<u32>,
pub otp: RefCell<String>,

View file

@ -1,9 +1,10 @@
use gtk::glib;
mod imp {
use gtk::subclass::prelude::*;
use super::*;
use crate::models::Account;
use gtk::subclass::prelude::*;
#[derive(Debug, Default)]
pub struct AccountSorter;

View file

@ -1,11 +1,13 @@
use super::account::Account;
use glib::StaticType;
use gtk::{gio, glib, prelude::*, subclass::prelude::*};
use super::account::Account;
mod imp {
use super::*;
use std::cell::RefCell;
use super::*;
#[derive(Debug, Default)]
pub struct AccountsModel(pub RefCell<Vec<Account>>);

View file

@ -1,8 +1,9 @@
use std::{str::FromStr, string::ToString};
use gettextrs::gettext;
use gtk::glib;
use ring::hmac;
use serde::{de::Deserializer, ser::Serializer, Deserialize, Serialize};
use std::{str::FromStr, string::ToString};
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Eq, PartialEq, Clone, Copy, glib::Enum)]

View file

@ -1,7 +1,8 @@
use std::{fs, fs::File, path::PathBuf};
use anyhow::Result;
use diesel::{prelude::*, r2d2, r2d2::ConnectionManager};
use once_cell::sync::Lazy;
use std::{fs, fs::File, path::PathBuf};
type Pool = r2d2::Pool<ConnectionManager<SqliteConnection>>;

View file

@ -1,7 +1,9 @@
use crate::config;
use std::collections::HashMap;
use once_cell::sync::OnceCell;
use rand::RngCore;
use std::collections::HashMap;
use crate::config;
pub static SECRET_SERVICE: OnceCell<oo7::Keyring> = OnceCell::new();

View file

@ -1,8 +1,12 @@
use super::Algorithm;
use std::{
convert::TryInto,
time::{SystemTime, UNIX_EPOCH},
};
use anyhow::{anyhow, Result};
use ring::hmac;
use std::convert::TryInto;
use std::time::{SystemTime, UNIX_EPOCH};
use super::Algorithm;
pub static STEAM_CHARS: &str = "23456789BCDFGHJKMNPQRTVWXY";
pub static STEAM_DEFAULT_PERIOD: u32 = 30;

View file

@ -1,11 +1,12 @@
use std::{fmt::Write, str::FromStr};
use percent_encoding::percent_decode_str;
use url::Url;
use crate::{
backup::RestorableItem,
models::{otp, Account, Algorithm, OTPMethod},
};
use percent_encoding::percent_decode_str;
use std::fmt::Write;
use std::str::FromStr;
use url::Url;
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Clone)]

View file

@ -1,22 +1,24 @@
use super::algorithm::{Algorithm, OTPMethod};
use crate::{
models::{database, otp, Account, AccountsModel, FAVICONS_PATH},
schema::providers,
};
use anyhow::Result;
use core::cmp::Ordering;
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
use glib::{clone, Cast, StaticType, ToValue};
use gtk::{gdk_pixbuf, gio, glib, prelude::*, subclass::prelude::*};
use std::{
cell::{Cell, RefCell},
str::FromStr,
string::ToString,
time::{SystemTime, UNIX_EPOCH},
};
use anyhow::Result;
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
use glib::{clone, Cast, StaticType, ToValue};
use gtk::{gdk_pixbuf, gio, glib, prelude::*, subclass::prelude::*};
use unicase::UniCase;
use url::Url;
use super::algorithm::{Algorithm, OTPMethod};
use crate::{
models::{database, otp, Account, AccountsModel, FAVICONS_PATH},
schema::providers,
};
#[derive(Debug)]
pub struct ProviderPatch {
pub name: String,
@ -60,10 +62,11 @@ pub struct DiProvider {
pub method: String,
}
mod imp {
use super::*;
use glib::{ParamSpec, ParamSpecObject, ParamSpecString, ParamSpecUInt, Value};
use gst::glib::{ParamSpecUInt64, SourceId};
use super::*;
pub struct Provider {
pub id: Cell<u32>,
pub name: RefCell<String>,
@ -387,8 +390,8 @@ impl Provider {
let icon_name = glib::base64_encode(icon_name.as_bytes());
let small_icon_name = format!("{icon_name}_32x32");
let large_icon_name = format!("{icon_name}_96x96");
// TODO: figure out why trying to grab icons at specific size causes stack size errors
// We need two sizes:
// TODO: figure out why trying to grab icons at specific size causes stack size
// errors We need two sizes:
// - 32x32 for the accounts lists
// - 96x96 elsewhere
if let Some(best_favicon) = favicon.find_best().await {

View file

@ -1,10 +1,12 @@
use super::provider::Provider;
use gtk::glib;
use super::provider::Provider;
mod imp {
use super::*;
use gtk::subclass::prelude::*;
use super::*;
#[derive(Debug, Default)]
pub struct ProviderSorter;

View file

@ -1,12 +1,14 @@
use super::{otp, Account, Algorithm, OTPMethod, Provider, ProviderPatch};
use anyhow::Result;
use glib::StaticType;
use gtk::{gio, glib, prelude::*, subclass::prelude::*};
use super::{otp, Account, Algorithm, OTPMethod, Provider, ProviderPatch};
mod imp {
use super::*;
use std::cell::RefCell;
use super::*;
#[derive(Debug, Default)]
pub struct ProvidersModel(pub RefCell<Vec<Provider>>);
@ -60,8 +62,9 @@ impl ProvidersModel {
) -> Result<Provider> {
let provider = match self.find_by_name(name) {
Some(p) => {
// Update potenitally different properties than what we have in the pre-shipped database
// Note this does a comparaison first to avoid a uselesss rewrite
// Update potenitally different properties than what we have in the pre-shipped
// database Note this does a comparaison first to avoid a
// uselesss rewrite
p.update(&ProviderPatch {
name: name.to_owned(),
website,

View file

@ -1,21 +1,24 @@
use crate::{
models::{otp, Account, OTPMethod, OTPUri, Provider, ProvidersModel},
widgets::{Camera, ErrorRevealer, ProviderImage, UrlRow},
};
use std::str::FromStr;
use anyhow::Result;
use gettextrs::gettext;
use glib::{clone, signal::Inhibit};
use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use gtk_macros::spawn;
use once_cell::sync::{Lazy, OnceCell};
use std::str::FromStr;
use crate::{
models::{otp, Account, OTPMethod, OTPUri, Provider, ProvidersModel},
widgets::{Camera, ErrorRevealer, ProviderImage, UrlRow},
};
mod imp {
use crate::widgets::providers::ProviderPage;
use std::cell::RefCell;
use glib::subclass::{InitializingObject, Signal};
use super::*;
use glib::subclass::{InitializingObject, Signal};
use std::cell::RefCell;
use crate::widgets::providers::ProviderPage;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/account_add.ui")]
@ -269,8 +272,9 @@ impl AccountAddDialog {
}),
);
// in case the provider doesn't exists, let the user create a new one by showing a dialog for that
// TODO: replace this whole completion provider thing with a custom widget
// in case the provider doesn't exists, let the user create a new one by showing
// a dialog for that TODO: replace this whole completion provider thing
// with a custom widget
imp.provider_completion.connect_no_matches(clone!(@weak self as dialog => move |completion| {
let imp = dialog.imp();
let model = imp.model.get().unwrap();

View file

@ -1,8 +1,3 @@
use super::qrcode_paintable::QRCodePaintable;
use crate::{
models::{Account, OTPMethod, Provider, ProvidersModel},
widgets::UrlRow,
};
use gettextrs::gettext;
use gtk::{
gdk,
@ -11,17 +6,24 @@ use gtk::{
subclass::prelude::*,
CompositeTemplate,
};
use super::qrcode_paintable::QRCodePaintable;
use crate::{
models::{Account, OTPMethod, Provider, ProvidersModel},
widgets::UrlRow,
};
mod imp {
use std::cell::RefCell;
use glib::subclass::{self, Signal};
use once_cell::sync::{Lazy, OnceCell};
use super::*;
use crate::{
models::Provider,
widgets::{editable_label::EditableSpin, EditableLabel},
};
use super::*;
use glib::subclass::{self, Signal};
use once_cell::sync::{Lazy, OnceCell};
use std::cell::RefCell;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/account_details_page.ui")]
pub struct AccountDetailsPage {

View file

@ -3,6 +3,7 @@ mod details;
mod qrcode_paintable;
mod row;
pub use self::{add::AccountAddDialog, row::AccountRow};
pub use details::AccountDetailsPage;
pub use qrcode_paintable::{QRCodeData, QRCodePaintable};
pub use self::{add::AccountAddDialog, row::AccountRow};

View file

@ -63,9 +63,10 @@ mod imp {
});
});
}
use super::*;
use std::cell::RefCell;
use super::*;
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug, Default)]
pub struct QRCodePaintable {

View file

@ -1,16 +1,18 @@
use crate::models::{Account, OTPMethod};
use gtk::{gdk, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use std::cell::RefCell;
mod imp {
use crate::widgets::Window;
use gtk::{gdk, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use super::*;
use crate::models::{Account, OTPMethod};
mod imp {
use adw::subclass::prelude::*;
use gettextrs::gettext;
use glib::{subclass, ParamSpec, ParamSpecObject, Value};
use once_cell::sync::Lazy;
use super::*;
use crate::widgets::Window;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/account_row.ui")]
pub struct AccountRow {

View file

@ -1,4 +1,8 @@
use crate::widgets::CameraPaintable;
use std::{
cell::{Cell, RefCell},
os::unix::prelude::RawFd,
};
use adw::subclass::prelude::*;
use anyhow::Result;
use ashpd::{desktop::screenshot::ScreenshotProxy, zbus};
@ -17,10 +21,10 @@ use gtk::{
use gtk_macros::spawn;
use image::GenericImageView;
use once_cell::sync::Lazy;
use std::cell::{Cell, RefCell};
use std::os::unix::prelude::RawFd;
use zbar_rust::ZBarImageScanner;
use crate::widgets::CameraPaintable;
mod screenshot {
use super::*;

View file

@ -1,17 +1,18 @@
use std::os::unix::io::AsRawFd;
use crate::widgets::camera::CameraEvent;
use gst::prelude::*;
use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{
gdk,
glib::{self, clone, Sender},
graphene,
prelude::*,
subclass::prelude::*,
};
use gtk_macros::send;
use once_cell::sync::Lazy;
use tracing::error;
use crate::widgets::camera::CameraEvent;
static PIPELINE_NAME: Lazy<glib::GString> = Lazy::new(|| glib::GString::from("camera"));
/// Fancy Camera with QR code detection using ZBar
///
@ -21,8 +22,6 @@ static PIPELINE_NAME: Lazy<glib::GString> = Lazy::new(|| glib::GString::from("ca
/// pipewiresrc -- tee
/// \
/// queue -- glsinkbin
///
///
mod imp {
use std::cell::RefCell;
@ -74,7 +73,8 @@ mod imp {
) {
let snapshot = snapshot.downcast_ref::<gtk::Snapshot>().unwrap();
if let Some(ref image) = *self.sink_paintable.borrow() {
// Transformation to avoid stretching the camera. We translate and scale the image.
// Transformation to avoid stretching the camera. We translate and scale the
// image.
let aspect = width / height.max(std::f64::EPSILON); // Do not divide by zero.
let image_aspect = image.intrinsic_aspect_ratio();

View file

@ -1,9 +1,10 @@
use gtk::{glib, prelude::*, subclass::prelude::*};
mod imp {
use super::*;
use adw::subclass::prelude::*;
use super::*;
#[derive(Debug, Default, gtk::CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/editable_label.ui")]
pub struct EditableLabel {

View file

@ -1,10 +1,11 @@
use gtk::{glib, prelude::*, subclass::prelude::*};
mod imp {
use super::*;
use glib::subclass;
use gtk::CompositeTemplate;
use super::*;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/error_revealer.ui")]
pub struct ErrorRevealer {

View file

@ -1,4 +1,5 @@
use crate::{utils::spawn_tokio, widgets::Camera};
use std::{cell::Cell, rc::Rc};
use adw::subclass::prelude::*;
use anyhow::Result;
use gtk::{
@ -10,14 +11,14 @@ use gtk::{
};
use gtk_macros::get_action;
use once_cell::sync::OnceCell;
use std::cell::Cell;
use std::rc::Rc;
use tokio::{
select,
sync::oneshot,
time::{sleep, Duration},
};
use crate::{utils::spawn_tokio, widgets::Camera};
mod imp {
use super::*;
@ -67,8 +68,8 @@ impl CameraPage {
let (tx, rx) = oneshot::channel();
// This is required because for whatever reason `glib::clone!` wouldn't let it be moved into
// the closure.
// This is required because for whatever reason `glib::clone!` wouldn't let it
// be moved into the closure.
let tx = Rc::new(Cell::new(Some(tx)));
// This is to make it safe to access `src` inside of the connected closure to
@ -121,8 +122,8 @@ impl CameraPage {
let (tx, rx) = oneshot::channel();
// This is required because for whatever reason `glib::clone!` wouldn't let it be moved into
// the closure.
// This is required because for whatever reason `glib::clone!` wouldn't let it
// be moved into the closure.
let tx = Rc::new(Cell::new(Some(tx)));
// This is to make it safe to access `src` inside of the connected closure to

View file

@ -1,4 +1,5 @@
use crate::{config, models::keyring, utils::spawn_tokio, widgets::ErrorRevealer};
use std::cell::{Cell, RefCell};
use gettextrs::gettext;
use gtk::{
gio,
@ -9,7 +10,8 @@ use gtk::{
};
use gtk_macros::{action, get_action};
use once_cell::sync::{Lazy, OnceCell};
use std::cell::{Cell, RefCell};
use crate::{config, models::keyring, utils::spawn_tokio, widgets::ErrorRevealer};
mod imp {
use super::*;

View file

@ -1,5 +1,11 @@
use super::camera_page::CameraPage;
use super::password_page::PasswordPage;
use adw::prelude::*;
use gettextrs::gettext;
use glib::clone;
use gtk::{gio, glib, subclass::prelude::*, CompositeTemplate};
use gtk_macros::{action, get_action, spawn};
use once_cell::sync::OnceCell;
use super::{camera_page::CameraPage, password_page::PasswordPage};
use crate::{
backup::{
Aegis, AndOTP, Backupable, Bitwarden, FreeOTP, Google, LegacyAuthenticator, Operation,
@ -8,23 +14,21 @@ use crate::{
config,
models::ProvidersModel,
};
use adw::prelude::*;
use gettextrs::gettext;
use glib::clone;
use gtk::{gio, glib, subclass::prelude::*, CompositeTemplate};
use gtk_macros::{action, get_action, spawn};
use once_cell::sync::OnceCell;
mod imp {
use super::*;
use std::{
cell::{Cell, RefCell},
collections::HashMap,
};
use adw::subclass::{preferences_window::PreferencesWindowImpl, window::AdwWindowImpl};
use glib::{
subclass::{self, Signal},
ParamSpec, ParamSpecBoolean, Value,
};
use once_cell::sync::Lazy;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use super::*;
#[derive(Debug, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/preferences.ui")]
@ -197,8 +201,9 @@ impl PreferencesWindow {
}),
);
// FreeOTP is first in all of these lists, since its the way to backup Authenticator for use
// with Authenticator. Others are sorted alphabetically.
// FreeOTP is first in all of these lists, since its the way to backup
// Authenticator for use with Authenticator. Others are sorted
// alphabetically.
self.register_backup::<FreeOTP>(&["text/plain"]);
self.register_backup::<Aegis>(&["application/json"]);

View file

@ -1,13 +1,13 @@
use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{gdk, glib};
use gtk::{gdk, glib, prelude::*, subclass::prelude::*};
pub(crate) mod imp {
use super::*;
use std::cell::Cell;
use glib::{ParamSpec, ParamSpecFloat, Value};
use gtk::{graphene, gsk};
use once_cell::sync::Lazy;
use std::cell::Cell;
use super::*;
#[derive(Debug, Default)]
pub struct ProgressIcon {

View file

@ -1,11 +1,12 @@
use super::ProviderPage;
use crate::models::{Provider, ProviderSorter, ProvidersModel};
use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use glib::clone;
use gtk::{glib, pango, subclass::prelude::*, CompositeTemplate};
use row::ProviderActionRow;
use super::ProviderPage;
use crate::models::{Provider, ProviderSorter, ProvidersModel};
enum View {
List,
Form,
@ -13,12 +14,12 @@ enum View {
}
mod imp {
use crate::config;
use super::*;
use adw::subclass::window::AdwWindowImpl;
use glib::subclass::{self, Signal};
use super::*;
use crate::config;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/providers_dialog.ui")]
pub struct ProvidersDialog {
@ -222,7 +223,8 @@ impl ProvidersDialog {
fn add_provider(&self) {
self.set_view(View::Form);
// By not setting the current provider we implicitly say it's for creating a new one
// By not setting the current provider we implicitly say it's for creating a new
// one
self.imp().page.set_provider(None);
}
@ -256,10 +258,12 @@ impl ProvidersDialog {
mod row {
use super::*;
mod imp {
use super::*;
use glib::{ParamSpec, ParamSpecObject, Value};
use std::cell::RefCell;
use glib::{ParamSpec, ParamSpecObject, Value};
use super::*;
#[derive(Debug, Default)]
pub struct ProviderActionRow {
pub provider: RefCell<Option<Provider>>,

View file

@ -1,20 +1,22 @@
use crate::models::RUNTIME;
use crate::models::{Provider, FAVICONS_PATH};
use glib::{clone, Receiver, Sender};
use gtk::{gio, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use gtk_macros::send;
use tracing::error;
use crate::models::{Provider, FAVICONS_PATH, RUNTIME};
pub enum ImageAction {
Ready(String),
Failed,
}
mod imp {
use super::*;
use glib::{subclass, ParamSpec, ParamSpecObject, ParamSpecUInt, Value};
use std::cell::{Cell, RefCell};
use glib::{subclass, ParamSpec, ParamSpecObject, ParamSpecUInt, Value};
use super::*;
#[derive(Debug, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/provider_image.ui")]
pub struct ProviderImage {
@ -265,7 +267,7 @@ impl ProviderImage {
fn do_action(&self, action: ImageAction) -> glib::Continue {
let imp = self.imp();
let image_path = match action {
//TODO: handle network failure and other errors differently
// TODO: handle network failure and other errors differently
ImageAction::Failed => {
imp.image.set_from_icon_name(Some("provider-fallback"));
"invalid".to_string()

View file

@ -1,9 +1,10 @@
use glib::clone;
use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use crate::{
models::{Account, Provider, ProviderSorter, ProvidersModel},
widgets::providers::ProviderRow,
};
use glib::clone;
use gtk::{glib, prelude::*, subclass::prelude::*, CompositeTemplate};
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub enum ProvidersListView {
@ -12,9 +13,10 @@ pub enum ProvidersListView {
}
mod imp {
use super::*;
use glib::subclass::{self, Signal};
use super::*;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/providers_list.ui")]
pub struct ProvidersList {

View file

@ -1,17 +1,20 @@
use crate::{
models::{i18n, otp, Algorithm, OTPMethod, Provider, ProviderPatch, FAVICONS_PATH},
widgets::{ErrorRevealer, ProviderImage},
};
use adw::prelude::*;
use gettextrs::gettext;
use glib::{clone, translate::IntoGlib};
use gtk::{gdk_pixbuf, gio, glib, subclass::prelude::*, CompositeTemplate};
use crate::{
models::{i18n, otp, Algorithm, OTPMethod, Provider, ProviderPatch, FAVICONS_PATH},
widgets::{ErrorRevealer, ProviderImage},
};
mod imp {
use std::cell::RefCell;
use glib::subclass::{self, Signal};
use super::*;
use crate::models::OTPMethod;
use glib::subclass::{self, Signal};
use std::cell::RefCell;
#[derive(Debug, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/provider_page.ui")]
@ -230,8 +233,9 @@ impl ProviderPage {
}
}
// Validate the information typed by the user in order to enable/disable the save action
// Note that we don't validate the urls other than: does `url` crate can parse it or not
// Validate the information typed by the user in order to enable/disable the
// save action Note that we don't validate the urls other than: does `url`
// crate can parse it or not
fn validate(&self) {
let imp = self.imp();

View file

@ -1,19 +1,23 @@
use std::time::{SystemTime, UNIX_EPOCH};
use adw::prelude::*;
use gtk::{glib, glib::clone, subclass::prelude::*, CompositeTemplate};
use crate::{
models::{Account, AccountSorter, OTPMethod, Provider},
widgets::{accounts::AccountRow, ProgressIcon, ProviderImage},
};
use adw::prelude::*;
use gtk::{glib, glib::clone, subclass::prelude::*, CompositeTemplate};
use std::time::{SystemTime, UNIX_EPOCH};
mod imp {
use super::*;
use std::cell::RefCell;
use glib::{
subclass::{self, Signal},
ParamSpec, ParamSpecObject, Value,
};
use once_cell::sync::Lazy;
use std::cell::RefCell;
use super::*;
#[derive(Debug, Default, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/provider_row.ui")]

View file

@ -3,10 +3,12 @@ use glib::{clone, ToValue};
use gtk::{glib, subclass::prelude::*};
mod imp {
use super::*;
use std::cell::RefCell;
use adw::subclass::prelude::*;
use glib::{ParamSpec, ParamSpecString, Value};
use std::cell::RefCell;
use super::*;
#[derive(Debug, Default)]
pub struct UrlRow {

View file

@ -1,3 +1,9 @@
use gettextrs::gettext;
use glib::{clone, signal::Inhibit};
use gtk::{gio, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use gtk_macros::{action, get_action};
use once_cell::sync::OnceCell;
use crate::{
application::Application,
config,
@ -9,11 +15,6 @@ use crate::{
AccountAddDialog, ErrorRevealer,
},
};
use gettextrs::gettext;
use glib::{clone, signal::Inhibit};
use gtk::{gio, glib, prelude::*, subclass::prelude::*, CompositeTemplate};
use gtk_macros::{action, get_action};
use once_cell::sync::OnceCell;
#[derive(PartialEq, Eq, Debug)]
pub enum View {
@ -23,10 +24,11 @@ pub enum View {
}
mod imp {
use super::*;
use adw::subclass::prelude::*;
use glib::subclass;
use super::*;
#[derive(Debug, CompositeTemplate)]
#[template(resource = "/com/belmoussaoui/Authenticator/window.ui")]
pub struct Window {