aboutsummaryrefslogtreecommitdiffstats
path: root/src/actions.rs
blob: 71dd96a47b44e9896010ebafa44d1ab7da11505b (plain) (blame)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
use crate::prelude::*;

pub async fn login(
    email: &str,
    password: &crate::locked::Password,
) -> Result<(String, String, u32, String, crate::locked::Keys)> {
    let config = crate::config::Config::load_async().await?;
    let client =
        crate::api::Client::new(&config.base_url(), &config.identity_url());

    let iterations = client.prelogin(email).await?;
    let identity =
        crate::identity::Identity::new(email, password, iterations)?;

    let (access_token, refresh_token, protected_key) = client
        .login(&identity.email, &identity.master_password_hash)
        .await?;
    let master_keys = crate::cipherstring::CipherString::new(&protected_key)?
        .decrypt_locked(&identity.keys)?;

    Ok((
        access_token,
        refresh_token,
        iterations,
        protected_key,
        crate::locked::Keys::new(master_keys),
    ))
}

pub async fn unlock(
    email: &str,
    password: &crate::locked::Password,
    iterations: u32,
    protected_key: &str,
) -> Result<crate::locked::Keys> {
    let identity =
        crate::identity::Identity::new(email, password, iterations)?;

    let protected_key =
        crate::cipherstring::CipherString::new(protected_key)?;
    let master_keys = protected_key.decrypt_locked(&identity.keys)?;

    Ok(crate::locked::Keys::new(master_keys))
}

pub async fn sync(
    access_token: &str,
    refresh_token: &str,
) -> Result<(Option<String>, String, Vec<crate::api::Cipher>)> {
    let res = sync_once(access_token).await;
    match res {
        Ok((protected_key, ciphers)) => Ok((None, protected_key, ciphers)),
        Err(crate::error::Error::RequestUnauthorized) => {
            let access_token =
                exchange_refresh_token_async(refresh_token).await?;
            let (protected_key, ciphers) = sync_once(&access_token).await?;
            Ok((Some(access_token), protected_key, ciphers))
        }
        Err(e) => Err(e),
    }
}

async fn sync_once(
    access_token: &str,
) -> Result<(String, Vec<crate::api::Cipher>)> {
    let config = crate::config::Config::load_async().await?;
    let client =
        crate::api::Client::new(&config.base_url(), &config.identity_url());
    client.sync(access_token).await
}

pub fn add(
    access_token: &str,
    refresh_token: &str,
    cipher: &crate::api::Cipher,
) -> Result<Option<String>> {
    match add_once(access_token, cipher) {
        Ok(()) => Ok(None),
        Err(crate::error::Error::RequestUnauthorized) => {
            let access_token = exchange_refresh_token(refresh_token)?;
            add_once(&access_token, cipher)?;
            Ok(Some(access_token))
        }
        Err(e) => Err(e),
    }
}

fn add_once(access_token: &str, cipher: &crate::api::Cipher) -> Result<()> {
    let config = crate::config::Config::load()?;
    let client =
        crate::api::Client::new(&config.base_url(), &config.identity_url());
    client.add(access_token, cipher)?;
    Ok(())
}

fn exchange_refresh_token(refresh_token: &str) -> Result<String> {
    let config = crate::config::Config::load()?;
    let client =
        crate::api::Client::new(&config.base_url(), &config.identity_url());
    client.exchange_refresh_token(refresh_token)
}

async fn exchange_refresh_token_async(refresh_token: &str) -> Result<String> {
    let config = crate::config::Config::load_async().await?;
    let client =
        crate::api::Client::new(&config.base_url(), &config.identity_url());
    client.exchange_refresh_token_async(refresh_token).await
}