Files
GNX-mailEnterprise/venv/lib/python3.12/site-packages/allauth/account/tests/test_signup.py
Iliyan Angelov c67067a2a4 Mail
2025-09-14 23:24:25 +03:00

389 lines
14 KiB
Python

from __future__ import absolute_import
import django
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.contrib.messages.middleware import MessageMiddleware
from django.contrib.sessions.middleware import SessionMiddleware
from django.core import mail
from django.test.client import Client, RequestFactory
from django.test.utils import override_settings
from django.urls import reverse
import pytest
from pytest_django.asserts import assertTemplateUsed
from allauth.account import app_settings
from allauth.account.adapter import get_adapter
from allauth.account.forms import BaseSignupForm, SignupForm
from allauth.account.models import EmailAddress
from allauth.core import context
from allauth.tests import TestCase
from allauth.utils import get_username_max_length
class CustomSignupFormTests(TestCase):
@override_settings(
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE=True,
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE=True,
)
def test_custom_form_field_order(self):
expected_field_order = [
"email",
"email2",
"password1",
"password2",
"username",
"last_name",
"first_name",
]
class TestSignupForm(forms.Form):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
field_order = expected_field_order
class CustomSignupForm(SignupForm, TestSignupForm):
# ACCOUNT_SIGNUP_FORM_CLASS is only abided by when the
# BaseSignupForm definition is loaded the first time on Django
# startup. @override_settings() has therefore no effect.
pass
form = CustomSignupForm()
self.assertEqual(list(form.fields.keys()), expected_field_order)
def test_user_class_attribute(self):
from django.contrib.auth import get_user_model
from django.db.models.query_utils import DeferredAttribute
class CustomSignupForm(SignupForm):
# ACCOUNT_SIGNUP_FORM_CLASS is only abided by when the
# BaseSignupForm definition is loaded the first time on Django
# startup. @override_settings() has therefore no effect.
pass
User = get_user_model()
data = {
"username": "username",
"email": "user@example.com",
"password1": "very-secret",
"password2": "very-secret",
}
form = CustomSignupForm(data, email_required=True)
assert isinstance(User.username, DeferredAttribute)
form.is_valid()
assert isinstance(User.username, DeferredAttribute)
class BaseSignupFormTests(TestCase):
@override_settings(
ACCOUNT_USERNAME_REQUIRED=True, ACCOUNT_USERNAME_BLACKLIST=["username"]
)
def test_username_in_blacklist(self):
data = {
"username": "username",
"email": "user@example.com",
}
form = BaseSignupForm(data, email_required=True)
self.assertFalse(form.is_valid())
@override_settings(
ACCOUNT_USERNAME_REQUIRED=True, ACCOUNT_USERNAME_BLACKLIST=["username"]
)
def test_username_not_in_blacklist(self):
data = {
"username": "theusername",
"email": "user@example.com",
}
form = BaseSignupForm(data, email_required=True)
self.assertTrue(form.is_valid())
@override_settings(ACCOUNT_USERNAME_REQUIRED=True)
def test_username_maxlength(self):
data = {
"username": "username",
"email": "user@example.com",
}
form = BaseSignupForm(data, email_required=True)
max_length = get_username_max_length()
field = form.fields["username"]
self.assertEqual(field.max_length, max_length)
widget = field.widget
self.assertEqual(widget.attrs.get("maxlength"), str(max_length))
@override_settings(
ACCOUNT_USERNAME_REQUIRED=True, ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE=True
)
def test_signup_email_verification(self):
data = {
"username": "username",
"email": "user@example.com",
}
form = BaseSignupForm(data, email_required=True)
self.assertFalse(form.is_valid())
data = {
"username": "username",
"email": "user@example.com",
"email2": "user@example.com",
}
form = BaseSignupForm(data, email_required=True)
self.assertTrue(form.is_valid())
data["email2"] = "anotheruser@example.com"
form = BaseSignupForm(data, email_required=True)
self.assertFalse(form.is_valid())
@override_settings(
ACCOUNT_DEFAULT_HTTP_PROTOCOL="https",
ACCOUNT_EMAIL_VERIFICATION=app_settings.EmailVerificationMethod.MANDATORY,
ACCOUNT_AUTHENTICATION_METHOD=app_settings.AuthenticationMethod.USERNAME,
ACCOUNT_SIGNUP_FORM_CLASS=None,
ACCOUNT_EMAIL_SUBJECT_PREFIX=None,
LOGIN_REDIRECT_URL="/accounts/profile/",
ACCOUNT_SIGNUP_REDIRECT_URL="/accounts/welcome/",
ACCOUNT_ADAPTER="allauth.account.adapter.DefaultAccountAdapter",
ACCOUNT_USERNAME_REQUIRED=True,
)
class SignupTests(TestCase):
def test_signup_same_email_verified_externally(self):
user = self._test_signup_email_verified_externally(
"john@example.com", "john@example.com"
)
self.assertEqual(EmailAddress.objects.filter(user=user).count(), 1)
EmailAddress.objects.get(
verified=True, email="john@example.com", user=user, primary=True
)
def test_signup_other_email_verified_externally(self):
"""
John is invited on john@example.org, but signs up via john@example.com.
Email verification is by-passed, their home email address is
used as a secondary.
"""
user = self._test_signup_email_verified_externally(
"john@example.com", "john@example.org"
)
self.assertEqual(EmailAddress.objects.filter(user=user).count(), 2)
EmailAddress.objects.get(
verified=False, email="john@example.com", user=user, primary=False
)
EmailAddress.objects.get(
verified=True, email="john@example.org", user=user, primary=True
)
def _test_signup_email_verified_externally(self, signup_email, verified_email):
username = "johndoe"
request = RequestFactory().post(
reverse("account_signup"),
{
"username": username,
"email": signup_email,
"password1": "johndoe",
"password2": "johndoe",
},
)
# Fake stash_verified_email
SessionMiddleware(lambda request: None).process_request(request)
MessageMiddleware(lambda request: None).process_request(request)
request.user = AnonymousUser()
request.session["account_verified_email"] = verified_email
from allauth.account.views import signup
with context.request_context(request):
resp = signup(request)
self.assertEqual(resp.status_code, 302)
self.assertEqual(
resp["location"], get_adapter().get_signup_redirect_url(request)
)
self.assertEqual(len(mail.outbox), 0)
return get_user_model().objects.get(username=username)
@override_settings(
ACCOUNT_USERNAME_REQUIRED=True,
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE=True,
)
def test_signup_password_twice_form_error(self):
resp = self.client.post(
reverse("account_signup"),
data={
"username": "johndoe",
"email": "john@example.org",
"password1": "johndoe",
"password2": "janedoe",
},
)
if django.VERSION >= (4, 1):
self.assertFormError(
resp.context["form"],
"password2",
"You must type the same password each time.",
)
else:
self.assertFormError(
resp,
"form",
"password2",
"You must type the same password each time.",
)
@override_settings(
ACCOUNT_USERNAME_REQUIRED=True, ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE=True
)
def test_signup_email_twice(self):
request = RequestFactory().post(
reverse("account_signup"),
{
"username": "johndoe",
"email": "john@example.org",
"email2": "john@example.org",
"password1": "johndoe",
"password2": "johndoe",
},
)
SessionMiddleware(lambda request: None).process_request(request)
MessageMiddleware(lambda request: None).process_request(request)
request.user = AnonymousUser()
from allauth.account.views import signup
with context.request_context(request):
signup(request)
user = get_user_model().objects.get(username="johndoe")
self.assertEqual(user.email, "john@example.org")
@override_settings(
AUTH_PASSWORD_VALIDATORS=[
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
"OPTIONS": {
"min_length": 9,
},
}
]
)
def test_django_password_validation(self):
resp = self.client.post(
reverse("account_signup"),
{
"username": "johndoe",
"email": "john@example.com",
"password1": "johndoe",
"password2": "johndoe",
},
)
if django.VERSION >= (4, 1):
self.assertFormError(resp.context["form"], None, [])
self.assertFormError(
resp.context["form"],
"password1",
["This password is too short. It must contain at least 9 characters."],
)
else:
self.assertFormError(resp, "form", None, [])
self.assertFormError(
resp,
"form",
"password1",
["This password is too short. It must contain at least 9 characters."],
)
def test_prevent_enumeration_with_mandatory_verification(settings, user_factory):
settings.ACCOUNT_PREVENT_ENUMERATION = True
settings.ACCOUNT_AUTHENTICATION_METHOD = app_settings.AuthenticationMethod.EMAIL
settings.ACCOUNT_EMAIL_VERIFICATION = app_settings.EmailVerificationMethod.MANDATORY
user = user_factory(username="john", email="john@example.org", password="doe")
c = Client()
resp = c.post(
reverse("account_signup"),
{
"username": "johndoe",
"email": user.email,
"password1": "johndoe",
"password2": "johndoe",
},
)
assert resp.status_code == 302
assert resp["location"] == reverse("account_email_verification_sent")
assertTemplateUsed(resp, "account/email/account_already_exists_message.txt")
assert EmailAddress.objects.filter(email="john@example.org").count() == 1
def test_prevent_enumeration_off(settings, user_factory):
settings.ACCOUNT_PREVENT_ENUMERATION = False
settings.ACCOUNT_AUTHENTICATION_METHOD = app_settings.AuthenticationMethod.EMAIL
settings.ACCOUNT_EMAIL_VERIFICATION = app_settings.EmailVerificationMethod.MANDATORY
user = user_factory(username="john", email="john@example.org", password="doe")
c = Client()
resp = c.post(
reverse("account_signup"),
{
"username": "johndoe",
"email": user.email,
"password1": "johndoe",
"password2": "johndoe",
},
)
assert resp.status_code == 200
assert resp.context["form"].errors == {
"email": ["A user is already registered with this email address."]
}
def test_prevent_enumeration_strictly(settings, user_factory):
settings.ACCOUNT_PREVENT_ENUMERATION = "strict"
settings.ACCOUNT_AUTHENTICATION_METHOD = app_settings.AuthenticationMethod.EMAIL
settings.ACCOUNT_EMAIL_VERIFICATION = app_settings.EmailVerificationMethod.NONE
user = user_factory(username="john", email="john@example.org", password="doe")
c = Client()
resp = c.post(
reverse("account_signup"),
{
"username": "johndoe",
"email": user.email,
"password1": "johndoe",
"password2": "johndoe",
},
)
assert resp.status_code == 302
assert resp["location"] == settings.LOGIN_REDIRECT_URL
assert EmailAddress.objects.filter(email="john@example.org").count() == 2
def test_prevent_enumeration_on(settings, user_factory):
settings.ACCOUNT_PREVENT_ENUMERATION = True
settings.ACCOUNT_AUTHENTICATION_METHOD = app_settings.AuthenticationMethod.EMAIL
settings.ACCOUNT_EMAIL_VERIFICATION = app_settings.EmailVerificationMethod.NONE
user = user_factory(username="john", email="john@example.org", password="doe")
c = Client()
resp = c.post(
reverse("account_signup"),
{
"username": "johndoe",
"email": user.email,
"password1": "johndoe",
"password2": "johndoe",
},
)
assert resp.status_code == 200
assert resp.context["form"].errors == {
"email": ["A user is already registered with this email address."]
}
@pytest.mark.django_db
def test_get_initial_with_valid_email():
"""Test that the email field is populated with a valid email."""
request = RequestFactory().get("/signup/?email=test@example.com")
from allauth.account.views import signup
SessionMiddleware(lambda request: None).process_request(request)
request.user = AnonymousUser()
with context.request_context(request):
view = signup(request)
assert view.context_data["view"].get_initial()["email"] == "test@example.com"