12 Commits

Author SHA1 Message Date
lizerk
7dcf84dcd1 feat(auth): add session management and settings integration 2026-04-11 23:31:14 +03:00
lizerk
6ee32111db chore: configure vscode flake8 and commit lint cleanup 2026-03-31 19:17:56 +03:00
lizerk
2815efe069 chore: finalize backend lint cleanup 2026-03-31 17:53:29 +03:00
lizerk
3f59f8ebb9 Add backend OpenAPI docs and clean test suite 2026-03-31 17:05:31 +03:00
lizerk
0539f50233 refactor: переход на строгий AD-only LDAP, регистрация + верификация email
- Удалён 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-ограничения работают независимо
- Полевые ошибки регистрации с красной подсветкой на фронте
2026-03-19 00:48:13 +03:00
lizerk
bf9bc8f341 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: успешно
2026-03-18 19:33:35 +03:00
lizerk
bebe61b727 refactor(api): создание базового AnonymousAPIView для DRY
ПРОБЛЕМА:
- 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: успешно
2026-03-18 19:32:15 +03:00
lizerk
aa70c23f0f refactor(api): вынос LDAP логики из RegisterAPIView в миксин
ПРОБЛЕМА:
- 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: успешно
2026-03-18 19:28:01 +03:00
lizerk
1bc6961b1d refactor(auth): упростить VerifyEmailAPIView - удалить LDAP логику, использовать сигналы
Изменения:
- 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 раза короче и понятнее
2026-03-18 17:57:56 +03:00
a335594932 fix: remove mocks from LDAP tests, use real LDAP integration, set gender default=0 2026-02-16 21:12:25 +03:00
19464a38cf refactor(employees): DRY duplicate logic in employees and departments
employees.py:
- Extracted _perform_user_update() method (180 lines)
- Simplified me PATCH: removed ~150 lines of duplicate code
- Simplified partial_update: removed ~155 lines of duplicate code
- Total reduction: ~255 lines (930 → 675)

departments.py:
- Extracted _perform_set_head() method (70 lines)
- Simplified set_head action: removed ~50 lines of duplicate code
- Simplified partial_update head branch: removed ~70 lines of duplicate code
- Total reduction: ~140 lines (752 → 612)

manage.py check: System check identified no issues
2026-02-16 16:32:12 +03:00
8efcabf530 refactor(employees): split monolithic views.py (4593 lines) into views/ package
- 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)
2026-02-16 16:18:03 +03:00