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:
|
except DirectoryUnavailable:
|
||||||
return _unavailable(request)
|
return _unavailable(request)
|
||||||
except services.OutcomeUnknown:
|
except services.OutcomeUnknown:
|
||||||
|
_drop_own_session(request)
|
||||||
return render(request, "profile/email_unknown.html", status=500)
|
return render(request, "profile/email_unknown.html", status=500)
|
||||||
|
_drop_own_session(request)
|
||||||
return render(request, "profile/email_undone.html")
|
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
|
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):
|
def test_undoing_also_drops_a_request_made_in_the_meantime(people, adapters):
|
||||||
path = confirmed_undo_path(adapters)
|
path = confirmed_undo_path(adapters)
|
||||||
signed_in(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
|
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):
|
def test_a_failure_before_any_write_leaves_the_request_clean(people, adapters, monkeypatch):
|
||||||
client = signed_in(adapters)
|
client = signed_in(adapters)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user