use crate::error::{self, Result};
use crate::key_source::KeySource;
use crate::schema::decoded::{Decoded, Hex};
use crate::schema::{Delegations, KeyHolder, RoleId, RoleKeys, Root, Signed, Targets};
use crate::sign::Sign;
use snafu::{ensure, OptionExt, ResultExt};
use std::collections::HashMap;
pub(crate) type KeyList = HashMap<Decoded<Hex>, Box<dyn Sign>>;
impl KeyHolder {
pub(crate) fn get_keys(&self, keys: &[Box<dyn KeySource>]) -> Result<KeyList> {
match self {
Self::Delegations(delegations) => get_targets_keys(delegations, keys),
Self::Root(root) => get_root_keys(root, keys),
}
}
pub(crate) fn role_keys(&self, name: RoleId) -> Result<RoleKeys> {
match self {
Self::Delegations(delegations) => {
if let RoleId::DelegatedRole(name) = name.clone() {
for role in &delegations.roles {
if role.name == name.clone() {
return Ok(role.keys());
}
}
}
}
Self::Root(root) => {
if let RoleId::StandardRole(roletype) = name {
return Ok(root
.roles
.get(&roletype)
.context(error::NoRoleKeysinRootSnafu {
role: roletype.to_string(),
})?
.clone());
}
}
}
let role = match name {
RoleId::StandardRole(role) => role.to_string(),
RoleId::DelegatedRole(role_name) => role_name,
};
Err(error::Error::SigningKeysNotFound { role })
}
pub(crate) fn verify_role(&self, targets: &Signed<Targets>, name: &str) -> Result<()> {
match self {
Self::Delegations(delegations) => {
delegations
.verify_role(targets, name)
.context(error::VerifyRoleMetadataSnafu {
role: name.to_string(),
})
}
Self::Root(root) => root
.verify_role(targets)
.context(error::VerifyRoleMetadataSnafu {
role: name.to_string(),
}),
}
}
}
pub(crate) fn get_root_keys(root: &Root, keys: &[Box<dyn KeySource>]) -> Result<KeyList> {
let mut root_keys = KeyList::new();
for source in keys {
let key_pair = source.as_sign().context(error::KeyPairFromKeySourceSnafu)?;
if let Some(key_id) = root.key_id(key_pair.as_ref()) {
root_keys.insert(key_id, key_pair);
}
}
ensure!(!root_keys.is_empty(), error::KeysNotFoundInRootSnafu);
Ok(root_keys)
}
pub(crate) fn get_targets_keys(
delegations: &Delegations,
keys: &[Box<dyn KeySource>],
) -> Result<KeyList> {
let mut delegations_keys = KeyList::new();
for source in keys {
let key_pair = source.as_sign().context(error::KeyPairFromKeySourceSnafu)?;
if let Some(key_id) = delegations.key_id(key_pair.as_ref()) {
delegations_keys.insert(key_id, key_pair);
}
}
Ok(delegations_keys)
}