Only Owner of the Profile able to Update the data

Question:

Using class Based (APIView) in Django rest framework for Getting and Patch (Updating) UserInfo data.

views.py

class getUserInfo(APIView):
    permission_classes = [permissions.IsAuthenticated]

    def get(self, request, format=None):
        user = request.user
        userinfos = user.userinfo_set.all()
        serializer = UserInfoSerializers(userinfos, many=True)
        return Response(serializer.data)

    def patch(self, request, pk, format=None):
        user = UserInfo.objects.get(id=pk)
        serializer = UserInfoSerializers(instance=user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializers.py

from django.contrib.auth.models import User
from .models import UserInfo

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'first_name', 'username')

class UserInfoSerializers(serializers.ModelSerializer):
    user = UserSerializer(many=False, required=True)

    class Meta:
        model = UserInfo
        fields = ('id', 'picture', 'profession', 'user')

Everything is working so far so good. Able to GET and PATCH (Update) logged-in user data.
While Testing the API in Postman, I found out that if User1 is logged in he can change the data of User2 by only using the pk of User2.

urls.py

urlpatterns = [
    path('userinfo/', views.getUserInfo.as_view(), name="UserInfo"),
    path('userinfo/<str:pk>/', views.getUserInfo.as_view()),
    path('api/token/', views.MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('register/', views.RegisterView.as_view(), name='auth_register'),
]

Using rest_framework_simplejwt for Auth

models.py


from django.contrib.auth.models import User

class UserInfo(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    picture = models.ImageField(upload_to="profile_pics", null=True)
    profession = models.CharField(max_length=200, null=True)

    def __str__(self):
        return "%s's Profile Picture" % self.user

Any help would be appreciated

Asked By: Gaurav Joshi

||

Answers:

Don’t use the primary key to get the user.You are using user = request.user to get the user on get method, use the same mechanism also on update. Then the login user can only update his/her info not others info or another way you can check the user = UserInfo.objects.get(id=pk) is same as the current user request.user . If not you can show an exception.

Answered By: Pranta chakraborty

For Retrieving and Updating an object, you can use RetrieveUpdateAPIView

class GetUserInfo(generics.RetrieveUpdateAPIView):
    permission_classes = [IsAuthenticated]
    queryset = UserInfo.objects.all()
    serializer_class = UserInfoSerializers
    
    def get_object(self):
        return self.request.user

Here we are getting an object, it will be called from get_object method. Instead of getting user using PK, we get the current user.

You can use same url for getting and updating the user, just change the method in postman while you hit the api. GET for retrieving and PATCH for partial update.

path('userinfo/', views.GetUserInfo.as_view(), name="UserInfo"),

Answered By: Sarath R