Skip to content

Commit e16dfb3

Browse files
timabilovtimabilov
andauthored
feat: get implicit permissions filter policies domain by matching function (#226)
Signed-off-by: timabilov <timabilov33@gmail.com> Co-authored-by: timabilov <timabilov33@gmail.com>
1 parent 9489048 commit e16dfb3

4 files changed

Lines changed: 99 additions & 29 deletions

File tree

casbin/enforcer.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from functools import partial
2+
13
from casbin.management_enforcer import ManagementEnforcer
24
from casbin.util import join_slice, array_remove_duplicates, set_subtract
35

@@ -150,20 +152,26 @@ def get_implicit_permissions_for_user(
150152
get_permissions_for_user("alice") can only get: [["alice", "data2", "read"]].
151153
But get_implicit_permissions_for_user("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
152154
153-
Inherited roles can be matched by domain.
155+
For given domain policies are filtered by corresponding domain matching function of DomainManager
156+
Inherited roles can be matched by domain. For domain neutral policies set:
157+
filter_policy_dom = False
158+
154159
filter_policy_dom: bool - For given *domain*, policies will be filtered by domain as well. Default = True
155160
"""
156161
roles = self.get_implicit_roles_for_user(user, domain)
157162

158163
roles.insert(0, user)
159164

160165
res = []
161-
for role in roles:
162-
if domain and filter_policy_dom:
163-
permissions = self.get_permissions_for_user_in_domain(role, domain)
164-
else:
165-
permissions = self.get_permissions_for_user(role)
166166

167+
# policy domain should be matched by domain_match_fn of DomainManager
168+
if domain:
169+
domain = partial(self.get_role_manager().domain_matching_func, domain)
170+
171+
for role in roles:
172+
permissions = self.get_permissions_for_user_in_domain(
173+
role, domain if filter_policy_dom else ""
174+
)
167175
res.extend(permissions)
168176

169177
return res

examples/rbac_with_domain_and_policy_pattern_policy.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
p, admin, domain.*, data1, read
2+
p, user, domain.*, data3, read
23
p, user, domain.1, data2, read
34
p, user, domain.1, data2, write
45

tests/test_management_api.py

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ def test_get_policy_matching_function(self):
111111
e.get_policy(),
112112
[
113113
["admin", "domain.*", "data1", "read"],
114+
["user", "domain.*", "data3", "read"],
114115
["user", "domain.1", "data2", "read"],
115116
["user", "domain.1", "data2", "write"],
116117
],
@@ -127,21 +128,26 @@ def test_get_policy_matching_function(self):
127128
[["alice", "user", "*"]],
128129
)
129130

130-
# first p record matches to domain.3
131+
# first and second p record matches to domain.3
131132
self.assertEqual(
132133
e.get_filtered_policy(1, partial(km2_fn, "domain.3")),
133-
[["admin", "domain.*", "data1", "read"]],
134-
)
135-
136-
# first and second p record should be matched to (.., domain.1, read)
137-
self.assertEqual(
138-
e.get_filtered_policy(1, partial(km2_fn, "domain.1"), "", "read"),
139134
[
140135
["admin", "domain.*", "data1", "read"],
141-
["user", "domain.1", "data2", "read"],
136+
["user", "domain.*", "data3", "read"],
142137
],
143138
)
144139

140+
self.assertEqual(
141+
sorted(e.get_filtered_policy(1, partial(km2_fn, "domain.1"), "", "read")),
142+
sorted(
143+
[
144+
["admin", "domain.*", "data1", "read"],
145+
["user", "domain.1", "data2", "read"],
146+
["user", "domain.*", "data3", "read"],
147+
]
148+
),
149+
)
150+
145151
def test_get_policy_multiple_matching_functions(self):
146152
e = self.get_enforcer(
147153
get_examples("rbac_with_domain_and_policy_pattern_model.conf"),
@@ -152,6 +158,7 @@ def test_get_policy_multiple_matching_functions(self):
152158
e.get_policy(),
153159
[
154160
["admin", "domain.*", "data1", "read"],
161+
["user", "domain.*", "data3", "read"],
155162
["user", "domain.1", "data2", "read"],
156163
["user", "domain.1", "data2", "write"],
157164
],
@@ -160,30 +167,47 @@ def test_get_policy_multiple_matching_functions(self):
160167
km2_fn = casbin.util.key_match2_func
161168

162169
self.assertEqual(
163-
e.get_filtered_policy(
164-
1, partial(km2_fn, "domain.2"), lambda a: "data" in a
170+
sorted(
171+
e.get_filtered_policy(
172+
1, partial(km2_fn, "domain.2"), lambda a: "data" in a
173+
)
174+
),
175+
sorted(
176+
[
177+
["admin", "domain.*", "data1", "read"],
178+
["user", "domain.*", "data3", "read"],
179+
]
165180
),
166-
[["admin", "domain.*", "data1", "read"]],
167181
)
168182

169183
self.assertEqual(
170-
e.get_filtered_policy(
171-
1, partial(km2_fn, "domain.1"), lambda a: "data" in a, "read"
184+
sorted(
185+
e.get_filtered_policy(
186+
1, partial(km2_fn, "domain.1"), lambda a: "data" in a, "read"
187+
)
188+
),
189+
sorted(
190+
[
191+
["admin", "domain.*", "data1", "read"],
192+
["user", "domain.1", "data2", "read"],
193+
["user", "domain.*", "data3", "read"],
194+
]
172195
),
173-
[
174-
["admin", "domain.*", "data1", "read"],
175-
["user", "domain.1", "data2", "read"],
176-
],
177196
)
178197

179198
self.assertEqual(
180-
e.get_filtered_policy(
181-
1, partial(km2_fn, "domain.1"), "", "reading".startswith
199+
sorted(
200+
e.get_filtered_policy(
201+
1, partial(km2_fn, "domain.1"), "", "reading".startswith
202+
)
203+
),
204+
sorted(
205+
[
206+
["admin", "domain.*", "data1", "read"],
207+
["user", "domain.1", "data2", "read"],
208+
["user", "domain.*", "data3", "read"],
209+
]
182210
),
183-
[
184-
["admin", "domain.*", "data1", "read"],
185-
["user", "domain.1", "data2", "read"],
186-
],
187211
)
188212

189213
def test_modify_policy_api(self):

tests/test_rbac_api.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,43 @@ def test_enforce_implicit_permissions_api_with_domain(self):
233233
)
234234
self.assertEqual(e.get_implicit_permissions_for_user("bob", "domain1"), [])
235235

236+
def test_enforce_implicit_permissions_api_with_domain_matching_function(self):
237+
238+
e = self.get_enforcer(
239+
get_examples("rbac_with_domain_and_policy_pattern_model.conf"),
240+
get_examples("rbac_with_domain_and_policy_pattern_policy.csv"),
241+
)
242+
243+
e.get_role_manager().add_domain_matching_func(casbin.util.key_match2_func)
244+
245+
self.assertEqual(
246+
e.get_implicit_permissions_for_user("alice", "domain.3"),
247+
[["user", "domain.*", "data3", "read"]],
248+
)
249+
250+
self.assertEqual(
251+
e.get_implicit_permissions_for_user("alice", "domain.1"),
252+
[
253+
["user", "domain.*", "data3", "read"],
254+
["user", "domain.1", "data2", "read"],
255+
["user", "domain.1", "data2", "write"],
256+
],
257+
)
258+
259+
self.assertEqual(
260+
e.get_implicit_permissions_for_user("bob", "domain.3"),
261+
[["admin", "domain.*", "data1", "read"]],
262+
)
263+
264+
self.assertEqual(
265+
e.get_implicit_permissions_for_user("bob", "domain.2"),
266+
[],
267+
)
268+
269+
self.assertEqual(
270+
sorted(e.get_implicit_permissions_for_user("bob", "domain.1")), []
271+
)
272+
236273
def test_enforce_implicit_permissions_api_with_domain_ignore_domain_policies_filter(
237274
self,
238275
):

0 commit comments

Comments
 (0)