Compare commits

..

3 commits

Author SHA1 Message Date
63a116c2b2 Merge branch 'master' of https://git.addwin.ir/addwin/winofy-backend 2026-08-15 09:45:59 +03:30
1409a9cddf FIX(winofy): add gooyal auth
add gooyal auth
2026-08-15 09:44:49 +03:30
d2cc4c2ec6 FIX(winofy): add gooyal auth
add gooyal auth
2026-08-15 09:43:47 +03:30
6 changed files with 71 additions and 15 deletions

View file

@ -1,12 +1,11 @@
SECRET_KEY=change-me SECRET_KEY=change-me
DEBUG=True DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1 ALLOWED_HOSTS=winofy-staging.winsoo.ir,localhost,127.0.0.1
DB_NAME=winofy_dev DB_NAME=winofy_dev
DB_USER= DB_USER=
DB_PASSWORD= DB_PASSWORD=
DB_HOST=localhost DB_HOST=localhost
DB_PORT=5432
REDIS_URL=redis://localhost:6379/1 REDIS_URL=redis://localhost:6379/1

View file

@ -4,6 +4,8 @@ from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
from apps.core.permissions import IsStoreOwner from apps.core.permissions import IsStoreOwner
from apps.stores.models import Store from apps.stores.models import Store
@ -60,8 +62,13 @@ class SellerProductViewSet(viewsets.ModelViewSet):
"""Seller's own product management (S06 list, S07 add, S08 inventory).""" """Seller's own product management (S06 list, S07 add, S08 inventory)."""
schema_tags = ['Seller · Products'] schema_tags = ['Seller · Products']
permission_classes = [IsAuthenticated, IsStoreOwner]
serializer_class = SellerProductSerializer serializer_class = SellerProductSerializer
# permission_classes = [IsAuthenticated, IsStoreOwner]
# TODO: IsStoreOwner?
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):

View file

@ -1,6 +1,8 @@
from rest_framework import mixins, viewsets from rest_framework import mixins, viewsets
from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.permissions import AllowAny, IsAuthenticated
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
from .models import Address, City, Neighborhood from .models import Address, City, Neighborhood
from .serializers import AddressSerializer, CitySerializer, NeighborhoodSerializer from .serializers import AddressSerializer, CitySerializer, NeighborhoodSerializer
@ -28,8 +30,11 @@ class NeighborhoodViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, view
class AddressViewSet(viewsets.ModelViewSet): class AddressViewSet(viewsets.ModelViewSet):
schema_tags = ['Addresses'] schema_tags = ['Addresses']
permission_classes = [IsAuthenticated]
serializer_class = AddressSerializer serializer_class = AddressSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):

View file

@ -6,6 +6,8 @@ from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
from apps.core.permissions import IsStoreOwner from apps.core.permissions import IsStoreOwner
from . import services from . import services
@ -27,8 +29,11 @@ class CartView(APIView):
"""The authenticated user's cart, grouped by store (C07).""" """The authenticated user's cart, grouped by store (C07)."""
schema_tags = ['Cart'] schema_tags = ['Cart']
permission_classes = [IsAuthenticated]
serializer_class = CartSerializer serializer_class = CartSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get(self, request): def get(self, request):
cart, _ = Cart.objects.get_or_create(user=request.user) cart, _ = Cart.objects.get_or_create(user=request.user)
@ -45,8 +50,11 @@ class CartItemView(APIView):
"""Add/update/remove a single product line in the authenticated user's cart.""" """Add/update/remove a single product line in the authenticated user's cart."""
schema_tags = ['Cart'] schema_tags = ['Cart']
permission_classes = [IsAuthenticated]
serializer_class = CartItemWriteSerializer serializer_class = CartItemWriteSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
@extend_schema(request=CartItemWriteSerializer, responses=CartItemSerializer) @extend_schema(request=CartItemWriteSerializer, responses=CartItemSerializer)
def post(self, request): def post(self, request):
@ -86,8 +94,11 @@ class CheckoutView(APIView):
"""Splits the authenticated customer's multi-store cart into per-store orders (C08).""" """Splits the authenticated customer's multi-store cart into per-store orders (C08)."""
schema_tags = ['Checkout'] schema_tags = ['Checkout']
permission_classes = [IsAuthenticated]
serializer_class = CheckoutSerializer serializer_class = CheckoutSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
@extend_schema(request=CheckoutSerializer, responses=OrderGroupSerializer) @extend_schema(request=CheckoutSerializer, responses=OrderGroupSerializer)
def post(self, request): def post(self, request):
@ -102,8 +113,11 @@ class OrderGroupViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewse
"""Customer order history — each group may contain orders from several stores.""" """Customer order history — each group may contain orders from several stores."""
schema_tags = ['Orders'] schema_tags = ['Orders']
permission_classes = [IsAuthenticated]
serializer_class = OrderGroupSerializer serializer_class = OrderGroupSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):
@ -115,8 +129,11 @@ class OrderViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
"""Customer-facing single-order tracking (C09) + cancel.""" """Customer-facing single-order tracking (C09) + cancel."""
schema_tags = ['Orders'] schema_tags = ['Orders']
permission_classes = [IsAuthenticated]
serializer_class = OrderSerializer serializer_class = OrderSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):
@ -136,8 +153,13 @@ class SellerOrderViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, views
"""Seller order management (S09 list w/ status tabs, S10 detail + stepper actions).""" """Seller order management (S09 list w/ status tabs, S10 detail + stepper actions)."""
schema_tags = ['Seller · Orders'] schema_tags = ['Seller · Orders']
permission_classes = [IsAuthenticated, IsStoreOwner]
serializer_class = OrderSerializer serializer_class = OrderSerializer
# permission_classes = [IsAuthenticated, IsStoreOwner]
# TODO: IsStoreOwner
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):
@ -184,8 +206,11 @@ class NotificationViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, view
"""Shared notification feed (S16 for sellers; same model serves the customer app).""" """Shared notification feed (S16 for sellers; same model serves the customer app)."""
schema_tags = ['Notifications'] schema_tags = ['Notifications']
permission_classes = [IsAuthenticated]
serializer_class = NotificationSerializer serializer_class = NotificationSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):

View file

@ -3,6 +3,7 @@ from rest_framework.decorators import action
from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
from apps.core.permissions import IsStoreOwner from apps.core.permissions import IsStoreOwner
from .models import Review from .models import Review
@ -14,10 +15,14 @@ class ReviewViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.Gen
schema_tags = ['Reviews'] schema_tags = ['Reviews']
serializer_class = ReviewSerializer serializer_class = ReviewSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_permissions(self): def get_permissions(self):
if self.action == 'create': if self.action == 'create':
return [IsAuthenticated()] return [IsAuthenticatedOrTokenMatchesOASRequirements]
return [AllowAny()] return [AllowAny()]
def get_queryset(self): def get_queryset(self):
@ -32,8 +37,13 @@ class SellerReviewViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
"""Reviews left for the authenticated seller's store, with reply support.""" """Reviews left for the authenticated seller's store, with reply support."""
schema_tags = ['Seller · Reviews'] schema_tags = ['Seller · Reviews']
permission_classes = [IsAuthenticated, IsStoreOwner]
serializer_class = ReviewSerializer serializer_class = ReviewSerializer
# permission_classes = [IsAuthenticated, IsStoreOwner]
# TODO:
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):

View file

@ -9,6 +9,8 @@ from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
from apps.core.permissions import IsStoreOwner from apps.core.permissions import IsStoreOwner
from .models import Store, StoreCategory, StoreWorkingHours from .models import Store, StoreCategory, StoreWorkingHours
@ -70,8 +72,11 @@ class SellerStoreView(APIView):
"""The authenticated seller's own store — GET/PATCH to manage it, POST to create it.""" """The authenticated seller's own store — GET/PATCH to manage it, POST to create it."""
schema_tags = ['Seller · Store'] schema_tags = ['Seller · Store']
permission_classes = [IsAuthenticated]
serializer_class = SellerStoreSerializer serializer_class = SellerStoreSerializer
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get(self, request): def get(self, request):
store = get_object_or_404(Store, owner=request.user) store = get_object_or_404(Store, owner=request.user)
@ -102,8 +107,13 @@ class SellerStoreWorkingHoursView(APIView):
"""Bulk get/set the authenticated seller's weekly working hours (S14).""" """Bulk get/set the authenticated seller's weekly working hours (S14)."""
schema_tags = ['Seller · Store'] schema_tags = ['Seller · Store']
permission_classes = [IsAuthenticated, IsStoreOwner]
serializer_class = StoreWorkingHoursSerializer serializer_class = StoreWorkingHoursSerializer
# permission_classes = [IsAuthenticated, IsStoreOwner]
# TODO:
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
def get(self, request): def get(self, request):
hours = StoreWorkingHours.objects.filter(store=request.user.store) hours = StoreWorkingHours.objects.filter(store=request.user.store)