use std::iter::FromIterator;
use thiserror::Error;
use crate::Scope;
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Error)]
#[error("insufficient scope")]
pub struct InsufficientScope;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ScopePolicy {
alternatives: Vec<Scope>,
}
impl ScopePolicy {
#[inline]
pub fn deny_all() -> Self {
Self {
alternatives: Vec::new(),
}
}
#[inline]
pub fn allow_all() -> Self {
Self {
alternatives: vec![Scope::empty()],
}
}
#[inline]
pub fn allow_one(scopes: Scope) -> Self {
Self {
alternatives: vec![scopes],
}
}
#[inline]
pub fn or_allow(self, scopes: Scope) -> Self {
let mut s = self;
s.alternatives.push(scopes);
s
}
#[inline]
pub fn allow(&mut self, scopes: Scope) {
self.alternatives.push(scopes);
}
}
impl aliri_traits::Policy for ScopePolicy {
type Request = Scope;
type Denial = InsufficientScope;
fn evaluate(&self, held: &Self::Request) -> Result<(), Self::Denial> {
let allowed = self.alternatives.iter().any(|req| held.contains_all(req));
if allowed {
Ok(())
} else {
Err(InsufficientScope)
}
}
}
impl IntoIterator for ScopePolicy {
type Item = Scope;
type IntoIter = <Vec<Scope> as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.alternatives.into_iter()
}
}
#[derive(Clone, Debug)]
pub struct Iter<'a> {
iter: std::slice::Iter<'a, Scope>,
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a Scope;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<'a> IntoIterator for &'a ScopePolicy {
type Item = &'a Scope;
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter {
iter: self.alternatives.iter(),
}
}
}
impl Extend<Scope> for ScopePolicy {
#[inline]
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = Scope>,
{
self.alternatives.extend(iter)
}
}
impl FromIterator<Scope> for ScopePolicy {
#[inline]
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Scope>,
{
let mut set = Self::deny_all();
set.extend(iter);
set
}
}