auth_framework/auth_modular/
session_manager.rs1use crate::errors::{AuthError, Result};
4use crate::storage::{AuthStorage, SessionData};
5use std::collections::HashMap;
6use std::sync::Arc;
7use std::time::Duration;
8use tracing::{debug, info};
9
10pub struct SessionManager {
12 storage: Arc<dyn AuthStorage>,
13}
14
15impl SessionManager {
16 pub fn new(storage: Arc<dyn AuthStorage>) -> Self {
18 Self { storage }
19 }
20
21 pub async fn create_session(
23 &self,
24 user_id: &str,
25 expires_in: Duration,
26 ip_address: Option<String>,
27 user_agent: Option<String>,
28 ) -> Result<String> {
29 debug!("Creating session for user '{}'", user_id);
30
31 if expires_in.is_zero() {
33 return Err(AuthError::invalid_credential(
34 "session_duration",
35 "Session duration must be greater than zero",
36 ));
37 }
38
39 if expires_in > Duration::from_secs(365 * 24 * 60 * 60) {
40 return Err(AuthError::invalid_credential(
42 "session_duration",
43 "Session duration exceeds maximum allowed (1 year)",
44 ));
45 }
46
47 let session_id = crate::utils::string::generate_id(Some("sess"));
48 let session = SessionData::new(session_id.clone(), user_id, expires_in)
49 .with_metadata(ip_address, user_agent);
50
51 self.storage.store_session(&session_id, &session).await?;
52
53 info!("Session '{}' created for user '{}'", session_id, user_id);
54 Ok(session_id)
55 }
56
57 pub async fn get_session(&self, session_id: &str) -> Result<Option<SessionData>> {
59 debug!("Getting session '{}'", session_id);
60
61 let session = self.storage.get_session(session_id).await?;
62
63 if let Some(ref session_data) = session
65 && session_data.is_expired()
66 {
67 let _ = self.delete_session(session_id).await;
69 return Ok(None);
70 }
71
72 Ok(session)
73 }
74
75 pub async fn delete_session(&self, session_id: &str) -> Result<()> {
77 debug!("Deleting session '{}'", session_id);
78
79 self.storage.delete_session(session_id).await?;
80 info!("Session '{}' deleted", session_id);
81 Ok(())
82 }
83
84 pub async fn update_session_activity(&self, session_id: &str) -> Result<()> {
86 if let Some(mut session) = self.storage.get_session(session_id).await? {
87 session.last_activity = chrono::Utc::now();
88 self.storage.store_session(session_id, &session).await?;
89 }
90 Ok(())
91 }
92
93 pub async fn get_user_sessions(&self, user_id: &str) -> Result<Vec<(String, SessionData)>> {
95 debug!("Getting all sessions for user '{}'", user_id);
98 Ok(vec![])
99 }
100
101 pub async fn delete_user_sessions(&self, user_id: &str) -> Result<()> {
103 debug!("Deleting all sessions for user '{}'", user_id);
104
105 let sessions = self.get_user_sessions(user_id).await?;
107 for (session_id, _) in sessions {
108 let _ = self.delete_session(&session_id).await;
109 }
110
111 info!("All sessions deleted for user '{}'", user_id);
112 Ok(())
113 }
114
115 pub async fn cleanup_expired_sessions(&self) -> Result<()> {
117 debug!("Cleaning up expired sessions");
118
119 Ok(())
122 }
123
124 pub async fn validate_session(&self, session_id: &str) -> Result<Option<String>> {
126 if let Some(session) = self.get_session(session_id).await?
127 && !session.is_expired()
128 {
129 let _ = self.update_session_activity(session_id).await;
131 return Ok(Some(session.user_id));
132 }
133 Ok(None)
134 }
135
136 pub async fn extend_session(&self, session_id: &str, additional_time: Duration) -> Result<()> {
138 debug!(
139 "Extending session '{}' by {:?}",
140 session_id, additional_time
141 );
142
143 if let Some(mut session) = self.storage.get_session(session_id).await? {
144 session.expires_at += chrono::Duration::from_std(additional_time)
145 .map_err(|e| AuthError::internal(format!("Failed to convert duration: {}", e)))?;
146 self.storage.store_session(session_id, &session).await?;
147 info!("Session '{}' extended", session_id);
148 }
149
150 Ok(())
151 }
152
153 pub async fn count_active_sessions(&self) -> Result<u64> {
156 debug!("Counting active sessions");
157
158 let active_count = self.storage.count_active_sessions().await?;
160
161 debug!("Found {} active sessions", active_count);
162 Ok(active_count)
163 }
164
165 pub async fn get_session_security_metrics(&self) -> Result<HashMap<String, serde_json::Value>> {
167 debug!("Collecting session security metrics");
168
169 let mut metrics = HashMap::new();
170 let active_count = self.count_active_sessions().await?;
171
172 metrics.insert(
173 "active_sessions".to_string(),
174 serde_json::Value::Number(serde_json::Number::from(active_count)),
175 );
176 metrics.insert(
177 "last_check".to_string(),
178 serde_json::Value::String(chrono::Utc::now().to_rfc3339()),
179 );
180
181 Ok(metrics)
182 }
183}
184
185