drf-access-policy
drf-access-policy copied to clipboard
[Question] Dealing with unnecessary repetition of DB hits...
So, I have a Membership model, with 3 roles - viewer, member, manager I created a group for all users that aren't django staff or admins to filter out some processing My problem is I have to repeat the same calls to get the membership instance to check for the permission. (A member can be a part of multiple schedules)
class ShiftAccessPolicy(BaseAccessPolicy):
statements = [
{
"action": "*",
"principal": ["admin", "staff"],
"effect": "allow",
},
{
"action": ["list", "retrieve"],
"principal": "group:auth_user",
"effect": "allow",
"condition": "is_schedule_member"
},
{
"action": "create",
"principal": "group:auth_user",
"effect": "allow",
"condition_expression": "is_not_viewer_only"
},
{
"action": [ "archive"],
"principal": "group:auth_user",
"effect": "allow",
"condition_expression": "is_schedule_manager"
}
]
def is_schedule_manager(self, request, view, action):
membership = request.user.member.membership_set.filter(schedule__id=view.kwargs.get('schedule_pk'))
if membership.exists():
membership = membership[0]
return Roles.SCHEDULE_MANAGER == membership.role
else:
return False
def is_schedule_member(self, request, view, action):
membership = request.user.member.membership_set.filter(schedule__id=view.kwargs.get('schedule_pk'))
return membership.exists()
def is_viewer_only(self, request, view, action):
membership = request.user.member.membership_set.filter(schedule__id=view.kwargs.get('schedule_pk'))
if membership.exists():
membership = membership[0]
return Roles.VIEWER != membership.role
else:
return False
As can be seen - each time I have to get the membership... 3 questions came into mind:
- Is there a better way to use the access policy module that I'm missing?
- Should we implement a "shared" instance for the types of cases?
- in the case that I would use the same condition (lets say is_schedule_member would have been called multiple times) shouldn't we cache the result from the first time it was called?
I have never faced this issue, but maybe there could be a method on the policy class called get_membership()?
You could implement caching there, with the key based on the combination of user id and schedule id.
I can't think of an approach specific to this package.