use crate::ability::Ability;
use crate::rule::{Effect, Rule};
pub struct AbilityBuilder<A, S, C> {
claims: Option<C>,
rules: Vec<Rule<A, S, C>>,
}
impl<A, S, C> AbilityBuilder<A, S, C> {
pub(crate) fn new(claims: C) -> Self {
Self {
claims: Some(claims),
rules: Vec::new(),
}
}
pub fn claims(&self) -> &C {
self.claims.as_ref().expect("claims accessed after `build`")
}
pub fn can(&mut self, action: A, subject: S) -> &mut Self {
self.rules
.push(Rule::unconditional(Effect::Allow, action, subject));
self
}
pub fn cannot(&mut self, action: A, subject: S) -> &mut Self {
self.rules
.push(Rule::unconditional(Effect::Deny, action, subject));
self
}
pub fn can_if<R, F>(&mut self, action: A, subject: S, predicate: F) -> &mut Self
where
R: 'static,
F: Fn(&C, &R) -> bool + Send + Sync + 'static,
{
self.rules
.push(Rule::conditional(Effect::Allow, action, subject, predicate));
self
}
pub fn cannot_if<R, F>(&mut self, action: A, subject: S, predicate: F) -> &mut Self
where
R: 'static,
F: Fn(&C, &R) -> bool + Send + Sync + 'static,
{
self.rules
.push(Rule::conditional(Effect::Deny, action, subject, predicate));
self
}
pub fn build(&mut self) -> Ability<A, S, C> {
Ability::new(
self.claims.take().expect("`build` called more than once"),
std::mem::take(&mut self.rules),
)
}
}