diff --git a/src/cli/key/userid.rs b/src/cli/key/userid.rs index 06d036b3..5771a4ed 100644 --- a/src/cli/key/userid.rs +++ b/src/cli/key/userid.rs @@ -198,6 +198,7 @@ instead of the current time.", )] #[clap(group(ArgGroup::new("cert_input").args(&["cert_file", "cert"]).required(true)))] #[clap(group(ArgGroup::new("revoker_input").args(&["revoker_file", "revoker"])))] +#[clap(group(ArgGroup::new("cert-userid").args(&["name", "email", "userid"]).required(true)))] pub struct RevokeCommand { #[clap( long, @@ -249,18 +250,39 @@ for the file to contain more than one certificate.", )] pub revoker_file: Option, + #[clap( + long = "name", + value_name = "NAME", + help = "Revoke the given name user ID", + long_help = "\ +Revoke the given name user ID. Must match a user ID exactly. To revoke +a user ID that contains more than just a name, use `--userid`.", + )] + pub name: Option, + + #[clap( + long = "email", + value_name = "ADDRESS", + help = "Revoke the given email address user ID", + long_help = "\ +Revoke the given email address user ID. Must match a user ID exactly. +To revoke a user ID that contains more than just an email address name, +use `--userid`.", + )] + pub email: Option, + #[clap( long, value_name = "USERID", - help = "The user ID to revoke", + help = "Revoke the given user ID", long_help = "\ -The user ID to revoke. +Revoke the given user ID. By default, this must exactly match a self-signed User ID. Use \ `--force` to generate a revocation certificate for a User ID that is \ not self signed." )] - pub userid: String, + pub userid: Option, #[clap( value_enum, diff --git a/src/commands/key/userid.rs b/src/commands/key/userid.rs index 8492c86a..73249578 100644 --- a/src/commands/key/userid.rs +++ b/src/commands/key/userid.rs @@ -35,7 +35,13 @@ use crate::cli::types::FileOrStdout; use crate::common::NULL_POLICY; use crate::common::RevocationOutput; use crate::common::get_secret_signer; -use crate::common::userid::{lint_userids, lint_names, lint_emails}; +use crate::common::userid::{ + lint_email, + lint_emails, + lint_name, + lint_names, + lint_userids, +}; use crate::parse_notations; /// Handle the revocation of a User ID @@ -51,7 +57,7 @@ impl UserIDRevocation { /// Create a new UserIDRevocation pub fn new( sq: &Sq, - userid: String, + uid: UserID, force: bool, cert: Cert, revoker: Option, @@ -62,7 +68,7 @@ impl UserIDRevocation { let (revoker, mut signer) = get_secret_signer(sq, &cert, revoker.as_ref())?; - let uid = UserID::from(userid.as_str()); + let userid = String::from_utf8_lossy(uid.value()).to_string(); let revocation_packet = { // Create a revocation for a User ID. @@ -516,6 +522,16 @@ pub fn userid_revoke( panic!("clap enforces --cert or --cert-file"); }; + let userid = if let Some(n) = command.name { + lint_name(&n)?; + UserID::from(n) + } else if let Some(e) = command.email { + lint_email(&e)?; + UserID::from_address(None, None, e)? + } else { + UserID::from(command.userid.expect("one of the three must be given")) + }; + let revoker = if let Some(file) = command.revoker_file { let br = file.open()?; Some(Cert::from_buffered_reader(br)?) @@ -529,7 +545,7 @@ pub fn userid_revoke( let revocation = UserIDRevocation::new( &sq, - command.userid, + userid, sq.force, cert, revoker,