use crate::cli::logs;
use crate::hooks::executor::HookExecutor;
use crate::models::cli::RecipientCommands;
use crate::models::configuration::Configuration;
use crate::models::password_store::{PasswordStore, Recipient};
use crate::recipients;
use crate::recipients::public_key;
use anyhow::Context;
pub fn dispatch(
command: &RecipientCommands,
configuration: &Configuration,
offline: bool,
) -> anyhow::Result<()> {
match command {
RecipientCommands::Add(args) => add(
configuration,
args.store_selection.store.as_ref(),
&public_key::get(&args.keys)?,
args.name.as_ref(),
offline,
),
RecipientCommands::Remove(args) => remove(
configuration,
args.store_selection.store.as_ref(),
&args.public_key,
args.ignore_unknown,
offline,
),
RecipientCommands::List(args) => {
list(configuration, args.store_selection.store.as_ref(), offline)
}
}
}
fn add(
configuration: &Configuration,
store_name: Option<&String>,
public_keys: &[(String, String)],
name: Option<&String>,
offline: bool,
) -> anyhow::Result<()> {
if let Some(registration) = configuration.select_store(store_name) {
let store_path = registration.path();
let hooks = HookExecutor {
configuration,
registration,
offline,
force: false,
};
let mut store = if store_path.exists() {
hooks.execute_pull_commands()?;
configuration
.decrypt_store(registration)
.context("Cannot decrypt store")?
} else {
PasswordStore::default()
};
for public_key in public_keys {
if let Some(recipient) = store
.recipients
.iter_mut()
.find(|recipient| recipient.public_key == public_key.0)
{
if let Some(name) = name {
name.clone_into(&mut recipient.name);
}
} else {
store.recipients.push(Recipient {
public_key: public_key.0.clone(),
name: name.map_or(&public_key.1, |value| value).clone(),
});
}
}
Configuration::encrypt_store(registration, &store).context("Cannot encrypt store")?;
for public_key in public_keys {
logs::recipient_added(&public_key.0);
}
if configuration.identities.is_empty() && registration.identities.is_empty() {
logs::no_identities_exist_yet(®istration.name);
}
hooks.execute_push_commands()?;
Ok(())
} else {
anyhow::bail!(
"No store found in configuration. Run 'pasejo store add ...' first to add one"
)
}
}
fn remove(
configuration: &Configuration,
store_name: Option<&String>,
public_key: &str,
ignore_unknown: bool,
offline: bool,
) -> anyhow::Result<()> {
if let Some(registration) = configuration.select_store(store_name) {
let hooks = HookExecutor {
configuration,
registration,
offline,
force: false,
};
hooks.execute_pull_commands()?;
let mut store = configuration
.decrypt_store(registration)
.context("Cannot decrypt store")?;
if store.recipients.len() == 1 && store.recipients[0].public_key == public_key {
anyhow::bail!(
"Cannot remove the last recipient from the store. Please add a new recipient before removing this one."
)
}
if !store
.recipients
.iter()
.any(|recipient| recipient.public_key == public_key)
{
if ignore_unknown {
logs::recipient_does_not_exist_ignored(public_key);
return Ok(());
}
anyhow::bail!("Recipient not found in the store");
}
store
.recipients
.retain(|recipient| recipient.public_key != public_key);
Configuration::encrypt_store(registration, &store).context("Cannot encrypt store")?;
logs::recipient_removed(public_key);
hooks.execute_push_commands()?;
Ok(())
} else {
anyhow::bail!(
"No store found in configuration. Run 'pasejo store add ...' first to add one"
)
}
}
fn list(
configuration: &Configuration,
store_name: Option<&String>,
offline: bool,
) -> anyhow::Result<()> {
if let Some(registration) = configuration.select_store(store_name) {
let hooks = HookExecutor {
configuration,
registration,
offline,
force: false,
};
hooks.execute_pull_commands()?;
let store = configuration
.decrypt_store(registration)
.context("Cannot decrypt store")?;
for recipient in &store.recipients {
println!(
"{}",
recipients::format_recipient(&recipient.public_key, &recipient.name)
);
}
Ok(())
} else {
anyhow::bail!(
"No store found in configuration. Run 'pasejo store add ...' first to add one"
)
}
}