Port sq key approvals update to the user ID designator framework.
- See #434.
This commit is contained in:
parent
c7795149c2
commit
9712dc5cc6
@ -239,23 +239,10 @@ pub struct UpdateCommand {
|
||||
OneValueAndFileRequiresOutput,
|
||||
ApprovalsListDoc>,
|
||||
|
||||
#[clap(
|
||||
long = "name",
|
||||
help = "Change approvals on this name user ID",
|
||||
)]
|
||||
pub names: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
long = "email",
|
||||
help = "Change approvals on this email address user ID",
|
||||
)]
|
||||
pub emails: Vec<String>,
|
||||
|
||||
#[clap(
|
||||
long = "userid",
|
||||
help = "Change approvals on this user ID",
|
||||
)]
|
||||
pub userids: Vec<String>,
|
||||
#[command(flatten)]
|
||||
pub userids: UserIDDesignators<
|
||||
userid_designator::ExistingUserIDEmailNameArgs,
|
||||
userid_designator::OptionalValue>,
|
||||
|
||||
#[clap(
|
||||
long = "remove-all",
|
||||
|
@ -13,7 +13,6 @@ use sequoia_wot as wot;
|
||||
use crate::Sq;
|
||||
use crate::cli;
|
||||
use crate::cli::key::approvals;
|
||||
use crate::common::userid::make_userid_filter;
|
||||
|
||||
pub fn dispatch(sq: Sq, command: approvals::Command)
|
||||
-> Result<()>
|
||||
@ -108,11 +107,9 @@ fn update(
|
||||
) -> Result<()> {
|
||||
let store = sq.cert_store_or_else()?;
|
||||
|
||||
let handle =
|
||||
sq.resolve_cert(&command.cert, sequoia_wot::FULLY_TRUSTED)?.1;
|
||||
|
||||
let key = sq.lookup_one(handle, None, true)?;
|
||||
let key = sq.resolve_cert(&command.cert, sequoia_wot::FULLY_TRUSTED)?.0;
|
||||
let vcert = key.with_policy(sq.policy, sq.time)?;
|
||||
let userids = command.userids.resolve(&vcert)?;
|
||||
|
||||
// Lookup any explicitly goodlisted certifiers. We need these to
|
||||
// verify the certifications.
|
||||
@ -133,10 +130,16 @@ fn update(
|
||||
// Now, create new approval signatures.
|
||||
let mut approval_signatures = Vec::new();
|
||||
|
||||
// For the selected user IDs.
|
||||
let uid_filter = make_userid_filter(
|
||||
&command.names, &command.emails, &command.userids)?;
|
||||
for uid in vcert.userids().filter(uid_filter) {
|
||||
// resolve returns ResolvedUserIDs, which contain UserIDs, but we
|
||||
// need ValidUserIDAmalgamations.
|
||||
let all = userids.is_empty();
|
||||
let mut designated_userids = BTreeSet::from_iter(
|
||||
userids.into_iter().map(|u| u.userid().clone()));
|
||||
for uid in vcert.userids() {
|
||||
if ! all && ! designated_userids.remove(uid.userid()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
wprintln!(initial_indent = " - ", "{}",
|
||||
String::from_utf8_lossy(uid.value()));
|
||||
|
||||
@ -262,6 +265,7 @@ fn update(
|
||||
next_approved.into_iter(),
|
||||
)?);
|
||||
}
|
||||
assert!(designated_userids.is_empty());
|
||||
|
||||
// Finally, add the new signatures.
|
||||
let key = key.insert_packets(approval_signatures)?;
|
||||
|
@ -1,6 +1,5 @@
|
||||
use sequoia_openpgp as openpgp;
|
||||
use openpgp::packet::UserID;
|
||||
use openpgp::cert::amalgamation::ValidUserIDAmalgamation;
|
||||
|
||||
/// A canonical user ID.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
@ -298,41 +297,6 @@ pub fn lint_emails(emails: &[String]) -> Result<(), anyhow::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a list of names, email addresses, and user IDs, returns a
|
||||
/// user ID filter.
|
||||
///
|
||||
/// The names and email addresses are linted first, returning an error
|
||||
/// with hints if there are any issues found.
|
||||
///
|
||||
/// If neither names, email addresses, or user IDs are given, the
|
||||
/// filter accepts all user IDs.
|
||||
///
|
||||
/// Should be used for subcommands that operate on (subsets of) user
|
||||
/// IDs.
|
||||
pub fn make_userid_filter<'c>(
|
||||
names: &'c [String],
|
||||
emails: &'c [String],
|
||||
userids: &'c [String]
|
||||
)
|
||||
-> anyhow::Result<Box<dyn Fn(&ValidUserIDAmalgamation) -> bool + 'c>>
|
||||
{
|
||||
lint_names(names)?;
|
||||
lint_emails(emails)?;
|
||||
|
||||
Ok(Box::new(|uid: &ValidUserIDAmalgamation| {
|
||||
if emails.is_empty() && names.is_empty() && userids.is_empty() {
|
||||
// No filter, list all user IDs.
|
||||
true
|
||||
} else {
|
||||
std::str::from_utf8(uid.value())
|
||||
.map(|u| names.iter().any(|v| u == v)
|
||||
|| emails.iter().any(|v| u == v)
|
||||
|| userids.iter().any(|v| u == v))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
Loading…
Reference in New Issue
Block a user