Django Rest Framework is ignoring my IsOwnerOrReadOnly permissions
I created a permissions file for permission isOwnerOrReadOnly
, but the has_object_permission function is not called at all (I am setting the print instruction there).
This is how I use this permission in my view:
class CarDetail(generics.RetrieveUpdateDestroyAPIView):
.....
serializer_class = car_serializers.CarSerializer
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAuthenticatedOrReadOnly,IsOwnerOrReadOnly,)
What am I missing?
source to share
@adeleinr I am assuming you have declared your own get_object method (I would ask you about this in a comment, but have no good reason to do so: D), in which case you need to use check_object_permissions on get_object (also in PUT, DELETE). Use this in your get_object
obj = get_object_or_404(queryset, **filter) self.check_object_permissions(self.request, obj)
source to share
I was inspired by the article How can I delete any YouTube video and wanted to check if django works safely in my project, and ended up here.
This is a pretty important question! And the answer is very good.
Django Rest Framework
makes the false impression that everything is working fine when you look at it through the API view.
The object that authenticates the user:
The entity that authenticates the user has NOT :
The hidden DELETE button makes you feel like everything is fine.
You are authenticated, the delete button is hidden. Cool! You don't notice until you test it with CURL or some other tool and spot this huge security hole.
Django is sometimes too much magic ...
Example:
views.py
@authentication_classes((ExpiringTokenAuthentication, SessionAuthentication))
@permission_classes((IsOwnerOrReadOnly, ))
class UserFavouritesSpotDetail(RetrieveUpdateDestroyAPIView):
model = UsersSpotsList
serializer_class = FavouritesSpotsListSerializer
def get_queryset(self):
queryset = UsersSpotsList.objects.filter(
role=1)
return queryset
def get_object(self):
queryset = self.get_queryset()
obj = get_object_or_404(
queryset,
pk=self.kwargs['pk'],
role=1)
self.check_object_permissions(self.request, obj)
return obj
Note the key line mentioned by Shivansh:
self.check_object_permissions(self.request, obj)
When I was absent, this vulnerability existed.
permissions.py
from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `user` attribute.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
return obj.user == request.user
TEST, for example http://www.getpostman.com/
provide the token of the user who does not own the object.
If everything is in order, you should see a "detail": "You do not have permission to perform this action."
source to share