1use crate::store::CurrentUser;
4use sova_core::{Error, Result};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum Ability {
9 View,
10 Create,
11 Update,
12 Delete,
13}
14
15pub trait Policy<R>: Send + Sync {
17 fn view(&self, user: &CurrentUser, r: &R) -> bool;
18 fn create(&self, _user: &CurrentUser) -> bool {
19 true
20 }
21 fn update(&self, user: &CurrentUser, r: &R) -> bool;
22 fn delete(&self, user: &CurrentUser, r: &R) -> bool;
23}
24
25pub(crate) fn can_ability<P, R>(user: &CurrentUser, ability: Ability, resource: &R) -> bool
27where
28 P: Policy<R> + Default,
29{
30 let policy = P::default();
31 match ability {
32 Ability::View => policy.view(user, resource),
33 Ability::Create => policy.create(user),
34 Ability::Update => policy.update(user, resource),
35 Ability::Delete => policy.delete(user, resource),
36 }
37}
38
39pub(crate) fn authorize_ability<P, R>(
40 user: &CurrentUser,
41 ability: Ability,
42 resource: &R,
43) -> Result<()>
44where
45 P: Policy<R> + Default,
46{
47 if can_ability::<P, R>(user, ability, resource) {
48 Ok(())
49 } else {
50 Err(Error::Forbidden)
51 }
52}