use super::{Auth, AuthCredentials, AuthStorage, FileAuthStorage};
use crate::Result;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
pub struct AuthManager {
storage: Box<dyn AuthStorage>,
providers: Arc<RwLock<HashMap<String, Box<dyn Auth>>>>,
}
impl AuthManager {
pub async fn new() -> Result<Self> {
let storage = FileAuthStorage::default_with_result()?;
Ok(Self {
storage: Box::new(storage),
providers: Arc::new(RwLock::new(HashMap::new())),
})
}
pub fn with_storage(storage: Box<dyn AuthStorage>) -> Self {
Self {
storage,
providers: Arc::new(RwLock::new(HashMap::new())),
}
}
pub async fn register_provider(&self, auth: Box<dyn Auth>) {
let mut providers = self.providers.write().await;
providers.insert(auth.provider_id().to_string(), auth);
}
pub async fn get_credentials(&self, provider_id: &str) -> Result<Option<AuthCredentials>> {
let providers = self.providers.read().await;
if let Some(provider) = providers.get(provider_id) {
if provider.has_credentials().await {
return Ok(Some(provider.get_credentials().await?));
}
}
self.storage.get(provider_id).await
}
pub async fn set_credentials(&self, provider_id: &str, credentials: AuthCredentials) -> Result<()> {
let providers = self.providers.read().await;
if let Some(provider) = providers.get(provider_id) {
provider.set_credentials(credentials.clone()).await?;
}
self.storage.set(provider_id, credentials).await
}
pub async fn remove_credentials(&self, provider_id: &str) -> Result<()> {
let providers = self.providers.read().await;
if let Some(provider) = providers.get(provider_id) {
provider.remove_credentials().await?;
}
self.storage.remove(provider_id).await
}
pub async fn list_credentials(&self) -> Result<Vec<String>> {
self.storage.list().await
}
pub async fn has_credentials(&self, provider_id: &str) -> bool {
let providers = self.providers.read().await;
if let Some(provider) = providers.get(provider_id) {
if provider.has_credentials().await {
return true;
}
}
self.storage.get(provider_id).await.unwrap_or(None).is_some()
}
}