Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django rules object permissions

I am trying to use django rules to configure object permissions in django and the django admin interface.

Now when I add permission rules, they will always only be called with the first param, but the object is always None.

For example I if I would create this predicate:

@rules.predicate
def is_book_author(user, book):
    return book.author == user

And then add it to the django permission set:

rules.add_perm('books.view_book', is_book_author)

Now when I log into the admin interface with a user, then the is_book_author will be called with the user and None. It will be called multiple times (once per object), but the object ist always None.

I am using rules 2.0.0 with django 2.1.1 and python 3.7.

Any ideas if I'm doing something wrong or how to configure django to call the predicate with the individual object?

like image 223
Tigerware Avatar asked Sep 22 '18 09:09

Tigerware


1 Answers

As django-rules documentation states:

Django Admin does not support object-permissions, in the sense that it will never ask for permission to perform an action on an object, only whether a user is allowed to act on (any) instances of a model.

If you'd like to tell Django whether a user has permissions on a specific object, you'd have to override the following methods of a model's ModelAdmin:

has_view_permission(user, obj=None)
has_change_permission(user, obj=None)
has_delete_permission(user, obj=None)

rules comes with a custom ModelAdmin subclass, rules.contrib.admin.ObjectPermissionsModelAdmin, that overrides these methods to pass on the edited model instance to the authorization backends, thus enabling permissions per object in the Admin:

# books/admin.py
from django.contrib import admin
from rules.contrib.admin import ObjectPermissionsModelAdmin
from .models import Book

class BookAdmin(ObjectPermissionsModelAdmin):
    pass

admin.site.register(Book, BookAdmin)

Now this allows you to specify permissions like this:

rules.add_perm('books', rules.always_allow)
rules.add_perm('books.add_book', has_author_profile)
rules.add_perm('books.change_book', is_book_author_or_editor)
rules.add_perm('books.delete_book', is_book_author)

To preserve backwards compatibility, Django will ask for either view or change permission. For maximum flexibility, rules behaves subtly different: rules will ask for the change permission if and only if no rule exists for the view permission.

like image 157
Kamil Niski Avatar answered Oct 22 '22 01:10

Kamil Niski