Skip to main content

auth/
config.rs

1use platform_core::{
2    AppContext, RuntimeConfigDescriptor, RuntimeConfigScope, RuntimeConfigSnapshot,
3    RuntimeConfigType,
4};
5use std::sync::LazyLock;
6use std::time::Duration;
7
8const SESSION_CACHE_KEY: &str = "auth.session_cache";
9
10pub const SESSION_CACHE_MAX_TTL: Duration = Duration::from_secs(12 * 60 * 60);
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum SessionCacheMode {
14    Database,
15    Redis,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct AuthRuntimeConfig {
20    pub session_cache: SessionCacheMode,
21}
22
23impl AuthRuntimeConfig {
24    #[must_use]
25    pub fn from_context(ctx: &AppContext) -> Self {
26        Self::from_snapshot(&ctx.runtime_config.snapshot())
27    }
28
29    #[must_use]
30    pub fn from_snapshot(snapshot: &RuntimeConfigSnapshot) -> Self {
31        let session_cache = snapshot
32            .raw(SESSION_CACHE_KEY)
33            .and_then(serde_json::Value::as_str)
34            .and_then(SessionCacheMode::from_value)
35            .unwrap_or(SessionCacheMode::Database);
36        Self { session_cache }
37    }
38}
39
40impl Default for AuthRuntimeConfig {
41    fn default() -> Self {
42        Self {
43            session_cache: SessionCacheMode::Database,
44        }
45    }
46}
47
48impl SessionCacheMode {
49    fn from_value(value: &str) -> Option<Self> {
50        match value {
51            "database" => Some(Self::Database),
52            "redis" => Some(Self::Redis),
53            _ => None,
54        }
55    }
56}
57
58pub static RUNTIME_CONFIG: LazyLock<Vec<RuntimeConfigDescriptor>> = LazyLock::new(|| {
59    vec![RuntimeConfigDescriptor {
60        key: SESSION_CACHE_KEY.to_owned(),
61        scope: RuntimeConfigScope::Shared,
62        group: None,
63        section: None,
64        order: 10,
65        visible_when: None,
66        generated: None,
67        value_type: RuntimeConfigType::Enum(&["database", "redis"]),
68        default: serde_json::json!("database"),
69        editable: true,
70        restart_only: true,
71        description: "Session cache backend used by auth session resolution.",
72    }]
73});
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use platform_core::{RuntimeConfigRegistry, RuntimeConfigSnapshot};
79    use std::collections::BTreeMap;
80
81    #[test]
82    fn defaults_to_database_cache() {
83        let registry = RuntimeConfigRegistry::try_new(RUNTIME_CONFIG.clone()).unwrap();
84        let snapshot = RuntimeConfigSnapshot::resolve(&registry, "api", &BTreeMap::new());
85
86        let config = AuthRuntimeConfig::from_snapshot(&snapshot);
87
88        assert_eq!(config.session_cache, SessionCacheMode::Database);
89    }
90}