Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add adapter execution functions #3

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,4 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.idea/
65 changes: 65 additions & 0 deletions casbin_async_redis_adapter/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ async def _delete_policy_lines(self, ptype, rule):
else:
await self.client.lrem(self.key, 0, json.dumps(line.dict()))

async def _update_policy_line(self, ptype, old_rule, new_rule):
# TODO
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, @BustDot

Can you help with this?

I'm trying to migrate async-sqlalchemy-adapter to async-redis-adapter, but I'm missing some execution functions. I've added some, but this function is beyond my reach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wu-clan he may be very busy to help on this. Can you do it with the help of ChatGPT? Or @leeqvip can you help on this?

...

async def save_policy(self, model) -> bool:
"""Implement add Interface for casbin. Save the policy in mongodb

Expand Down Expand Up @@ -129,6 +133,21 @@ async def add_policy(self, sec, ptype, rule):
await self._save_policy_line(ptype, rule)
return True

async def add_policies(self, sec, ptype, rules):
"""Adds policy rules to redis

Args:
sec (str): Section name, 'g' or 'p'
ptype (str): Policy type, 'g', 'g2', 'p', etc.
rules (Iterable[CasbinRule]): Casbin rules will be added

Returns:
bool: True if succeed else False
"""
for rule in rules:
await self._save_policy_line(ptype, rule)
return True

async def remove_policy(self, sec, ptype, rule):
"""Remove policy rules in redis(rules duplicate will all be removed)

Expand All @@ -143,6 +162,21 @@ async def remove_policy(self, sec, ptype, rule):
await self._delete_policy_lines(ptype, rule)
return True

async def remove_policies(self, sec, ptype, rules):
"""Remove policy rules in redis(rules duplicate will all be removed)

Args:
sec (str): Section name, 'g' or 'p'
ptype (str): Policy type, 'g', 'g2', 'p', etc.
rules (Iterable[CasbinRule]): Casbin rules if it is exactly same as will be removed.

Returns:
bool: True if succeed else False
"""
for rule in rules:
await self._delete_policy_lines(ptype, rule)
return True

async def remove_filtered_policy(self, sec, ptype, field_index, *field_values):
"""Remove policy rules that match the filter from the storage.
This is part of the Auto-Save feature.
Expand Down Expand Up @@ -181,3 +215,34 @@ async def remove_filtered_policy(self, sec, ptype, field_index, *field_values):

await self.client.lrem(self.key, 0, "__CASBIN_DELETED__")
return True

async def update_policy(self, sec, ptype, old_rule, new_rule):
"""Update policy rule in redis.

Args:
sec (str): section type
ptype (str): policy type
old_rule (List[str]): old: the old rule that needs to be modified
new_rule (List[str]): new: the new rule to replace the old rule

Returns:
bool: True if succeed else False
"""
await self._update_policy_line(ptype, old_rule, new_rule)
return True

async def update_policies(self, sec, ptype, old_rules, new_rules):
"""Update policy rule in redis.

Args:
sec (str): section type
ptype (str): policy type
old_rules (List[List[str]]): old: the old rule that needs to be modified
new_rules (List[List[str]]): new: the new rule to replace the old rule

Returns:
bool: True if succeed else False
"""
for i in range(len(old_rules)):
await self.update_policy(sec, ptype, old_rules[i], new_rules[i])
return True
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from setuptools import setup, find_packages, __version__
from setuptools import setup, find_packages
from os import path

desc_file = "README.md"
Expand Down
58 changes: 58 additions & 0 deletions tests/test_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,33 @@ async def test_add_policy(self):
self.assertTrue(e.enforce("alice", "data2", "read"))
self.assertTrue(e.enforce("alice", "data2", "write"))

async def test_add_policies(self):
e = await get_enforcer()
adapter = e.get_adapter()
self.assertTrue(e.enforce("alice", "data1", "read"))
self.assertFalse(e.enforce("alice", "data1", "write"))
self.assertFalse(e.enforce("bob", "data2", "read"))
self.assertTrue(e.enforce("bob", "data2", "write"))
self.assertTrue(e.enforce("alice", "data2", "read"))
self.assertTrue(e.enforce("alice", "data2", "write"))

# test add_policy after insert rules
await adapter.add_policies(
sec="p",
ptype="p",
rules=(("alice", "data1", "write"), ("bob", "data2", "read")),
)

# reload policies from database
await e.load_policy()

self.assertTrue(e.enforce("alice", "data1", "read"))
self.assertTrue(e.enforce("alice", "data1", "write"))
self.assertTrue(e.enforce("bob", "data2", "read"))
self.assertTrue(e.enforce("bob", "data2", "write"))
self.assertTrue(e.enforce("alice", "data2", "read"))
self.assertTrue(e.enforce("alice", "data2", "write"))

async def test_remove_policy(self):
"""
test remove_policy
Expand Down Expand Up @@ -129,6 +156,37 @@ async def test_remove_policy(self):
self.assertFalse(e.enforce("alice", "data2", "write"))
self.assertTrue(result)

async def test_remove_policies(self):
"""
test remove_policy
"""
e = await get_enforcer()
adapter = e.get_adapter()
self.assertTrue(e.enforce("alice", "data1", "read"))
self.assertFalse(e.enforce("alice", "data1", "write"))
self.assertFalse(e.enforce("bob", "data2", "read"))
self.assertTrue(e.enforce("bob", "data2", "write"))
self.assertTrue(e.enforce("alice", "data2", "read"))
self.assertTrue(e.enforce("alice", "data2", "write"))

# test remove_policy after delete a role definition
result = await adapter.remove_policies(
sec="p",
ptype="p",
rules=(("data2_admin", "data2", "read"), ("data2_admin", "data2", "write")),
)

# reload policies from database
await e.load_policy()

self.assertTrue(e.enforce("alice", "data1", "read"))
self.assertFalse(e.enforce("alice", "data1", "write"))
self.assertFalse(e.enforce("bob", "data2", "read"))
self.assertTrue(e.enforce("bob", "data2", "write"))
self.assertFalse(e.enforce("alice", "data2", "read"))
self.assertFalse(e.enforce("alice", "data2", "write"))
self.assertTrue(result)

async def test_remove_policy_no_remove_when_rule_is_incomplete(self):
adapter = Adapter("localhost", 6379)
e = casbin.AsyncEnforcer(get_fixture("rbac_with_resources_roles.conf"), adapter)
Expand Down
Loading