use std::collections::HashMap;
use tracing::debug;
use super::resolver::KeyResolver;
use crate::{
Entry, Result,
auth::{
crypto::verify_entry_signature,
settings::AuthSettings,
types::{KeyStatus, Operation, ResolvedAuth, SigKey},
},
};
pub struct AuthValidator {
auth_cache: HashMap<String, ResolvedAuth>,
pub(crate) resolver: KeyResolver,
}
impl AuthValidator {
pub fn new() -> Self {
Self {
auth_cache: HashMap::new(),
resolver: KeyResolver::new(),
}
}
pub fn validate_entry(
&mut self,
entry: &Entry,
auth_settings: &AuthSettings,
instance: Option<&crate::Instance>,
) -> Result<bool> {
if let SigKey::Direct(key_name) = &entry.sig.key
&& key_name.is_empty()
&& entry.sig.sig.is_none()
{
debug!("Unsigned entry detected: {:?}", entry);
return Ok(true);
}
if auth_settings.get_all_keys()?.is_empty() {
debug!(
"No keys configured in auth settings, allowing all access: {:?}",
entry
);
return Ok(true);
}
let resolved_auth = self.resolver.resolve_sig_key_with_pubkey(
&entry.sig.key,
auth_settings,
instance,
entry.sig.pubkey.as_deref(),
)?;
if resolved_auth.key_status != KeyStatus::Active {
return Ok(false);
}
verify_entry_signature(entry, &resolved_auth.public_key).map_err(|e| e.into())
}
pub fn resolve_sig_key(
&mut self,
sig_key: &SigKey,
auth_settings: &AuthSettings,
instance: Option<&crate::Instance>,
) -> Result<ResolvedAuth> {
self.resolver
.resolve_sig_key(sig_key, auth_settings, instance)
}
pub fn resolve_sig_key_with_pubkey(
&mut self,
sig_key: &SigKey,
auth_settings: &AuthSettings,
instance: Option<&crate::Instance>,
pubkey_override: Option<&str>,
) -> Result<ResolvedAuth> {
self.resolver
.resolve_sig_key_with_pubkey(sig_key, auth_settings, instance, pubkey_override)
}
pub fn check_permissions(
&self,
resolved: &ResolvedAuth,
operation: &Operation,
) -> Result<bool> {
super::permissions::check_permissions(resolved, operation)
}
pub fn clear_cache(&mut self) {
self.auth_cache.clear();
self.resolver.clear_cache();
}
}
impl Default for AuthValidator {
fn default() -> Self {
Self::new()
}
}