refactor(api): полная инкапсуляция LDAP логики в миксин

ПРОБЛЕМА:
- 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: успешно
This commit is contained in:
lizerk 2026-03-18 19:33:35 +03:00
parent bebe61b727
commit bf9bc8f341
2 changed files with 66 additions and 26 deletions

View File

@ -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:

View File

@ -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,
*,