|
9 | 9 | from django.test import TestCase, override_settings |
10 | 10 | from django.urls import reverse |
11 | 11 |
|
| 12 | +from ..models import ConfirmAccessToken |
12 | 13 | from ..views import EMAIL_CHANGE_CONFIRM_SALT, EMAIL_CHANGE_REQUEST_SALT |
13 | | -from .factories import OAuthUserFactory, StaffFactory, UserFactory |
| 14 | +from .factories import StaffFactory, UserFactory |
14 | 15 |
|
15 | 16 | EMAIL_CHANGE_URL = reverse("users:email_change_confirm_password") |
16 | 17 | ELEVATE_URL = reverse("users:elevate") |
@@ -78,22 +79,45 @@ class TestEmailChangePasswordlessUserMustElevate(TestCase): |
78 | 79 | """Users without a usable password must also elevate, via an emailed code.""" |
79 | 80 |
|
80 | 81 | def setUp(self): |
81 | | - self.user = OAuthUserFactory() |
82 | | - self.client.force_login(self.user) |
| 82 | + cache.clear() |
| 83 | + self.user = UserFactory() |
| 84 | + self.user.set_unusable_password() |
| 85 | + self.user.save() |
| 86 | + # Passwordless users log in with an emailed code, through the custom |
| 87 | + # backend. The first backend is OAuth, which disables the email field. |
| 88 | + self.client.force_login(self.user, backend=settings.CUSTOM_AUTH_BACKEND) |
83 | 89 |
|
84 | | - def test_unelevated_passwordless_user_redirected_to_elevate(self): |
85 | | - signed = make_signed_value(self.user, NEW_EMAIL) |
86 | | - response = self.client.get(url_with_value(signed), follow=False) |
87 | | - self.assertEqual(response.status_code, 302) |
| 90 | + def test_email_change_is_held_until_elevated_with_emailed_code(self): |
| 91 | + from django.core import mail |
| 92 | + |
| 93 | + response = self.client.post( |
| 94 | + ACCOUNT_URL, {"full_name": self.user.full_name, "email": NEW_EMAIL} |
| 95 | + ) |
| 96 | + change_url = response["Location"] |
| 97 | + self.assertIn(EMAIL_CHANGE_URL, change_url) |
| 98 | + |
| 99 | + response = self.client.get(change_url) |
88 | 100 | self.assertIn(ELEVATE_URL, response["Location"]) |
| 101 | + self.assertEqual(len(mail.outbox), 0) |
89 | 102 |
|
90 | | - def test_elevated_passwordless_user_can_complete_email_change(self): |
91 | | - elevate_session(self) |
92 | | - signed = make_signed_value(self.user, NEW_EMAIL) |
93 | | - response = self.client.get(url_with_value(signed), follow=False) |
| 103 | + # With no password to enter, the elevate page offers an emailed code. |
| 104 | + send_code_url = reverse("users:elevate_send_confirm_access_email") |
| 105 | + self.assertContains(self.client.get(response["Location"]), send_code_url) |
| 106 | + |
| 107 | + next_query = urlencode({"next": change_url}) |
| 108 | + self.client.post(f"{send_code_url}?{next_query}") |
| 109 | + code = ConfirmAccessToken.objects.get(user=self.user).token |
| 110 | + response = self.client.post( |
| 111 | + f"{reverse('users:elevate_check_code')}?{next_query}", {"code": code} |
| 112 | + ) |
| 113 | + self.assertEqual(response["HX-Redirect"], change_url) |
| 114 | + |
| 115 | + mail.outbox.clear() |
| 116 | + response = self.client.get(change_url) |
94 | 117 | self.assertRedirects( |
95 | 118 | response, CONFIRM_LINK_SENT_URL, fetch_redirect_response=False |
96 | 119 | ) |
| 120 | + self.assertIn(NEW_EMAIL, [addr for msg in mail.outbox for addr in msg.to]) |
97 | 121 |
|
98 | 122 |
|
99 | 123 | class TestEmailChangeTokenValidation(TestCase): |
|
0 commit comments