2026-09-07 19:43:48 +03:00

131 lines
5.4 KiB
Python

"""Сериализаторы для аутентификации и регистрации."""
import re
from typing import Any, Dict
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError as DjangoValidationError
from rest_framework import serializers
from api.v1.serializers import Base64ImageField
from employees.models import Employee, Position
from employees.utils import _normalize_phone
class EmailSerializer(serializers.Serializer):
email = serializers.EmailField()
class EmailVerifySerializer(serializers.Serializer):
email = serializers.EmailField()
code = serializers.CharField(max_length=6)
class RegisterSerializer(serializers.Serializer):
"""Сериализатор регистрации.
Проверяет контакты, нормализует телефон до E.164 и ограничивает допустимые
значения некоторых полей.
"""
first_name = serializers.CharField(max_length=150)
last_name = serializers.CharField(max_length=150)
phone_number = serializers.CharField(
max_length=100, required=False, allow_blank=True
)
phone = serializers.CharField(
max_length=100, required=False, allow_blank=True, write_only=True
)
email = serializers.EmailField()
password = serializers.CharField(min_length=8, write_only=True)
birth_date = serializers.DateField()
telegram = serializers.CharField(required=False, allow_blank=True, default="")
whatsapp = serializers.CharField(required=False, allow_blank=True, default="")
wechat = serializers.CharField(required=False, allow_blank=True, default="")
avatar = Base64ImageField(required=True)
patronymic = serializers.CharField(required=False, allow_blank=True, default="")
gender = serializers.IntegerField(
required=True,
min_value=1,
max_value=2,
error_messages={
"required": 'Поле "Пол" обязательно для заполнения.',
"invalid": "Укажите пол: 1 - Мужской, 2 - Женский.",
"min_value": "Укажите пол: 1 - Мужской, 2 - Женский.",
"max_value": "Укажите пол: 1 - Мужской, 2 - Женский.",
},
)
position = serializers.IntegerField(required=False, allow_null=True)
skills = serializers.ListField(child=serializers.IntegerField(), required=False)
def validate_first_name(self, value: str) -> str:
value = value.strip()
if not value:
raise serializers.ValidationError("Имя обязательно для заполнения.")
if re.search(r"\d", value):
raise serializers.ValidationError("Имя не должно содержать цифры.")
if not re.match(r"^[\w\s\-\']+$", value, re.UNICODE):
raise serializers.ValidationError(
"Имя может содержать только буквы, пробелы, дефисы и апострофы."
)
return value
def validate_last_name(self, value: str) -> str:
value = value.strip()
if not value:
raise serializers.ValidationError("Фамилия обязательна для заполнения.")
if re.search(r"\d", value):
raise serializers.ValidationError("Фамилия не должна содержать цифры.")
if not re.match(r"^[\w\s\-\']+$", value, re.UNICODE):
raise serializers.ValidationError(
"Фамилия может содержать только буквы, пробелы, дефисы и апострофы."
)
return value
def validate_patronymic(self, value: str) -> str:
value = value.strip()
if not value:
return value
if re.search(r"\d", value):
raise serializers.ValidationError("Отчество не должно содержать цифры.")
if not re.match(r"^[\w\s\-\']+$", value, re.UNICODE):
raise serializers.ValidationError(
"Отчество может содержать только буквы, пробелы, дефисы и апострофы."
)
return value
def validate(self, attrs: Dict[str, Any]) -> Dict[str, Any]:
if not attrs.get("phone_number") and attrs.get("phone"):
attrs["phone_number"] = attrs["phone"]
norm = _normalize_phone(attrs.get("phone_number"))
if not norm:
raise serializers.ValidationError(
{"phone_number": ("Неверный номер телефона (требуется формат E.164).")}
)
attrs["phone_number"] = norm
pos_id = attrs.get("position")
if pos_id is not None:
if not Position.objects.filter(pk=pos_id).exists():
raise serializers.ValidationError(
{"position": "Указанная должность не найдена."}
)
password_user = Employee(
email=attrs["email"],
first_name=attrs["first_name"],
last_name=attrs["last_name"],
)
try:
validate_password(attrs["password"], user=password_user)
except DjangoValidationError as exc:
raise serializers.ValidationError({"password": exc.messages}) from exc
return attrs