Skip to content
thesarfo

Note

Permissions

Restricting endpoints with IsAuthenticated, per-action permissions via get_permissions(), and a custom IsAdminOrReadOnly permission class.

views 0

Now, lets say we want to protect our endpoints, we can do it globally in our settings.py file. But in this scenario let’s say we want to protect only our customer endpoint/viewset. We have something in drf called permission classes which allow us to do that. the most common one is “IsAuthenticated” which requires that the user is authenticated before hitting our endpoint/view. See below

from rest_framework.permissions import IsAuthenticated
class CustomerViewSet(CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericViewSet):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
permission_classes = [IsAuthenticated]

Now what if we want to have different permissions for different actions like (Create, Retrieve, Update). Let’s say we want anybody to Retrieve Customers, but we only want authenticated users/admins to update or create customers. For that we have to override a method in our viewset called ‘get_permissions’. see below

class CustomerViewSet(CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericViewSet):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
permission_classes = [IsAuthenticated] #permission class
def get_permissions(self):
'''we allow anyone to hit our endpoint with a get request, anything else requires authentication'''
if self.request == 'GET':
return [AllowAny()] # permission object
return [IsAuthenticated()] # permission object

Custom Permissions

Currently, our products endpoint ‘/store/products’ is visible to anyone including anonymous users, which means anonymous users can make post requests to our server and create a product. we dont want that. We only want admin users to be able to modify products but anyone including anonymous users should be able to retrieve the list of products. We need to create a custom permission called IsAdminorReadOnly. drf already comes built in with IsAuthenticatedOrReadOnly tho. In the store app, create a file called ‘permissions.py’ and see below

from rest_framework.permissions import BasePermission
from rest_framework import permissions
class IsAdminOrReadOnly(BasePermission):
def has_permission(self, request, view):
if request.method in permissions.SAFE_METHODS: # safe methods is a variable in the implementations of the permissions that we've imported. it includes 'GET', 'HEAD' and 'OPTIONS'
return True # i.e the person has permissions
return bool(request.user and request.user.is_staff) # any other http methods, we check if the user is logged in and if they are staff(admin) before we return True to give it to to them

And in our product viewset we add this permission class to is.

views.py
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_class = ProductFilter
pagination_class = DefaultPagination
permission_classes = [IsAdminOrReadOnly] # this is it

Now visit the same endpoint again and you’ll not see that form below to either create or modify a product unless you’re an admin user.