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
4use crate::{DedupedMatch, Source, VerificationResult};
5use parking_lot::RwLock;
6use std::collections::HashMap;
7use std::sync::{Arc, OnceLock};
8
9/// A registry for input sources.
10#[derive(Default)]
11pub struct SourceRegistry {
12    sources: RwLock<HashMap<String, Arc<dyn Source + Send + Sync>>>,
13}
14
15impl SourceRegistry {
16    pub fn new() -> Self {
17        Self::default()
18    }
19
20    pub fn register(&self, source: Arc<dyn Source + Send + Sync>) {
21        let mut lock = self.sources.write();
22        lock.insert(source.name().to_string(), source);
23    }
24
25    pub fn get(&self, name: &str) -> Option<Arc<dyn Source + Send + Sync>> {
26        let lock = self.sources.read();
27        lock.get(name).cloned()
28    }
29}
30
31pub static SOURCE_REGISTRY: OnceLock<SourceRegistry> = OnceLock::new();
32
33pub fn get_source_registry() -> &'static SourceRegistry {
34    SOURCE_REGISTRY.get_or_init(|| SourceRegistry {
35        sources: RwLock::new(HashMap::new()),
36    })
37}
38
39/// A trait for custom verification logic (OAuth2, multi-step, etc).
40#[async_trait::async_trait]
41pub trait CustomVerifier: Send + Sync {
42    fn name(&self) -> &str;
43    async fn verify(&self, group: &DedupedMatch) -> (VerificationResult, HashMap<String, String>);
44}
45
46/// A registry for custom verifiers.
47#[derive(Default)]
48pub struct VerifierRegistry {
49    verifiers: RwLock<HashMap<String, Arc<dyn CustomVerifier>>>,
50}
51
52impl VerifierRegistry {
53    pub fn new() -> Self {
54        Self::default()
55    }
56
57    pub fn register(&self, verifier: Arc<dyn CustomVerifier>) {
58        let mut lock = self.verifiers.write();
59        lock.insert(verifier.name().to_string(), verifier);
60    }
61
62    pub fn get(&self, name: &str) -> Option<Arc<dyn CustomVerifier>> {
63        let lock = self.verifiers.read();
64        lock.get(name).cloned()
65    }
66}
67
68pub static VERIFIER_REGISTRY: OnceLock<VerifierRegistry> = OnceLock::new();
69
70pub fn get_verifier_registry() -> &'static VerifierRegistry {
71    VERIFIER_REGISTRY.get_or_init(|| VerifierRegistry {
72        verifiers: RwLock::new(HashMap::new()),
73    })
74}