Django rest framework api permission - django

I would like to limit the access to myweb/api in django rest framework.
I've tried:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
But it limits all the requests however I want to limit access only to myweb/api page

You could add liberal permissions in settings.py file and add more restrictive ones in the specific api view.
In settings.py, add something like :
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
),
of you could also use AllowAny permission.
You can set the authentication policy on a per-view, or per-viewset basis, using the APIView class based views.
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
Or, if you're using the #api_view decorator with function based views.
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
#api_view('GET')
#permission_classes((IsAuthenticated, ))
def example_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
When you set new permission classes through class attribute or decorators you're telling the view to ignore the default list set over the settings.py file.

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})

Can I restrict Endpoints with dry-yasg with this type of view?

I have the following in my views.py
I've been reading the documentation and trying to work out is there a way to exclude certain endpoints for this view.
from EoX.models import Vendor
from rest_framework import viewsets
from rest_framework import permissions
from .serializers import VendorSerializer
from url_filter.integrations.drf import DjangoFilterBackend
from drf_yasg.utils import swagger_auto_schema
from django.utils.decorators import method_decorator
class VendorViewSet(viewsets.ModelViewSet):
queryset = Vendor.objects.all()
serializer_class = VendorSerializer
permission_classes = [permissions.AllowAny]
filter_backends = [DjangoFilterBackend]
filter_fields = ['name',]
I can exclude the view all together with
schema=None
I tried decorating it with
#method_decorator(name='list', decorator=swagger_auto_schema(
operation_description="description from swagger_auto_schema via method_decorator"
))
and that changes the description of the 'get' endpoint.
but trying
#method_decorator(name='list', decorator=swagger_auto_schema(methods=['get'],
operation_description="description from swagger_auto_schema via method_decorator"
))
throws an error
AssertionError:methodormethodscan only be specified on #action or #api_view views
Is this a bug? or just not a supported feature, and is there a way to accomplish what I am trying?
Many thanks.

Django rest-framework Social Oauth2: How to set permission classes per view or method

I'd like to set permission per view or method using Django rest-framework Social Oauth2.
How should I set permission to each view or method?
At first, I've tried to set 'DEFAULT_AUTHENTICATION_CLASSES' in settings.py. But some method doesn't need authentication, I'd like to set AllowAny. So, I've tried to set decorator to the method but it doesn't work.
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
'rest_framework_social_oauth2.authentication.SocialAuthentication',
),
}
views.py
#permission_classes([AllowAny, ])
#api_view(['POST'])
def someMethod(request):
return foo
I resolved it by myself. Commented out DEFAULT_AUTHENTICATION_CLASSES on settings.py. And imported these Authentification and authentication_classes on views.py.
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
# 'rest_framework_social_oauth2.authentication.SocialAuthentication',
),
}
views.py
from rest_framework.decorators import authentication_classes
from oauth2_provider.contrib.rest_framework import OAuth2Authentication
from rest_framework_social_oauth2.authentication import SocialAuthentication
class SampleViewSet(viewsets.ViewSet):
authentication_classes = [OAuth2Authentication, SocialAuthentication]
def someMethodNeedAuth:
return foo
#authentication_classes([AllowAny, ])
#api_view(['POST'])
def someMethodAllowAny(request):
return bar

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',
)
}