0

This is my permission:

class IsFllowOrAdminUserOrReadOnly(permissions.BasePermission):
    """
    Allow any users to follow objects and ReadOnly. Allow all requests for
    admin users.
    """
    def has_permission(self, request, view):
        return request.method in permissions.SAFE_METHODS or request.user.is_staff

    def has_object_permission(self, request, view, obj):
        # Allow watching objects.
        if view.action=='follow':
            return True

        return request.method in permissions.SAFE_METHODS or request.user.is_staff

And this is my viewset (and follow action):

class PageViewSet(viewsets.ModelViewSet):
    queryset = Page.objects.all()
    serializer_class = PageSerializer
    permission_classes = (IsAuthenticated, IsCreationOrFollowOrOwnerOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user, location=self.request.user.userextended.location)

    @detail_route(methods=['post'])
    def follow(self, request, pk=None):
        page = self.get_object()    

        page.users.add(request.user)

        return Response(status=status.HTTP_204_NO_CONTENT)

The problem is, when an authenticated user tries to follow an object, it gives me a 403_FORBIDDEN error even though I have the code:

if view.action=='follow':
    return True

Any idea how I should fix this?

Note that this issue is different than this one I posted earlier: DjangoRestFramework - How to properly seperate has_permission and has_object_permission because this permission only allows admin users to create objects whereas the other post allows any users to create objects.

Community
  • 1
  • 1
SilentDev
  • 20,997
  • 28
  • 111
  • 214

1 Answers1

1

A detail_route request or POST request won't reach the has_object_permission. Only PUT, PATCH, DELETE will reach has_object_permission

So try:

def has_permission(self, request, view):
    if request.user.is_authenticated() and view.action=='follow':
        return True
    return request.method in permissions.SAFE_METHODS or request.user.is_staff

def has_object_permission(self, request, view, obj):
    return request.method in permissions.SAFE_METHODS or request.user.is_staff

this will allow:

  • unauthenticated users to readonly
  • authenticated users to readonly & follow
  • admin can perform any request
Anush Devendra
  • 5,285
  • 1
  • 32
  • 24
  • The issue with the code you posted is that by removing `has_permission`, any users are now allowed to make POST requests to create objects, which I don't want. – SilentDev Nov 03 '15 at 21:41