Add public registration cancellation
This commit is contained in:
parent
8170373148
commit
d5a5fed69a
7 changed files with 174 additions and 8 deletions
|
|
@ -68,6 +68,23 @@ class RegistrationVerificationAdapterTests(unittest.TestCase):
|
|||
with self.assertRaisesRegex(RuntimeError, "wrong purpose"):
|
||||
adapter.consume("x" * 32)
|
||||
|
||||
@patch("user_engine.adapters.registration_verification.urlopen")
|
||||
def test_cancel_requires_cancellation_purpose(self, opener):
|
||||
opener.return_value = Response(json.dumps({
|
||||
"purpose": "public-registration-cancel",
|
||||
"verification_id": "fvc_1", "registration_id": "reg_1",
|
||||
"email": "person@example.test", "preferred_username": "person",
|
||||
"client_id": "coulomb-social", "tenant": "tenant:coulomb",
|
||||
"source_system": "mail-verifier",
|
||||
"assurance": {"mailbox_control": True},
|
||||
}).encode())
|
||||
adapter = HTTPRegistrationVerificationAdapter(
|
||||
base_url="http://verification", bearer_token="secret"
|
||||
)
|
||||
evidence = adapter.cancel("x" * 32)
|
||||
self.assertEqual("reg_1", evidence.registration_id)
|
||||
self.assertTrue(opener.call_args.args[0].full_url.endswith("/cancel"))
|
||||
|
||||
@patch("user_engine.adapters.registration_verification.urlopen")
|
||||
def test_expired_and_replayed_handles_have_the_same_redacted_failure(self, opener):
|
||||
adapter = HTTPRegistrationVerificationAdapter(
|
||||
|
|
|
|||
|
|
@ -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"):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue