use super::audit::AuditLogger;
use super::session::SessionManager;
use super::{AuthProvider, AuthorizationProvider, SecurityError, User, Credentials, Permission};
use std::collections::HashMap;
use std::sync::Arc;
pub struct SecurityManager {
auth_providers: HashMap<String, Arc<dyn AuthProvider>>,
auth_provider: Arc<dyn AuthProvider>,
authz_provider: Arc<dyn AuthorizationProvider>,
session_manager: Arc<SessionManager>,
audit_logger: Arc<AuditLogger>,
}
impl SecurityManager {
pub fn new(
auth_provider: Arc<dyn AuthProvider>,
authz_provider: Arc<dyn AuthorizationProvider>,
) -> Self {
Self {
auth_providers: HashMap::new(),
auth_provider: auth_provider.clone(),
authz_provider,
session_manager: Arc::new(SessionManager::new()),
audit_logger: Arc::new(AuditLogger::new()),
}
}
pub fn add_auth_provider(&mut self, name: String, provider: Arc<dyn AuthProvider>) {
self.auth_providers.insert(name, provider);
}
pub async fn authenticate(&self, username: &str, password: &str) -> Result<User, SecurityError> {
let credentials = Credentials::username_password(username.to_string(), password.to_string());
let auth_result = self.auth_provider.authenticate(&credentials).await?;
if auth_result.success {
let user = auth_result.user.ok_or_else(|| SecurityError::AuthenticationFailed("No user in successful auth result".to_string()))?;
self.audit_logger
.log_auth_event(&user.id, "login", "User authenticated successfully")
.await;
Ok(user)
} else {
Err(SecurityError::AuthenticationFailed(auth_result.error_message.unwrap_or_else(|| "Authentication failed".to_string())))
}
}
pub async fn authenticate_with_provider(
&self,
provider_name: &str,
username: &str,
password: &str,
) -> Result<User, SecurityError> {
let provider = self
.auth_providers
.get(provider_name)
.ok_or_else(|| SecurityError::AuthenticationFailed("Provider not found".to_string()))?;
let credentials = Credentials::username_password(username.to_string(), password.to_string());
let auth_result = provider.authenticate(&credentials).await?;
if auth_result.success {
let user = auth_result.user.ok_or_else(|| SecurityError::AuthenticationFailed("No user in successful auth result".to_string()))?;
self.audit_logger
.log_auth_event(&user.id, "login", &format!("User authenticated with provider: {}", provider_name))
.await;
Ok(user)
} else {
Err(SecurityError::AuthenticationFailed(auth_result.error_message.unwrap_or_else(|| "Authentication failed".to_string())))
}
}
pub async fn check_permission(
&self,
user: &User,
resource: &str,
action: &str,
) -> Result<bool, SecurityError> {
let permission = Permission::ViewCharts;
let has_permission = self
.authz_provider
.has_permission(user, &permission)
.await?;
self.audit_logger
.log_authz_event(
&user.id,
"permission_check",
&format!("Permission check for {} on {}: {}", action, resource, has_permission),
)
.await;
Ok(has_permission)
}
pub async fn create_session(&self, user: &User) -> Result<super::session::Session, SecurityError> {
let session = self.session_manager.create_session(user).await?;
self.audit_logger
.log_session_event(&user.id, "session_created", "New session created")
.await;
Ok(session)
}
pub async fn get_session(&self, session_id: &str) -> Result<Option<super::session::Session>, SecurityError> {
self.session_manager.get_session(session_id).await
}
pub async fn invalidate_session(&self, session_id: &str) -> Result<(), SecurityError> {
if let Some(session) = self.session_manager.get_session(session_id).await? {
self.audit_logger
.log_session_event(&session.user_id, "session_invalidated", "Session invalidated")
.await;
}
self.session_manager.invalidate_session(session_id).await
}
pub async fn update_session_activity(&self, session_id: &str) -> Result<(), SecurityError> {
self.session_manager.update_session_activity(session_id).await
}
pub async fn cleanup_expired_sessions(&self) -> Result<usize, SecurityError> {
let cleaned_count = self.session_manager.cleanup_expired_sessions().await?;
if cleaned_count > 0 {
self.audit_logger
.log_session_event("system", "cleanup", &format!("Cleaned up {} expired sessions", cleaned_count))
.await;
}
Ok(cleaned_count)
}
pub async fn get_user_audit_logs(&self, user_id: &str) -> Vec<super::audit::AuditLogEntry> {
self.audit_logger.get_user_logs(user_id).await
}
pub async fn get_category_audit_logs(&self, category: &str) -> Vec<super::audit::AuditLogEntry> {
self.audit_logger.get_category_logs(category).await
}
pub async fn export_audit_logs_json(&self) -> Result<String, serde_json::Error> {
self.audit_logger.export_logs_json().await
}
pub async fn export_audit_logs_csv(&self) -> String {
self.audit_logger.export_logs_csv().await
}
pub fn session_manager(&self) -> Arc<SessionManager> {
self.session_manager.clone()
}
pub fn audit_logger(&self) -> Arc<AuditLogger> {
self.audit_logger.clone()
}
pub fn auth_provider(&self) -> Arc<dyn AuthProvider> {
self.auth_provider.clone()
}
pub fn authz_provider(&self) -> Arc<dyn AuthorizationProvider> {
self.authz_provider.clone()
}
}