mtotp_lib/
lib.rs

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