plexus_core/plexus/
test_validator.rs1use super::auth::{AuthContext, SessionValidator};
8use async_trait::async_trait;
9use serde_json::json;
10
11pub struct TestSessionValidator;
30
31impl TestSessionValidator {
32 pub fn new() -> Self {
33 Self
34 }
35}
36
37impl Default for TestSessionValidator {
38 fn default() -> Self {
39 Self::new()
40 }
41}
42
43#[async_trait]
44impl SessionValidator for TestSessionValidator {
45 async fn validate(&self, cookie: &str) -> Option<AuthContext> {
46 tracing::debug!("TestSessionValidator validating cookie: {}", cookie);
47
48 if let Some(user_id) = cookie.strip_prefix("session=") {
50 tracing::info!("Test auth: Simple format - user_id={}", user_id);
51 return Some(AuthContext {
52 user_id: user_id.to_string(),
53 session_id: format!("test-session-{}", user_id),
54 roles: vec!["user".to_string()],
55 metadata: json!({
56 "tenant_id": "test-tenant",
57 "email": format!("{}@test.com", user_id),
58 "test_mode": true
59 }),
60 });
61 }
62
63 if let Some(params) = cookie.strip_prefix("test_user=") {
65 let parts: Vec<&str> = params.split('|').collect();
66 if parts.is_empty() {
67 tracing::warn!("Test auth: Invalid advanced format - no user_id");
68 return None;
69 }
70
71 let user_id = parts[0].to_string();
72 let mut tenant = "test-tenant".to_string();
73 let mut roles = vec!["user".to_string()];
74
75 for part in parts.iter().skip(1) {
77 if let Some((key, value)) = part.split_once('=') {
78 match key {
79 "tenant" => tenant = value.to_string(),
80 "roles" => roles = value.split(',').map(|s| s.trim().to_string()).collect(),
81 _ => tracing::warn!("Test auth: Unknown parameter: {}", key),
82 }
83 }
84 }
85
86 tracing::info!(
87 "Test auth: Advanced format - user_id={}, tenant={}, roles={:?}",
88 user_id, tenant, roles
89 );
90
91 return Some(AuthContext {
92 user_id: user_id.clone(),
93 session_id: format!("test-session-{}", user_id),
94 roles,
95 metadata: json!({
96 "tenant_id": tenant,
97 "email": format!("{}@test.com", user_id),
98 "test_mode": true
99 }),
100 });
101 }
102
103 tracing::debug!("Test auth: Cookie format not recognized");
105 None
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 #[tokio::test]
114 async fn test_simple_format() {
115 let validator = TestSessionValidator::new();
116
117 let result = validator.validate("session=alice").await;
118 assert!(result.is_some());
119
120 let auth = result.unwrap();
121 assert_eq!(auth.user_id, "alice");
122 assert_eq!(auth.session_id, "test-session-alice");
123 assert!(auth.has_role("user"));
124 assert_eq!(auth.tenant(), Some("test-tenant".to_string()));
125 assert!(auth.is_authenticated());
126 }
127
128 #[tokio::test]
129 async fn test_advanced_format_with_tenant() {
130 let validator = TestSessionValidator::new();
131
132 let result = validator.validate("test_user=bob|tenant=acme").await;
133 assert!(result.is_some());
134
135 let auth = result.unwrap();
136 assert_eq!(auth.user_id, "bob");
137 assert_eq!(auth.tenant(), Some("acme".to_string()));
138 assert!(auth.has_role("user"));
139 }
140
141 #[tokio::test]
142 async fn test_advanced_format_with_roles() {
143 let validator = TestSessionValidator::new();
144
145 let result = validator.validate("test_user=charlie|roles=admin,editor,user").await;
146 assert!(result.is_some());
147
148 let auth = result.unwrap();
149 assert_eq!(auth.user_id, "charlie");
150 assert!(auth.has_role("admin"));
151 assert!(auth.has_role("editor"));
152 assert!(auth.has_role("user"));
153 assert!(!auth.has_role("superuser"));
154 }
155
156 #[tokio::test]
157 async fn test_advanced_format_complete() {
158 let validator = TestSessionValidator::new();
159
160 let result = validator.validate("test_user=dave|tenant=globex|roles=admin,user").await;
161 assert!(result.is_some());
162
163 let auth = result.unwrap();
164 assert_eq!(auth.user_id, "dave");
165 assert_eq!(auth.tenant(), Some("globex".to_string()));
166 assert!(auth.has_role("admin"));
167 assert!(auth.has_role("user"));
168 }
169
170 #[tokio::test]
171 async fn test_invalid_format() {
172 let validator = TestSessionValidator::new();
173
174 let result = validator.validate("invalid-cookie").await;
176 assert!(result.is_none());
177
178 let result = validator.validate("").await;
180 assert!(result.is_none());
181
182 let result = validator.validate("random=garbage").await;
184 assert!(result.is_none());
185 }
186
187 #[tokio::test]
188 async fn test_metadata_includes_test_mode() {
189 let validator = TestSessionValidator::new();
190
191 let result = validator.validate("session=testuser").await;
192 let auth = result.unwrap();
193
194 assert_eq!(auth.metadata.get("test_mode").and_then(|v| v.as_bool()), Some(true));
196 }
197}