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

Simpler, more concise rule declarations with R objects #9

Open
daisylb opened this issue Apr 20, 2018 · 2 comments
Open

Simpler, more concise rule declarations with R objects #9

daisylb opened this issue Apr 20, 2018 · 2 comments

Comments

@daisylb
Copy link
Owner

daisylb commented Apr 20, 2018

bridgekeeper.rules should expose a R class, with an API similar to django.db.models.Q.

This class would take keyword arguments, with either constants, functions that take a user, or other Bridgekeeper rules as values.

This class should take keyword arguments, where keys are attribute names (traversing relationships with __ where applicable), and values are either database values, functions that take a user, or (where the target attribute is a relationship) another Bridgekeeper rule object.

As an example of what this might look like, here's a couple of snippets from the documentation, alongside the equivalent rule expressed in terms of R.

blue_widgets_only = Attribute('colour', matches='blue')
blue_widgets_only = R(colour='blue')
perms['shrubbery.update_shrubbery'] = Attribute('branch', lambda user: user.profile.branch)
perms['shrubbery.update_shrubbery'] = R(branch=lambda user: user.profile.branch)
perms['shrubbery.update_shrubbery'] = Relation(
    'branch',
    models.Branch,
    # This rule gets checked against the branch object, not the shrubbery
    Attribute('store', lambda user: user.profile.branch.store),
)

perms['shrubbery.update_shrubbery'] = R(branch__store=lambda user: user.profile.branch.store)
perms['foo.view_application'] = Relation(
    'applicant', Applicant, perms['foo.view_applicant'])

perms['foo.view_application'] = R(applicant=perms['foo.view_applicant'])
perms['foo.view_customer'] = ManyRelation(
    'agencies', Agency, Is(lambda user: user.agency))

perms['foo.view_customer'] = R(agencies=lambda user: user.agency)
perms['shrubbery.update_shrubbery'] = is_staff | (
    is_shrubber & Relation(
        'branch',
        models.Branch,
        Attribute('store', lambda user: user.profile.branch.store),
    )
) | (
    is_apprentice & Attribute('branch', lambda user: user.profile.branch)
)

perms['shrubbery.update_shrubbery'] = is_staff | (
    is_shrubber & R(branch__store=lambda user: user.profile.branch.store)
) | (
    is_apprentice & R(branch=lambda user: user.profile.branch)
)
@daisylb
Copy link
Owner Author

daisylb commented Apr 20, 2018

It is worth pointing out that this work will depend on work for #3, which will also decrease the verbosity of some of the non-R examples a bit.

@daisylb
Copy link
Owner Author

daisylb commented Apr 20, 2018

As an aside, lookups (__gt, __in etc) could also be supported. This could be done with each one being a rule object of its own that takes a property and a value_or_function, since they'd need to do one thing for Q lookups and another for Python-land checks, and rule objects are already a mechanism for doing that. My intention is not to do that at first though, since we haven't encountered a need for testing anything other than equality yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant