From bf9bc8f34158a92855ac547d04fc093174479c7e Mon Sep 17 00:00:00 2001 From: lizerk Date: Wed, 18 Mar 2026 19:33:35 +0300 Subject: [PATCH] =?UTF-8?q?refactor(api):=20=D0=BF=D0=BE=D0=BB=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=B8=D0=BD=D0=BA=D0=B0=D0=BF=D1=81=D1=83=D0=BB=D1=8F?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20LDAP=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=20=D0=BC=D0=B8=D0=BA=D1=81=D0=B8=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ПРОБЛЕМА: - RegisterAPIView знал о режиме LDAP (вызывал _is_ldap_enabled()) - if ldap_enabled: create_ldap_user() else: create_db_user() - View имел LDAP-специфичную логику выбора режима - Нарушение принципа инкапсуляции РЕШЕНИЕ: Создан единый метод в LdapUserCreationMixin: create_user(first_name, last_name, email, phone, password, ...) - Автоматически выбирает LDAP или БД режим - Инкапсулирует вызов _is_ldap_enabled() - View больше не знает о существовании LDAP ИЗМЕНЕНИЯ: mixins.py: + create_user() - фасад, выбирает режим автоматически • create_ldap_user() - остался для внутреннего использования • create_db_user() - остался для внутреннего использования auth.py: - Удалён import _is_ldap_enabled - Удалён блок if ldap_enabled: ... else: ... - Заменён на: emp, error = self.create_user(...) РЕЗУЛЬТАТ: - View НЕ знает про LDAP вообще - Вся LDAP логика инкапсулирована в миксине - Чистое разделение ответственности - Упрощение: -18 строк в view БЫЛО в RegisterAPIView: ldap_enabled = _is_ldap_enabled() if ldap_enabled: emp, err = self.create_ldap_user(...) else: emp = self.create_db_user(...) СТАЛО: emp, err = self.create_user(...) Django check: успешно --- backend/api/v1/employees/views/auth.py | 39 ++++++----------- backend/api/v1/employees/views/mixins.py | 53 ++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 26 deletions(-) diff --git a/backend/api/v1/employees/views/auth.py b/backend/api/v1/employees/views/auth.py index cb911af9..e728885b 100644 --- a/backend/api/v1/employees/views/auth.py +++ b/backend/api/v1/employees/views/auth.py @@ -21,7 +21,7 @@ from rest_framework.views import APIView from ..serializers import (EmailSerializer, EmailVerifySerializer, RegisterSerializer) from ._helpers import Employee -from .mixins import LdapUserCreationMixin, _is_ldap_enabled +from .mixins import LdapUserCreationMixin logger = logging.getLogger(__name__) @@ -186,31 +186,18 @@ class RegisterAPIView(LdapUserCreationMixin, AnonymousAPIView): avatar_bytes = None avatar_name = None - ldap_enabled = _is_ldap_enabled() - - if ldap_enabled: - # Режим с LDAP: создаём disabled учётку в LDAP + пароль - emp, error_response = self.create_ldap_user( - first_name=v["first_name"], - last_name=v["last_name"], - email=email, - phone_e164=phone_norm, - password=password, - avatar_bytes=avatar_bytes, - is_active=False, # disabled до верификации email - ) - if error_response: - return error_response - else: - # Режим без LDAP: создаём пользователя напрямую в БД - emp = self.create_db_user( - first_name=v["first_name"], - last_name=v["last_name"], - email=email, - phone_number=phone_norm, - password=password, - is_active=False, # не активен до верификации email - ) + # Создаём пользователя (миксин сам выберет LDAP или БД режим) + emp, error_response = self.create_user( + first_name=v["first_name"], + last_name=v["last_name"], + email=email, + phone=phone_norm, + password=password, + avatar_bytes=avatar_bytes, + is_active=False, # не активен до верификации email + ) + if error_response: + return error_response # 2) Заполняем доп.поля БД if avatar_bytes: diff --git a/backend/api/v1/employees/views/mixins.py b/backend/api/v1/employees/views/mixins.py index 36f4efda..4f280233 100644 --- a/backend/api/v1/employees/views/mixins.py +++ b/backend/api/v1/employees/views/mixins.py @@ -28,10 +28,63 @@ class LdapUserCreationMixin: из основного метода регистрации. Методы: + create_user(): Создаёт пользователя (выбирает LDAP или БД автоматически) create_ldap_user(): Создаёт пользователя в LDAP через DirectoryService create_db_user(): Создаёт пользователя напрямую в БД (fallback без LDAP) """ + def create_user( + self, + *, + first_name: str, + last_name: str, + email: str, + phone: str, + password: str, + avatar_bytes: Optional[bytes] = None, + is_active: bool = False, + ) -> tuple[Optional['Employee'], Optional[Response]]: + """Создаёт пользователя - автоматически выбирает LDAP или БД режим. + + View не должен знать о режиме LDAP - вся логика инкапсулирована здесь. + + Args: + first_name: Имя + last_name: Фамилия + email: Email (нормализованный, lowercase) + phone: Телефон в E.164 формате + password: Пароль + avatar_bytes: Байты аватара (опционально) + is_active: False до верификации email + + Returns: + tuple[Employee | None, Response | None]: + - (Employee, None) при успехе + - (None, Response) при ошибке (Response для возврата клиенту) + """ + if _is_ldap_enabled(): + # Режим с LDAP: создаём disabled учётку в LDAP + пароль + return self.create_ldap_user( + first_name=first_name, + last_name=last_name, + email=email, + phone_e164=phone, + password=password, + avatar_bytes=avatar_bytes, + is_active=is_active, + ) + else: + # Режим без LDAP: создаём пользователя напрямую в БД + emp = self.create_db_user( + first_name=first_name, + last_name=last_name, + email=email, + phone_number=phone, + password=password, + is_active=is_active, + ) + return emp, None + def create_ldap_user( self, *,