Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework custom permissions per view

I want to create permissions in Django Rest Framework, based on view + method + user permissions.

Is there a way to achieve this without manually writing each permission, and checking the permissions of the group that the user is in?

Also, another problem I am facing is that permission objects are tied up to a certain model. Since I have views that affect different models, or I want to grant different permissions on the method PUT, depending on what view I accessed (because it affects different fields), I want my permissions to be tied to a certain view, and not to a certain model.

Does anyone know how this can be done?

I am looking for a solution in the sort of:

  1. Create a Permissions object with the following parameters: View_affected, list_of_allowed_methods(GET,POST,etc.)

  2. Create a Group object that has that permission associated

  3. Add a user to the group

  4. Have my default permission class take care of everything.

From what I have now, the step that is giving me problems is step 1. Because I see no way of tying a Permission with a View, and because Permissions ask for a model, and I do not want a model.

like image 907
user3616859 Avatar asked May 17 '14 22:05

user3616859


3 Answers

Well, the first step could be done easy with DRF. See http://www.django-rest-framework.org/api-guide/permissions#custom-permissions.

You must do something like that:

from functools import partial

from rest_framework import permissions

class MyPermission(permissions.BasePermission):

    def __init__(self, allowed_methods):
        super().__init__()
        self.allowed_methods = allowed_methods

    def has_permission(self, request, view):
        return request.method in self.allowed_methods


class ExampleView(APIView):
    permission_classes = (partial(MyPermission, ['GET', 'HEAD']),)
like image 52
YAtOff Avatar answered Oct 01 '22 06:10

YAtOff


Custom permission can be created in this way, more info in official documentation( https://www.django-rest-framework.org/api-guide/permissions/):

from rest_framework.permissions import BasePermission


# Custom permission for users with "is_active" = True.
class IsActive(BasePermission):
    """
    Allows access only to "is_active" users.
    """
    def has_permission(self, request, view):
        return request.user and request.user.is_active

# Usage
from rest_framework.views import APIView
from rest_framework.response import Response

from .permissions import IsActive   # Path to our custom permission

class ExampleView(APIView):
    permission_classes = (IsActive,)

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)
like image 33
Alexandr S. Avatar answered Oct 01 '22 06:10

Alexandr S.


I took this idea and got it to work like so:

class genericPermissionCheck(permissions.BasePermission):
    
    def __init__(self, action, entity):
        self.action = action
        self.entity = entity
    
    def has_permission(self, request, view):
        print self.action
        print self.entity
        if request.user and request.user.role.access_rights.filter(action=self.action,entity=self.entity):
            print 'permission granted'            
            return True
        else:
            return False

I used partially in the decorator for the categories action in my viewset class like so:

    @list_route(methods=['get'],permission_classes=[partial(genericPermissionCheck,'Fetch','Categories')])
    def Categories(self, request):

"access_rights" maps to an array of objects with a pair of actions and object e.g. 'Edit' and 'Blog'

like image 40
user10809331 Avatar answered Oct 01 '22 07:10

user10809331