1
//! Low-level, plumbing subcommands.
2

            
3
use std::str::FromStr;
4

            
5
use anyhow::Result;
6
use clap::{ArgMatches, Args, FromArgMatches, Parser, Subcommand};
7

            
8
use arti_client::{InertTorClient, TorClient, TorClientConfig};
9
use tor_keymgr::KeystoreId;
10
use tor_rtcompat::Runtime;
11

            
12
/// The `keys-raw` subcommands the arti CLI will be augmented with.
13
#[derive(Debug, Parser)]
14
pub(crate) enum RawSubcommands {
15
    /// Run plumbing key management commands.
16
    #[command(subcommand)]
17
    KeysRaw(RawSubcommand),
18
}
19

            
20
/// The `keys-raw` subcommand.
21
#[derive(Subcommand, Debug, Clone)]
22
pub(crate) enum RawSubcommand {
23
    /// Remove keystore entry by raw ID.
24
    RemoveById(RemoveByIdArgs),
25
}
26

            
27
/// The arguments of the [`RemoveById`](RawSubcommand::RemoveById) subcommand.
28
#[derive(Debug, Clone, Args)]
29
pub(crate) struct RemoveByIdArgs {
30
    /// The raw ID of the keystore entry to remove.
31
    ///
32
    /// The raw ID of an entry can be obtained from the field "Location" of the
33
    /// output of `arti keys list`.
34
    raw_entry_id: String,
35

            
36
    /// Identifier of the keystore to remove the entry from.
37
    /// If omitted, the primary store will be used ("arti").
38
    #[arg(short, long, default_value_t = String::from("arti"))]
39
    keystore_id: String,
40
}
41

            
42
/// Run the `keys-raw` subcommand.
43
pub(crate) fn run<R: Runtime>(
44
    runtime: R,
45
    keys_matches: &ArgMatches,
46
    config: &TorClientConfig,
47
) -> Result<()> {
48
    let subcommand =
49
        RawSubcommand::from_arg_matches(keys_matches).expect("Could not parse keys subcommand");
50
    let client = TorClient::with_runtime(runtime)
51
        .config(config.clone())
52
        .create_inert()?;
53

            
54
    match subcommand {
55
        RawSubcommand::RemoveById(args) => run_raw_remove(&args, &client),
56
    }
57
}
58

            
59
/// Run `key raw-remove-by-id` subcommand.
60
fn run_raw_remove(args: &RemoveByIdArgs, client: &InertTorClient) -> Result<()> {
61
    let keymgr = client.keymgr()?;
62
    let keystore_id = KeystoreId::from_str(&args.keystore_id)?;
63
    keymgr.remove_unchecked(&args.raw_entry_id, &keystore_id)?;
64

            
65
    Ok(())
66
}