from __future__ import annotations import logging from datetime import timedelta from django.utils import timezone from django.utils.crypto import get_random_string from drf_spectacular.utils import ( OpenApiResponse, extend_schema, inline_serializer, ) from rest_framework import serializers from rest_framework.response import Response from api.v1.employees.serializers import ( EmailSerializer, EmailVerifySerializer, ) from api.v1.employees.views._helpers import Employee from common.emails import send_templated_mail from ..base import AnonymousAPIView logger = logging.getLogger(__name__) class ResendEmailAPIView(AnonymousAPIView): throttle_scope = "auth_email" @extend_schema( tags=["Auth"], summary="Повторно отправить код подтверждения email", request=EmailSerializer, responses={ 200: inline_serializer( "ResendEmailResponse", {"ok": serializers.BooleanField()}, ), 400: OpenApiResponse(description="Email уже подтвержден."), 404: OpenApiResponse(description="Пользователь не найден."), }, ) def post(self, request): ser = EmailSerializer(data=request.data) ser.is_valid(raise_exception=True) email = ser.validated_data["email"] user = Employee.objects.filter(email__iexact=email).first() if not user: return Response({"ok": False, "error": "user_not_found"}, status=404) if user.email_verified: return Response({"ok": False, "error": "already_verified"}, status=400) user.email_activation_code = get_random_string(6, "0123456789") user.email_activation_sent_at = timezone.now() user.save( update_fields=[ "email_activation_code", "email_activation_sent_at", ] ) send_templated_mail( subject="Подтверждение регистрации", to=[user.email], template_base="emails/registration_verify_code", context={"code": user.email_activation_code, "user": user}, ) return Response({"ok": True}, status=200) class VerifyEmailAPIView(AnonymousAPIView): @extend_schema( tags=["Auth"], summary="Подтвердить email кодом", request=EmailVerifySerializer, responses={ 200: inline_serializer( "VerifyEmailResponse", { "ok": serializers.BooleanField(), "user_id": serializers.IntegerField(), }, ), 400: OpenApiResponse(description="Код пустой, неверный или истек."), 404: OpenApiResponse(description="Пользователь не найден."), }, ) def post(self, request): ser = EmailVerifySerializer(data=request.data) ser.is_valid(raise_exception=True) email = ser.validated_data["email"].strip().lower() code = ser.validated_data["code"].strip() user = Employee.objects.filter(email__iexact=email).first() if not user: return Response({"ok": False, "error": "user_not_found"}, status=404) if not code: return Response({"ok": False, "error": "empty_code"}, status=400) code_sent_at = getattr(user, "email_activation_sent_at", None) or getattr( user, "created_at", None ) if code_sent_at and not user.email_verified: if timezone.now() - code_sent_at > timedelta(minutes=5): user.delete() return Response({"ok": False, "error": "expired"}, status=400) if not user.verify_email(code): return Response({"ok": False, "error": "invalid_code"}, status=400) user.is_active = True user._ldap_changes = {"is_active": True} user.save() return Response({"ok": True, "user_id": user.id}, status=200)