diff --git a/crates/asp/src/utils/jwk.rs b/crates/asp/src/utils/jwk.rs index aba1413..d1d4f50 100644 --- a/crates/asp/src/utils/jwk.rs +++ b/crates/asp/src/utils/jwk.rs @@ -67,7 +67,7 @@ impl JwtExt for Jwk { // 4. Convert that Pkey into the PKCS#8 encoded private key (and then base64 encode it) let key_pair: Box = match self.key_type() { "EC" => match self.curve() { - Some("p-256") => Box::new(EcKeyPair::from_jwk(self)?), + Some("P-256") => Box::new(EcKeyPair::from_jwk(self)?), _ => bail!("Unsupported curve type"), }, "OKP" => match self.curve() { diff --git a/src/commands/keys/delete.rs b/src/commands/keys/delete.rs index ba38ff5..c8d9eba 100644 --- a/src/commands/keys/delete.rs +++ b/src/commands/keys/delete.rs @@ -2,72 +2,72 @@ use anstyle::{AnsiColor, Color as AnstyleColor, Reset, Style as Anstyle}; use anyhow::Context; use asp::keys::AspKeyType; use clap::Parser; -use dialoguer::{Confirm, theme::ColorfulTheme, console::Term}; +use dialoguer::{console::Term, theme::ColorfulTheme, Confirm}; use indoc::writedoc; use sea_orm::ModelTrait; use std::io::Write; use crate::{ - entities::keys::{Entity as KeysEntity, Model as KeysModel}, - commands::{AspmSubcommand, KeysQueryResult, KeysEntityExt} + commands::{AspmSubcommand, KeysEntityExt, KeysQueryResult}, + entities::keys::{Entity as KeysEntity, Model as KeysModel}, }; /// Deletes a saved key, after asking for confirmation. #[derive(Parser, Debug)] -pub struct KeysDeleteCommand { - /// Will disable any confirmation prompts. This is not recommended unless you knowingly give a full fingerprint, as it is easy to accidentally (and permanently) delete wrong keys otherwise. - #[arg(long)] - no_confirm: bool, - /// The key to export. This can either be a fingerprint obtained with the `keys list` command, or an alias to search for. +pub struct KeysDeleteCommand { + /// Will disable any confirmation prompts. This is not recommended unless you knowingly give a full fingerprint, as it is easy to accidentally (and permanently) delete wrong keys otherwise. + #[arg(long)] + no_confirm: bool, + /// The key to export. This can either be a fingerprint obtained with the `keys list` command, or an alias to search for. key: String, } #[async_trait::async_trait] impl AspmSubcommand for KeysDeleteCommand { - async fn execute(&self, state: crate::AspmState) -> Result<(), anyhow::Error> { - // Fetch key from db + async fn execute(&self, state: crate::AspmState) -> Result<(), anyhow::Error> { + // Fetch key from db let entry = KeysEntity::query_key(&state.db, &self.key) - .await - .context("Unable to query keys from database")?; - let key: KeysModel = match entry { - KeysQueryResult::None => { - eprintln!( - "{style}No keys matching the given query were found{reset}", - style = Anstyle::new() - .fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightRed))) - .render(), - reset = Reset.render() - ); - std::process::exit(1); - } - KeysQueryResult::One(key) => key, - KeysQueryResult::Many(mut keys) => { - eprintln!( - "{style}More than one keys matching the given query were found{reset}", - style = Anstyle::new() - .fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightYellow))) - .render(), - reset = Reset::default().render() - ); - keys.remove(0) - } - }; + .await + .context("Unable to query keys from database")?; + let key: KeysModel = match entry { + KeysQueryResult::None => { + eprintln!( + "{style}No keys matching the given query were found{reset}", + style = Anstyle::new() + .fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightRed))) + .render(), + reset = Reset.render() + ); + std::process::exit(1); + } + KeysQueryResult::One(key) => key, + KeysQueryResult::Many(mut keys) => { + eprintln!( + "{style}More than one keys matching the given query were found{reset}", + style = Anstyle::new() + .fg_color(Some(AnstyleColor::Ansi(AnsiColor::BrightYellow))) + .render(), + reset = Reset::default().render() + ); + keys.remove(0) + } + }; - if !self.no_confirm { - // Construct styles - let reset = Reset::default().render(); - let alias_style = Anstyle::new() - .underline() - .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightCyan))) - .render(); - let key_style = Anstyle::new() - .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightGreen))) - .render(); - let value_style = Anstyle::new() - .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightYellow))) - .render(); - let _ = writedoc! { + if !self.no_confirm { + // Construct styles + let reset = Reset::default().render(); + let alias_style = Anstyle::new() + .underline() + .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightCyan))) + .render(); + let key_style = Anstyle::new() + .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightGreen))) + .render(); + let value_style = Anstyle::new() + .fg_color(Some(anstyle::Color::Ansi(AnsiColor::BrightYellow))) + .render(); + let _ = writedoc! { std::io::stderr(), " {alias_style}{alias}:{reset} @@ -79,20 +79,22 @@ impl AspmSubcommand for KeysDeleteCommand { alias = key.alias }; - let confirmation = Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt("Are you sure you want to delete this key?") - .interact_on(&Term::stderr()) - .context("Unable to prompt on stderr")?; + let confirmation = Confirm::with_theme(&ColorfulTheme::default()) + .with_prompt("Are you sure you want to delete this key?") + .interact_on(&Term::stderr()) + .context("Unable to prompt on stderr")?; - if !confirmation { - std::process::exit(1); - } - } + if !confirmation { + std::process::exit(1); + } + } - let fingerprint = key.fingerprint.clone(); - key.delete(&state.db).await.context("Unable to delete key")?; - println!("Successfully deleted key with fingerprint {}", fingerprint); + let fingerprint = key.fingerprint.clone(); + key.delete(&state.db) + .await + .context("Unable to delete key")?; + println!("Successfully deleted key with fingerprint {}", fingerprint); - Ok(()) - } -} \ No newline at end of file + Ok(()) + } +} diff --git a/src/commands/keys/mod.rs b/src/commands/keys/mod.rs index 6390513..2753e6e 100644 --- a/src/commands/keys/mod.rs +++ b/src/commands/keys/mod.rs @@ -1,11 +1,11 @@ use clap::{Parser, Subcommand}; +pub mod delete; pub mod export; pub mod generate; #[cfg(feature = "gpg-compat")] pub mod import_gpg; pub mod list; -pub mod delete; /// A subcommand to allow the management of keys, which can then be used to create, modify, or delete profiles. #[derive(Parser)] diff --git a/src/main.rs b/src/main.rs index 7748aa3..c807614 100644 --- a/src/main.rs +++ b/src/main.rs @@ -87,7 +87,14 @@ fn main() { if let Err(e) = cli(parsed) { match verbose { true => { - eprintln!("An error occurred while running that command:\n{e:?}"); + eprintln!( + "An error occurred while running that command:\n{e:?}\nStack:\n{stack}", + stack = e + .chain() + .map(|entry| format!("\t- {entry}")) + .collect::>() + .join("\n") + ); } false => eprintln!("An error occurred while running that command:\n{e}"), }