Jason
Jason

Reputation: 281

Mixins for Permissions Django REST ListCreateAPIView

I'm sorry if I may have wrong code but I havent really been doing django rest much. I want to detect permissions from django's built in User model. I added a permission to a user model but for some reason has_perm doesn't work. I instead use user_objects.all() and detect if the permission object is there. I want to return an error 400: Unauthorized if the user does not have permission.

Heres my current solution(not working):

class ProgramListCreateView(PermissionRequiredMixin,ListCreateAPIView):
    permission_required = Permission.objects.get(name="Can CRUD")
    permission_classes = (IsAuthenticated,)
    queryset = Program.objects.all()
    serializer_class = ProgramSerializer

    def check_user(self,request):
        if self.permission_required in request.user.user_permissions.all():
            return True
        return Response(status=400)

when I send a json with the user token without the permission, it still creates the object

Heres my mixin:

 class PermissionRequiredMixin(object):
    user_check_failure_path = 'auth_login'
    permission_required = None

    def check_user(self, user):
        return user.has_perm(self.permission_required)

note: has_perm always returns false for some reason even if I add it using user.user_permissions.add(permission_object)

Upvotes: 1

Views: 4821

Answers (2)

Jason
Jason

Reputation: 281

Heres what I did: I created a Mixin that extends the default generic API Views and I just override the put post and get functions

class MasterGenericAPIViewMixin(ListCreateAPIView, RetrieveUpdateDestroyAPIView):
codename = None

def post(self, request, *args, **kwargs):
    permission = Permission.objects.get(codename=self.codename)
    if permission not in request.user.user_permissions.all():
        return Response(status=403, data={
            "error": "not authorized to add"
        })

    return self.create(request, *args, **kwargs)

def put(self, request, *args, **kwargs):
    permission = Permission.objects.get(codename=self.codename)
    if permission not in request.user.user_permissions.all():
        return Response(status=403, data={
            "error": "not authorized to edit"
        })
    return self.update(request, *args, **kwargs)

def delete(self, request, *args, **kwargs):
    permission = Permission.objects.get(codename=self.codename)
    print(permission)
    print(request.user)
    if permission not in request.user.user_permissions.all():
        return Response(status=403, data={
            "error": "not authorized to delete"
        })
    return self.destroy(request, *args, **kwargs)

all my views extended this class

Upvotes: 1

Shift 'n Tab
Shift 'n Tab

Reputation: 9443

Sounds like you are trying to verify if a particular user has permission to your APIView.

You can simply use DjangoModelPermissions read more

class ProgramListCreateView(ListCreateAPIView):
    permission_classes = (IsAuthenticated, DjangoModelPermissions)
    ...

You can also use the custom permission read more

from rest_framework import permissions

class UserPermission(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        '''
         Object-level permission to only allow user model manipulation
        '''

        # IF you  would like to allow GET, HEAD or OPTIONS requests,
        if request.method in permissions.SAFE_METHODS:
            return True

        # check if user is owner
        return request.user == obj

USAGE

from custom_permission import UserPermission

class ProgramListCreateView(ListCreateAPIView):
    permission_classes = (UserPermission, )
    ...

OR

If you want to make your permission globally you can include it on your settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
        'rest_framework.permissions.DjangoModelPermissions',
    )
}

Upvotes: 1

Related Questions