use std::{convert::Infallible, error::Error, future::Future, sync::Arc};
use futures_util::future::{Ready, ok};
use crate::{access::rule::AccessRule, core::HandlerInput};
#[cfg(test)]
mod tests;
pub trait AccessPolicy: Send {
type Error: Error + Send;
type Future: Future<Output = Result<bool, Self::Error>> + Send;
fn is_granted(&self, input: HandlerInput) -> Self::Future;
}
#[derive(Default, Clone)]
pub struct InMemoryAccessPolicy {
rules: Arc<Vec<AccessRule>>,
}
impl<T> From<T> for InMemoryAccessPolicy
where
T: IntoIterator<Item = AccessRule>,
{
fn from(rules: T) -> Self {
Self {
rules: Arc::new(rules.into_iter().collect()),
}
}
}
impl AccessPolicy for InMemoryAccessPolicy {
type Error = Infallible;
type Future = Ready<Result<bool, Self::Error>>;
fn is_granted(&self, input: HandlerInput) -> Self::Future {
let mut result = false;
let rules = Arc::clone(&self.rules);
for rule in rules.iter() {
if rule.accepts(&input.update) {
result = rule.is_granted();
log::info!("Found rule: {rule:?} (is_granted={result:?})");
break;
}
}
ok(result)
}
}