0

I'm trying to do crud API with IsOwnerOrReadOnly permission but other users can still delete posts from the others. Could you please have a look? I have no clue what goes wrong. My guess is that it has something to do with this line

return obj.author == request.user.userprofile

// permissions.py

from rest_framework import permissions


class IsOwnerOrReadOnly(permissions.BasePermission):
   def has_object_permission(self,request,view, obj):
     if request.method in permissions.SAFE_METHODS:
        return True
    
    return obj.author == request.user.userprofile

// views.py

class PostDetail(APIView):
permission_classes = [
        permissions.IsAuthenticatedOrReadOnly,
        IsOwnerOrReadOnly,
    ]

def get_obj(self, pk):
    try:
        return Post.objects.get(id=pk)
    except Post.DoesNotExist:
        raise Http404

def get(self, request, pk, format=None):
    post = self.get_obj(pk)
    serializer = PostSerializer(post)
    return Response(serializer.data)

def put(self, request, pk, format=None):
    post = self.get_obj(pk)
    serializer = PostSerializer(post, data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

def delete(self, request, pk, format=None):
    post = self.get_obj(pk)
    post.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

// models.py

class Post(models.Model):
  id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
  author = models.ForeignKey(Profile,on_delete=models.CASCADE)
  title = models.CharField(max_length=200, blank=True, null=True)
  content = models.TextField(blank=True, null=True)
  tags = models.ManyToManyField('Tag',blank=True)
  answers = models.IntegerField(default=0)
  last_modified = models.DateTimeField(auto_now=True)
  created = models.DateTimeField(auto_now_add=True)

  def __str__(self):
    return self.title

class Profile(models.Model):
  id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
  user = models.OneToOneField(User, related_name='userprofile', on_delete=models.CASCADE)
  name = models.CharField(max_length=200, blank=True, null=True)
  email = models.EmailField(max_length=200, blank=True, null=True)
  location = models.CharField(max_length=200, blank=True, null=True)
  intro = models.CharField(max_length=200, blank=True, null=True)
  bio = models.TextField(blank=True, null=True)
  profile_image = models.ImageField(default=None, upload_to='profile/', blank=True, null=True)
  github = models.CharField(max_length=200, blank=True, null=True)
  linkedin = models.CharField(max_length=200, blank=True, null=True)
  created = models.DateTimeField(default=timezone.now)

  def __str__(self):
    return str(self.user.username)

1 Answers1

0

I think the object permission is never called, Try to explicitly call the APIVIew check_object_permissions in the get_obj method.

def get_obj(self, pk):
    obj = get_object_or_404(Post, pk=pk)
    self.check_object_permissions(self.request, obj)
    return obj

https://www.django-rest-framework.org/api-guide/permissions/#object-level-permissions

Aprimus
  • 1,463
  • 1
  • 14
  • 12