Features: 1) Add confirm_password field to UserSerializer; 2) Implement phone number and email validation in UserSerializer; 3) Enforce password matching logic in UserSerializer validation;

Fixes: 1) Add missing import for `validate_email`; 2) Add missing import for `validate_phone_number`; 3) Correct `password` validation with `compare_digest`;

Extra: 1) Enhance validation error messages for malformed phone number and email; 2) Minor refactor to improve code readability.
This commit is contained in:
Egor Pavlovich Gorbunov 2025-09-01 13:09:22 +03:00
parent 8fc8effd90
commit 06b88254e0

View file

@ -1,12 +1,14 @@
import logging
from collections.abc import Collection
from contextlib import suppress
from hmac import compare_digest
from typing import Any
from constance import config
from django.contrib.auth import authenticate
from django.contrib.auth.models import update_last_login
from django.contrib.auth.password_validation import validate_password
from django.core.validators import validate_email
from django.utils.translation import gettext_lazy as _
from drf_spectacular.utils import extend_schema_field
from rest_framework.exceptions import AuthenticationFailed, ValidationError
@ -30,6 +32,7 @@ from core.serializers import ProductSimpleSerializer
from core.utils.security import is_safe_key
from evibes import settings
from vibes_auth.models import User
from vibes_auth.validators import validate_phone_number
logger = logging.getLogger("django")
@ -37,6 +40,7 @@ logger = logging.getLogger("django")
class UserSerializer(ModelSerializer):
avatar_url = SerializerMethodField(required=False, read_only=True)
password = CharField(write_only=True, required=False)
confirm_password = CharField(write_only=True, required=False)
is_staff = BooleanField(read_only=True)
recently_viewed = SerializerMethodField(required=False, read_only=True)
attributes = JSONField(required=False)
@ -91,6 +95,25 @@ class UserSerializer(ModelSerializer):
def validate(self, attrs):
if "password" in attrs:
validate_password(attrs["password"])
if not compare_digest(attrs["password"], attrs["confirm_password"]):
raise ValidationError(_("passwords do not match"))
if "confirm_password" in attrs:
validate_password(attrs["confirm_password"])
if not compare_digest(attrs["password"], attrs["confirm_password"]):
raise ValidationError(_("passwords do not match"))
if "phone_number" in attrs:
validate_phone_number(attrs["phone_number"])
if User.objects.filter(phone_number=attrs["phone_number"]).exclude(
uuid=self.instance.uuid
).exists():
phone_number = attrs["phone_number"]
raise ValidationError(_(f"malformed phone number: {phone_number}"))
if "email" in attrs:
validate_email(attrs["email"])
if User.objects.filter(email=attrs["email"]).exclude(uuid=self.instance.uuid).exists():
email = attrs["email"]
raise ValidationError(_(f"malformed email: {email}"))
return attrs
@extend_schema_field(ProductSimpleSerializer(many=True))