Check if object parent user == request.user on child object create/update

Viewed 39

I want to check if parent object user is request.user to correctly add child amd grandchild object permissions. Wanna figure out how to do it properly in Django & DRF.

Models:

class Parent(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)

class Child(models.Model):
    parent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='childs')

class SecondChild(models.Model):
    parent = models.ForeignKey(Child, on_delete=models.CASCADE, related_name='secondchilds')

Views:

class ParentViewSet(viewsets.ModelViewSet):
    queryset = Parent.objects.all()
    serializer_class = ParentSerializer
    permission_classes = [permissions.IsAuthenticated, IsOwner]

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)

    def get_queryset(self):
        user = self.request.user
        if user.is_superuser:
            return Parent.objects.all()
        return Parent.objects.filter(user=user).prefetch_related('childs', 'childs__secondchilds')


class ChildViewSet(viewsets.ModelViewSet):
    queryset = Child.objects.all()
    serializer_class = ChildSerializer
    permission_classes = [permissions.IsAuthenticated]

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        parent_id = self.request.data.get('parent_id')
        parent_instance = Parent.objects.filter(id=parent_id).first()
        if not serializer.is_valid(raise_exception=True):
            print(serializer.errors)
        serializer.save(parent=parent_instance)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def get_queryset(self):
        user = self.request.user
        if user.is_superuser:
            return Parent.objects.all()
        return Child.objects.filter(parent__user=user).prefetch_related('SecondChild')
1 Answers

you can do the checking on your custom permission class, then add the it to your view's permission_classes list

permissions

class IsParentOwnerOrReadOnly(permissions.BasePermission):
    def has_permission(self, request, view):
        parent_id = int(request.data.get('parent_id'))
        parent_instance = Parent.objects.filter(id=parent_id).first()
        return (request.method in permissions.SAFE_METHODS or
                (parent_instance and request.user == parent_instance.user))

views

class ChildViewSet(viewsets.ModelViewSet):
    ...
    permission_classes = [permissions.IsAuthenticated, IsParentOwnerOrReadOnly]
    ...
Related