statusline 0.23.1

Simple and fast bash PS1 line with useful features
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD as base64engine};
use orion::aead::{self, SecretKey};
use std::path::PathBuf;

#[derive(Debug, thiserror::Error)]
pub enum KeyLoadError {
    #[error("io error: {0}")]
    Io(#[from] std::io::Error),
    #[error("base64 decode error: {0}")]
    Base64Decode(#[from] base64::DecodeError),
    #[error("cryptographic error: {0}")]
    Crypto(#[from] orion::errors::UnknownCryptoError),
}

fn key_path() -> PathBuf {
    std::env::home_dir()
        .unwrap_or_default()
        .join(".ssh/workgroup")
}

pub fn key_load() -> Result<SecretKey, KeyLoadError> {
    let encoded_key = std::fs::read_to_string(key_path())?;
    let key = base64engine.decode(encoded_key)?;
    Ok(SecretKey::from_slice(&key)?)
}

pub fn key_create() -> std::io::Result<()> {
    let key = SecretKey::default();
    let encoded_key = base64engine.encode(key.unprotected_as_bytes());
    std::fs::write(key_path(), encoded_key)
}

pub fn chain_open(key: Option<&SecretKey>) -> Vec<String> {
    if let Some(key) = key
        && let Ok(chain) = std::env::var("WORKGROUP_CHAIN")
        && let Ok(chain) = base64engine.decode(chain)
        && let Ok(chain) = aead::open(key, &chain)
        && let Ok(chain) = String::from_utf8(chain)
        && !chain.is_empty()
    {
        return chain.split(' ').map(ToOwned::to_owned).collect();
    }

    if let Ok(conn) = std::env::var("SSH_CONNECTION")
        && let Some(host) = conn.split_whitespace().next()
    {
        return vec![host.to_owned()];
    }

    vec![]
}

#[must_use]
pub fn chain_seal(chain: &[String], key: &SecretKey) -> String {
    base64engine.encode(aead::seal(key, chain.join(" ").as_bytes()).unwrap())
}