diff --git a/engine/core/viewsets.py b/engine/core/viewsets.py index 1ee307ef..dea0b3b7 100644 --- a/engine/core/viewsets.py +++ b/engine/core/viewsets.py @@ -266,6 +266,7 @@ class CategoryViewSet(EvibesViewSet): AllowAny, ], ) + @method_decorator(ratelimit(key="ip", rate="4/s" if not settings.DEBUG else "44/s")) def seo_meta(self, request: Request, *args, **kwargs) -> Response: category = self.get_object() @@ -506,6 +507,7 @@ class ProductViewSet(EvibesViewSet): # noinspection PyUnusedLocal @action(detail=True, methods=["get"], url_path="feedbacks") + @method_decorator(ratelimit(key="ip", rate="2/s" if not settings.DEBUG else "44/s")) def feedbacks(self, request: Request, *args, **kwargs) -> Response: product = self.get_object() qs = Feedback.objects.filter(order_product__product=product) @@ -522,6 +524,7 @@ class ProductViewSet(EvibesViewSet): AllowAny, ], ) + @method_decorator(ratelimit(key="ip", rate="4/s" if not settings.DEBUG else "44/s")) def seo_meta(self, request: Request, *args, **kwargs) -> Response: p = self.get_object() images = list(p.images.all()[:6]) @@ -561,6 +564,10 @@ class ProductViewSet(EvibesViewSet): } return Response(SeoSnapshotSerializer(payload).data) + @method_decorator(ratelimit(key="ip", rate="4/s" if not settings.DEBUG else "44/s")) + def retrieve(self, request, *args, **kwargs): + return super().retrieve(request, *args, **kwargs) + @extend_schema_view(**VENDOR_SCHEMA) class VendorViewSet(EvibesViewSet): @@ -665,6 +672,7 @@ class OrderViewSet(EvibesViewSet): return obj @action(detail=False, methods=["get"], url_path="current") + @method_decorator(ratelimit(key="ip", rate="1/s" if not settings.DEBUG else "44/s")) def current(self, request: Request, *args, **kwargs) -> Response: if not request.user.is_authenticated: raise PermissionDenied(permission_denied_message) @@ -678,6 +686,7 @@ class OrderViewSet(EvibesViewSet): ) @action(detail=True, methods=["post"], url_path="buy") + @method_decorator(ratelimit(key="ip", rate="1/s" if not settings.DEBUG else "44/s")) def buy(self, request: Request, *args, **kwargs) -> Response: serializer = BuyOrderSerializer(data=request.data) serializer.is_valid(raise_exception=True) @@ -731,6 +740,7 @@ class OrderViewSet(EvibesViewSet): return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": str(e)}) @action(detail=True, methods=["post"], url_path="add_order_product") + @method_decorator(ratelimit(key="ip", rate="1/s" if not settings.DEBUG else "44/s")) def add_order_product(self, request: Request, *args, **kwargs) -> Response: serializer = AddOrderProductSerializer(data=request.data) serializer.is_valid(raise_exception=True) @@ -750,6 +760,7 @@ class OrderViewSet(EvibesViewSet): return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": str(ve)}) @action(detail=True, methods=["post"], url_path="remove_order_product") + @method_decorator(ratelimit(key="ip", rate="1/s" if not settings.DEBUG else "44/s")) def remove_order_product(self, request: Request, *args, **kwargs) -> Response: serializer = RemoveOrderProductSerializer(data=request.data) serializer.is_valid(raise_exception=True) @@ -769,6 +780,7 @@ class OrderViewSet(EvibesViewSet): return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": str(ve)}) @action(detail=True, methods=["post"], url_path="bulk_add_order_products") + @method_decorator(ratelimit(key="ip", rate="1/s" if not settings.DEBUG else "44/s")) def bulk_add_order_products(self, request: Request, *args, **kwargs) -> Response: serializer = BulkAddOrderProductsSerializer(data=request.data) serializer.is_valid(raise_exception=True) @@ -788,6 +800,7 @@ class OrderViewSet(EvibesViewSet): return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": str(ve)}) @action(detail=True, methods=["post"], url_path="bulk_remove_order_products") + @method_decorator(ratelimit(key="ip", rate="1/s" if not settings.DEBUG else "44/s")) def bulk_remove_order_products(self, request: Request, *args, **kwargs) -> Response: serializer = BulkRemoveOrderProductsSerializer(data=request.data) serializer.is_valid(raise_exception=True) diff --git a/engine/vibes_auth/docs/drf/messaging.py b/engine/vibes_auth/docs/drf/messaging.py index 6898b062..8fe89f4f 100644 --- a/engine/vibes_auth/docs/drf/messaging.py +++ b/engine/vibes_auth/docs/drf/messaging.py @@ -1,3 +1,4 @@ +from django.utils.translation import gettext_lazy as _ from drf_spectacular.utils import OpenApiParameter from engine.vibes_auth.messaging.serializers import ( diff --git a/engine/vibes_auth/messaging/forwarders/telegram.py b/engine/vibes_auth/messaging/forwarders/telegram.py index a24d26e2..f8f09d58 100644 --- a/engine/vibes_auth/messaging/forwarders/telegram.py +++ b/engine/vibes_auth/messaging/forwarders/telegram.py @@ -14,7 +14,6 @@ from django.contrib.auth import get_user_model from django.db.models import Q from engine.vibes_auth.choices import SenderType -from engine.vibes_auth.messaging.services import send_message as svc_send_message from engine.vibes_auth.models import ChatThread logger = logging.getLogger(__name__) @@ -97,6 +96,8 @@ def build_router() -> Optional["Router"]: @router.message() async def any_message(message: types.Message): # type: ignore[valid-type] + from engine.vibes_auth.messaging.services import send_message as svc_send_message + if not message.from_user or not message.text: return tid = message.from_user.id diff --git a/evibes/settings/drf.py b/evibes/settings/drf.py index 5ac3f992..10710ce8 100644 --- a/evibes/settings/drf.py +++ b/evibes/settings/drf.py @@ -113,7 +113,7 @@ SPECTACULAR_SETTINGS = { "ENABLE_DJANGO_DEPLOY_CHECK": not DEBUG, # noqa: F405 "SWAGGER_UI_FAVICON_HREF": r"/static/favicon.png", "SWAGGER_UI_SETTINGS": { - "connectSocket": True, + "connectSocket": False, "socketMaxMessages": 8, "socketMessagesInitialOpened": False, },