How to use GraphQL customized Authentication class? - django

With Django REST Framework(DRF) I can customize Authentication class and Permission class simply like this
from django_cognito_jwt import JSONWebTokenAuthentication
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
class CognitoQuestionViewSet(viewsets.ModelViewSet):
authentication_classes = (JSONWebTokenAuthentication,)
permission_classes = (IsAuthenticated,)
queryset = Question.objects.all()
serializer_class = QuestionSerializer
In the GraphQL docs. It is using standard Django login which is different from my project. I had checked with source LoginRequiredMixin but no luck. I don't see Authentication class there then I can override it
Problem:
How to customize GraphQL Authentication class and Permission class like one I did in DRF

After trials and tries with django-graphql-jwt with no luck. vinayan3 has the answer on my question. Because django-cognito-jwt is considered as a DRF complement.
Solution:
Just replace TokenAuthentication with JSONWebTokenAuthentication from django_cognito_jwt

Related

DRF APIview with authentication

I have a class someAPI(APIView). I would like this one to be accessed by only authorised users.
I tried this link How to use login_required in django rest view
and
https://www.django-rest-framework.org/api-guide/authentication/
but none of them seem work.
My current authentication protocol is logging in with username and password. I guess a reason is because I implement this authentication with basic django (https://docs.djangoproject.com/en/3.1/topics/auth/default/) but not DRF.
from rest_framework.views import APIView
from rest_framework import authentication, permissions
from django.http import JsonResponse
class APICostAnalysisController(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self, request):
""" Initiate get API for getting cost analysis """
return JsonResponse(APICostAnalysisImpl().get(), safe=False,json_dumps_params={'indent': 2})

How to hide POST form in Django REST framework?

I have Django REST framework form like this:
and I would like to do a simple thing: hide POST form (in the red rectangle) when the user is not logged in. I just don't know how to do it, because all I have is model, view that inherits from ListCreateAPIView and serializer inhgeriting from ModelSerializer.
You can use Django rest framework Authentication and Permission classes: https://www.django-rest-framework.org/api-guide/authentication/
from rest_framework.permissions import IsAuthenticated
if you use generic or viewsets class add this line inside your view class
permission_classes = [IsAuthenticated]
or you can set permission to admins only by import
from rest_framework.permissions import IsAdminUser
and
permission_classes = [IsAdminUser]

Custom view and url for DRF

I'd like to know how to add a custom view and url using DRF.
I currently have a UserDetail(APIView) class that can display a user object using a url like /users/123/ but I'd like to also have the ability to view a users history with a url like /users/123/history/ which would likely call on a new method within the UserDetail class. Is there a way to do this?
I've tried looking through DRFs documentation and it looks like they can achieve this through ViewSets and custom Routers, but I get errors when using ViewSets likes needing to define a queryset.
from rest_framework.viewsets import ModelViewSet
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
class UserDetail(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserCreateSerializer
permission_classes = (IsAuthenticated,)
#detail_route(methods=['GET'])
def history(self, request, pk):
user= self.get_object()
serializer = UserCreateSerializer(user)
return Response(serializer.data)

Django REST Framework - Custom Permissions not Evaluating

I'm trying to set custom permissions on a class that extends viewsets.ModelViewSet and it appears that my permissions are not being evaluated. Here is my view:
from rest_framework import viewsets
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
import models
import serializers
from permissions import IsAdminOrAuthenticatedReadOnly
class KPIViewSet(viewsets.ModelViewSet):
'''
API endpoint that allows KPI metadata to be viewed or edited
'''
authentication_classes = (BasicAuthentication,)
permission_classes = (IsAdminOrAuthenticatedReadOnly,)
queryset = models.KPI.objects.all()
serializer_class = serializers.KPISerializer
And here is my permission class:
from rest_framework.permissions import BasePermission, SAFE_METHODS
class IsAdminOrAuthenticatedReadOnly(BasePermission):
def has_permissions(self, request, view):
if request.method in SAFE_METHODS:
return request.user and request.user.is_authenticated()
return request.user and request.user.is_staff()
The problem I'm running into is that IsAdminOrAuthenticatedReadOnly never seems to get evaluated. I tested this both by forcing it to always return "False" and by switching the permission_classes value to "IsAuthenticated" in the view. In the former scenario, a request to the endpoint returns as if there were no authentication requirement. In the later, authentication is enforced as expected.
Any ideas what I'm missing?
The method name is has_permission not has_permissions (no s) ;)

Cannot apply DjangoModelPermissions when rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly is enabled

I am trying to make MongoEngine work with Django REST framework. By following this link Getting mongoengine and django rest framework to play nice, I manage to get everything working, but have to disable "PERMISSION CLASSES" in REST framework, like below
'DEFAULT_PERMISSION_CLASSES': [
#'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
Otherwise, I get this error "Cannot apply DjangoModelPermissions on a view that does not have .model or .queryset property.". The reason seems to be that the returned value from "Collection.objects" or "Collection.objects.all()" can not pass "has_permission" function in permission.py in REST framework.
Could anyone help to look at this?
Or you can just add:
from rest_framework import permissions
and in the view classes add
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
In your views.py import the following models:
from rest_framework.permissions import AllowAny
from rest_framework.decorators import api_view, permission_classes
Before declaring the function (the view function) add:
#api_view(['GET', 'POST'])
#permission_classes((AllowAny, ))
or
#api_view(['GET', 'PUT', 'DELETE'])
#permission_classes((AllowAny, ))
As per Django REST docs:
This permission class ties into Django's standard django.contrib.auth
model permissions. This permission must only be applied to views
that have a .queryset property or get_queryset() method.
This means that on your view, you must have the queryset properly set, e.g:
queryset = SampleModel.objects.all()
Best approach will be to authenticate at a view-base level. So your view must look like this:
from rest_framework.views import APIView
from rest_framework.permissions import DjangoModelPermissionsOrAnonReadOnly
class SampleAPIView(APIView):
queryset = SampleModel.objects.all()
serializer_class = SampleSerializer
permission_classes = [DjangoModelPermissionsOrAnonReadOnly,]
And just in case you are using JWT authentication, you just need to add this to settings.py:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}