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 objectCustom 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 BasePermissionfrom 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 themAnd in our product viewset we add this permission class to is.
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 itNow 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.