7

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?

6
  • Well at that moment the book does not exists yet. add_book is the permission to add a book, not to "save" the book. I think you should handle this in the form (or even in the form just "inject" the user, such that he/she can simply never add other data). Commented Sep 22, 2018 at 9:54
  • Thanks for your comment, but I have the problem with all 4 permissions. I replaced add_book in the question with the view_book permission to clarify.
    – Tigerware
    Commented Sep 22, 2018 at 10:05
  • 1
    @BluE I'm trying to solve your issue but everything works for me just fine. I used testapp to debug it and still cannot reproduce your issue. Could you provide whole files where you use ObjectPermissionsModelAdmin and add_perm with predicate? Take a look also on github.com/dfunckt/django-rules/blob/v2.0.0/tests/testapp/… Try to compare your code with that from the repo. Commented Oct 10, 2018 at 19:46
  • @KamilNiski I will update the question after work today to add the requested information. Quick question: Were you using the same django version, when you tried the example?
    – Tigerware
    Commented Oct 11, 2018 at 8:34
  • Yes, I used exactly the same versions of libraries as you specified Commented Oct 11, 2018 at 9:14

1 Answer 1

8
+25

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.

2
  • I already use the ObjectPermissionsModelAdmin, but as said the object passed is always None. (Otherwise the predicate would not be called at all)
    – Tigerware
    Commented Oct 10, 2018 at 6:58
  • Please compare your setup with testapp in django-rules repo github.com/dfunckt/django-rules/blob/master/tests/testapp/… I'm inspecting the tests that use predicate and i can see book being passed correctly Commented Oct 10, 2018 at 8:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.