- 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)
46 lines
2.1 KiB
Python
46 lines
2.1 KiB
Python
# api/auth/serializers.py
|
||
from api.v1.employees.views._helpers import PHONE_FIELD
|
||
from django.contrib.auth import get_user_model
|
||
from employees.utils import _normalize_phone
|
||
from employees.models import Employee
|
||
from rest_framework import serializers
|
||
from rest_framework.exceptions import AuthenticationFailed
|
||
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
|
||
|
||
User = get_user_model()
|
||
|
||
|
||
class PhoneOrEmailTokenObtainPairSerializer(TokenObtainPairSerializer):
|
||
"""
|
||
Принимает email ИЛИ phone/phone_number + password.
|
||
Если пришёл телефон — ищем пользователя и подставляем его email.
|
||
"""
|
||
|
||
def __init__(self, *args, **kwargs):
|
||
super().__init__(*args, **kwargs)
|
||
# <- КЛЮЧЕВОЕ: email (username_field) не обязателен
|
||
self.fields[self.username_field].required = False
|
||
# добавляем телефонные поля
|
||
self.fields["phone"] = serializers.CharField(required=False, allow_blank=True)
|
||
self.fields["phone_number"] = serializers.CharField(required=False, allow_blank=True)
|
||
|
||
def validate(self, attrs):
|
||
raw_phone = self.initial_data.get("phone") or self.initial_data.get("phone_number")
|
||
if raw_phone and not attrs.get(self.username_field):
|
||
qfield = PHONE_FIELD or "phone_number"
|
||
norm = _normalize_phone(raw_phone) or str(raw_phone).strip()
|
||
try:
|
||
user = Employee.objects.get(**{qfield: norm})
|
||
# подставляем email в стандартный механизм SimpleJWT
|
||
attrs[self.username_field] = user.email
|
||
except Employee.DoesNotExist:
|
||
pass # базовая валидация ниже вернёт 401
|
||
|
||
data = super().validate(attrs)
|
||
|
||
# не выдаём токены, если email не подтверждён/аккаунт не активен
|
||
if not self.user.email_verified or not self.user.is_active:
|
||
raise AuthenticationFailed("email_not_verified", code="email_not_verified")
|
||
|
||
return data
|