smart-password-manager-cli 0.1.0

Command line interface for smart password management built on smartpasslib. Generate deterministic passwords from secret phrases without storing them.
use anyhow::{Result, bail};
use serde::Serialize;
use smartpasslib::SmartPasswordManager;

use crate::clipboard;
use crate::output;
use crate::qr;
use crate::secret;

use super::find_entry;

#[derive(Serialize)]
struct GetJson<'a> {
    description: &'a str,
    public_key: &'a str,
    length: usize,
    password: &'a str,
}

pub fn run(
    key: Option<String>,
    description: Option<String>,
    secret_arg: Option<String>,
    secret_stdin: bool,
    copy: bool,
    qr_flag: bool,
    json: bool,
) -> Result<()> {
    let manager = SmartPasswordManager::new()?;
    let entry = find_entry(&manager, key, description)?;

    let secret_phrase = secret::resolve_secret(secret_arg, secret_stdin, "Secret phrase: ")?;

    let valid = smartpasslib::verify_secret(&secret_phrase, &entry.public_key)?;
    if !valid {
        bail!("Wrong secret phrase");
    }

    let password = smartpasslib::generate_smart_password_sync(&secret_phrase, entry.length)?;

    if qr_flag {
        qr::render(&password);
        return Ok(());
    }

    if copy {
        if clipboard::copy(&password) {
            output::success(&format!(
                "Password for '{}' copied to clipboard",
                entry.description
            ));
        } else {
            bail!("No clipboard available");
        }
        return Ok(());
    }

    if json {
        let obj = GetJson {
            description: &entry.description,
            public_key: &entry.public_key,
            length: entry.length,
            password: &password,
        };
        let s = serde_json::to_string_pretty(&obj)?;
        println!("{s}");
    } else {
        output::print_password(&password);
    }

    Ok(())
}