1
use std::path::Path;
2

            
3
use clap::{
4
  Args,
5
  Subcommand,
6
};
7

            
8
pub use export_secrets::ExportSecrets;
9
pub use init_vault::InitVault;
10
pub use purge_secrets::PurgeSecrets;
11
pub use show_secrets::ShowSecrets;
12
pub use store_secret::StoreSecret;
13

            
14
use super::context::Context;
15

            
16
mod export_secrets;
17
mod init_vault;
18
mod purge_secrets;
19
mod show_secrets;
20
mod store_secret;
21

            
22
#[derive(Debug, Args)]
23
pub struct Vault {
24
  #[command(subcommand)]
25
  command: Option<VaultCommand>,
26

            
27
  #[arg(short, long, help = "The path to the secret vault")]
28
  vault_location: Option<String>,
29
}
30

            
31
#[derive(Debug, Subcommand)]
32
enum VaultCommand {
33
  #[command(visible_aliases = ["init"], about = "Initialize a new secret vault")]
34
  InitVault(InitVault),
35

            
36
  #[command(visible_aliases = ["store", "set"], arg_required_else_help = true, about = "Store a secret")]
37
  StoreSecret(StoreSecret),
38

            
39
  #[command(visible_aliases = ["show", "get", "s"], arg_required_else_help = true, about = "Retrieve a secret")]
40
  ShowSecrets(ShowSecrets),
41

            
42
  #[command(visible_aliases = ["purge", "rm"], arg_required_else_help = true, about = "Purge and delete a secret")]
43
  PurgeSecrets(PurgeSecrets),
44

            
45
  #[command(
46
    visible_aliases = ["export", "e"],
47
    arg_required_else_help = true,
48
    about = "Export secrets to a file"
49
  )]
50
  ExportSecrets(ExportSecrets),
51
}
52

            
53
impl Vault {
54
  pub fn execute(&self, context: &mut Context) -> anyhow::Result<()> {
55
    if let Some(vault_location) = &self.vault_location {
56
      context.set_vault_location(vault_location);
57
    }
58

            
59
    match &self.command {
60
      Some(command) => command.run(context),
61
      None => Err(anyhow::anyhow!("No subcommand provided")),
62
    }
63
  }
64
}
65

            
66
impl VaultCommand {
67
  pub fn run(&self, context: &Context) -> anyhow::Result<()> {
68
    match self {
69
      VaultCommand::InitVault(init_vault) => init_vault.execute(context),
70
      VaultCommand::StoreSecret(store_secret) => store_secret.execute(context),
71
      VaultCommand::ShowSecrets(show_secrets) => show_secrets.execute(context),
72
      VaultCommand::PurgeSecrets(purge_secrets) => purge_secrets.execute(context),
73
      VaultCommand::ExportSecrets(export_secrets) => export_secrets.execute(context),
74
    }
75
  }
76
}
77

            
78
fn verify_vault(vault_location: &str) -> anyhow::Result<()> {
79
  let path = Path::new(vault_location);
80
  if !path.exists() || !path.is_dir() {
81
    anyhow::bail!("The store does not exist");
82
  }
83

            
84
  Ok(())
85
}
86

            
87
fn verify_key(keys_location: &str, key_name: &str) -> anyhow::Result<()> {
88
  let keys_path = Path::new(keys_location);
89
  if !keys_path.exists() || !keys_path.is_dir() {
90
    anyhow::bail!("The keys location does not exist");
91
  }
92

            
93
  let key_name = format!("{key_name}.key",);
94
  let key_path = keys_path.join(key_name);
95
  if !key_path.exists() || !key_path.is_file() {
96
    anyhow::bail!("The key does not exist");
97
  }
98

            
99
  Ok(())
100
}