dfunckt / django-rules

Awesome Django authorization, without the database

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Predicate never gets called with object from django

Bluejanis opened this issue · comments

I try to use rules within django to enable object permissions, but the django admin interface always calls those predicates without any object. As far as I know there is no control to tell django what kind of object to pass. So it passes None. This seems broken.

For reference I have also created a stackoverflow question here.

This is covered in the docs:

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)

Actually I may be mistaken about the actual cause of the problem here.

I am seeing the same issue with DRF views. user is never an object, just the shortname, and obj is always None, even if I use the rest_framework_rules addon and it's permission decorator with a lambda to pass the correct obj. If the ModelAdmin method doesn't fix your issue @Bluejanis then we may be both experiencing a bug with this app and Django 2.1

@Routhinator: I was already using the ObjectPermissionsModelAdmin. (Otherwise the predicates would not be called at all. I should have mentioned that.) Since you can reproduce it, I guess it is indeed a bug.

One more note: honestly I think the docs could be improved regarding which parts are relevant for django, which features work by themself and which features are for both scenarios.

I may have gotten this working, I missed the part where I needed to provide a lamba function to rest_framework_rules permissions decorator to get the object to pass. The PermissionsMixin didn't work for me. Perhaps you also need to provide a lamba when calling the permissions check.

    @permission_required(
        'writings.change_writing',
        fn=lambda request, slug: Writing.objects.get(slug=slug)
    )
    def update(self, request, *args, **kwargs):
        super(WritingViewSet, self).update(request, *args, **kwargs)