Skip to main content

modkit_auth/
auth_mode.rs

1use crate::{config_error::ConfigError, plugin_traits::ClaimsPlugin};
2use serde::{Deserialize, Serialize};
3use std::{collections::HashMap, sync::Arc};
4
5/// Configuration for authentication - simplified to single plugin only
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct AuthModeConfig {
8    /// Name of the plugin to use
9    pub provider: String,
10}
11
12impl Default for AuthModeConfig {
13    fn default() -> Self {
14        AuthModeConfig {
15            provider: "default".to_owned(),
16        }
17    }
18}
19
20/// Registry of available claims plugins
21#[derive(Default)]
22pub struct PluginRegistry {
23    plugins: HashMap<String, Arc<dyn ClaimsPlugin>>,
24}
25
26impl PluginRegistry {
27    /// Register a plugin with a name
28    pub fn register(&mut self, name: impl Into<String>, plugin: Arc<dyn ClaimsPlugin>) {
29        self.plugins.insert(name.into(), plugin);
30    }
31
32    /// Get a plugin by name.
33    ///
34    /// # Errors
35    /// Returns `ConfigError::UnknownPlugin` if no plugin with the given name exists.
36    pub fn get(&self, name: &str) -> Result<&Arc<dyn ClaimsPlugin>, ConfigError> {
37        self.plugins
38            .get(name)
39            .ok_or_else(|| ConfigError::UnknownPlugin(name.to_owned()))
40    }
41
42    /// Check if a plugin exists
43    #[must_use]
44    pub fn contains(&self, name: &str) -> bool {
45        self.plugins.contains_key(name)
46    }
47
48    /// Get all plugin names
49    #[must_use]
50    pub fn plugin_names(&self) -> Vec<String> {
51        self.plugins.keys().cloned().collect()
52    }
53
54    /// Number of registered plugins
55    #[must_use]
56    pub fn len(&self) -> usize {
57        self.plugins.len()
58    }
59
60    /// Check if registry is empty
61    #[must_use]
62    pub fn is_empty(&self) -> bool {
63        self.plugins.is_empty()
64    }
65}
66
67#[cfg(test)]
68#[cfg_attr(coverage_nightly, coverage(off))]
69mod tests {
70    use super::*;
71    use crate::{claims::Claims, claims_error::ClaimsError};
72    use serde_json::Value;
73
74    struct MockPlugin;
75
76    impl ClaimsPlugin for MockPlugin {
77        fn name(&self) -> &'static str {
78            "mock"
79        }
80
81        fn normalize(&self, _raw: &Value) -> Result<Claims, ClaimsError> {
82            unimplemented!()
83        }
84    }
85
86    #[test]
87    fn test_registry_basic_operations() {
88        let mut registry = PluginRegistry::default();
89        assert!(registry.is_empty());
90
91        registry.register("mock", Arc::new(MockPlugin));
92        assert_eq!(registry.len(), 1);
93        assert!(registry.contains("mock"));
94        assert!(!registry.contains("other"));
95
96        let plugin = registry.get("mock").unwrap();
97        assert_eq!(plugin.name(), "mock");
98
99        let result = registry.get("unknown");
100        assert!(matches!(result, Err(ConfigError::UnknownPlugin(_))));
101    }
102
103    #[test]
104    fn test_auth_mode_config_serialization() {
105        let config = AuthModeConfig {
106            provider: "keycloak".to_owned(),
107        };
108        let json = serde_json::to_string(&config).unwrap();
109        assert!(json.contains("\"provider\":\"keycloak\""));
110
111        // Test deserialization
112        let deserialized: AuthModeConfig = serde_json::from_str(&json).unwrap();
113        assert_eq!(deserialized.provider, "keycloak");
114    }
115
116    #[test]
117    fn test_auth_mode_config_default() {
118        let config = AuthModeConfig::default();
119        assert_eq!(config.provider, "default");
120    }
121}