use std::sync::Arc;
use tracing::debug;
use tracing::warn;
use crate::authentication::enums::subject_type::SubjectType;
use crate::authentication::model::subject::Subject;
use crate::authorization::enums::policy_type::PolicyType;
use crate::authorization::metadata_provider::local::LocalAuthorizationMetadataProvider;
use crate::authorization::metadata_provider::AuthorizationMetadataProvider;
use crate::authorization::model::acl::Acl;
use crate::authorization::model::policy::Policy;
use crate::authorization::model::policy_entry::PolicyEntry;
use crate::authorization::model::resource::Resource;
use crate::authorization::provider::AuthorizationError;
use crate::config::AuthConfig;
pub type ManagerResult<T> = Result<T, AuthorizationError>;
pub struct AuthorizationMetadataManager {
authorization_provider: Arc<LocalAuthorizationMetadataProvider>,
authentication_provider: Option<Arc<dyn std::any::Any + Send + Sync>>,
}
impl AuthorizationMetadataManager {
pub fn with_providers(
authorization_provider: Arc<LocalAuthorizationMetadataProvider>,
authentication_provider: Option<Arc<dyn std::any::Any + Send + Sync>>,
) -> Self {
Self {
authorization_provider,
authentication_provider,
}
}
pub fn new(_config: AuthConfig) -> ManagerResult<Self> {
Err(AuthorizationError::ConfigurationError(
"AuthorizationMetadataManager::new requires factory implementation. Use with_providers() instead."
.to_string(),
))
}
pub async fn shutdown(&mut self) {
debug!("Shutting down AuthorizationMetadataManager");
}
pub async fn create_acl(&self, mut acl: Acl) -> ManagerResult<()> {
self.validate_acl(&acl)?;
Self::init_acl(&mut acl);
self.verify_subject_exists(&acl).await?;
let subject_key = acl.subject_key();
let subject_type = acl.subject_type();
match self
.authorization_provider
.get_acl(&UserSubjectWrapper {
key: subject_key.to_string(),
subject_type,
})
.await?
{
None => {
debug!("Creating new ACL for subject: {}", subject_key);
self.authorization_provider.create_acl(acl).await
}
Some(mut old_acl) => {
debug!("ACL already exists for subject {}, updating policies", subject_key);
old_acl.update_policies(acl.policies().clone());
self.authorization_provider.update_acl(old_acl).await
}
}
}
pub async fn update_acl(&self, mut acl: Acl) -> ManagerResult<()> {
self.validate_acl(&acl)?;
Self::init_acl(&mut acl);
self.verify_subject_exists(&acl).await?;
let subject_key = acl.subject_key();
let subject_type = acl.subject_type();
match self
.authorization_provider
.get_acl(&UserSubjectWrapper {
key: subject_key.to_string(),
subject_type,
})
.await?
{
None => {
debug!("No existing ACL for subject {}, creating new", subject_key);
self.authorization_provider.create_acl(acl).await
}
Some(mut old_acl) => {
debug!("Updating existing ACL for subject: {}", subject_key);
old_acl.update_policies(acl.policies().clone());
self.authorization_provider.update_acl(old_acl).await
}
}
}
pub async fn delete_acl<S: Subject + Send + Sync>(&self, subject: &S) -> ManagerResult<()> {
self.delete_acl_with_filter(subject, None, None).await
}
pub async fn delete_acl_with_filter<S: Subject + Send + Sync>(
&self,
subject: &S,
policy_type: Option<PolicyType>,
resource: Option<&Resource>,
) -> ManagerResult<()> {
self.verify_subject_by_ref(subject).await?;
let policy_type = policy_type.unwrap_or(PolicyType::Custom);
let mut acl = self.authorization_provider.get_acl(subject).await?.ok_or_else(|| {
AuthorizationError::InternalError(format!(
"The ACL for subject '{}' does not exist",
subject.subject_key()
))
})?;
if let Some(resource) = resource {
debug!(
"Deleting resource {:?} from {:?} policy for subject {}",
resource,
policy_type,
subject.subject_key()
);
acl.delete_policy(policy_type, resource);
if acl.policies().is_empty() {
self.authorization_provider.delete_acl(subject).await
} else {
self.authorization_provider.update_acl(acl).await
}
} else {
debug!("Deleting entire ACL for subject: {}", subject.subject_key());
self.authorization_provider.delete_acl(subject).await
}
}
pub async fn get_acl<S: Subject + Send + Sync>(&self, subject: &S) -> ManagerResult<Option<Acl>> {
self.verify_subject_by_ref(subject).await?;
self.authorization_provider.get_acl(subject).await
}
pub async fn list_acl(
&self,
subject_filter: Option<&str>,
resource_filter: Option<&str>,
) -> ManagerResult<Vec<Acl>> {
self.authorization_provider
.list_acl(subject_filter, resource_filter)
.await
}
fn init_acl(acl: &mut Acl) {
let mut policies = acl.policies().clone();
for policy in policies.iter_mut() {
let _ = policy.policy_type();
}
acl.set_policies(policies);
}
fn validate_acl(&self, acl: &Acl) -> ManagerResult<()> {
if acl.policies().is_empty() {
return Err(AuthorizationError::InvalidContext(
"The policies list is empty".to_string(),
));
}
for policy in acl.policies() {
self.validate_policy(policy)?;
}
Ok(())
}
fn validate_policy(&self, policy: &Policy) -> ManagerResult<()> {
if policy.entries().is_empty() {
return Err(AuthorizationError::InvalidContext(
"Policy entries list is empty".to_string(),
));
}
for entry in policy.entries() {
self.validate_policy_entry(entry)?;
}
Ok(())
}
fn validate_policy_entry(&self, entry: &PolicyEntry) -> ManagerResult<()> {
if entry.actions().is_empty() {
return Err(AuthorizationError::InvalidContext(
"PolicyEntry actions list is empty".to_string(),
));
}
Ok(())
}
async fn verify_subject_exists(&self, acl: &Acl) -> ManagerResult<()> {
if acl.subject_type() == SubjectType::User {
warn!(
"Subject validation for USER type is not yet implemented (subject: {})",
acl.subject_key()
);
}
Ok(())
}
async fn verify_subject_by_ref<S: Subject + Send + Sync>(&self, subject: &S) -> ManagerResult<()> {
if subject.subject_type() == SubjectType::User {
warn!(
"Subject validation for USER type is not yet implemented (subject: {})",
subject.subject_key()
);
}
Ok(())
}
}
struct UserSubjectWrapper {
key: String,
subject_type: SubjectType,
}
impl Subject for UserSubjectWrapper {
fn subject_key(&self) -> &str {
&self.key
}
fn subject_type(&self) -> SubjectType {
self.subject_type
}
}