Override request.user in djangorestframework-simplejwt

Viewed 11

There are two user models in my project:

class User(AbstractUser):
    id = models.AutoField(primary_key=True)
    email = models.EmailField(unique=True)
    ...

class ProjectMember(UserModel):
    project = models.ForeignKey("project.Project")

I use djangorestframework-simplejwt for authorization and it gives me a User instance in request.user inside a view, here is an example:

from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.views import APIView


class CurrentUserView(ListAPIView):
    permission_classes = [IsAuthenticated]

    def get(self, request: Request):
        # there will be User instance
        current_user = request.user
        # Will raise an exception
        current_user.project
        # some other code here
        ...

I have a user, but I cannot access project, because it defined in ProjectMember and not accessible via User.

I found out that I can get ProjectMember instance by checking the special attribute:

    def get(self, request: Request):
        # there will be ProjectMember instance
        current_user = request.user.projectmember
        # I can access project now
        current_user.project
        # some other code here
        ...

But now I have to repeat this code in every view I use my current user. How can I override the request.user for it to be always a ProjectMember (if it is an instance of ProjectMember, of course)?

1 Answers

I found the solution while writing the question.

Override JWTAuthentication like this:

# users/auth/custom_auth.py
from rest_framework_simplejwt.authentication import JWTAuthentication


class CustomAuth(JWTAuthentication):
    def authenticate(self, request):
        user, access = super().authenticate(request)
        if hasattr(user, 'projectmember'):
            user = user.projectmember
        return user, access

And in settings.py change:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication'
    ],
}

to path to new class (users/auth/custom_auth.py:CustomAuth in my case):

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'users.auth.custom_auth.CustomAuth'
    ],
}
Related