use crate::authentication::strategy::AuthenticationStrategy;
use crate::authorization::context::authentication_context::AuthenticationContext;
use crate::AuthServiceResult;
pub struct AuthenticationEvaluator<S>
where
S: AuthenticationStrategy,
{
authentication_strategy: S,
}
impl<S> AuthenticationEvaluator<S>
where
S: AuthenticationStrategy,
{
pub fn new(authentication_strategy: S) -> Self {
Self {
authentication_strategy,
}
}
pub async fn evaluate(&self, context: &dyn AuthenticationContext) -> AuthServiceResult<()> {
self.authentication_strategy.authenticate(context).await
}
pub fn strategy(&self) -> &S {
&self.authentication_strategy
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::authentication::context::default_authentication_context::DefaultAuthenticationContext;
use crate::authentication::strategy::allow_all::AllowAllAuthenticationStrategy;
struct TestStrategy {
should_succeed: bool,
}
impl AuthenticationStrategy for TestStrategy {
fn authenticate<'a>(
&'a self,
_context: &'a dyn AuthenticationContext,
) -> crate::authentication::strategy::AuthenticationFuture<'a> {
Box::pin(async move {
if self.should_succeed {
Ok(())
} else {
Err(crate::AuthServiceError::new(
crate::AuthOperation::Authenticate,
crate::AuthFailureKind::Unauthenticated,
))
}
})
}
}
#[test]
fn test_evaluator_creation() {
let strategy = AllowAllAuthenticationStrategy;
let evaluator = AuthenticationEvaluator::new(strategy);
assert!(std::ptr::eq(&evaluator.authentication_strategy, evaluator.strategy()));
}
#[tokio::test]
async fn test_evaluate_success() {
let strategy = TestStrategy { should_succeed: true };
let evaluator = AuthenticationEvaluator::new(strategy);
let context = DefaultAuthenticationContext::new();
let result = evaluator.evaluate(&context).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_evaluate_failure() {
let strategy = TestStrategy { should_succeed: false };
let evaluator = AuthenticationEvaluator::new(strategy);
let context = DefaultAuthenticationContext::new();
let result = evaluator.evaluate(&context).await;
assert!(result.is_err());
let error = result.expect_err("authentication must fail");
assert_eq!(error.operation(), crate::AuthOperation::Authenticate);
assert_eq!(error.kind(), crate::AuthFailureKind::Unauthenticated);
}
#[tokio::test]
async fn test_evaluate_with_allow_all_strategy() {
let strategy = AllowAllAuthenticationStrategy;
let evaluator = AuthenticationEvaluator::new(strategy);
let context = DefaultAuthenticationContext::new();
let result = evaluator.evaluate(&context).await;
assert!(result.is_ok());
}
}