Skip to main content

auth_framework/
user_context.rs

1//! User context and authentication state management
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use uuid::Uuid;
6
7/// Represents authenticated user context
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct UserContext {
10    pub user_id: String,
11    pub username: String,
12    pub email: Option<String>,
13    pub scopes: crate::types::Scopes,
14    pub authenticated_at: std::time::SystemTime,
15    pub session_id: String,
16    pub attributes: crate::types::UserAttributesString,
17}
18
19impl UserContext {
20    pub fn new(user_id: String, username: String, email: Option<String>) -> Self {
21        Self {
22            user_id,
23            username,
24            email,
25            scopes: crate::types::Scopes::empty(),
26            authenticated_at: std::time::SystemTime::now(),
27            session_id: Uuid::new_v4().to_string(),
28            attributes: crate::types::UserAttributesString::empty(),
29        }
30    }
31
32    pub fn with_scopes(mut self, scopes: Vec<String>) -> Self {
33        self.scopes = scopes.into();
34        self
35    }
36
37    pub fn add_attribute(&mut self, key: String, value: String) {
38        self.attributes.insert(key, value);
39    }
40
41    pub fn has_scope(&self, scope: &str) -> bool {
42        self.scopes.contains(&scope.to_string())
43    }
44}
45
46/// Session store for managing user authentication state
47
48impl UserContext {
49    /// Create a new builder for UserContext
50    pub fn builder(user_id: impl Into<String>, username: impl Into<String>) -> UserContextBuilder {
51        UserContextBuilder::new(user_id.into(), username.into())
52    }
53}
54
55/// A builder for UserContext
56pub struct UserContextBuilder {
57    user_id: String,
58    username: String,
59    email: Option<String>,
60    scopes: Vec<String>,
61    attributes: HashMap<String, String>,
62}
63
64impl UserContextBuilder {
65    pub fn new(user_id: String, username: String) -> Self {
66        Self {
67            user_id,
68            username,
69            email: None,
70            scopes: Vec::new(),
71            attributes: HashMap::new(),
72        }
73    }
74
75    pub fn email(mut self, email: impl Into<String>) -> Self {
76        self.email = Some(email.into());
77        self
78    }
79
80    pub fn scope(mut self, scope: impl Into<String>) -> Self {
81        self.scopes.push(scope.into());
82        self
83    }
84
85    pub fn scopes(mut self, scopes: Vec<String>) -> Self {
86        self.scopes = scopes;
87        self
88    }
89
90    pub fn attribute(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
91        self.attributes.insert(key.into(), value.into());
92        self
93    }
94
95    pub fn build(self) -> UserContext {
96        let mut ctx = UserContext::new(self.user_id, self.username, self.email);
97        ctx.scopes = self.scopes.into();
98        ctx.attributes = self.attributes.into();
99        ctx
100    }
101}
102
103#[derive(Debug, Clone)]
104pub struct SessionStore {
105    sessions: std::collections::HashMap<String, UserContext>,
106}
107
108impl SessionStore {
109    pub fn new() -> Self {
110        Self {
111            sessions: HashMap::new(),
112        }
113    }
114
115    pub fn create_session(&mut self, user_context: UserContext) -> String {
116        let session_id = user_context.session_id.clone();
117        self.sessions.insert(session_id.clone(), user_context);
118        session_id
119    }
120
121    pub fn get_session(&self, session_id: &str) -> Option<&UserContext> {
122        self.sessions.get(session_id)
123    }
124
125    pub fn invalidate_session(&mut self, session_id: &str) -> bool {
126        self.sessions.remove(session_id).is_some()
127    }
128
129    pub fn validate_session(&self, session_id: &str) -> bool {
130        self.sessions.contains_key(session_id)
131    }
132}
133
134impl Default for SessionStore {
135    fn default() -> Self {
136        Self::new()
137    }
138}