From 37892e1b1578db42543ec81e0120ebda3492afc7 Mon Sep 17 00:00:00 2001 From: Nekotoxin Date: Sat, 30 Apr 2022 12:02:50 +0800 Subject: [PATCH] fix: allow permissions management to use additional p-types (#256) * fix: allow permissions management to use additional p-types * code reuse and change a function name --- casbin/enforcer.py | 30 +++++++++++++++++-- casbin/synced_enforcer.py | 22 ++++++++++++++ examples/rbac_with_multiple_policy_model.conf | 16 ++++++++++ examples/rbac_with_multiple_policy_policy.csv | 8 +++++ tests/test_rbac_api.py | 25 ++++++++++++++++ 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 examples/rbac_with_multiple_policy_model.conf create mode 100644 examples/rbac_with_multiple_policy_policy.csv diff --git a/casbin/enforcer.py b/casbin/enforcer.py index d1aabca6..aab27333 100644 --- a/casbin/enforcer.py +++ b/casbin/enforcer.py @@ -164,6 +164,26 @@ def get_implicit_permissions_for_user(self, user, domain="", filter_policy_dom=T get_permissions_for_user("alice") can only get: [["alice", "data2", "read"]]. But get_implicit_permissions_for_user("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. + For given domain policies are filtered by corresponding domain matching function of DomainManager + Inherited roles can be matched by domain. For domain neutral policies set: + filter_policy_dom = False + + filter_policy_dom: bool - For given *domain*, policies will be filtered by domain as well. Default = True + """ + return self.get_named_implicit_permissions_for_user("p", user, domain, filter_policy_dom) + + def get_named_implicit_permissions_for_user(self, ptype, user, domain="", filter_policy_dom=True): + """ + gets implicit permissions for a user or role by named policy. + Compared to get_permissions_for_user(), this function retrieves permissions for inherited roles. + For example: + p, admin, data1, read + p, alice, data2, read + g, alice, admin + + get_permissions_for_user("alice") can only get: [["alice", "data2", "read"]]. + But get_implicit_permissions_for_user("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. + For given domain policies are filtered by corresponding domain matching function of DomainManager Inherited roles can be matched by domain. For domain neutral policies set: filter_policy_dom = False @@ -182,7 +202,9 @@ def get_implicit_permissions_for_user(self, user, domain="", filter_policy_dom=T domain = partial(domain_matching_func, domain) for role in roles: - permissions = self.get_permissions_for_user_in_domain(role, domain if filter_policy_dom else "") + permissions = self.get_named_permissions_for_user_in_domain( + ptype, role, domain if filter_policy_dom else "" + ) res.extend(permissions) return res @@ -235,4 +257,8 @@ def delete_roles_for_user_in_domain(self, user, role, domain): def get_permissions_for_user_in_domain(self, user, domain): """gets permissions for a user or role inside domain.""" - return self.get_filtered_policy(0, user, domain) + return self.get_named_permissions_for_user_in_domain("p", user, domain) + + def get_named_permissions_for_user_in_domain(self, ptype, user, domain): + """gets permissions for a user or role with named policy inside domain.""" + return self.get_filtered_named_policy(ptype, 0, user, domain) diff --git a/casbin/synced_enforcer.py b/casbin/synced_enforcer.py index 48a758c6..8c063d6e 100644 --- a/casbin/synced_enforcer.py +++ b/casbin/synced_enforcer.py @@ -464,6 +464,23 @@ def get_implicit_permissions_for_user(self, user, *domain, filter_policy_dom=Tru with self._rl: return self._e.get_implicit_permissions_for_user(user, *domain, filter_policy_dom=filter_policy_dom) + def get_named_implicit_permissions_for_user(self, ptype, user, *domain, filter_policy_dom=True): + """ + gets implicit permissions for a user or role by named policy. + Compared to get_permissions_for_user(), this function retrieves permissions for inherited roles. + For example: + p, admin, data1, read + p, alice, data2, read + g, alice, admin + + get_permissions_for_user("alice") can only get: [["alice", "data2", "read"]]. + But get_implicit_permissions_for_user("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. + """ + with self._rl: + return self._e.get_named_implicit_permissions_for_user( + ptype, user, *domain, filter_policy_dom=filter_policy_dom + ) + def get_implicit_users_for_permission(self, *permission): """ gets implicit users for a permission. @@ -505,6 +522,11 @@ def get_permissions_for_user_in_domain(self, user, domain): with self._rl: return self._e.get_permissions_for_user_in_domain(user, domain) + def get_named_permissions_for_user_in_domain(self, ptype, user, domain): + """gets permissions for a user or role by named policy inside domain.""" + with self._rl: + return self._e.get_named_permissions_for_user_in_domain(ptype, user, domain) + def enable_auto_build_role_links(self, auto_build_role_links): """controls whether to rebuild the role inheritance relations when a role is added or deleted.""" with self._wl: diff --git a/examples/rbac_with_multiple_policy_model.conf b/examples/rbac_with_multiple_policy_model.conf new file mode 100644 index 00000000..6a7fb091 --- /dev/null +++ b/examples/rbac_with_multiple_policy_model.conf @@ -0,0 +1,16 @@ +[request_definition] +r = user, thing, action + +[policy_definition] +p = role, thing, action +p2 = role, action + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = g(r.user, p.role) && r.thing == p.thing && r.action == p.action +m2 = g(r.user, p2.role) && r.action == p.action + +[role_definition] +g = _,_ \ No newline at end of file diff --git a/examples/rbac_with_multiple_policy_policy.csv b/examples/rbac_with_multiple_policy_policy.csv new file mode 100644 index 00000000..18e9cbc2 --- /dev/null +++ b/examples/rbac_with_multiple_policy_policy.csv @@ -0,0 +1,8 @@ +p, user, /data, GET +p, admin, /data, POST + +p2, user, view +p2, admin, create + +g, admin, user +g, alice, admin \ No newline at end of file diff --git a/tests/test_rbac_api.py b/tests/test_rbac_api.py index 2f5d3bc7..50fbd20b 100644 --- a/tests/test_rbac_api.py +++ b/tests/test_rbac_api.py @@ -204,6 +204,31 @@ def test_enforce_implicit_permissions_api(self): sorted([["bob", "data2", "write"]]), ) + def test_enforce_implicit_permissions_api_with_multiple_policy(self): + e = self.get_enforcer( + get_examples("rbac_with_multiple_policy_model.conf"), + get_examples("rbac_with_multiple_policy_policy.csv"), + ) + + self.assertEqual( + sorted(e.get_named_implicit_permissions_for_user("p", "alice")), + sorted( + [ + ["user", "/data", "GET"], + ["admin", "/data", "POST"], + ] + ), + ) + self.assertEqual( + sorted(e.get_named_implicit_permissions_for_user("p2", "alice")), + sorted( + [ + ["user", "view"], + ["admin", "create"], + ] + ), + ) + def test_enforce_implicit_permissions_api_with_domain(self): e = self.get_enforcer( get_examples("rbac_with_domains_model.conf"),