upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/login.rs
blob: a6ce76d20dcb447e7da79d3044cb213c4ef9d693 (plain)
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
use anyhow::{bail, Context, Result};
use nostr::prelude::{FromSkStr, ToBech32};
use zeroize::Zeroize;

use crate::{
    cli_interactor::{Interactor, InteractorPrompt, PromptPasswordParms},
    config::{ConfigManagement, ConfigManager},
    key_handling::{
        encryption::{EncryptDecrypt, Encryptor},
        users::{UserManagement, UserManager},
    },
};

/// handles the encrpytion and storage of key material
pub fn launch(nsec: &Option<String>, password: &Option<String>) -> Result<nostr::Keys> {
    // if nsec parameter
    if let Some(nsec_unwrapped) = nsec {
        // get key or fail without prompts
        let key = nostr::Keys::from_sk_str(nsec_unwrapped).context("invalid nsec parameter")?;
        println!(
            "logged in as {}",
            &key.public_key()
                .to_bech32()
                .context("public key should always produce bech32")?
        );

        // if password, add user to enable password login in future
        if password.is_some() {
            UserManager::default()
                .add(nsec, password)
                .context("could not store identity")?;
        }
        return Ok(key);
    }

    // if encrypted nsec stored, attempt password
    let cfg = ConfigManager
        .load()
        .context("failed to load application config")?;
    let key = if let Some(user) = cfg.users.last() {
        let mut pass = if let Some(p) = password.clone() {
            p
        } else {
            println!(
                "login as {}",
                &user
                    .public_key
                    .to_bech32()
                    .context("public key should always produce bech32")?
            );
            Interactor::default()
                .password(PromptPasswordParms::default().with_prompt("password"))
                .context("failed to get password input from interactor.password")?
        };

        let key_result = Encryptor
            .decrypt_key(&user.encrypted_key, pass.as_str())
            .context("failed to decrypt key with provided password");
        pass.zeroize();

        key_result.context(format!(
            "failed to log in as {}",
            &user
                .public_key
                .to_bech32()
                .context("public key should always produce bech32")?
        ))?
    } else {
        // no nsec but password supplied
        if password.is_some() {
            bail!("no nsec available to decrypt with specified password");
        }
        // otherwise add new user with nsec and password prompts
        UserManager::default()
            .add(nsec, password)
            .context("failed to add user")?
    };
    println!(
        "logged in as {}",
        &key.public_key()
            .to_bech32()
            .context("public key should always produce bech32")?
    );
    Ok(key)
}