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}