Home > Net >  In a project in drf, I have endpoint "api/v1/invoice/#id/" so I want to give access to vie
In a project in drf, I have endpoint "api/v1/invoice/#id/" so I want to give access to vie

Time:11-02

I have an endpoint /api/v1/invoice/#id/

I want that only author of this invoice should be able to view invoice Or staff should be able to view this invoice And superuser should be able to view, update, delete invoice

I tried creating permissions.py file in my app:

permissions.py

from rest_framework.permissions import BasePermission


class AuthorGetStaffGetAdminAll(BasePermission):
    edit_methods = ("PUT", "PATCH", "DELETE")

    def has_permission(self, request, view):
        if request.user.is_authenticated:
            return True
        return False

    def has_object_permission(self, request, view, obj):
        if request.user.is_superuser:
            return True

        if obj.author == request.user and request.method not in self.edit_methods:
            return True

        if request.user.is_staff and request.method not in self.edit_methods:
            return True

        return False

serializer.py

class InvoiceSerializer(serializers.ModelSerializer):
    order = serializers.SlugRelatedField(slug_field='id', queryset=order.Order.objects.all())
    id = serializers.CharField(max_length=100, read_only=True)
    class Meta:
        model = invoice.Invoice
        fields = ['id', 'invoice_series', 'order', 'payment_id']

view.py

class InvoiceDisplayView(APIView):
    permission_classes = [AuthorGetStaffGetAdminAll]

    def get(self, request, invoice_id):
        invoice = Invoice.objects.get(id__iexact=invoice_id)
        serializer = InvoiceSerializer(invoice)
        return Response(serializer.data)

urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('v1/invoices/<str:invoice_id>/', views.InvoiceDisplayView.as_view(), name="invoice_view"),
]

CodePudding user response:

Since you are using APIView and not generic view, you have to call check_object_permissions explicitly, this answer explains everything.

Your get method should look like this:

    def get(self, request, invoice_id):
        invoice = Invoice.objects.get(id__iexact=invoice_id)
        self.check_object_permissions(request, invoice)   # This calls permissions
        serializer = InvoiceSerializer(invoice)
        return Response(serializer.data)

CodePudding user response:

APIView do not have object level permission check. You can update your APIView with RetrieveUpdateDestroyAPIView :

class InvoiceDisplayView(RetrieveUpdateDestroyAPIView):
    
    lookup_field = 'invoice_id'  # primary key
    permissions_classes = [IsAuthenticatedAndOwner]
    queryset = Invoice.objects.all()
    serializer_class = InvoiceSerializer

if your primary key is invoice_id you can do this and no get method is required, this alone serves put update delete and get all alone, usually primary_key is just id or pk , in that case lookup_field will be 'id' or 'pk' and you need to update your urls as well :

urlpatterns = [
    path('v1/invoices/<int:id>/', views.InvoiceDisplayView.as_view(), name="invoice_view"),
]
  • Related