django-authority/docs/create_per_object_permission.txt
2011-02-21 09:04:31 -08:00

118 lines
3.6 KiB
Text

.. _create-per-object-permission:
==============================
Create a per-object permission
==============================
django-authority provides a super simple but nifty feature called *per-object
permission*. A description would be::
Attach a <codename> to an object
Attach a <codename> to an user
If the user has <codename> and the object has <codename> then do-something,
otherwise do-something-else.
This might sound strange but let's have a closer look on this pattern.
In terms of users and flatpages a visual example would be:
.. image:: .static/authority-object-1to1.png
*The user is allowed to review the flatpage "Events".*
You are not limited to a 1:1 relation, you can add this ``codename`` to
multiple objects:
.. image:: .static/authority-object-1toN.png
*The user is allowed to review the flatpages "Events" and "Contact".*
And you can do this with any objects in any direction:
.. image:: .static/authority-object-NtoN.png
*The user is allowed to review the flatpages "Events" and "Contact". Another
user is allowed to publish the flatpage "Events".*
Create per-object permissions
=============================
Creating per-object permissions is super simple. See this piece of permission
class code::
class FlatPagePermission(BasePermission):
label = 'flatpage_permission'
checks = ('review',)
authority.register(FlatPage, FlatPagePermission)
This permission class is similar to the one we already created in
:ref:`create-basic-permission` but we added the line::
checks = ('review',)
This tells the permission class that it has a permission check (or ``codename``)
``review``. Under the hood this check gets translated to ``review_flatpage``
(``review_<modelname>``).
.. important:: Be sure that you have understand that we have not written any
line of code yet. We just added the ``codename`` to the checks attribute.
Attach per-object permissions to objects
========================================
Please see :ref:`handling-admin` for this.
Check per-object permissions
============================
As we noted above, we have not written any permission comparing code yet. This
is your work. In theory the permission lookup for per-object permissions is::
if <theuser> has <codename> and <object> has <codename>:
return True
else:
return False
.. important::
The syntax is similiar to the permission checks we've already
seen in :ref:`create-basic-permission` for the basic permissions but now
we have to pass each function a model instance we want to check!
In your python code
-------------------
::
from myapp.permissions import FlatPagePermission
def my_view(request):
check = FlatPagePermission(request.user)
flatpage_object = Flatpage.objects.get(url='/homepage/')
if check.review_flatpage(flatpage_object):
print "Yay, you can change *this* flatpage!"
Using the view decorator
------------------------
::
from django.contrib.auth import Flatpage
from authority.decorators import permission_required_or_403
@permission_required_or_403('flatpage_permission.review_flatpage',
(Flatpage, 'url__iexact', 'url')) # The flatpage_object
def my_view(request, url):
# ...
See :ref:`check-decorator` how the decorator works in detail.
In your templates
-----------------
::
{% ifhasperm "flatpage_permission.review_flatpage" request.user flatpage_object %}
Yay, you can change *this* flatpage!
{% else %}
Nope, sorry. You aren't allowed to change *this* flatpage.
{% endifhasperm %}
See :ref:`check-templates` how the template tag works in detail.