use super::auth::{AuthContext, SessionValidator};
use async_trait::async_trait;
use serde_json::json;
pub struct TestSessionValidator;
impl TestSessionValidator {
pub fn new() -> Self {
Self
}
}
impl Default for TestSessionValidator {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl SessionValidator for TestSessionValidator {
async fn validate(&self, cookie: &str) -> Option<AuthContext> {
tracing::debug!("TestSessionValidator validating cookie: {}", cookie);
if let Some(user_id) = cookie.strip_prefix("session=") {
tracing::info!("Test auth: Simple format - user_id={}", user_id);
return Some(AuthContext {
user_id: user_id.to_string(),
session_id: format!("test-session-{}", user_id),
roles: vec!["user".to_string()],
metadata: json!({
"tenant_id": "test-tenant",
"email": format!("{}@test.com", user_id),
"test_mode": true
}),
});
}
if let Some(params) = cookie.strip_prefix("test_user=") {
let parts: Vec<&str> = params.split('|').collect();
if parts.is_empty() {
tracing::warn!("Test auth: Invalid advanced format - no user_id");
return None;
}
let user_id = parts[0].to_string();
let mut tenant = "test-tenant".to_string();
let mut roles = vec!["user".to_string()];
for part in parts.iter().skip(1) {
if let Some((key, value)) = part.split_once('=') {
match key {
"tenant" => tenant = value.to_string(),
"roles" => roles = value.split(',').map(|s| s.trim().to_string()).collect(),
_ => tracing::warn!("Test auth: Unknown parameter: {}", key),
}
}
}
tracing::info!(
"Test auth: Advanced format - user_id={}, tenant={}, roles={:?}",
user_id, tenant, roles
);
return Some(AuthContext {
user_id: user_id.clone(),
session_id: format!("test-session-{}", user_id),
roles,
metadata: json!({
"tenant_id": tenant,
"email": format!("{}@test.com", user_id),
"test_mode": true
}),
});
}
tracing::debug!("Test auth: Cookie format not recognized");
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_simple_format() {
let validator = TestSessionValidator::new();
let result = validator.validate("session=alice").await;
assert!(result.is_some());
let auth = result.unwrap();
assert_eq!(auth.user_id, "alice");
assert_eq!(auth.session_id, "test-session-alice");
assert!(auth.has_role("user"));
assert_eq!(auth.tenant(), Some("test-tenant".to_string()));
assert!(auth.is_authenticated());
}
#[tokio::test]
async fn test_advanced_format_with_tenant() {
let validator = TestSessionValidator::new();
let result = validator.validate("test_user=bob|tenant=acme").await;
assert!(result.is_some());
let auth = result.unwrap();
assert_eq!(auth.user_id, "bob");
assert_eq!(auth.tenant(), Some("acme".to_string()));
assert!(auth.has_role("user"));
}
#[tokio::test]
async fn test_advanced_format_with_roles() {
let validator = TestSessionValidator::new();
let result = validator.validate("test_user=charlie|roles=admin,editor,user").await;
assert!(result.is_some());
let auth = result.unwrap();
assert_eq!(auth.user_id, "charlie");
assert!(auth.has_role("admin"));
assert!(auth.has_role("editor"));
assert!(auth.has_role("user"));
assert!(!auth.has_role("superuser"));
}
#[tokio::test]
async fn test_advanced_format_complete() {
let validator = TestSessionValidator::new();
let result = validator.validate("test_user=dave|tenant=globex|roles=admin,user").await;
assert!(result.is_some());
let auth = result.unwrap();
assert_eq!(auth.user_id, "dave");
assert_eq!(auth.tenant(), Some("globex".to_string()));
assert!(auth.has_role("admin"));
assert!(auth.has_role("user"));
}
#[tokio::test]
async fn test_invalid_format() {
let validator = TestSessionValidator::new();
let result = validator.validate("invalid-cookie").await;
assert!(result.is_none());
let result = validator.validate("").await;
assert!(result.is_none());
let result = validator.validate("random=garbage").await;
assert!(result.is_none());
}
#[tokio::test]
async fn test_metadata_includes_test_mode() {
let validator = TestSessionValidator::new();
let result = validator.validate("session=testuser").await;
let auth = result.unwrap();
assert_eq!(auth.metadata.get("test_mode").and_then(|v| v.as_bool()), Some(true));
}
}