Search code examples
pythondjangodjango-rest-frameworkdjango-rest-auth

Django Rest Framework and Auth: How to override UserDetailsView


I'm using django-rest-auth for API endpoints for my custom user model. Getting user details, I send a GET request to /rest-auth/user/. This works fine with an authenticated user, but is forbidden for an unauthenticated user marked by a 403 Forbidden error.

However, I want other users to be able to view each other's details. How can I change this?

This test is the one which demonstrates this error:

def test_get_user(self):
        # /rest-auth/user/ (GET)
        # params: username, first_name, last_name
        # returns: pk, username, email, first_name, last_name
        client = APIClient()
        client.login(username=self.user2.username, 
                     password=self.user2.password)

        path = "/rest-auth/user/"
        user_data = {
            "username": self.username,
        }
        expected_response = {
            "pk": self.id,
            "username": self.username,
            "email": self.email,
            "first_name": '',
            "last_name": '',
        }

        response = client.get(path, user_data)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data, expected_response)

EDIT: I tried to override the permissions of UserDetailsView, yet I failed to do so properly. How do I do this correctly?

from rest_auth import views
from rest_framework.permissions import IsAuthenticatedOrReadOnly


class CustomUserDetailsView(views.UserDetailsView):
    permission_classes = (IsAuthenticatedOrReadOnly, )

Solution

  • django-rest-auth /rest-auth/user/ only allow you to get details of the authenticated user.

    class UserDetailsView(RetrieveUpdateAPIView):
    """
    Reads and updates UserModel fields
    Accepts GET, PUT, PATCH methods.
    
    Default accepted fields: username, first_name, last_name
    Default display fields: pk, username, email, first_name, last_name
    Read-only fields: pk, email
    
    Returns UserModel fields.
    """
    serializer_class = UserDetailsSerializer
    permission_classes = (IsAuthenticated,)
    
    def get_object(self):
        return self.request.user
    
    def get_queryset(self):
        """
        Adding this method since it is sometimes called when using
        django-rest-swagger
        https://github.com/Tivix/django-rest-auth/issues/275
        """
        return get_user_model().objects.all()
    

    if you want unauthenticated users to read all user objects you have write your own view.

    serializers.py

    User = get_user_model()
    class UserSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = User
            fields = "__all__"
    

    views.py

    class UserDetailApiView(generics.RetrieveAPIView):
    permission_classes = (IsAuthenticatedOrReadOnly,)
    queryset = get_user_model().objects.all()
    serializer_class = UserSerializer
    

    urls.py

    path('api/users/<int:pk>',views.UserDetailApiView.as_view(),name='user')