Skip to main content

keyhog_core/
registry.rs

1//! Global registry for pluggable components (Sources, Verifiers).
2//! This allows adding new features in a single file without modifying the core.
3
4// Debt bucket: 10 items predating the crate floor raising `missing_docs` to
5// `warn`. Remove this allow once each registry item carries a doc line.
6#![allow(missing_docs)]
7
8use crate::{DedupedMatch, Source, VerificationResult};
9use parking_lot::RwLock;
10use std::collections::HashMap;
11use std::sync::{Arc, OnceLock};
12
13/// A registry for input sources.
14#[derive(Default)]
15pub struct SourceRegistry {
16    sources: RwLock<HashMap<String, Arc<dyn Source + Send + Sync>>>,
17}
18
19impl SourceRegistry {
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    pub fn register(&self, source: Arc<dyn Source + Send + Sync>) {
25        let mut lock = self.sources.write();
26        lock.insert(source.name().to_string(), source);
27    }
28
29    pub fn get(&self, name: &str) -> Option<Arc<dyn Source + Send + Sync>> {
30        let lock = self.sources.read();
31        lock.get(name).cloned()
32    }
33}
34
35pub static SOURCE_REGISTRY: OnceLock<SourceRegistry> = OnceLock::new();
36
37/// Return the global registry of scannable source backends.
38pub fn get_source_registry() -> &'static SourceRegistry {
39    SOURCE_REGISTRY.get_or_init(|| SourceRegistry {
40        sources: RwLock::new(HashMap::new()),
41    })
42}
43
44/// A trait for custom verification logic (OAuth2, multi-step, etc).
45#[async_trait::async_trait]
46pub trait CustomVerifier: Send + Sync {
47    fn name(&self) -> &str;
48    async fn verify(&self, group: &DedupedMatch) -> (VerificationResult, HashMap<String, String>);
49}
50
51/// A registry for custom verifiers.
52#[derive(Default)]
53pub struct VerifierRegistry {
54    verifiers: RwLock<HashMap<String, Arc<dyn CustomVerifier>>>,
55}
56
57impl VerifierRegistry {
58    pub fn new() -> Self {
59        Self::default()
60    }
61
62    pub fn register(&self, verifier: Arc<dyn CustomVerifier>) {
63        let mut lock = self.verifiers.write();
64        lock.insert(verifier.name().to_string(), verifier);
65    }
66
67    pub fn get(&self, name: &str) -> Option<Arc<dyn CustomVerifier>> {
68        let lock = self.verifiers.read();
69        lock.get(name).cloned()
70    }
71}
72
73pub static VERIFIER_REGISTRY: OnceLock<VerifierRegistry> = OnceLock::new();
74
75/// Return the global registry of credential verifiers.
76pub fn get_verifier_registry() -> &'static VerifierRegistry {
77    VERIFIER_REGISTRY.get_or_init(|| VerifierRegistry {
78        verifiers: RwLock::new(HashMap::new()),
79    })
80}