mtotp_lib/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
pub use error::*;
use std::collections::HashMap;

mod database;
pub mod error;
pub mod otp;

pub async fn init() {
    database::init().await;
}

pub async fn print_codes() -> Vec<PrintCode> {
    let mut codes: Vec<PrintCode> = Vec::new();
    let registered_codes = database::registered::find_all().await;
    for x in registered_codes {
        let label = x.label;
        let uuid = x.uuid;
        match otp::totp(x.secret.as_str(), 30, 6) {
            Ok(code) => {
                codes.push(PrintCode { uuid, label, code });
            }
            Err(err) => {
                codes.push(PrintCode {
                    uuid,
                    label,
                    code: match err {
                        Error::Hmac(_) => "HMac key error".to_owned(),
                        Error::Message(msg) => msg.content,
                        Error::Other(_) => "Exception".to_owned(),
                    },
                });
            }
        };
    }
    codes
}

pub async fn save_url(url: String) -> Result<PrintCode> {
    let url = match url::Url::parse(url.as_str()) {
        Ok(url) => url,
        Err(err) => {
            return Err(Error::message(format!("Invalid url : {}", err)));
        }
    };
    let path_split = url.path().split("/");
    let label = path_split.last().expect("").to_owned();
    let mut query_map: HashMap<String, String> = HashMap::new();
    for (key, value) in url.query_pairs() {
        query_map.insert(key.to_string(), value.to_string());
    }
    let secret = query_map
        .get::<String>(&("secret".to_string()))
        .expect("secret not found")
        .to_string();
    let issuer = match query_map.get::<String>(&("issuer".to_string())) {
        None => "".to_string(),
        Some(so) => so.to_string(),
    };
    Ok(save_register(label, secret, issuer).await?)
}

pub async fn save_register(label: String, secret: String, issuer: String) -> Result<PrintCode> {
    let code = match otp::totp(secret.as_str(), 30, 6) {
        Ok(code) => code,
        Err(err) => {
            return Err(err);
        }
    };
    let registered = database::registered::Model {
        uuid: uuid::Uuid::new_v4().to_string(),
        label: label.clone(),
        secret,
        issuer,
    };
    database::registered::insert(registered.clone()).await;
    Ok(PrintCode {
        uuid: registered.uuid,
        label: registered.label,
        code,
    })
}

pub async fn remove(uuid: &str) {
    database::registered::delete_by_uuid(uuid).await;
}

pub async fn rename(uuid: &str, label: &str) {
    database::registered::update_label_by_uuid(uuid, label).await;
}

pub struct PrintCode {
    pub uuid: String,
    pub label: String,
    pub code: String,
}