use std::{fs::create_dir_all, path::PathBuf};
use clap::Parser;
use log::{debug, info};
use crate::{
sop::{Certificate, SopError},
store::{EncryptedStore, EncryptedStoreError, Store},
Config, LeafCommand,
};
#[derive(Debug, Parser)]
pub struct InitCommand {
#[clap(long)]
name: String,
#[clap(long)]
key: Option<PathBuf>,
#[clap(long)]
cert: Option<PathBuf>,
}
impl LeafCommand for InitCommand {
type Error = InitError;
fn run(&self, config: &Config) -> Result<(), InitError> {
info!("init password store");
debug!("{config:#?}");
let store_dir = config.store();
if !store_dir.exists() {
println!("creating {}", store_dir.display());
create_dir_all(store_dir).map_err(|err| InitError::CreateDir(store_dir.into(), err))?;
}
let mut store = Store::default();
let encrypted = EncryptedStore::new(config.sop(), config.store());
if let Some(key) = &self.key {
encrypted.install_key(key)?;
let cert = encrypted.extract_cert()?;
store.push_cert(&self.name, &cert);
} else if let Some(cert) = &self.cert {
encrypted.install_cert(cert)?;
let cert = Certificate::load(cert)?;
store.push_cert(&self.name, &cert);
} else {
return Err(InitError::NoKey);
}
encrypted.write_store(&store)?;
Ok(())
}
}
#[derive(Debug, thiserror::Error)]
pub enum InitError {
#[error("failed to create store directory {0}")]
CreateDir(PathBuf, #[source] std::io::Error),
#[error("neither --key or --cert has been specified")]
NoKey,
#[error(transparent)]
Encrypted(#[from] EncryptedStoreError),
#[error(transparent)]
Sop(#[from] SopError),
}