Either install the last release:
pip install django-rules-light
Either install a development version:
pip install -e git+https://github.com/yourlabs/django-rules-light.git#egg=django-rules-light
That should be enough to work with the registry.
To enable the middleware that processes rules_light.Denied
exception, add to setings.MIDDLEWARE_CLASSES
:
MIDDLEWARE_CLASSES = (
# ...
'rules_light.middleware.Middleware',
)
See docs on middleware</middleware>
for more details.
To enable autodiscovery of rules in the various apps installed in your project, add to urls.py
(as early as possible):
import rules_light
rules_light.autodiscover()
See docs on registry</registry>
for more details.
To enable logging, add a rules_light
logger for example:
LOGGING = {
# ...
'handlers': {
# ...
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'rules_light': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
}
}
}
See docs on logging</logging>
for more details on logging.
Add to settings.INSTALLED_APPS
:
INSTALLED_APPS = (
'rules_light',
# ....
)
Then the view should be usable, install it as such:
url(r'^rules/', include('rules_light.urls')),
See docs on debugging</debug>
for more details on debugging rules.
Declaring rules consist of filling up the rules_light.registry
dict. This dict uses rule "names" as keys, ie. do_something
, some_app.some_model.create
, etc, etc ... For values, it can use booleans:
# Enable read for everybody
rules_light.registry['your_app.your_model.read'] = True
# Disable delete for everybody
rules_light.registry['your_app.your_model.delete'] = False
Optionnaly, use the Python dict method setdefault()
in default rules. For example:
# Only allow everybody if another (project-specific) callback was not set
rules_light.registry.setdefault('your_app.your_model.read', True)
It can also use callbacks:
def your_custom_rule(user, rule_name, model, *args, **kwargs):
if user in model.your_custom_stuff:
return True # Allow user !
rules_light.registry['app.model.read'] = your_custom_rule
See docs on registry</registry>
for more details.
Callbacks may also be used to decorate each other, using rules_light.make_decorator()
will transform a simple rule callback, into a rule callback that can also be used as decorator for another callback.
Just decorate a callback with make_decorator()
to make it reusable as decorator:
@rules_light.make_decorator
def some_condition(user, rule, *args, **kwargs):
# do stuff
rules_light.registry.setdefault('your_app.your_model.create', some_condition)
@some_condition
def extra_condition(user, rule, *args, **kwargs):
# do extra stuff
rules_light.registry.setdefault('your_app.your_model.update', extra_condition)
This will cause some_condition()
to be evaluated first, and if it passes, extra_condition()
will be evaluated to, for the update rule.
See docs on decorator</decorator>
for more details.
The rule registry is in charge of using rules, using the run()
method. It should return True or False.
For example with this:
def some_condition(user, rulename, *args, **kwargs):
# ...
rules_light.registry['your_app.your_model.create'] = some_condition
Doing:
rules_light.run(request.user, 'your_app.your_model.create')
Will call:
some_condition(request.user, 'your_app.your_model.create')
Kwargs are forwarded, for example:
rules_light.run(request.user, 'your_app.your_model.create',
with_widget=request.GET['widget'])
Will call:
some_condition(request.user, 'your_app.your_model.create',
with_widget=request.GET['widget'])
See docs on registry</registry>
for more details.
The require()
method is useful too, it does the same as run()
except that it will raise rules_light.Denied
. This will block the request process and will be catched by the middleware if installed.
See docs on registry</registry>
for more details.
You can decorate a class based view as such:
@rules_light.class_decorator
class SomeCreateView(views.CreateView):
model=SomeModel
This will automatically require 'some_app.some_model.create'
.
See docs on class decorator</class_decorator>
for more usages of the decorator.
If your project wants to change the behaviour of your_app
to allows users to create models and edit the models they have created, you could add after rules_light.autodiscover()
:
def my_model_or_staff(user, rulename, obj):
return user.is_staff or user == obj.author
rules_light.registry['your_app.your_model.create'] = True
rules_light.registry['your_app.your_model.update'] = my_model_or_staff
rules_light.registry['your_app.your_model.delete'] = my_model_or_staff
As you can see, a project can completely change the security logic of an app, which should enpower creative django developers hehe ...
See docs on registry</registry>
for more details.
django-rules-light comes with a predefined is_staff
rule which you could use in your_app/rules_light_registry.py
:
import rules_light
# Allow all users to see your_model
rules_light.registry.setdefault('your_app.your_model.read', True)
# Allow admins to create and edit models
rules_light.registry.setdefault('your_app.your_model.create', rules_light.is_staff)
rules_light.registry.setdefault('your_app.your_model.update', rules_light.is_staff)
rules_light.registry.setdefault('your_app.your_model.delete', rules_light.is_staff)
See docs on shortcuts</shortcuts>
.
See security testing docs</testing>
.