use crate::authorization::context::default_authorization_context::DefaultAuthorizationContext;
use crate::authorization::provider::AuthorizationError;
use crate::authorization::strategy::abstract_authorization_strategy::AuthorizationStrategy;
pub type EvaluatorResult<T> = Result<T, AuthorizationError>;
pub struct AuthorizationEvaluator<S>
where
S: AuthorizationStrategy,
{
authorization_strategy: S,
}
impl<S> AuthorizationEvaluator<S>
where
S: AuthorizationStrategy,
{
pub fn new(authorization_strategy: S) -> Self {
Self { authorization_strategy }
}
pub fn evaluate(&self, contexts: &[DefaultAuthorizationContext]) -> EvaluatorResult<()> {
if contexts.is_empty() {
return Ok(());
}
for context in contexts {
self.authorization_strategy.evaluate(context)?;
}
Ok(())
}
pub fn strategy(&self) -> &S {
&self.authorization_strategy
}
}
unsafe impl<S> Send for AuthorizationEvaluator<S> where S: AuthorizationStrategy {}
unsafe impl<S> Sync for AuthorizationEvaluator<S> where S: AuthorizationStrategy {}
#[cfg(test)]
mod tests {
use super::*;
use crate::authorization::strategy::abstract_authorization_strategy::StrategyResult;
struct MockStrategy {
should_fail: bool,
}
impl AuthorizationStrategy for MockStrategy {
fn evaluate(&self, _context: &DefaultAuthorizationContext) -> StrategyResult<()> {
if self.should_fail {
Err(AuthorizationError::PermissionDenied {
subject: "test".to_string(),
resource: "test".to_string(),
reason: "mock failure".to_string(),
})
} else {
Ok(())
}
}
}
#[test]
fn test_evaluator_empty_contexts() {
let strategy = MockStrategy { should_fail: false };
let evaluator = AuthorizationEvaluator::new(strategy);
let result = evaluator.evaluate(&[]);
assert!(result.is_ok());
}
#[test]
fn test_evaluator_success() {
let strategy = MockStrategy { should_fail: false };
let evaluator = AuthorizationEvaluator::new(strategy);
let context = DefaultAuthorizationContext::default();
let result = evaluator.evaluate(&[context]);
assert!(result.is_ok());
}
#[test]
fn test_evaluator_failure() {
let strategy = MockStrategy { should_fail: true };
let evaluator = AuthorizationEvaluator::new(strategy);
let context = DefaultAuthorizationContext::default();
let result = evaluator.evaluate(&[context]);
assert!(result.is_err());
}
#[test]
fn test_evaluator_multiple_contexts_success() {
let strategy = MockStrategy { should_fail: false };
let evaluator = AuthorizationEvaluator::new(strategy);
let contexts = vec![
DefaultAuthorizationContext::default(),
DefaultAuthorizationContext::default(),
DefaultAuthorizationContext::default(),
];
let result = evaluator.evaluate(&contexts);
assert!(result.is_ok());
}
#[test]
fn test_evaluator_multiple_contexts_one_failure() {
let strategy = MockStrategy { should_fail: true };
let evaluator = AuthorizationEvaluator::new(strategy);
let contexts = vec![
DefaultAuthorizationContext::default(),
DefaultAuthorizationContext::default(),
];
let result = evaluator.evaluate(&contexts);
assert!(result.is_err());
}
#[test]
fn test_evaluator_get_strategy() {
let strategy = MockStrategy { should_fail: false };
let evaluator = AuthorizationEvaluator::new(strategy);
let _strategy_ref = evaluator.strategy();
}
}