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.
-
-
-