use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::info;
use tracing::warn;
use super::authentication_metadata_manager::AuthenticationMetadataManager;
use super::authentication_metadata_manager::ManagerResult;
use crate::authentication::enums::user_status::UserStatus;
use crate::authentication::enums::user_type::UserType;
use crate::authentication::model::user::User;
use crate::authentication::provider::AuthenticationMetadataProvider;
use crate::authorization::metadata_provider::AuthorizationMetadataProvider;
use crate::config::AuthConfig;
use crate::AuthFailureKind;
use crate::AuthOperation;
use crate::AuthServiceError;
pub struct AuthenticationMetadataManagerImpl<A, B>
where
A: AuthenticationMetadataProvider + 'static,
B: AuthorizationMetadataProvider + 'static,
{
authentication_metadata_provider: Arc<RwLock<Option<A>>>,
authorization_metadata_provider: Arc<RwLock<Option<B>>>,
}
impl
AuthenticationMetadataManagerImpl<
crate::LocalAuthenticationMetadataProvider,
crate::LocalAuthorizationMetadataProvider,
>
{
pub fn with_registry(registry: &crate::ProviderRegistry) -> impl AuthenticationMetadataManager {
AuthenticationMetadataManagerImpl::new(
Some(crate::provider_owner::legacy::RegistryUserMetadata::new(registry)),
Some(crate::provider_owner::legacy::RegistryAclMetadata::new(registry)),
)
}
}
impl<A, B> AuthenticationMetadataManagerImpl<A, B>
where
A: AuthenticationMetadataProvider,
B: AuthorizationMetadataProvider,
{
pub fn new(auth_provider: Option<A>, authz_provider: Option<B>) -> Self {
Self {
authentication_metadata_provider: Arc::new(RwLock::new(auth_provider)),
authorization_metadata_provider: Arc::new(RwLock::new(authz_provider)),
}
}
pub async fn set_authentication_provider(&self, provider: A) {
let mut guard = self.authentication_metadata_provider.write().await;
*guard = Some(provider);
}
pub async fn set_authorization_provider(&self, provider: B) {
let mut guard = self.authorization_metadata_provider.write().await;
*guard = Some(provider);
}
fn validate_user(&self, user: &User, is_create: bool) -> ManagerResult<()> {
if user.username().is_empty() {
return Err(AuthServiceError::new(
AuthOperation::ManageMetadata,
AuthFailureKind::InvalidInput,
));
}
if is_create && user.password().is_none() {
return Err(AuthServiceError::new(
AuthOperation::ManageMetadata,
AuthFailureKind::InvalidInput,
));
}
if is_create && user.user_type().is_none() {
return Err(AuthServiceError::new(
AuthOperation::ManageMetadata,
AuthFailureKind::InvalidInput,
));
}
Ok(())
}
fn handle_exception(&self, error: AuthServiceError) -> AuthServiceError {
warn!("Authentication metadata manager operation failed: {}", error);
error
}
async fn init_user_from_string(&self, init_user_str: &str, provider: &A) -> ManagerResult<()> {
if init_user_str.trim().starts_with('{') {
if let Ok(mut user) = serde_json::from_str::<User>(init_user_str) {
user.set_user_type(UserType::Super);
self.create_user_if_not_exists(user, provider).await?;
return Ok(());
}
warn!("Failed to parse init_authentication_user as JSON, trying simple format");
}
let parts: Vec<&str> = init_user_str.splitn(2, ':').collect();
if parts.len() != 2 {
warn!("Invalid init_authentication_user format; expected username:password or JSON");
return Ok(()); }
let username = parts[0].trim();
let password = parts[1].trim();
if !username.is_empty() && !password.is_empty() {
let mut user = User::of_with_type(username, password, UserType::Super);
user.set_user_status(UserStatus::Enable);
self.create_user_if_not_exists(user, provider).await?;
}
Ok(())
}
async fn init_inner_client_user(&self, credentials_str: &str, provider: &A) -> ManagerResult<()> {
#[derive(serde::Deserialize)]
struct SessionCredentials {
#[serde(rename = "accessKey")]
access_key: String,
#[serde(rename = "secretKey")]
secret_key: String,
}
match serde_json::from_str::<SessionCredentials>(credentials_str) {
Ok(credentials) => {
let mut user = User::of_with_type(credentials.access_key, credentials.secret_key, UserType::Super);
user.set_user_status(UserStatus::Enable);
self.create_user_if_not_exists(user, provider).await?;
}
Err(_) => {
warn!("Failed to parse inner_client_authentication_credentials");
}
}
Ok(())
}
async fn create_user_if_not_exists(&self, user: User, provider: &A) -> ManagerResult<()> {
match provider.get_user(user.username().as_str()).await {
Ok(_existing) => {
info!("User '{}' already exists, skipping creation", user.username());
Ok(())
}
Err(error) if error.kind() == AuthFailureKind::NotFound => {
provider.create_user(user.clone()).await?;
info!("Created super user '{}'", user.username());
Ok(())
}
Err(error) => Err(error),
}
}
}
#[allow(async_fn_in_trait)]
impl<A, B> AuthenticationMetadataManager for AuthenticationMetadataManagerImpl<A, B>
where
A: AuthenticationMetadataProvider,
B: AuthorizationMetadataProvider,
{
async fn shutdown(&mut self) -> ManagerResult<()> {
info!("Shutting down authentication metadata manager");
let mut auth_guard = self.authentication_metadata_provider.write().await;
if let Some(mut provider) = auth_guard.take() {
let _ = provider.shutdown().await; }
let mut authz_guard = self.authorization_metadata_provider.write().await;
if let Some(mut provider) = authz_guard.take() {
provider.shutdown(); }
info!("Authentication metadata manager shutdown complete");
Ok(())
}
async fn init_user(&self, auth_config: &AuthConfig) -> ManagerResult<()> {
info!("Initializing default super user from configuration");
let guard = self.authentication_metadata_provider.read().await;
let provider = match &*guard {
Some(p) => p,
None => {
return Err(AuthServiceError::not_initialized(
"Authentication metadata provider is not configured",
));
}
};
let init_user_str = auth_config.init_authentication_user.as_str();
if !init_user_str.is_empty() {
self.init_user_from_string(init_user_str, provider).await?;
}
let inner_credentials = auth_config.inner_client_authentication_credentials.as_str();
if !inner_credentials.is_empty() {
self.init_inner_client_user(inner_credentials, provider).await?;
}
Ok(())
}
async fn create_user(&self, user: User) -> ManagerResult<()> {
self.validate_user(&user, true)?;
let guard = self.authentication_metadata_provider.read().await;
let provider = match &*guard {
Some(p) => p,
None => {
return Err(AuthServiceError::not_initialized(
"Authentication metadata provider is not configured",
));
}
};
match provider.get_user(user.username().as_str()).await {
Ok(_) => {
return Err(AuthServiceError::new(
AuthOperation::ManageMetadata,
AuthFailureKind::Conflict,
))
}
Err(error) if error.kind() == AuthFailureKind::NotFound => {}
Err(error) => return Err(error),
}
let mut user_to_create = user.clone();
if user_to_create.user_type().is_none() {
user_to_create.set_user_type(UserType::Normal);
}
if user_to_create.user_status().is_none() {
user_to_create.set_user_status(UserStatus::Enable);
}
provider
.create_user(user_to_create)
.await
.map_err(|e| self.handle_exception(e))?;
info!("User '{}' created successfully", user.username());
Ok(())
}
async fn update_user(&self, user: User) -> ManagerResult<()> {
self.validate_user(&user, false)?;
let guard = self.authentication_metadata_provider.read().await;
let provider = match &*guard {
Some(p) => p,
None => {
return Err(AuthServiceError::not_initialized(
"Authentication metadata provider is not configured",
));
}
};
let existing_user = provider.get_user(user.username().as_str()).await?;
let mut updated_user = existing_user.clone();
if let Some(new_password) = user.password() {
updated_user.set_password(new_password.clone());
}
if let Some(new_type) = user.user_type() {
updated_user.set_user_type(new_type);
}
if let Some(new_status) = user.user_status() {
updated_user.set_user_status(new_status);
}
provider
.update_user(updated_user)
.await
.map_err(|e| self.handle_exception(e))?;
info!("User '{}' updated successfully", user.username());
Ok(())
}
async fn delete_user(&self, username: &str) -> ManagerResult<()> {
if username.is_empty() {
return Err(AuthServiceError::new(
AuthOperation::ManageMetadata,
AuthFailureKind::InvalidInput,
));
}
let auth_guard = self.authentication_metadata_provider.read().await;
let auth_provider = match &*auth_guard {
Some(p) => p,
None => {
return Err(AuthServiceError::not_initialized(
"Authentication metadata provider is not configured",
));
}
};
let delete_user_result = auth_provider
.delete_user(username)
.await
.map_err(|e| self.handle_exception(e));
let authz_guard = self.authorization_metadata_provider.read().await;
if let Some(authz_provider) = &*authz_guard {
let user = User::of(username);
let _ = authz_provider.delete_acl(&user).await; }
delete_user_result?;
info!("User '{}' and related ACLs deleted successfully", username);
Ok(())
}
async fn get_user(&self, username: &str) -> ManagerResult<User> {
if username.is_empty() {
return Err(AuthServiceError::new(
AuthOperation::ReadMetadata,
AuthFailureKind::InvalidInput,
));
}
let guard = self.authentication_metadata_provider.read().await;
let provider = match &*guard {
Some(p) => p,
None => {
return Err(AuthServiceError::not_initialized(
"Authentication metadata provider is not configured",
));
}
};
provider.get_user(username).await.map_err(|e| self.handle_exception(e))
}
async fn list_users(&self, filter: Option<&str>) -> ManagerResult<Vec<User>> {
let guard = self.authentication_metadata_provider.read().await;
let provider = match &*guard {
Some(p) => p,
None => {
return Err(AuthServiceError::not_initialized(
"Authentication metadata provider is not configured",
));
}
};
provider.list_user(filter).await.map_err(|e| self.handle_exception(e))
}
async fn is_super_user(&self, username: &str) -> ManagerResult<bool> {
if username.is_empty() {
return Ok(false);
}
match self.get_user(username).await {
Ok(user) => Ok(matches!(user.user_type(), Some(UserType::Super))),
Err(error) if error.kind() == AuthFailureKind::NotFound => Ok(false),
Err(error) => Err(error),
}
}
}
impl<A, B> Default for AuthenticationMetadataManagerImpl<A, B>
where
A: AuthenticationMetadataProvider,
B: AuthorizationMetadataProvider,
{
fn default() -> Self {
Self::new(None, None)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::authentication::provider::local_authentication_metadata_provider::LocalAuthenticationMetadataProvider;
use crate::authorization::metadata_provider::local::LocalAuthorizationMetadataProvider;
#[tokio::test]
async fn test_manager_creation() {
let manager = AuthenticationMetadataManagerImpl::<
LocalAuthenticationMetadataProvider,
LocalAuthorizationMetadataProvider,
>::default();
assert!(manager.authentication_metadata_provider.read().await.is_none());
}
#[tokio::test]
async fn test_validate_user_creation() {
let manager = AuthenticationMetadataManagerImpl::<
LocalAuthenticationMetadataProvider,
LocalAuthorizationMetadataProvider,
>::default();
let user = User::of_with_type("test_user", "password", UserType::Normal);
assert!(manager.validate_user(&user, true).is_ok());
let user = User::of_with_type("", "password", UserType::Normal);
assert!(manager.validate_user(&user, true).is_err());
let mut user = User::of("test_user");
user.set_user_type(UserType::Normal);
assert!(manager.validate_user(&user, true).is_err());
}
#[tokio::test]
async fn test_is_super_user_with_empty_username() {
let manager = AuthenticationMetadataManagerImpl::<
LocalAuthenticationMetadataProvider,
LocalAuthorizationMetadataProvider,
>::default();
let result = manager.is_super_user("").await.unwrap();
assert!(!result);
}
}