winofy-backend/apps/reviews/views.py
Ali Asadi 674ca34041 Add missing required_alternate_scopes across OAS-gated views
Several views using IsAuthenticatedOrTokenMatchesOASRequirements were
missing scope entries for methods they actually expose (GET on
list/retrieve-only viewsets, PUT/PATCH/DELETE on ModelViewSets), and
two had a stale POST entry for a method that doesn't exist
(SellerStoreWorkingHoursView, OrderGroupViewSet). Fixes:
- SellerStoreView, SellerStoreWorkingHoursView (apps/stores/views.py)
- AddressViewSet (apps/locations/views.py)
- SellerReviewViewSet (apps/reviews/views.py)
- SellerProductViewSet (apps/catalog/views.py)
- OrderGroupViewSet, OrderViewSet, SellerOrderViewSet,
  NotificationViewSet (apps/orders/views.py)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-31 14:46:02 +03:30

57 lines
2.2 KiB
Python

from rest_framework import mixins, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
from apps.core.permissions import IsStoreOwner
from .filters import ReviewFilter
from .models import Review
from .serializers import ReviewSerializer, SellerReplySerializer
class ReviewViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
"""Customer reviews — create after a delivered order, list is public per store."""
schema_tags = ['Reviews']
serializer_class = ReviewSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
filterset_class = ReviewFilter
queryset = Review.objects.select_related('customer', 'store')
def get_permissions(self):
if self.action == 'create':
return [IsAuthenticatedOrTokenMatchesOASRequirements]
return [AllowAny()]
class SellerReviewViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""Reviews left for the authenticated seller's store, with reply support."""
schema_tags = ['Seller · Reviews']
serializer_class = ReviewSerializer
# permission_classes = [IsAuthenticated, IsStoreOwner]
# TODO:
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"GET": [[]],
"POST": [[]],
}
def get_queryset(self):
if getattr(self, 'swagger_fake_view', False):
return Review.objects.none()
return Review.objects.filter(store=self.request.user.store).select_related('customer')
@action(detail=True, methods=['post'])
def reply(self, request, pk=None):
review = self.get_object()
serializer = SellerReplySerializer(data=request.data)
serializer.is_valid(raise_exception=True)
review.seller_reply = serializer.validated_data['seller_reply']
review.save(update_fields=['seller_reply', 'updated_at'])
return Response(ReviewSerializer(review).data)