Django allauth - ACCOUNT_UNIQUE_EMAIL doesn't prevent duplicate emails on signup

I'm making a basic website where users sign up with an email, a username, and a psssword.

I'm using dj_rest_auth, which wraps allauth to provide a REST API interface. Here's an example registration call:

POST: http://127.0.0.1:8000/api/auth/registration/

Body:
{
  "username": "new_user3",
  "password1": "testtest@123",
  "password2": "testtest@123",
  "email": "h@h.com"
}

These are the flags I've set in settings.py:

ACCOUNT_EMAIL_VERIFICATION = 'none'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True

Yet, when I send the registration request twice, and only change the username (not email), it goes through just fine: Screenshot showing two different users with the same email.

What's the easiest way to have this fail if the email is a duplicate? Ideally I'm looking for something the library itself provides, and not a custom class.

The documentation of the allauth settings [allauth-docs] says:

ACCOUNT_UNIQUE_EMAIL (default: True)

Enforce uniqueness of email addresses. On the database level, this implies that only one user account can have an email address marked as verified. Forms prevent a user from registering with or adding an additional email address if that email address is in use by another account.

The source code [GitHub] also seems to indicate this:

class Migration(migrations.Migration):
    # …
    
    operations = (
        [
            migrations.AlterUniqueTogether(
                name="emailaddress",
                unique_together={("user", "email")},
            ),
            migrations.AddConstraint(
                model_name="emailaddress",
                constraint=models.UniqueConstraint(
                    condition=models.Q(("verified", True)),
                    fields=["email"],
                    name="unique_verified_email",
                ),
            ),
        ]
        if getattr(settings, "ACCOUNT_UNIQUE_EMAIL", True)
        else []
    )

So the conditon=Q(verified=True) part says that the email is required to be unique, only for rows with verified=True.

Note furthermore that it does not even check if the email is unique in a caseinsensitive way, so Foo@bar.com and foo@bar.com are seen as different email addresses.

Вернуться на верх