- Удалён LDAP_SERVER_TYPE и все OpenLDAP ветки кода
- user_service.py: только AD (sAMAccountName, UAC, microsoft.modify_password)
- auth_backends.py: AD фильтры и атрибуты (objectCategory, objectGUID)
- Удалён server_configs.py (больше не нужен)
- Удалён OpenLDAP Docker окружение (docker-compose.ldap.yml, ldap/, QUICKSTART_LDAP.md)
- Фронтенд: мульти-шаговая регистрация, AvatarCropper 3:4, verify-email страница
- Убран CSRF для JWT API, IP-ограничения работают независимо
- Полевые ошибки регистрации с красной подсветкой на фронте
ПРОБЛЕМА:
- 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: успешно
ПРОБЛЕМА:
- RegisterAPIView содержал ~30 строк LDAP-специфичной логики
- DirectoryService, DirectoryUserDTO, обработка исключений - всё в основном методе
- Нарушение принципа единственной ответственности
- Сложность тестирования и переиспользования
РЕШЕНИЕ:
Создан api/v1/employees/views/mixins.py с миксинами:
1. LdapUserCreationMixin:
- create_ldap_user() - создание пользователя в LDAP через DirectoryService
- create_db_user() - создание пользователя напрямую в БД (fallback без LDAP)
- Централизованная обработка DirectoryLdapError/DirectoryDbError
- Возвращает (Employee, None) при успехе или (None, Response) при ошибке
2. LdapPasswordMixin:
- update_ldap_password() - обновление пароля в LDAP
- Подготовка для использования в PasswordChangeView и других endpoints
ИЗМЕНЕНИЯ:
- auth.py: RegisterAPIView использует LdapUserCreationMixin
- Блок if ldap_enabled заменён на вызовы self.create_ldap_user() / self.create_db_user()
- _helpers.py: удалён _is_ldap_enabled (перемещён в mixins.py)
- Уменьшено количество строк в RegisterAPIView: ~190 → ~170
ПРЕИМУЩЕСТВА:
- Чёткое разделение: общая логика регистрации vs LDAP-специфика
- Переиспользование: миксины можно применить в других views
- Тестируемость: можно мокать методы миксина
- Читаемость: основной метод фокусируется на бизнес-логике
Django check: успешно
Изменения:
- VerifyEmailAPIView: 331 → 271 строк (-60 строк)
- Удалена вся логика if ldap_enabled с DirectoryService
- Удалены проверки LdapSyncState и обработка LDAP ошибок
- Активация пользователя теперь через сигнал sync_employee_to_ldap_on_save
- Используется _ldap_changes для передачи данных в сигнал
- Удален импорт DirectoryServiceError
Логика:
- ViewSet устанавливает is_active = True и _ldap_changes
- Сигнал автоматически синхронизирует активацию в LDAP
- Обработка ldap_enabled и ошибок происходит в сигнале
- Код стал в 3 раза короче и понятнее
- Split into 9 modules by ViewSet: departments, employees, positions,
roles, skills, actions, groups, auth, _helpers
- Created views/__init__.py with re-exports for backward compatibility
- Created employees/permissions.py re-export shim (views/ is now a
sub-package, so ..permissions resolves to employees.permissions)
- Fixed api/auth/serializers.py import: PHONE_FIELD from _helpers,
_normalize_phone from employees.utils
- Removed ~250+ debug print()/logger.info() statements from
departments.py and employees.py
- Removed dead _with_ldap_service() decorator from helpers
- Removed unreachable code at end of GroupViewSet.replace_members
manage.py check: System check identified no issues (0 silenced)