fix: undo no longer fails with a 400 in a signed-in browser
Undo ends every session of the user, including the one that opened the link; saving that deleted session at the end of the request made Django answer 400 although the address had been restored. The view now drops its own session (as sign-out does), also on the unclear-outcome page. Tests for both cases from a signed-in browser. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FocPJ75XPma7TcuYEMy8zm
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
94c1d39c9d
commit
3c11eef457
@@ -266,5 +266,18 @@ def email_undo(request, token):
|
||||
except DirectoryUnavailable:
|
||||
return _unavailable(request)
|
||||
except services.OutcomeUnknown:
|
||||
_drop_own_session(request)
|
||||
return render(request, "profile/email_unknown.html", status=500)
|
||||
_drop_own_session(request)
|
||||
return render(request, "profile/email_undone.html")
|
||||
|
||||
|
||||
def _drop_own_session(request):
|
||||
"""Undo ends every session of the user, also the one that opened the link.
|
||||
|
||||
Its row is gone, so saving it at the end of the request would fail with a 400; flushing it
|
||||
clears the cookie instead.
|
||||
"""
|
||||
session = getattr(request, "session", None)
|
||||
if session is not None:
|
||||
session.flush()
|
||||
|
||||
@@ -440,6 +440,19 @@ def test_undoing_restores_the_address_ends_the_sessions_and_tells_the_admin(peop
|
||||
assert Client().post(path).status_code == 410 and Client().get(path).status_code == 410
|
||||
|
||||
|
||||
def test_undoing_from_a_browser_that_is_still_signed_in_works(people, adapters):
|
||||
path = confirmed_undo_path(adapters)
|
||||
browser = signed_in(adapters) # the link is opened where the user is signed in
|
||||
response = browser.post(path)
|
||||
assert (
|
||||
response.status_code == 200
|
||||
and "Please change your password now." in response.content.decode()
|
||||
)
|
||||
assert mail_of(adapters) == OLD
|
||||
assert browser.get("/").status_code == 302 # its own session ended too
|
||||
assert UserSession.objects.filter(username="alice").count() == 0
|
||||
|
||||
|
||||
def test_undoing_also_drops_a_request_made_in_the_meantime(people, adapters):
|
||||
path = confirmed_undo_path(adapters)
|
||||
signed_in(adapters)
|
||||
@@ -593,6 +606,20 @@ def test_a_failure_after_the_undoing_write_still_ends_the_sessions(
|
||||
assert "user=alice" in caplog.text and OLD not in caplog.text
|
||||
|
||||
|
||||
def test_an_unclear_undo_from_a_signed_in_browser_shows_the_unclear_page(
|
||||
people, adapters, monkeypatch
|
||||
):
|
||||
path = confirmed_undo_path(adapters)
|
||||
browser = signed_in(adapters)
|
||||
|
||||
def broken(*args, **kwargs):
|
||||
raise RuntimeError("database trouble")
|
||||
|
||||
monkeypatch.setattr(services.mailer, "enqueue", broken)
|
||||
assert browser.post(path).status_code == 500 # not a 400 from its own ended session
|
||||
assert browser.get("/").status_code == 302
|
||||
|
||||
|
||||
def test_a_failure_before_any_write_leaves_the_request_clean(people, adapters, monkeypatch):
|
||||
client = signed_in(adapters)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user