daisylb / bridgekeeper

Django permissions, but with QuerySets
https://bridgekeeper.leigh.party/
MIT License
41 stars 14 forks source link

Added checks for EMPTY and UNIVERSAL in query function #26

Open johannesd opened 2 years ago

johannesd commented 2 years ago

I'm not sure if blanket rules are meant to be nested in Rs, but I think it would definitely be useful:

class MyModel(Model):
    pass

class MyOtherModel(Model):
    parent = models.ForeignKey(MyModel)

@blanket_rule
def is_admin(user):
    # something

perms['myapp.view_mymodel'] = is_admin # and more complex stuff
perms['myapp.view_myothermodel'] = R(parent=perms['myapp.view_mymodel'])

This is a minimal example where I just want to set permissions of MyOtherModel based on the existing permissions of the referenced model MyModel.

This currently leads to

  File "[...]/rest_framework/views.py", line 332, in check_permissions
    if not permission.has_permission(request, self):
  File "[...]/bridgekeeper/rest_framework.py", line 161, in has_permission
    return self.get_permission(request, view).is_possible_for(request.user)
  File "[...]/bridgekeeper/rules.py", line 86, in is_possible_for
    return self.query(user) is not EMPTY
  File "[...]/bridgekeeper/rules.py", line 367, in query
    accumulated_q &= add_prefix(child_q_obj, key)
  File "[...]/bridgekeeper/rules.py", line 535, in add_prefix
    for child in q_obj.children
AttributeError: 'Sentinel' object has no attribute 'children'

I fixed this by added checks for EMPTY and UNIVERSAL in query function and modify query appropriately.

Is this correct?