actix-casbin 1.1.0

An Actix actor for casbin
Documentation
use actix::prelude::*;
use casbin::prelude::*;
use casbin::Error as CasbinError;
use std::io::{Error, ErrorKind};
use std::sync::Arc;

#[cfg(feature = "runtime-tokio")]
use tokio::sync::RwLock;

#[cfg(feature = "runtime-async-std")]
use async_std::sync::RwLock;

pub enum CasbinCmd {
    Enforce(Vec<String>),
    AddPolicy(Vec<String>),
    AddPolicies(Vec<Vec<String>>),
    AddNamedPolicy(String, Vec<String>),
    AddNamedPolicies(String, Vec<Vec<String>>),
    AddGroupingPolicy(Vec<String>),
    AddGroupingPolicies(Vec<Vec<String>>),
    AddNamedGroupingPolicy(String, Vec<String>),
    AddNamedGroupingPolicies(String, Vec<Vec<String>>),
    RemovePolicy(Vec<String>),
    RemovePolicies(Vec<Vec<String>>),
    RemoveNamedPolicy(String, Vec<String>),
    RemoveNamedPolicies(String, Vec<Vec<String>>),
    RemoveGroupingPolicy(Vec<String>),
    RemoveGroupingPolicies(Vec<Vec<String>>),
    RemoveNamedGroupingPolicy(String, Vec<String>),
    RemoveNamedGroupingPolicies(String, Vec<Vec<String>>),
    RemoveFilteredNamedPolicy(String, usize, Vec<String>),
    RemoveFilteredNamedGroupingPolicy(String, usize, Vec<String>),
    AddRoleForUser(String, String, Option<String>),
    AddRolesForUser(String, Vec<String>, Option<String>),
    DeleteRoleForUser(String, String, Option<String>),
    DeleteRolesForUser(String, Option<String>),
    GetImplicitRolesForUser(String, Option<String>),
    GetImplicitPermissionsForUser(String, Option<String>),
}

pub enum CasbinResult {
    Enforce(bool),
    AddPolicy(bool),
    AddPolicies(bool),
    AddNamedPolicy(bool),
    AddNamedPolicies(bool),
    AddGroupingPolicy(bool),
    AddGroupingPolicies(bool),
    AddNamedGroupingPolicy(bool),
    AddNamedGroupingPolicies(bool),
    RemovePolicy(bool),
    RemovePolicies(bool),
    RemoveNamedPolicy(bool),
    RemoveNamedPolicies(bool),
    RemoveGroupingPolicy(bool),
    RemoveGroupingPolicies(bool),
    RemoveNamedGroupingPolicy(bool),
    RemoveNamedGroupingPolicies(bool),
    RemoveFilteredNamedPolicy(bool),
    RemoveFilteredNamedGroupingPolicy(bool),
    AddRoleForUser(bool),
    AddRolesForUser(bool),
    DeleteRoleForUser(bool),
    DeleteRolesForUser(bool),
    GetImplicitRolesForUser(Vec<String>),
    GetImplicitPermissionsForUser(Vec<Vec<String>>),
}

impl Message for CasbinCmd {
    type Result = Result<CasbinResult>;
}

pub struct CasbinActor<T: IEnforcer + 'static> {
    pub enforcer: Option<Arc<RwLock<T>>>,
}

impl<T: IEnforcer + 'static> CasbinActor<T> {
    pub async fn new<M: TryIntoModel, A: TryIntoAdapter>(
        m: M,
        a: A,
    ) -> Result<Addr<CasbinActor<T>>> {
        let enforcer = T::new(m, a).await?;
        Ok(Supervisor::start(|_| CasbinActor {
            enforcer: Some(Arc::new(RwLock::new(enforcer))),
        }))
    }

    pub fn set_enforcer(e: Arc<RwLock<T>>) -> Result<CasbinActor<T>> {
        Ok(CasbinActor { enforcer: Some(e) })
    }

    pub fn get_enforcer(&mut self) -> Option<Arc<RwLock<T>>> {
        self.enforcer.clone()
    }
}

impl<T: IEnforcer + 'static> Actor for CasbinActor<T> {
    type Context = Context<Self>;
}

impl<T: IEnforcer + 'static> Supervised for CasbinActor<T> {
    fn restarting(&mut self, _: &mut Self::Context) {
        self.enforcer.take();
    }
}

impl<T: IEnforcer + 'static> Handler<CasbinCmd> for CasbinActor<T> {
    type Result = ResponseActFuture<Self, Result<CasbinResult>>;

    fn handle(&mut self, msg: CasbinCmd, _: &mut Self::Context) -> Self::Result {
        let e = match &self.enforcer {
            Some(x) => x,
            None => {
                return Box::pin(actix::fut::err(CasbinError::IoError(Error::new(
                    ErrorKind::NotConnected,
                    "Enforcer dropped!",
                ))))
            }
        };
        let cloned_enforcer = Arc::clone(e);
        Box::pin(
            async move {
                let mut lock = cloned_enforcer.write().await;
                let result = match msg {
                    CasbinCmd::Enforce(policy) => lock.enforce(policy).map(CasbinResult::Enforce),
                    CasbinCmd::AddPolicy(policy) => {
                        lock.add_policy(policy).await.map(CasbinResult::AddPolicy)
                    }
                    CasbinCmd::AddPolicies(policy) => lock
                        .add_policies(policy)
                        .await
                        .map(CasbinResult::AddPolicies),
                    CasbinCmd::AddNamedPolicy(ptype, policy) => lock
                        .add_named_policy(&ptype, policy)
                        .await
                        .map(CasbinResult::AddNamedPolicy),
                    CasbinCmd::AddNamedPolicies(ptype, policy) => lock
                        .add_named_policies(&ptype, policy)
                        .await
                        .map(CasbinResult::AddNamedPolicies),
                    CasbinCmd::AddGroupingPolicy(policy) => lock
                        .add_grouping_policy(policy)
                        .await
                        .map(CasbinResult::AddGroupingPolicy),
                    CasbinCmd::AddGroupingPolicies(policy) => lock
                        .add_grouping_policies(policy)
                        .await
                        .map(CasbinResult::AddGroupingPolicies),
                    CasbinCmd::AddNamedGroupingPolicy(ptype, policy) => lock
                        .add_named_grouping_policy(&ptype, policy)
                        .await
                        .map(CasbinResult::AddNamedGroupingPolicy),
                    CasbinCmd::AddNamedGroupingPolicies(ptype, policy) => lock
                        .add_named_grouping_policies(&ptype, policy)
                        .await
                        .map(CasbinResult::AddNamedGroupingPolicies),
                    CasbinCmd::RemoveNamedPolicy(ptype, policy) => lock
                        .remove_named_policy(&ptype, policy)
                        .await
                        .map(CasbinResult::RemoveNamedPolicy),
                    CasbinCmd::RemoveNamedPolicies(ptype, policy) => lock
                        .remove_named_policies(&ptype, policy)
                        .await
                        .map(CasbinResult::RemoveNamedPolicies),
                    CasbinCmd::RemoveGroupingPolicy(policy) => lock
                        .remove_grouping_policy(policy)
                        .await
                        .map(CasbinResult::RemoveGroupingPolicy),
                    CasbinCmd::RemoveGroupingPolicies(policy) => lock
                        .remove_grouping_policies(policy)
                        .await
                        .map(CasbinResult::RemoveGroupingPolicies),
                    CasbinCmd::RemoveNamedGroupingPolicy(ptype, policy) => lock
                        .remove_named_grouping_policy(&ptype, policy)
                        .await
                        .map(CasbinResult::RemoveNamedGroupingPolicy),
                    CasbinCmd::RemoveNamedGroupingPolicies(ptype, policy) => lock
                        .remove_named_grouping_policies(&ptype, policy)
                        .await
                        .map(CasbinResult::RemoveNamedGroupingPolicies),
                    CasbinCmd::RemovePolicy(policy) => lock
                        .remove_policy(policy)
                        .await
                        .map(CasbinResult::RemovePolicy),
                    CasbinCmd::RemovePolicies(policy) => lock
                        .remove_policies(policy)
                        .await
                        .map(CasbinResult::RemovePolicies),
                    CasbinCmd::RemoveFilteredNamedPolicy(ptype, idx, policy) => lock
                        .remove_filtered_named_policy(&ptype, idx, policy)
                        .await
                        .map(CasbinResult::RemoveFilteredNamedPolicy),
                    CasbinCmd::RemoveFilteredNamedGroupingPolicy(ptype, idx, policy) => lock
                        .remove_filtered_named_grouping_policy(&ptype, idx, policy)
                        .await
                        .map(CasbinResult::RemoveFilteredNamedGroupingPolicy),
                    CasbinCmd::AddRoleForUser(user, roles, domain) => lock
                        .add_role_for_user(&user, &roles, domain.as_deref())
                        .await
                        .map(CasbinResult::AddRoleForUser),
                    CasbinCmd::AddRolesForUser(user, roles, domain) => lock
                        .add_roles_for_user(&user, roles, domain.as_deref())
                        .await
                        .map(CasbinResult::AddRolesForUser),
                    CasbinCmd::DeleteRoleForUser(user, roles, domain) => lock
                        .delete_role_for_user(&user, &roles, domain.as_deref())
                        .await
                        .map(CasbinResult::DeleteRoleForUser),
                    CasbinCmd::DeleteRolesForUser(user, domain) => lock
                        .delete_roles_for_user(&user, domain.as_deref())
                        .await
                        .map(CasbinResult::DeleteRolesForUser),
                    CasbinCmd::GetImplicitRolesForUser(name, domain) => {
                        Ok(CasbinResult::GetImplicitRolesForUser(
                            lock.get_implicit_roles_for_user(&name, domain.as_deref()),
                        ))
                    }
                    CasbinCmd::GetImplicitPermissionsForUser(name, domain) => {
                        Ok(CasbinResult::GetImplicitPermissionsForUser(
                            lock.get_implicit_permissions_for_user(&name, domain.as_deref()),
                        ))
                    }
                };
                drop(lock);
                result
            }
            .into_actor(self)
            .map(|res, _act, _ctx| res),
        )
    }
}