From 450fb3fe192ea699fea87d004306cdb1c9da9949 Mon Sep 17 00:00:00 2001 From: wf-yamaday Date: Sun, 10 Aug 2025 00:58:13 +0900 Subject: [PATCH 1/4] feat: add update_policy method to Adapter and corresponding tests in async api --- .../asynchronous/adapter.py | 20 +++++++++++++ tests/asynchronous/test_adapter.py | 29 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/casbin_pymongo_adapter/asynchronous/adapter.py b/casbin_pymongo_adapter/asynchronous/adapter.py index 70a4aff..82c6f21 100644 --- a/casbin_pymongo_adapter/asynchronous/adapter.py +++ b/casbin_pymongo_adapter/asynchronous/adapter.py @@ -169,3 +169,23 @@ async def remove_filtered_policy(self, sec, ptype, field_index, *field_values): query["ptype"] = ptype results = await self._collection.delete_many(query) return results.deleted_count > 0 + + async def update_policy(self, sec, ptype, old_rule, new_rule): + """Update the old_rule with the new_rule in the database (storage). + + Args: + sec (str): section type + ptype (str): policy type + old_rule (list[str]): the old rule that needs to be modified + new_rule (list[str]): the new rule to replace the old rule + """ + filter_query = {} + for index, value in enumerate(old_rule): + filter_query[f"v{index}"] = value + + await self._collection.find_one_and_update( + filter_query, + {"$set": {f"v{index}": value for index, value in enumerate(new_rule)}}, + ) + + return None diff --git a/tests/asynchronous/test_adapter.py b/tests/asynchronous/test_adapter.py index 5a66104..7f8f3f4 100644 --- a/tests/asynchronous/test_adapter.py +++ b/tests/asynchronous/test_adapter.py @@ -338,3 +338,32 @@ async def test_filtered_policy_with_raw_query(self): self.assertFalse(e.enforce("bob", "data1", "write")) self.assertFalse(e.enforce("bob", "data2", "read")) self.assertTrue(e.enforce("bob", "data2", "write")) + + async def test_update_policy(self): + e = await get_enforcer() + example_p = ["mike", "cookie", "eat"] + + self.assertTrue(e.enforce("alice", "data1", "read")) + await e.update_policy(["alice", "data1", "read"], ["alice", "data1", "no_read"]) + self.assertFalse(e.enforce("alice", "data1", "read")) + + self.assertFalse(e.enforce("bob", "data1", "read")) + await e.add_policy(example_p) + await e.update_policy(example_p, ["bob", "data1", "read"]) + self.assertTrue(e.enforce("bob", "data1", "read")) + + self.assertFalse(e.enforce("bob", "data1", "write")) + await e.update_policy(["bob", "data1", "read"], ["bob", "data1", "write"]) + self.assertTrue(e.enforce("bob", "data1", "write")) + + self.assertTrue(e.enforce("bob", "data2", "write")) + await e.update_policy(["bob", "data2", "write"], ["bob", "data2", "read"]) + self.assertFalse(e.enforce("bob", "data2", "write")) + + self.assertTrue(e.enforce("bob", "data2", "read")) + await e.update_policy(["bob", "data2", "read"], ["carl", "data2", "write"]) + self.assertFalse(e.enforce("bob", "data2", "write")) + + self.assertTrue(e.enforce("carl", "data2", "write")) + await e.update_policy(["carl", "data2", "write"], ["carl", "data2", "no_write"]) + self.assertFalse(e.enforce("bob", "data2", "write")) From bed5d3ab738d8cccf92820b540049999ee80dbe9 Mon Sep 17 00:00:00 2001 From: wf-yamaday Date: Sun, 10 Aug 2025 01:00:41 +0900 Subject: [PATCH 2/4] feat: implement update_policy method in Adapter and add corresponding tests in sync api --- casbin_pymongo_adapter/adapter.py | 20 ++++++++++++++++++++ tests/test_adapter.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/casbin_pymongo_adapter/adapter.py b/casbin_pymongo_adapter/adapter.py index 9472b9d..3cb9c25 100644 --- a/casbin_pymongo_adapter/adapter.py +++ b/casbin_pymongo_adapter/adapter.py @@ -175,3 +175,23 @@ def remove_filtered_policy(self, sec, ptype, field_index, *field_values): query["ptype"] = ptype results = self._collection.delete_many(query) return results.deleted_count > 0 + + def update_policy(self, sec, ptype, old_rule, new_rule): + """Update the old_rule with the new_rule in the database (storage). + + Args: + sec (str): section type + ptype (str): policy type + old_rule (list[str]): the old rule that needs to be modified + new_rule (list[str]): the new rule to replace the old rule + """ + filter_query = {} + for index, value in enumerate(old_rule): + filter_query[f"v{index}"] = value + + self._collection.find_one_and_update( + filter_query, + {"$set": {f"v{index}": value for index, value in enumerate(new_rule)}}, + ) + + return None diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 0da6f8c..602ad70 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -343,6 +343,35 @@ async def test_filtered_policy_with_raw_query(self): self.assertFalse(e.enforce("bob", "data2", "read")) self.assertTrue(e.enforce("bob", "data2", "write")) + async def test_update_policy(self): + e = get_enforcer() + example_p = ["mike", "cookie", "eat"] + + self.assertTrue(e.enforce("alice", "data1", "read")) + e.update_policy(["alice", "data1", "read"], ["alice", "data1", "no_read"]) + self.assertFalse(e.enforce("alice", "data1", "read")) + + self.assertFalse(e.enforce("bob", "data1", "read")) + e.add_policy(example_p) + e.update_policy(example_p, ["bob", "data1", "read"]) + self.assertTrue(e.enforce("bob", "data1", "read")) + + self.assertFalse(e.enforce("bob", "data1", "write")) + e.update_policy(["bob", "data1", "read"], ["bob", "data1", "write"]) + self.assertTrue(e.enforce("bob", "data1", "write")) + + self.assertTrue(e.enforce("bob", "data2", "write")) + e.update_policy(["bob", "data2", "write"], ["bob", "data2", "read"]) + self.assertFalse(e.enforce("bob", "data2", "write")) + + self.assertTrue(e.enforce("bob", "data2", "read")) + e.update_policy(["bob", "data2", "read"], ["carl", "data2", "write"]) + self.assertFalse(e.enforce("bob", "data2", "write")) + + self.assertTrue(e.enforce("carl", "data2", "write")) + e.update_policy(["carl", "data2", "write"], ["carl", "data2", "no_write"]) + self.assertFalse(e.enforce("bob", "data2", "write")) + def test_str(self): """ test __str__ function From 868979f633a6a819b0d3e2c37d253f235747fb52 Mon Sep 17 00:00:00 2001 From: wf-yamaday Date: Sun, 10 Aug 2025 01:03:37 +0900 Subject: [PATCH 3/4] feat: add update_policies method to Adapter and corresponding tests in async api --- .../asynchronous/adapter.py | 12 ++++++++ tests/asynchronous/test_adapter.py | 30 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/casbin_pymongo_adapter/asynchronous/adapter.py b/casbin_pymongo_adapter/asynchronous/adapter.py index 82c6f21..b124397 100644 --- a/casbin_pymongo_adapter/asynchronous/adapter.py +++ b/casbin_pymongo_adapter/asynchronous/adapter.py @@ -189,3 +189,15 @@ async def update_policy(self, sec, ptype, old_rule, new_rule): ) return None + + async def update_policies(self, sec, ptype, old_rules, new_rules): + """Update the old_rule with the new_rule in the database (storage). + + Args: + sec (str): section type + ptype (str): policy type + old_rules (list[list[str]]): the old rules that needs to be modified + new_rules (list[list[str]]): the new rules to replace the old rule + """ + for old_rule, new_rule in zip(old_rules, new_rules): + await self.update_policy(sec, ptype, old_rule, new_rule) diff --git a/tests/asynchronous/test_adapter.py b/tests/asynchronous/test_adapter.py index 7f8f3f4..a86ab9b 100644 --- a/tests/asynchronous/test_adapter.py +++ b/tests/asynchronous/test_adapter.py @@ -367,3 +367,33 @@ async def test_update_policy(self): self.assertTrue(e.enforce("carl", "data2", "write")) await e.update_policy(["carl", "data2", "write"], ["carl", "data2", "no_write"]) self.assertFalse(e.enforce("bob", "data2", "write")) + + async def test_update_policies(self): + e = await get_enforcer() + + old_rule_0 = ["alice", "data1", "read"] + old_rule_1 = ["bob", "data2", "write"] + old_rule_2 = ["data2_admin", "data2", "read"] + old_rule_3 = ["data2_admin", "data2", "write"] + + new_rule_0 = ["alice", "data_test", "read"] + new_rule_1 = ["bob", "data_test", "write"] + new_rule_2 = ["data2_admin", "data_test", "read"] + new_rule_3 = ["data2_admin", "data_test", "write"] + + old_rules = [old_rule_0, old_rule_1, old_rule_2, old_rule_3] + new_rules = [new_rule_0, new_rule_1, new_rule_2, new_rule_3] + + await e.update_policies(old_rules, new_rules) + + self.assertFalse(e.enforce("alice", "data1", "read")) + self.assertTrue(e.enforce("alice", "data_test", "read")) + + self.assertFalse(e.enforce("bob", "data2", "write")) + self.assertTrue(e.enforce("bob", "data_test", "write")) + + self.assertFalse(e.enforce("data2_admin", "data2", "read")) + self.assertTrue(e.enforce("data2_admin", "data_test", "read")) + + self.assertFalse(e.enforce("data2_admin", "data2", "write")) + self.assertTrue(e.enforce("data2_admin", "data_test", "write")) From 74618807bc1acb34765f0f5187baae5915b75f7b Mon Sep 17 00:00:00 2001 From: wf-yamaday Date: Sun, 10 Aug 2025 01:04:21 +0900 Subject: [PATCH 4/4] feat: implement update_policies method in Adapter and add corresponding tests in sync api --- casbin_pymongo_adapter/adapter.py | 12 ++++++++++++ tests/test_adapter.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/casbin_pymongo_adapter/adapter.py b/casbin_pymongo_adapter/adapter.py index 3cb9c25..9cb4beb 100644 --- a/casbin_pymongo_adapter/adapter.py +++ b/casbin_pymongo_adapter/adapter.py @@ -195,3 +195,15 @@ def update_policy(self, sec, ptype, old_rule, new_rule): ) return None + + def update_policies(self, sec, ptype, old_rules, new_rules): + """Update the old_rule with the new_rule in the database (storage). + + Args: + sec (str): section type + ptype (str): policy type + old_rules (list[list[str]]): the old rules that needs to be modified + new_rules (list[list[str]]): the new rules to replace the old rule + """ + for old_rule, new_rule in zip(old_rules, new_rules): + self.update_policy(sec, ptype, old_rule, new_rule) diff --git a/tests/test_adapter.py b/tests/test_adapter.py index 602ad70..523ed5e 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -372,6 +372,36 @@ async def test_update_policy(self): e.update_policy(["carl", "data2", "write"], ["carl", "data2", "no_write"]) self.assertFalse(e.enforce("bob", "data2", "write")) + async def test_update_policies(self): + e = get_enforcer() + + old_rule_0 = ["alice", "data1", "read"] + old_rule_1 = ["bob", "data2", "write"] + old_rule_2 = ["data2_admin", "data2", "read"] + old_rule_3 = ["data2_admin", "data2", "write"] + + new_rule_0 = ["alice", "data_test", "read"] + new_rule_1 = ["bob", "data_test", "write"] + new_rule_2 = ["data2_admin", "data_test", "read"] + new_rule_3 = ["data2_admin", "data_test", "write"] + + old_rules = [old_rule_0, old_rule_1, old_rule_2, old_rule_3] + new_rules = [new_rule_0, new_rule_1, new_rule_2, new_rule_3] + + e.update_policies(old_rules, new_rules) + + self.assertFalse(e.enforce("alice", "data1", "read")) + self.assertTrue(e.enforce("alice", "data_test", "read")) + + self.assertFalse(e.enforce("bob", "data2", "write")) + self.assertTrue(e.enforce("bob", "data_test", "write")) + + self.assertFalse(e.enforce("data2_admin", "data2", "read")) + self.assertTrue(e.enforce("data2_admin", "data_test", "read")) + + self.assertFalse(e.enforce("data2_admin", "data2", "write")) + self.assertTrue(e.enforce("data2_admin", "data_test", "write")) + def test_str(self): """ test __str__ function