code_mesh_core/auth/
manager.rs

1//! Authentication manager for Code Mesh
2
3use super::{Auth, AuthCredentials, AuthStorage, FileAuthStorage};
4use crate::Result;
5use std::collections::HashMap;
6use std::sync::Arc;
7use tokio::sync::RwLock;
8
9/// Authentication manager for managing provider credentials
10pub struct AuthManager {
11    storage: Box<dyn AuthStorage>,
12    providers: Arc<RwLock<HashMap<String, Box<dyn Auth>>>>,
13}
14
15impl AuthManager {
16    /// Create a new authentication manager
17    pub async fn new() -> Result<Self> {
18        let storage = FileAuthStorage::default_with_result()?;
19        Ok(Self {
20            storage: Box::new(storage),
21            providers: Arc::new(RwLock::new(HashMap::new())),
22        })
23    }
24    
25    /// Create with custom storage
26    pub fn with_storage(storage: Box<dyn AuthStorage>) -> Self {
27        Self {
28            storage,
29            providers: Arc::new(RwLock::new(HashMap::new())),
30        }
31    }
32    
33    /// Register a provider authentication
34    pub async fn register_provider(&self, auth: Box<dyn Auth>) {
35        let mut providers = self.providers.write().await;
36        providers.insert(auth.provider_id().to_string(), auth);
37    }
38    
39    /// Get credentials for a provider
40    pub async fn get_credentials(&self, provider_id: &str) -> Result<Option<AuthCredentials>> {
41        // First check if we have a provider registered
42        let providers = self.providers.read().await;
43        if let Some(provider) = providers.get(provider_id) {
44            if provider.has_credentials().await {
45                return Ok(Some(provider.get_credentials().await?));
46            }
47        }
48        
49        // Otherwise check storage
50        self.storage.get(provider_id).await
51    }
52    
53    /// Set credentials for a provider
54    pub async fn set_credentials(&self, provider_id: &str, credentials: AuthCredentials) -> Result<()> {
55        // If we have a provider registered, use it
56        let providers = self.providers.read().await;
57        if let Some(provider) = providers.get(provider_id) {
58            provider.set_credentials(credentials.clone()).await?;
59        }
60        
61        // Always persist to storage
62        self.storage.set(provider_id, credentials).await
63    }
64    
65    /// Remove credentials for a provider
66    pub async fn remove_credentials(&self, provider_id: &str) -> Result<()> {
67        // If we have a provider registered, use it
68        let providers = self.providers.read().await;
69        if let Some(provider) = providers.get(provider_id) {
70            provider.remove_credentials().await?;
71        }
72        
73        // Always remove from storage
74        self.storage.remove(provider_id).await
75    }
76    
77    /// List all providers with stored credentials
78    pub async fn list_credentials(&self) -> Result<Vec<String>> {
79        self.storage.list().await
80    }
81    
82    /// Check if a provider has credentials
83    pub async fn has_credentials(&self, provider_id: &str) -> bool {
84        // Check registered provider first
85        let providers = self.providers.read().await;
86        if let Some(provider) = providers.get(provider_id) {
87            if provider.has_credentials().await {
88                return true;
89            }
90        }
91        
92        // Check storage
93        self.storage.get(provider_id).await.unwrap_or(None).is_some()
94    }
95}