HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/unlimited-leads/Unlimited-Leads-Be/authorization/serializers.py
import uuid
import stripe
from rest_framework import serializers
from django.conf import settings
from django.contrib.auth.tokens import default_token_generator

from utils.validators import (
    validate_password_strength,
    validate_phone_number,
    validate_otp,
)
from .models import (
    UnlimitedLeadUser,
    VerificationMailRequest,
    ForgetPassowordRequest,
    LoginUserDevice,
)
from services.stripe.stripe import StripeUtils

stripe.api_key = settings.STRIPE_SECRET_KEY


class UserSignupSerializer(serializers.ModelSerializer):
    password = serializers.CharField(validators=[validate_password_strength])
    confirm_password = serializers.CharField()

    class Meta:
        model = UnlimitedLeadUser
        fields = [
            "first_name",
            "last_name",
            "email",
            "phone_number",
            "password",
            "confirm_password",
        ]
        extra_kwargs = {
            "first_name": {"required": True},
            "last_name": {"required": True},
            "phone_number": {"validators": [validate_phone_number]},
            "password": {"required": True, "write_only": True},
            "confirm_password": {"required": True, "write_only": True},
        }

    def validate_email(self, value):
        if UnlimitedLeadUser.objects.filter(email=value, is_deleted=False).exists():
            raise serializers.ValidationError("Email ID already exists.")
        return value

    def validate(self, attrs):
        if attrs["password"] != attrs["confirm_password"]:
            raise serializers.ValidationError(
                {"confirm_password": "Passwords and Confirm Password do not match."}
            )

        return attrs

    def create(self, validated_data):
        validated_data.pop("confirm_password")

        user = UnlimitedLeadUser(
            first_name=validated_data["first_name"],
            last_name=validated_data["last_name"],
            username=str(uuid.uuid4()),
            email=validated_data["email"],
            phone_number=validated_data["phone_number"],
        )
        user.set_password(validated_data["password"])
        user.save()

        try:
            customer_id = StripeUtils.create_customer(
                name=f"{user.first_name} {user.last_name}",
                email=user.email,
            )
            user.stripe_id = customer_id
            user.save()
        except Exception as e:
            raise serializers.ValidationError({"stripe_error": str(e)})

        return user


class LoginSerializer(serializers.Serializer):
    email = serializers.EmailField()
    password = serializers.CharField(validators=[validate_password_strength])
    device_type = serializers.ChoiceField(choices=LoginUserDevice.DEVICE_CHOICES)
    is_remember = serializers.BooleanField(default=False)

    class Meta:
        fields = ("email", "password")
        extra_kwargs = {"password": {"write_only": True}}

    def validate_email(self, value):
        if not UnlimitedLeadUser.objects.filter(email=value, is_deleted=False).exists():
            raise serializers.ValidationError("Email ID not exists. Consider signup.")
        return value


class VerifyAccountSerializer(serializers.Serializer):
    otp = serializers.CharField(validators=[validate_otp])
    email = serializers.EmailField()
    device_type = serializers.ChoiceField(choices=LoginUserDevice.DEVICE_CHOICES)
    is_remember = serializers.BooleanField(default=False)

    def validate_email(self, value):
        try:
            user = UnlimitedLeadUser.objects.get(email=value, is_deleted=False)
        except UnlimitedLeadUser.DoesNotExist:
            raise serializers.ValidationError("Email ID not exists. Consider signup.")

        return user

    def validate(self, attrs):
        otp = attrs["otp"]
        user = attrs["email"]
        try:
            verification = VerificationMailRequest.objects.get(
                user=user, otp__isnull=False
            )
        except VerificationMailRequest.DoesNotExist:
            raise serializers.ValidationError("You haven't requested verification")

        if verification.is_expired():
            raise serializers.ValidationError("OTP Expired")

        if not verification.verify_otp(otp):
            raise serializers.ValidationError("Invalid OTP")

        return super().validate(attrs)


class ForgetPasswordRequestSerializer(serializers.Serializer):
    email = serializers.EmailField()

    def validate_email(self, value):
        try:
            user = UnlimitedLeadUser.objects.get(email=value, is_deleted=False)
        except UnlimitedLeadUser.DoesNotExist:
            raise serializers.ValidationError("Email ID not exists. Consider signup.")

        return user


class ForgetPasswordSerializer(serializers.Serializer):
    email = serializers.EmailField()
    token = serializers.CharField()
    password = serializers.CharField(
        write_only=True, validators=[validate_password_strength]
    )

    def validate_email(self, value):
        try:
            user = UnlimitedLeadUser.objects.get(email=value, is_deleted=False)
        except UnlimitedLeadUser.DoesNotExist:
            raise serializers.ValidationError("Email ID not exists. Consider signup.")

        return user

    def validate(self, attrs):
        user = attrs["email"]
        token = attrs["token"]
        password = attrs["password"]

        if not default_token_generator.check_token(user, token):
            raise serializers.ValidationError("The link has been expired.")

        try:
            reset_request = ForgetPassowordRequest.objects.get(user=user, token=token)
        except ForgetPassowordRequest.DoesNotExist:
            raise serializers.ValidationError("You haven't requested forget password")

        if reset_request.is_expired():
            raise serializers.ValidationError("This link has expired")

        if user.check_password(password):
            raise serializers.ValidationError(
                "New password cannot be the same as the old password."
            )

        return attrs