portal: surface verified status #11

Merged
bstein merged 1 commits from feature/ariadne-integration-portal into master 2026-01-22 00:12:27 +00:00
3 changed files with 43 additions and 2 deletions

View File

@ -745,7 +745,15 @@ def register(app) -> None:
try: try:
with connect() as conn: with connect() as conn:
row = conn.execute( row = conn.execute(
"SELECT status, username, initial_password, initial_password_revealed_at FROM access_requests WHERE request_code = %s", """
SELECT status,
username,
initial_password,
initial_password_revealed_at,
email_verified_at
FROM access_requests
WHERE request_code = %s
""",
(code,), (code,),
).fetchone() ).fetchone()
if not row: if not row:
@ -757,7 +765,15 @@ def register(app) -> None:
except Exception: except Exception:
pass pass
row = conn.execute( row = conn.execute(
"SELECT status, username, initial_password, initial_password_revealed_at FROM access_requests WHERE request_code = %s", """
SELECT status,
username,
initial_password,
initial_password_revealed_at,
email_verified_at
FROM access_requests
WHERE request_code = %s
""",
(code,), (code,),
).fetchone() ).fetchone()
if not row: if not row:
@ -768,6 +784,7 @@ def register(app) -> None:
"ok": True, "ok": True,
"status": status, "status": status,
"username": row.get("username") or "", "username": row.get("username") or "",
"email_verified": bool(row.get("email_verified_at")),
} }
task_rows = conn.execute( task_rows = conn.execute(
""" """

View File

@ -206,3 +206,23 @@ class AccessRequestTests(TestCase):
resp = self.client.get(f"/api/access/request/verify-link?code=alice~CODE123&token={token}") resp = self.client.get(f"/api/access/request/verify-link?code=alice~CODE123&token={token}")
self.assertEqual(resp.status_code, 302) self.assertEqual(resp.status_code, 302)
self.assertIn("verified=1", resp.headers.get("Location", "")) self.assertIn("verified=1", resp.headers.get("Location", ""))
def test_status_includes_email_verified(self):
rows = {
"SELECT status": {
"status": "pending",
"username": "alice",
"initial_password": None,
"initial_password_revealed_at": None,
"email_verified_at": ar.datetime.now(ar.timezone.utc),
}
}
with mock.patch.object(ar, "connect", lambda: dummy_connect(rows)):
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.assertTrue(data.get("email_verified"))

View File

@ -442,6 +442,7 @@ async function copyRequestCode() {
async function checkStatus() { async function checkStatus() {
if (checking.value) return; if (checking.value) return;
error.value = ""; error.value = "";
verifyMessage.value = "";
const trimmed = statusForm.request_code.trim(); const trimmed = statusForm.request_code.trim();
if (!trimmed) return; if (!trimmed) return;
if (!trimmed.includes("~")) { if (!trimmed.includes("~")) {
@ -466,6 +467,9 @@ async function checkStatus() {
onboardingUrl.value = data.onboarding_url || ""; onboardingUrl.value = data.onboarding_url || "";
tasks.value = Array.isArray(data.tasks) ? data.tasks : []; tasks.value = Array.isArray(data.tasks) ? data.tasks : [];
blocked.value = Boolean(data.blocked); blocked.value = Boolean(data.blocked);
if (data.email_verified) {
verifyMessage.value = "Email confirmed.";
}
} catch (err) { } catch (err) {
error.value = err.message || "Failed to check status"; error.value = err.message || "Failed to check status";
status.value = "unknown"; status.value = "unknown";