Development Documentation (main branch) - For stable release docs, see docs.rs/eidetica
Skip to main content

eidetica/auth/validation/
resolver.rs

1//! Key resolution for authentication
2//!
3//! This module handles resolving authentication keys, both direct keys
4//! and delegation paths.
5
6use std::collections::HashMap;
7
8use super::delegation::DelegationResolver;
9use crate::{
10    Instance, Result,
11    auth::{
12        errors::AuthError,
13        settings::AuthSettings,
14        types::{KeyHint, ResolvedAuth, SigKey},
15    },
16};
17
18/// Key resolver for handling both direct and delegated key resolution
19pub struct KeyResolver {
20    /// Cache for resolved authentication data to improve performance
21    auth_cache: HashMap<String, ResolvedAuth>,
22    /// Delegation resolver for handling complex delegation paths
23    delegation_resolver: DelegationResolver,
24}
25
26impl KeyResolver {
27    /// Create a new key resolver
28    pub fn new() -> Self {
29        Self {
30            auth_cache: HashMap::new(),
31            delegation_resolver: DelegationResolver::new(),
32        }
33    }
34
35    /// Resolve authentication identifier to concrete authentication information
36    ///
37    /// Returns all matching ResolvedAuth entries. For name hints that match
38    /// multiple keys, all matches are returned so the caller can try signature
39    /// verification against each.
40    ///
41    /// # Arguments
42    /// * `sig_key` - The signature key identifier to resolve
43    /// * `auth_settings` - Authentication settings containing auth configuration
44    /// * `instance` - Instance for loading delegated trees (required for Delegation sig_key)
45    pub async fn resolve_sig_key(
46        &mut self,
47        sig_key: &SigKey,
48        auth_settings: &AuthSettings,
49        instance: Option<&Instance>,
50    ) -> Result<Vec<ResolvedAuth>> {
51        match sig_key {
52            SigKey::Direct { hint } => self.resolve_direct_key(hint, auth_settings),
53            SigKey::Delegation { path, hint } => {
54                let instance = instance.ok_or_else(|| AuthError::DatabaseRequired {
55                    operation: "delegated tree resolution".to_string(),
56                })?;
57                self.delegation_resolver
58                    .resolve_delegation_path(path, hint, auth_settings, instance)
59                    .await
60            }
61        }
62    }
63
64    /// Resolve a direct key reference from the main tree's auth settings
65    ///
66    /// Returns all matching ResolvedAuth entries. For name hints that match
67    /// multiple keys, all matches are returned so the caller can try signature
68    /// verification against each.
69    pub fn resolve_direct_key(
70        &mut self,
71        hint: &KeyHint,
72        auth_settings: &AuthSettings,
73    ) -> Result<Vec<ResolvedAuth>> {
74        // Use AuthSettings.resolve_hint which handles:
75        // - Global permission (returns single match with actual pubkey)
76        // - Direct pubkey lookup (returns single match)
77        // - Name lookup (may return multiple matches)
78        let matches = auth_settings.resolve_hint(hint)?;
79        if matches.is_empty() {
80            return Err(AuthError::KeyNotFound {
81                key_name: format!("hint({:?})", hint.hint_type()),
82            }
83            .into());
84        }
85
86        Ok(matches)
87    }
88
89    /// Clear the authentication cache
90    pub fn clear_cache(&mut self) {
91        self.auth_cache.clear();
92    }
93}
94
95impl Default for KeyResolver {
96    fn default() -> Self {
97        Self::new()
98    }
99}