authenticator/backup/
mod.rs1use anyhow::Result;
2
3use crate::{
4 models::{Account, Algorithm, Method, ProvidersModel, keyring},
5 utils::spawn_tokio_blocking,
6};
7
8pub enum Operation {
9 Backup,
10 Restore,
11}
12
13pub trait Restorable: Sized {
14 const ENCRYPTABLE: bool = false;
16
17 const SCANNABLE: bool = false;
19
20 const IDENTIFIER: &'static str;
22
23 type Item: RestorableItem;
24
25 fn title() -> String;
26 fn subtitle() -> String;
27
28 fn restore_from_data(from: &[u8], key: Option<&str>) -> Result<Vec<Self::Item>>;
34}
35
36pub trait RestorableItem {
37 fn account(&self) -> String;
38 fn issuer(&self) -> String;
39 fn secret(&self) -> String;
40 fn period(&self) -> Option<u32>;
41 fn method(&self) -> Method;
42 fn algorithm(&self) -> Algorithm;
43 fn digits(&self) -> Option<u32>;
44 fn counter(&self) -> Option<u32>;
45
46 fn restore(&self, provider: &ProvidersModel) -> Result<()> {
47 let owned_token = self.secret();
48 let token_exists =
49 spawn_tokio_blocking(async move { keyring::token_exists(&owned_token).await })?;
50 if !token_exists {
51 let provider = provider.find_or_create(
52 &self.issuer(),
53 self.period(),
54 self.method(),
55 None,
56 self.algorithm(),
57 self.digits(),
58 self.counter(),
59 None,
60 None,
61 )?;
62
63 let account =
64 Account::create(&self.account(), &self.secret(), self.counter(), &provider)?;
65 provider.add_account(&account);
66 } else {
67 tracing::info!(
68 "Account {}/{} already exists",
69 self.issuer(),
70 self.account()
71 );
72 }
73 Ok(())
74 }
75}
76
77pub trait Backupable: Sized {
78 const ENCRYPTABLE: bool = false;
80 const IDENTIFIER: &'static str;
82
83 fn title() -> String;
84 fn subtitle() -> String;
85 fn backup(provider: &ProvidersModel, key: Option<&str>) -> Result<Vec<u8>>;
87}
88
89mod aegis;
90mod andotp;
91mod bitwarden;
92mod freeotp;
93mod freeotp_json;
94mod google;
95mod legacy;
96mod raivootp;
97mod yandex;
98pub use self::{
99 aegis::Aegis, andotp::AndOTP, bitwarden::Bitwarden, freeotp::FreeOTP,
100 freeotp_json::FreeOTPJSON, google::Google, legacy::LegacyAuthenticator, raivootp::RaivoOTP,
101 yandex::Yandex,
102};