dfunckt / django-rules

Awesome Django authorization, without the database

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Does django-rules work with django rest framework viewsets?

limbera opened this issue · comments

Hi,

I am trying to integrate rules with DRF's viewsets but I keep getting an AttributeError: 'OrgViewSet' object has no attribute 'request'

Here is my viewset code:

class OrgViewSet(PermissionRequiredMixin,
                 mixins.ListModelMixin,
                 viewsets.GenericViewSet):
    permission_required = CHANGE_ORG
    queryset = Org.objects.all()
    serializer_class = OrgSerializer

Here is the stack trace

Internal Server Error: /orgs/
Traceback (most recent call last):
  File "/Users/dre/code/treebeard/venv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/Users/dre/code/treebeard/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/dre/code/treebeard/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/dre/code/treebeard/venv/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/dre/code/treebeard/venv/lib/python3.6/site-packages/rest_framework/viewsets.py", line 86, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/dre/code/treebeard/venv/lib/python3.6/site-packages/django/contrib/auth/mixins.py", line 90, in dispatch
    if not self.has_permission():
  File "/Users/dre/code/treebeard/venv/lib/python3.6/site-packages/rules/contrib/views.py", line 51, in has_permission
    return self.request.user.has_perms(perms, obj)
AttributeError: 'OrgViewSet' object has no attribute 'request'

Any help would be greatly appreciated.

@limbera I wouldn't expect the PermissionRequiredMixin to be compatible with DRF views out of the box -- AFAIK DRF's view hierarchy is completely separate to Django's and handles the request itself. You are probably better off trying to hook rules into DRF's permission system, rather than reusing the mixin directly.

We use a combination of DRF with dry-rest-permissions (https://github.com/dbkaplan/dry-rest-permissions) and incorporate django-rules as predicates which are checked in the model permission checker methods. This works like a charm.

#models.py
class ModelA(Models):
    some_field = ....

    @static_method
    def has_read_permission(request)
        return request.user.has_perm("a_model:read_permission", request)
# rules.py
add_perm("a_model:read_permission", is_superuser | 
    is_authenticated & is_group_member('SomeGroup'))
#in the viewset
class SomeView(ViewSet)
    permission_classes = (IsAuthenticated, DRYPermissions)

(code examples might contains errors, written down out of my head)

@escodebar hey, thanks for your work. DRF has its own permission system, that's completely separate from Django's. I know integration of rules with DRF is going to be very useful but I don't think it belongs into rules' core.

Seeing your work. given the functionality is completely additive and requires no changes to rules core in order to work, it should be trivial to make a separate package with the mixin and related tests. I'd happily link to that project from the README (and leave this ticket open as well, like, forever) so it's discoverable but I'm not inclined to accept this (or any other DRF-integration effort) into core.

@escodebar, thanks, this looks great 👍

Two quick bits of feedback: I think it'd be nice to have a complete example that shows how one would setup a couple of predicates and rules before showing how django-rest-framework-rules is used with DRF, as it now reads somewhat disconnected.

The other is that the project looks like it's a fork of rules even though it shares no code and it properly brings in rules as a dependency, building extra functionality upon it. I'm really not sure if there's a way to resolve this, just saying because I think it's going to confuse a few people trying to use django-rest-framework-rules.

django-rules works with django REST framework viewsets using the django-rest-framework-rules package.

lnstallation and usage are documented in django-rest-framework-rules' README, further examples can be found in django-rest-framework-rules' tests.

@dfunckt: I guess, that you can close this issue now.

rules now has built-in support for Django Rest Framework (contributed by @efficiosoft in #100). See here for docs on the feature: https://github.com/dfunckt/django-rules#permissions-in-django-rest-framework

DRF support ties well with the newly-added support for automatic permissions for models -- see https://github.com/dfunckt/django-rules#permissions-in-models (also by @efficiosoft, in #99)

All in all, I think rules now integrates well with DRF -- let me know of any feedback you may have.