actix_casbin/
casbin_actor.rs

1use actix::prelude::*;
2use casbin::prelude::*;
3use casbin::Error as CasbinError;
4use std::io::{Error, ErrorKind};
5use std::sync::Arc;
6
7#[cfg(feature = "runtime-tokio")]
8use tokio::sync::RwLock;
9
10#[cfg(feature = "runtime-async-std")]
11use async_std::sync::RwLock;
12
13pub enum CasbinCmd {
14    Enforce(Vec<String>),
15    AddPolicy(Vec<String>),
16    AddPolicies(Vec<Vec<String>>),
17    AddNamedPolicy(String, Vec<String>),
18    AddNamedPolicies(String, Vec<Vec<String>>),
19    AddGroupingPolicy(Vec<String>),
20    AddGroupingPolicies(Vec<Vec<String>>),
21    AddNamedGroupingPolicy(String, Vec<String>),
22    AddNamedGroupingPolicies(String, Vec<Vec<String>>),
23    RemovePolicy(Vec<String>),
24    RemovePolicies(Vec<Vec<String>>),
25    RemoveNamedPolicy(String, Vec<String>),
26    RemoveNamedPolicies(String, Vec<Vec<String>>),
27    RemoveGroupingPolicy(Vec<String>),
28    RemoveGroupingPolicies(Vec<Vec<String>>),
29    RemoveNamedGroupingPolicy(String, Vec<String>),
30    RemoveNamedGroupingPolicies(String, Vec<Vec<String>>),
31    RemoveFilteredNamedPolicy(String, usize, Vec<String>),
32    RemoveFilteredNamedGroupingPolicy(String, usize, Vec<String>),
33    AddRoleForUser(String, String, Option<String>),
34    AddRolesForUser(String, Vec<String>, Option<String>),
35    DeleteRoleForUser(String, String, Option<String>),
36    DeleteRolesForUser(String, Option<String>),
37    GetImplicitRolesForUser(String, Option<String>),
38    GetImplicitPermissionsForUser(String, Option<String>),
39}
40
41pub enum CasbinResult {
42    Enforce(bool),
43    AddPolicy(bool),
44    AddPolicies(bool),
45    AddNamedPolicy(bool),
46    AddNamedPolicies(bool),
47    AddGroupingPolicy(bool),
48    AddGroupingPolicies(bool),
49    AddNamedGroupingPolicy(bool),
50    AddNamedGroupingPolicies(bool),
51    RemovePolicy(bool),
52    RemovePolicies(bool),
53    RemoveNamedPolicy(bool),
54    RemoveNamedPolicies(bool),
55    RemoveGroupingPolicy(bool),
56    RemoveGroupingPolicies(bool),
57    RemoveNamedGroupingPolicy(bool),
58    RemoveNamedGroupingPolicies(bool),
59    RemoveFilteredNamedPolicy(bool),
60    RemoveFilteredNamedGroupingPolicy(bool),
61    AddRoleForUser(bool),
62    AddRolesForUser(bool),
63    DeleteRoleForUser(bool),
64    DeleteRolesForUser(bool),
65    GetImplicitRolesForUser(Vec<String>),
66    GetImplicitPermissionsForUser(Vec<Vec<String>>),
67}
68
69impl Message for CasbinCmd {
70    type Result = Result<CasbinResult>;
71}
72
73pub struct CasbinActor<T: IEnforcer + 'static> {
74    pub enforcer: Option<Arc<RwLock<T>>>,
75}
76
77impl<T: IEnforcer + 'static> CasbinActor<T> {
78    pub async fn new<M: TryIntoModel, A: TryIntoAdapter>(
79        m: M,
80        a: A,
81    ) -> Result<Addr<CasbinActor<T>>> {
82        let enforcer = T::new(m, a).await?;
83        Ok(Supervisor::start(|_| CasbinActor {
84            enforcer: Some(Arc::new(RwLock::new(enforcer))),
85        }))
86    }
87
88    pub fn set_enforcer(e: Arc<RwLock<T>>) -> Result<CasbinActor<T>> {
89        Ok(CasbinActor { enforcer: Some(e) })
90    }
91
92    pub fn get_enforcer(&mut self) -> Option<Arc<RwLock<T>>> {
93        self.enforcer.clone()
94    }
95}
96
97impl<T: IEnforcer + 'static> Actor for CasbinActor<T> {
98    type Context = Context<Self>;
99}
100
101impl<T: IEnforcer + 'static> Supervised for CasbinActor<T> {
102    fn restarting(&mut self, _: &mut Self::Context) {
103        self.enforcer.take();
104    }
105}
106
107impl<T: IEnforcer + 'static> Handler<CasbinCmd> for CasbinActor<T> {
108    type Result = ResponseActFuture<Self, Result<CasbinResult>>;
109
110    fn handle(&mut self, msg: CasbinCmd, _: &mut Self::Context) -> Self::Result {
111        let e = match &self.enforcer {
112            Some(x) => x,
113            None => {
114                return Box::pin(actix::fut::err(CasbinError::IoError(Error::new(
115                    ErrorKind::NotConnected,
116                    "Enforcer dropped!",
117                ))))
118            }
119        };
120        let cloned_enforcer = Arc::clone(e);
121        Box::pin(
122            async move {
123                let mut lock = cloned_enforcer.write().await;
124                let result = match msg {
125                    CasbinCmd::Enforce(policy) => lock.enforce(policy).map(CasbinResult::Enforce),
126                    CasbinCmd::AddPolicy(policy) => {
127                        lock.add_policy(policy).await.map(CasbinResult::AddPolicy)
128                    }
129                    CasbinCmd::AddPolicies(policy) => lock
130                        .add_policies(policy)
131                        .await
132                        .map(CasbinResult::AddPolicies),
133                    CasbinCmd::AddNamedPolicy(ptype, policy) => lock
134                        .add_named_policy(&ptype, policy)
135                        .await
136                        .map(CasbinResult::AddNamedPolicy),
137                    CasbinCmd::AddNamedPolicies(ptype, policy) => lock
138                        .add_named_policies(&ptype, policy)
139                        .await
140                        .map(CasbinResult::AddNamedPolicies),
141                    CasbinCmd::AddGroupingPolicy(policy) => lock
142                        .add_grouping_policy(policy)
143                        .await
144                        .map(CasbinResult::AddGroupingPolicy),
145                    CasbinCmd::AddGroupingPolicies(policy) => lock
146                        .add_grouping_policies(policy)
147                        .await
148                        .map(CasbinResult::AddGroupingPolicies),
149                    CasbinCmd::AddNamedGroupingPolicy(ptype, policy) => lock
150                        .add_named_grouping_policy(&ptype, policy)
151                        .await
152                        .map(CasbinResult::AddNamedGroupingPolicy),
153                    CasbinCmd::AddNamedGroupingPolicies(ptype, policy) => lock
154                        .add_named_grouping_policies(&ptype, policy)
155                        .await
156                        .map(CasbinResult::AddNamedGroupingPolicies),
157                    CasbinCmd::RemoveNamedPolicy(ptype, policy) => lock
158                        .remove_named_policy(&ptype, policy)
159                        .await
160                        .map(CasbinResult::RemoveNamedPolicy),
161                    CasbinCmd::RemoveNamedPolicies(ptype, policy) => lock
162                        .remove_named_policies(&ptype, policy)
163                        .await
164                        .map(CasbinResult::RemoveNamedPolicies),
165                    CasbinCmd::RemoveGroupingPolicy(policy) => lock
166                        .remove_grouping_policy(policy)
167                        .await
168                        .map(CasbinResult::RemoveGroupingPolicy),
169                    CasbinCmd::RemoveGroupingPolicies(policy) => lock
170                        .remove_grouping_policies(policy)
171                        .await
172                        .map(CasbinResult::RemoveGroupingPolicies),
173                    CasbinCmd::RemoveNamedGroupingPolicy(ptype, policy) => lock
174                        .remove_named_grouping_policy(&ptype, policy)
175                        .await
176                        .map(CasbinResult::RemoveNamedGroupingPolicy),
177                    CasbinCmd::RemoveNamedGroupingPolicies(ptype, policy) => lock
178                        .remove_named_grouping_policies(&ptype, policy)
179                        .await
180                        .map(CasbinResult::RemoveNamedGroupingPolicies),
181                    CasbinCmd::RemovePolicy(policy) => lock
182                        .remove_policy(policy)
183                        .await
184                        .map(CasbinResult::RemovePolicy),
185                    CasbinCmd::RemovePolicies(policy) => lock
186                        .remove_policies(policy)
187                        .await
188                        .map(CasbinResult::RemovePolicies),
189                    CasbinCmd::RemoveFilteredNamedPolicy(ptype, idx, policy) => lock
190                        .remove_filtered_named_policy(&ptype, idx, policy)
191                        .await
192                        .map(CasbinResult::RemoveFilteredNamedPolicy),
193                    CasbinCmd::RemoveFilteredNamedGroupingPolicy(ptype, idx, policy) => lock
194                        .remove_filtered_named_grouping_policy(&ptype, idx, policy)
195                        .await
196                        .map(CasbinResult::RemoveFilteredNamedGroupingPolicy),
197                    CasbinCmd::AddRoleForUser(user, roles, domain) => lock
198                        .add_role_for_user(&user, &roles, domain.as_deref())
199                        .await
200                        .map(CasbinResult::AddRoleForUser),
201                    CasbinCmd::AddRolesForUser(user, roles, domain) => lock
202                        .add_roles_for_user(&user, roles, domain.as_deref())
203                        .await
204                        .map(CasbinResult::AddRolesForUser),
205                    CasbinCmd::DeleteRoleForUser(user, roles, domain) => lock
206                        .delete_role_for_user(&user, &roles, domain.as_deref())
207                        .await
208                        .map(CasbinResult::DeleteRoleForUser),
209                    CasbinCmd::DeleteRolesForUser(user, domain) => lock
210                        .delete_roles_for_user(&user, domain.as_deref())
211                        .await
212                        .map(CasbinResult::DeleteRolesForUser),
213                    CasbinCmd::GetImplicitRolesForUser(name, domain) => {
214                        Ok(CasbinResult::GetImplicitRolesForUser(
215                            lock.get_implicit_roles_for_user(&name, domain.as_deref()),
216                        ))
217                    }
218                    CasbinCmd::GetImplicitPermissionsForUser(name, domain) => {
219                        Ok(CasbinResult::GetImplicitPermissionsForUser(
220                            lock.get_implicit_permissions_for_user(&name, domain.as_deref()),
221                        ))
222                    }
223                };
224                drop(lock);
225                result
226            }
227            .into_actor(self)
228            .map(|res, _act, _ctx| res),
229        )
230    }
231}