1pub use error::*;
2pub use database::join_paths;
3use std::collections::HashMap;
4
5mod database;
6pub mod error;
7pub mod otp;
8
9pub type Register = database::registered::Model;
10
11pub async fn init(folder: String) {
12 database::init(folder).await;
13}
14
15pub async fn print_codes() -> Vec<PrintCode> {
16 let mut codes: Vec<PrintCode> = Vec::new();
17 let registered_codes = database::registered::find_all().await;
18 for x in registered_codes {
19 let label = x.label;
20 let uuid = x.uuid;
21 match otp::totp(x.secret.as_str(), 30, 6) {
22 Ok(code) => {
23 codes.push(PrintCode { uuid, label, code });
24 }
25 Err(err) => {
26 codes.push(PrintCode {
27 uuid,
28 label,
29 code: match err {
30 Error::Hmac(_) => "HMac key error".to_owned(),
31 Error::Message(msg) => msg.content,
32 Error::Other(_) => "Exception".to_owned(),
33 },
34 });
35 }
36 };
37 }
38 codes
39}
40
41pub async fn registered_codes() -> Vec<Register> {
42 database::registered::find_all().await
43}
44
45pub async fn save_url(url: String) -> Result<PrintCode> {
46 let url = match url::Url::parse(url.as_str()) {
47 Ok(url) => url,
48 Err(err) => {
49 return Err(Error::message(format!("Invalid url : {}", err)));
50 }
51 };
52 let path_split = url.path().split("/");
53 let label = path_split.last().expect("").to_owned();
54 let mut query_map: HashMap<String, String> = HashMap::new();
55 for (key, value) in url.query_pairs() {
56 query_map.insert(key.to_string(), value.to_string());
57 }
58 let secret = query_map
59 .get::<String>(&("secret".to_string()))
60 .expect("secret not found")
61 .to_string();
62 let issuer = match query_map.get::<String>(&("issuer".to_string())) {
63 None => "".to_string(),
64 Some(so) => so.to_string(),
65 };
66 Ok(save_register(label, secret, issuer).await?)
67}
68
69pub async fn save_register(label: String, secret: String, issuer: String) -> Result<PrintCode> {
70 let code = match otp::totp(secret.as_str(), 30, 6) {
71 Ok(code) => code,
72 Err(err) => {
73 return Err(err);
74 }
75 };
76 let registered = database::registered::Model {
77 uuid: uuid::Uuid::new_v4().to_string(),
78 label: label.clone(),
79 secret,
80 issuer,
81 };
82 database::registered::insert(registered.clone()).await;
83 Ok(PrintCode {
84 uuid: registered.uuid,
85 label: registered.label,
86 code,
87 })
88}
89
90pub fn register_to_url(label: &str, secret: &str, issuer: &str) -> Result<String> {
91 let url = format!("otpauth://totp/{}?secret={}&issuer={}", label, secret, issuer);
92 Ok(url)
93}
94
95pub async fn remove(uuid: &str) {
96 database::registered::delete_by_uuid(uuid).await;
97}
98
99pub async fn rename(uuid: &str, label: &str) {
100 database::registered::update_label_by_uuid(uuid, label).await;
101}
102
103pub struct PrintCode {
104 pub uuid: String,
105 pub label: String,
106 pub code: String,
107}