From 7893c787b8a62beb36cd4682a6383cf87e8f7a7f Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Thu, 22 Jan 2026 18:48:19 -0300 Subject: [PATCH] onboarding: reveal temp password on demand --- .../atlas_portal/routes/access_requests.py | 16 ++-- backend/tests/test_access_requests.py | 46 +++++++++++ frontend/src/views/OnboardingView.vue | 77 ++++++++----------- 3 files changed, 90 insertions(+), 49 deletions(-) diff --git a/backend/atlas_portal/routes/access_requests.py b/backend/atlas_portal/routes/access_requests.py index 9740b05..25a1a6a 100644 --- a/backend/atlas_portal/routes/access_requests.py +++ b/backend/atlas_portal/routes/access_requests.py @@ -694,6 +694,9 @@ def register(app) -> None: code = (payload.get("request_code") or payload.get("code") or "").strip() if not code: return jsonify({"error": "request_code is required"}), 400 + reveal_initial_password = bool( + payload.get("reveal_initial_password") or payload.get("reveal_password") + ) if not rate_limit_allow( f"{ip}:{code}", @@ -852,15 +855,16 @@ def register(app) -> None: response["tasks"] = tasks response["automation_complete"] = provision_tasks_complete(conn, code) response["blocked"] = blocked - if status in {"awaiting_onboarding", "ready"}: + if status in {"awaiting_onboarding", "ready"} and reveal_initial_password: password = row.get("initial_password") revealed_at = row.get("initial_password_revealed_at") - if isinstance(password, str) and password and revealed_at is None: + if isinstance(password, str) and password: response["initial_password"] = password - conn.execute( - "UPDATE access_requests SET initial_password_revealed_at = NOW() WHERE request_code = %s AND initial_password_revealed_at IS NULL", - (code,), - ) + if revealed_at is None: + conn.execute( + "UPDATE access_requests SET initial_password_revealed_at = NOW() WHERE request_code = %s AND initial_password_revealed_at IS NULL", + (code,), + ) if status in {"awaiting_onboarding", "ready"}: response["onboarding_url"] = f"/onboarding?code={code}" if status in {"awaiting_onboarding", "ready"}: diff --git a/backend/tests/test_access_requests.py b/backend/tests/test_access_requests.py index 10d77cf..51e9c14 100644 --- a/backend/tests/test_access_requests.py +++ b/backend/tests/test_access_requests.py @@ -226,3 +226,49 @@ class AccessRequestTests(TestCase): data = resp.get_json() self.assertEqual(resp.status_code, 200) self.assertTrue(data.get("email_verified")) + + def test_status_hides_initial_password_without_reveal_flag(self): + rows = { + "SELECT status": { + "status": "awaiting_onboarding", + "username": "alice", + "initial_password": "temp-pass", + "initial_password_revealed_at": None, + "email_verified_at": None, + } + } + with ( + mock.patch.object(ar, "connect", lambda: dummy_connect(rows)), + mock.patch.object(ar, "_advance_status", lambda *args, **kwargs: "awaiting_onboarding"), + ): + resp = self.client.post( + "/api/access/request/status", + data=json.dumps({"request_code": "alice~CODE123"}), + content_type="application/json", + ) + data = resp.get_json() + self.assertEqual(resp.status_code, 200) + self.assertIsNone(data.get("initial_password")) + + def test_status_reveals_initial_password_with_flag(self): + rows = { + "SELECT status": { + "status": "awaiting_onboarding", + "username": "alice", + "initial_password": "temp-pass", + "initial_password_revealed_at": None, + "email_verified_at": None, + } + } + with ( + mock.patch.object(ar, "connect", lambda: dummy_connect(rows)), + mock.patch.object(ar, "_advance_status", lambda *args, **kwargs: "awaiting_onboarding"), + ): + resp = self.client.post( + "/api/access/request/status", + data=json.dumps({"request_code": "alice~CODE123", "reveal_initial_password": True}), + content_type="application/json", + ) + data = resp.get_json() + self.assertEqual(resp.status_code, 200) + self.assertEqual(data.get("initial_password"), "temp-pass") diff --git a/frontend/src/views/OnboardingView.vue b/frontend/src/views/OnboardingView.vue index 77a11cf..b04ec9c 100644 --- a/frontend/src/views/OnboardingView.vue +++ b/frontend/src/views/OnboardingView.vue @@ -108,7 +108,7 @@
{{ index + 1 }}. {{ section.title }}
{{ sectionStatusLabel(section) }} - {{ sectionProgress(section) }} + {{ sectionProgress(section) }}
@@ -149,11 +149,6 @@

-
-

Log in to check off onboarding steps and verify your Element recovery key.

- -
-
@@ -294,7 +289,7 @@