role_system/
auth_context.rs1use std::fmt::Debug;
8
9pub trait AuthenticationContext: Send + Sync + Debug {
14 type UserId: AsRef<str> + Debug;
16
17 type ContextData: Debug;
19
20 fn get_user_id(&self) -> &Self::UserId;
22
23 fn get_granted_scopes(&self) -> Vec<String>;
26
27 fn get_context(&self) -> &Self::ContextData;
29
30 fn is_valid(&self) -> bool;
33}
34
35#[derive(Debug)]
37pub struct JwtContext {
38 user_id: String,
40 scopes: Vec<String>,
42 valid: bool,
44 payload: std::collections::HashMap<String, String>,
46}
47
48impl JwtContext {
49 pub fn new(
51 user_id: String,
52 scopes: Vec<String>,
53 valid: bool,
54 payload: std::collections::HashMap<String, String>
55 ) -> Self {
56 Self {
57 user_id,
58 scopes,
59 valid,
60 payload,
61 }
62 }
63}
64
65impl AuthenticationContext for JwtContext {
66 type UserId = String;
67 type ContextData = std::collections::HashMap<String, String>;
68
69 fn get_user_id(&self) -> &Self::UserId {
70 &self.user_id
71 }
72
73 fn get_granted_scopes(&self) -> Vec<String> {
74 self.scopes.clone()
75 }
76
77 fn get_context(&self) -> &Self::ContextData {
78 &self.payload
79 }
80
81 fn is_valid(&self) -> bool {
82 self.valid
83 }
84}
85
86#[derive(Debug)]
88pub struct SessionContext {
89 user_id: String,
91 roles: Vec<String>,
93 active: bool,
95 data: std::collections::HashMap<String, String>,
97}
98
99impl SessionContext {
100 pub fn new(
102 user_id: String,
103 roles: Vec<String>,
104 active: bool,
105 data: std::collections::HashMap<String, String>,
106 ) -> Self {
107 Self {
108 user_id,
109 roles,
110 active,
111 data,
112 }
113 }
114
115 pub fn get_roles(&self) -> &[String] {
117 &self.roles
118 }
119}
120
121impl AuthenticationContext for SessionContext {
122 type UserId = String;
123 type ContextData = std::collections::HashMap<String, String>;
124
125 fn get_user_id(&self) -> &Self::UserId {
126 &self.user_id
127 }
128
129 fn get_granted_scopes(&self) -> Vec<String> {
130 self.roles.iter()
132 .map(|role| format!("role:{}", role))
133 .collect()
134 }
135
136 fn get_context(&self) -> &Self::ContextData {
137 &self.data
138 }
139
140 fn is_valid(&self) -> bool {
141 self.active
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn test_jwt_context() {
151 let mut payload = std::collections::HashMap::new();
152 payload.insert("exp".to_string(), "1625097600".to_string());
153 payload.insert("iat".to_string(), "1625011200".to_string());
154 payload.insert("iss".to_string(), "auth-system".to_string());
155
156 let context = JwtContext::new(
157 "user123".to_string(),
158 vec!["read:users".to_string(), "write:posts".to_string()],
159 true,
160 payload
161 );
162
163 assert_eq!(context.get_user_id(), "user123");
164 assert!(context.get_granted_scopes().contains(&"read:users".to_string()));
165 assert!(context.is_valid());
166 }
167
168 #[test]
169 fn test_session_context() {
170 let mut data = std::collections::HashMap::new();
171 data.insert("last_login".to_string(), "2023-01-01T00:00:00Z".to_string());
172
173 let context = SessionContext::new(
174 "user456".to_string(),
175 vec!["admin".to_string(), "editor".to_string()],
176 true,
177 data
178 );
179
180 assert_eq!(context.get_user_id(), "user456");
181 assert!(context.get_granted_scopes().contains(&"role:admin".to_string()));
182 assert!(context.is_valid());
183 assert_eq!(context.get_roles().len(), 2);
184 }
185}