Writing Rules and Permissions¶
In Bridgekeeper, a rule is something that is given a user and a resource, and either allows or blocks access to the resource. Rules are instances of the Rule
class (or rather, subclasses of that class), and can be combined together into composite rules.
A Bridgekeeper permission consists of a name, usually conforming to Django permission name conventions e.g. shrubberies.change_shrubbery
, and a rule. Permissions are created by assigning a rule instance to a name in bridgekeeper.perms
, which acts like a dictionary:
from bridgekeeper.rules import Attribute, is_staff
from bridgekeeper import perms
perms['shrubberies.change_shrubbery'] = is_staff
The rules
module provides a range of pre-made rule instances as well as rule classes you can instantiate, as shown above. You can also combine rules using the &
(and), |
(or), and ~
(not) operators:
perms['shrubberies.view_shrubbery'] = is_staff | Attribute(
'company', lambda user: user.company)
Finally, if none of the built-in rules do what you want, you can subclass Rule
yourself and write your own.
Blanket Rules¶
We introduced what blanket rules are, as well as how to write a custom one, in the Blanket rules section of the tutorial. There, we defined one rule for each role, but if we had more than two roles that might get a bit repetitive.
If you need your blanket rules to take arguments, the easiest way is to write a function that returns a rule, like so:
from bridgekeeper.rules import blanket_rule
def has_role(role):
def checker(user):
return user.profile.role == role
return blanket_rule(checker, repr_string=f"has_role({role!r})")
In this case, we’re using the optional repr_string
argument to override how the rule is displayed when debugging, so that we can see what the role
argument is. (We’re using PEP 498 f-strings here, which are supported in Python 3.6+, but you don’t have to.)