Add public registration cancellation
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

This commit is contained in:
tegwick 2026-08-10 19:27:41 +02:00
parent 8170373148
commit d5a5fed69a
7 changed files with 174 additions and 8 deletions

View file

@ -284,6 +284,35 @@ class PortalApplicationTests(unittest.TestCase):
self.assertEqual("200 OK", completed["status"])
self.assertIn(b"Create password", html)
def test_public_registration_browser_cancellation_is_bound_and_terminal(self):
verifier = FakeRegistrationVerification()
self.app.registration_verification = verifier
self.app.registration_clients = frozenset({"coulomb-social"})
self.app.registration_tenants = frozenset({"tenant:coulomb"})
invoke(self.app, "/api/v1/public/registrations", method="POST", body={
"username": "cancel.person", "email": "cancel@example.test",
"client_id": "coulomb-social", "tenant": "tenant:coulomb",
})
verifier.registration_id = verifier.requested.registration_id
confirmation, html = invoke(
self.app, "/registration/cancel", query="handle=" + "x" * 32
)
cookie = confirmation["headers"]["Set-Cookie"]
token = re.search(rb'name="csrf_token" value="([^"]+)"', html).group(1).decode()
canceled, html = invoke(
self.app, "/registration/cancel", method="POST", cookie=cookie,
form={"csrf_token": token, "handle": "x" * 32},
)
self.assertEqual("200 OK", canceled["status"])
self.assertIn(b"Registration canceled", html)
session = self.app.service.store.registration_session(verifier.registration_id)
self.assertEqual("abandoned", session.status.value)
verify, _ = invoke(
self.app, "/api/v1/public/registrations/verify", method="POST",
body={"handle": "x" * 32}, remote_addr="127.0.0.2",
)
self.assertEqual("400 Bad Request", verify["status"])
def test_public_registration_rejects_untrusted_password_setup_origin(self):
verifier = FakeRegistrationVerification()
self.app.registration_verification = verifier
@ -885,6 +914,9 @@ class FakeRegistrationVerification:
display_name=self.requested.display_name,
)
def cancel(self, opaque_handle):
return self.consume(opaque_handle)
class FakeProvisioning:
def __init__(self, password_setup_url="https://kc.example/setup/password?token=opaque"):