118 lines
4.0 KiB
Python
118 lines
4.0 KiB
Python
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)
|