use chrono::{DateTime, Duration, Utc}; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; #[derive(Clone, Debug)] pub struct Session { pub username: String, pub role: String, pub created_at: DateTime, pub expires_at: DateTime, } #[derive(Clone)] pub struct SessionManager { sessions: Arc>>, ttl_hours: i64, } impl SessionManager { pub fn new(ttl_hours: i64) -> Self { Self { sessions: Arc::new(RwLock::new(HashMap::new())), ttl_hours, } } /// Create a new session and return the session token. pub async fn create_session(&self, username: String, role: String) -> String { let token = format!("session-{}", uuid::Uuid::new_v4()); let now = Utc::now(); let session = Session { username, role, created_at: now, expires_at: now + Duration::hours(self.ttl_hours), }; self.sessions.write().await.insert(token.clone(), session); token } /// Validate a session token and return the session if valid and not expired. pub async fn validate_session(&self, token: &str) -> Option { let sessions = self.sessions.read().await; sessions.get(token).and_then(|s| { if s.expires_at > Utc::now() { Some(s.clone()) } else { None } }) } /// Revoke (delete) a session by token. pub async fn revoke_session(&self, token: &str) { self.sessions.write().await.remove(token); } /// Remove all expired sessions from the store. pub async fn cleanup_expired(&self) { let now = Utc::now(); self.sessions.write().await.retain(|_, s| s.expires_at > now); } }