From bebe61b72776453e958021a0cb33ff6cebe30625 Mon Sep 17 00:00:00 2001 From: lizerk Date: Wed, 18 Mar 2026 19:31:00 +0300 Subject: [PATCH] =?UTF-8?q?refactor(api):=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=B1=D0=B0=D0=B7=D0=BE=D0=B2=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20AnonymousAPIView=20=D0=B4=D0=BB=D1=8F=20DRY?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ПРОБЛЕМА: - ResendEmailAPIView, VerifyEmailAPIView, RegisterAPIView дублировали: • throttle_scope = "anon" • permission_classes = [AllowAny] - Нарушение DRY принципа (6 строк повторяющегося кода) РЕШЕНИЕ: Создан базовый класс AnonymousAPIView(APIView): - throttle_scope = "anon" - permission_classes = [AllowAny] - Используется для всех публичных auth endpoints ИЗМЕНЕНИЯ: - ResendEmailAPIView(AnonymousAPIView) - удалены дубли - VerifyEmailAPIView(AnonymousAPIView) - удалены дубли - RegisterAPIView(LdapUserCreationMixin, AnonymousAPIView) - удалены дубли РЕЗУЛЬТАТ: - Убрано 8 строк дублирования - Более чистая иерархия наследования - Легче добавлять новые анонимные endpoints - Единая точка для настройки throttling/permissions Django check: успешно --- backend/api/v1/employees/views/auth.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/api/v1/employees/views/auth.py b/backend/api/v1/employees/views/auth.py index 28c3ed11..cb911af9 100644 --- a/backend/api/v1/employees/views/auth.py +++ b/backend/api/v1/employees/views/auth.py @@ -26,12 +26,18 @@ from .mixins import LdapUserCreationMixin, _is_ldap_enabled logger = logging.getLogger(__name__) -class ResendEmailAPIView(APIView): - """POST /api/v1/auth/resend-email/ body: {"email": "..."}""" - +class AnonymousAPIView(APIView): + """Базовый класс для анонимных (публичных) API endpoints. + + Все auth-related views наследуются от этого класса для DRY. + """ throttle_scope = "anon" permission_classes = [AllowAny] + +class ResendEmailAPIView(AnonymousAPIView): + """POST /api/v1/auth/resend-email/ body: {"email": "..."}""" + def post(self, request): ser = EmailSerializer(data=request.data) ser.is_valid(raise_exception=True) @@ -55,10 +61,7 @@ class ResendEmailAPIView(APIView): return Response({"ok": True}, status=200) -class VerifyEmailAPIView(APIView): - throttle_scope = "anon" - permission_classes = [AllowAny] - +class VerifyEmailAPIView(AnonymousAPIView): def post(self, request): """Подтверждает email и активирует пользователя. @@ -94,14 +97,11 @@ class VerifyEmailAPIView(APIView): return Response({"ok": True, "user_id": user.id}, status=200) -class RegisterAPIView(LdapUserCreationMixin, APIView): +class RegisterAPIView(LdapUserCreationMixin, AnonymousAPIView): """Регистрация: создаём учётку в LDAP (disabled) с паролем, в БД — set_unusable_password. Использует LdapUserCreationMixin для вынесения LDAP-специфичной логики. """ - - throttle_scope = "anon" - permission_classes = [AllowAny] parser_classes = (JSONParser, FormParser, MultiPartParser) @transaction.atomic