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

315 lines
11 KiB
Python

from __future__ import absolute_import
import json
import django
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core import mail
from django.test.utils import override_settings
from django.urls import reverse
from allauth.account import app_settings
from allauth.account.models import EmailAddress
from allauth.tests import TestCase
@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 LoginTests(TestCase):
@override_settings(
ACCOUNT_AUTHENTICATION_METHOD=app_settings.AuthenticationMethod.USERNAME_EMAIL
)
def test_username_containing_at(self):
user = get_user_model().objects.create(username="@raymond.penners")
user.set_password("psst")
user.save()
EmailAddress.objects.create(
user=user,
email="raymond.penners@example.com",
primary=True,
verified=True,
)
resp = self.client.post(
reverse("account_login"),
{"login": "@raymond.penners", "password": "psst"},
)
self.assertRedirects(
resp, settings.LOGIN_REDIRECT_URL, fetch_redirect_response=False
)
def _create_user(self, username="john", password="doe", **kwargs):
user = get_user_model().objects.create(
username=username, is_active=True, **kwargs
)
if password:
user.set_password(password)
else:
user.set_unusable_password()
user.save()
return user
def _create_user_and_login(self, usable_password=True):
password = "doe" if usable_password else False
user = self._create_user(password=password)
self.client.force_login(user)
return user
def test_redirect_when_authenticated(self):
self._create_user_and_login()
c = self.client
resp = c.get(reverse("account_login"))
self.assertRedirects(resp, "/accounts/profile/", fetch_redirect_response=False)
def test_ajax_password_change(self):
self._create_user_and_login()
resp = self.client.post(
reverse("account_change_password"),
data={
"oldpassword": "doe",
"password1": "AbCdEf!123",
"password2": "AbCdEf!123456",
},
HTTP_X_REQUESTED_WITH="XMLHttpRequest",
)
self.assertEqual(resp["content-type"], "application/json")
data = json.loads(resp.content.decode("utf8"))
assert "same password" in data["form"]["fields"]["password2"]["errors"][0]
@override_settings(
ACCOUNT_EMAIL_VERIFICATION=app_settings.EmailVerificationMethod.OPTIONAL
)
def test_login_unverified_account_optional(self):
"""Tests login behavior when email verification is optional."""
user = get_user_model().objects.create(username="john")
user.set_password("doe")
user.save()
EmailAddress.objects.create(
user=user, email="user@example.com", primary=True, verified=False
)
resp = self.client.post(
reverse("account_login"), {"login": "john", "password": "doe"}
)
self.assertRedirects(
resp, settings.LOGIN_REDIRECT_URL, fetch_redirect_response=False
)
@override_settings(
ACCOUNT_EMAIL_VERIFICATION=app_settings.EmailVerificationMethod.OPTIONAL,
ACCOUNT_LOGIN_ATTEMPTS_LIMIT=3,
)
def test_login_failed_attempts_exceeded(self):
user = get_user_model().objects.create(username="john")
user.set_password("doe")
user.save()
EmailAddress.objects.create(
user=user, email="user@example.com", primary=True, verified=False
)
for i in range(5):
is_valid_attempt = i == 4
is_locked = i >= 3
resp = self.client.post(
reverse("account_login"),
{
"login": ["john", "John", "JOHN", "JOhn", "joHN"][i],
"password": ("doe" if is_valid_attempt else "wrong"),
},
)
if django.VERSION >= (4, 1):
self.assertFormError(
resp.context["form"],
None,
"Too many failed login attempts. Try again later."
if is_locked
else "The username and/or password you specified are not correct.",
)
else:
self.assertFormError(
resp,
"form",
None,
"Too many failed login attempts. Try again later."
if is_locked
else "The username and/or password you specified are not correct.",
)
@override_settings(
ACCOUNT_AUTHENTICATION_METHOD=app_settings.AuthenticationMethod.EMAIL,
ACCOUNT_EMAIL_VERIFICATION=app_settings.EmailVerificationMethod.MANDATORY,
ACCOUNT_LOGIN_ATTEMPTS_LIMIT=1,
)
def test_login_failed_attempts_exceeded_cleared_on_password_reset(self):
# Ensure that login attempts, once they hit the limit,
# can use the password reset mechanism to regain access.
user = get_user_model().objects.create(
username="john", email="john@example.org", is_active=True
)
user.set_password("doe")
user.save()
EmailAddress.objects.create(
user=user, email="john@example.org", primary=True, verified=True
)
resp = self.client.post(
reverse("account_login"), {"login": user.email, "password": "bad"}
)
if django.VERSION >= (4, 1):
self.assertFormError(
resp.context["form"],
None,
"The email address and/or password you specified are not correct.",
)
else:
self.assertFormError(
resp,
"form",
None,
"The email address and/or password you specified are not correct.",
)
resp = self.client.post(
reverse("account_login"), {"login": user.email, "password": "bad"}
)
if django.VERSION >= (4, 1):
self.assertFormError(
resp.context["form"],
None,
"Too many failed login attempts. Try again later.",
)
else:
self.assertFormError(
resp,
"form",
None,
"Too many failed login attempts. Try again later.",
)
self.client.post(reverse("account_reset_password"), data={"email": user.email})
body = mail.outbox[0].body
self.assertGreater(body.find("https://"), 0)
# Extract URL for `password_reset_from_key` view and access it
url = body[body.find("/password/reset/") :].split()[0]
resp = self.client.get(url)
# Follow the redirect the actual password reset page with the key
# hidden.
url = resp.url
resp = self.client.get(url)
self.assertTemplateUsed(
resp,
"account/password_reset_from_key.%s" % app_settings.TEMPLATE_EXTENSION,
)
self.assertFalse("token_fail" in resp.context_data)
new_password = "newpass123"
# Reset the password
resp = self.client.post(
url, {"password1": new_password, "password2": new_password}
)
self.assertRedirects(resp, reverse("account_reset_password_from_key_done"))
# Check the new password is in effect
user = get_user_model().objects.get(pk=user.pk)
self.assertTrue(user.check_password(new_password))
resp = self.client.post(
reverse("account_login"),
{"login": user.email, "password": new_password},
)
self.assertRedirects(
resp, settings.LOGIN_REDIRECT_URL, fetch_redirect_response=False
)
@override_settings(
ACCOUNT_AUTHENTICATION_METHOD=app_settings.AuthenticationMethod.EMAIL,
ACCOUNT_EMAIL_VERIFICATION=app_settings.EmailVerificationMethod.MANDATORY,
ACCOUNT_LOGIN_ATTEMPTS_LIMIT=1,
)
def test_login_using_unverified_email_address_is_prohibited(self):
user = get_user_model().objects.create(
username="john", email="john@example.org", is_active=True
)
user.set_password("doe")
user.save()
EmailAddress.objects.create(
user=user, email="john@example.org", primary=True, verified=True
)
EmailAddress.objects.create(
user=user, email="john@example.com", primary=True, verified=False
)
resp = self.client.post(
reverse("account_login"), {"login": "john@example.com", "password": "doe"}
)
self.assertRedirects(
resp,
reverse("account_email_verification_sent"),
fetch_redirect_response=False,
)
self.assertEqual(len(mail.outbox), 1)
assert mail.outbox[0].to == ["john@example.com"]
def test_login_unverified_account_mandatory(self):
"""Tests login behavior when email verification is mandatory."""
user = get_user_model().objects.create(username="john")
user.set_password("doe")
user.save()
EmailAddress.objects.create(
user=user, email="user@example.com", primary=True, verified=False
)
resp = self.client.post(
reverse("account_login"), {"login": "john", "password": "doe"}
)
self.assertRedirects(resp, reverse("account_email_verification_sent"))
def test_login_inactive_account(self):
"""
Tests login behavior with inactive accounts.
Inactive user accounts should be prevented from performing any actions,
regardless of their verified state.
"""
# Inactive and verified user account
user = get_user_model().objects.create(username="john", is_active=False)
user.set_password("doe")
user.save()
EmailAddress.objects.create(
user=user, email="john@example.com", primary=True, verified=True
)
resp = self.client.post(
reverse("account_login"), {"login": "john", "password": "doe"}
)
self.assertRedirects(resp, reverse("account_inactive"))
# Inactive and unverified user account
user = get_user_model().objects.create(username="doe", is_active=False)
user.set_password("john")
user.save()
EmailAddress.objects.create(
user=user, email="user@example.com", primary=True, verified=False
)
resp = self.client.post(
reverse("account_login"), {"login": "doe", "password": "john"}
)
self.assertRedirects(resp, reverse("account_inactive"))
@override_settings(ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS=False)
def test_account_authenticated_login_redirects_is_false(self):
self._create_user_and_login()
resp = self.client.get(reverse("account_login"))
self.assertEqual(resp.status_code, 200)