pythondjangopostgresqldjango-rest-frameworkdjoser

Custom Email Validation in Djoser Registration Not Working


I'm using Django with Djoser for authentication and need to restrict user registration to only those emails listed in my kontakte table. However, my custom email validation doesn't seem to be invoked. Here are the details:

Djoser Configuration:

DJOSER = {
    "PASSWORD_RESET_CONFIRM_URL": "auth/password-reset-confirm?uid={uid}&token={token}",
    "ACTIVATION_URL": "auth/activation?uid={uid}&token={token}",
    "SEND_ACTIVATION_EMAIL": True,
    "USER_CREATE_PASSWORD_RETYPE": True,
    "PASSWORD_RESET_CONFIRM_RETYPE": True,
    "PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND": True,
    "TOKEN_MODEL": None,
    "FROM_EMAIL": getenv("FROM_EMAIL"),
    "SERIALIZERS": {
        "user_create": "users.serializers.CustomUserCreateSerializer",
    },
}

Custom Serializer:

from rest_framework import serializers
from djoser.serializers import UserCreateSerializer
from .models import UserAccount, Kontakte

class CustomUserCreateSerializer(UserCreateSerializer):
    class Meta(UserCreateSerializer.Meta):
        model = UserAccount
        fields = ("email", "password", "is_active", "is_staff", "is_superuser")

    def validate_email(self, value):
        if not Kontakte.objects.filter(email=value).exists():
            raise serializers.ValidationError("You are not allowed to register.")
        return value

    def create(self, validated_data):
        user = UserAccount.objects.create_user(
            email=validated_data["email"], password=validated_data["password"]
        )
        return user

Problem:

What I Have Tried:

Any advice on what might be wrong or how to ensure my custom validation is used would be greatly appreciated. Thanks!


Solution

  • Sometimes the best way to check something's validity is not to do it at all; let the database do it. You can do just that here. Since you have a table of pre-authorized create a FK to that table from your UserAccount table; then intercept the FK violation error when it occurs.
    Unfortunately, I am not sufficiently versed in your obfuscation manager (Django/Djoser) so I'll provide raw sql to accomplish it: (see demo here)

    create table kontakte(valid_email text primary key); 
      
    create table registrations(id    integer generated always as identity
                                     primary key
                      ,name  text
                      ,email text
                      ,constraint valid_user_email 
                                  foreign key(email) 
                                  references kontakte(valid_email) 
                      );