mirror of
https://github.com/jazzband/django-authority.git
synced 2026-04-21 07:20:59 +00:00
118 lines
3.6 KiB
Text
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.
|