Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

rules manager for dynamic permissions with ACL like declarations

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 rules
Octocat-spinner-32 tests
Octocat-spinner-32 .gitignore
Octocat-spinner-32 README.rst
Octocat-spinner-32 TODO
Octocat-spinner-32 makefile
Octocat-spinner-32 requirements.txt
Octocat-spinner-32 run_tests.py
Octocat-spinner-32 setup.py
README.rst

Rules

Flexible rules library for Django

Install

Install:

pip install django-rules

Add rules to INSTALLED_APPS and run python manage.py syncdb to create the appropriate database tables.

Use

Some projects require complex and abstract business logic like:

User A is allowed to buy product XYZ if attribute B of User A equals 58

You need then low level granularity rules. Some solutions exist adding permission to the object itself in the DB. But sometimes, we may want to get permissions for an object which is not in DB.

That's why rules!

In rules, you create a set of assumptions like your customer do. For example:

Anonymous users can't see products of type A

Customer can see standard products

Sales representatives can see VIP products

Admin can see everything

to translate that in python code, you have to define:

a group
Anonymous, Customer, Sales rep, Admin are all groups. They are dynamically assigned to users because they validate a condition. Something like you are anonymous if you are not authenticated. You can belong to multiple groups.
a predicate
Any products, standard products, VIP products, everything are all predicates. A predicate is a method to caracterise something. How do you know than a product is of type B: product_type=="B". To be efficient, there is many way to implement your predicate. As of now, three are supported. apply_qs for a queryset, apply_obj for an object, apply_sqs for a search_queryset coming from Haystack.
a rule
The link between the group and the predicate through an action. Action may be: 'see products' in our example. Action are only strings

Here is what a rule looks file:

Rule.objects.create_rule(groups_in="anonymous", cant_do="see_products", predicate="A_products")

translating:

Anonymous users can't see products of type A

You have then to explain to 'rules' what anynomous and A_products means by subclassing Group and Predicate.

class Anonymous(Group):

name="anonymous" @classmethod def belong(cls, obj):

System Message: ERROR/3 (<string>, line 74)

Unexpected indentation.
return isinstance(obj, User) and obj.is_authenticated()

then the Predicate.

class Any(Predicate):

name="A_products" @classmethod def apply_qs(cls, qs):

System Message: ERROR/3 (<string>, line 82)

Unexpected indentation.
return {"product_type":"A"}

then, to check for it, just do:

list_of_products = ApplyRule(on=Product.objects.all(), action="see_products", for_=anonymous_user).check()

And you will get a queryset with the list of product validating your rules. Let say you have 3 products, 1 of type A , 1 of type B and 1 of type C.

You get:

list_of_products = [ productB, productC ]

Now, if you add a new rule for C product:

Anonymous users can't see products of type C

you will get:

list_of_products = [ productB ]

View decorator

You may want to decorate a view. There is an helper to do that simply. For example:

from rules.base import get_view_decorator

can_see_products = get_view_decorator("see_products")

@can_see_products def get(self, *args, **kwargs):

System Message: ERROR/3 (<string>, line 116)

Unexpected indentation.
...

Contribute

Install for contributing:

git clone git://github.com/anthony-tresontani/rules.git
mkvirtualenv rules
cd rules
python setup.py develop
pip install -r requirements.txt

Run tests:

./run_tests.py

Understand

Automatic group creation

Any object is automatically assigned a group by default containing the all objects of the same model. For ex, any Product instead will belong to the group group_product_model.

Something went wrong with that request. Please try again.