Bonk
Bonk

Reputation: 1949

Restrict update method to only modify request user's own data?

I have an Update method in DRF to allow users to update their own profile. The api endpoint is PUT /api/users/{id}/ where id is his own user id. If he attempts to update any other users profile he will receive a HTTP403.

The way I am doing it right now is

def update(self, request, *args, **kwargs):
    """
    Update user profile
    """
    if int(kwargs['id']) is not request.user.id:
        return Response({}, status=status.HTTP_403_FORBIDDEN)
    return super(UserViewSet, self).update(request, *args, **kwargs)

I am hoping to do this in a more elegant way, perhaps with a decorator or something?

Upvotes: 1

Views: 2323

Answers (2)

Rahul Gupta
Rahul Gupta

Reputation: 47846

You can create a CustomUpdatePermission class which will grant access to update requests depending on whether the id in the url and request.user.id matched or not.

We will check first check that its an update request. If it was, we will check the value of id in the url with the id of request.user. If they did not match, request will not be granted access and a 403 Forbidden response will be returned.

from rest_framework import permissions

class CustomUpdatePermission(permissions.BasePermission):
    """
    Permission class to check that a user can update his own resource only
    """

    def has_permission(self, request, view):
        # check that its an update request and user is modifying his resource only
        if view.action == 'update' and view.kwargs['id']!=request.user.id:
            return False # not grant access
        return True # grant access otherwise

You can include this permission class in your UserViewset by defining permission_classes setting.

class UserViewSet(viewsets.ModelViewSet):

    permission_classes = (CustomUpdatePermission,) # specify custom permission class here
    ...

Upvotes: 4

Gocht
Gocht

Reputation: 10256

If you are using Tokens to authenticate your users, with DRF you can access the current user in request.user as you can see in Docs.

So, you can match the request.user's with the incoming id in url, or use only the request.user to update info and stop passing id via URL.

Upvotes: 1

Related Questions