From cab192d946390b647a8b161904967d1d2a576488 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Sivakumar Date: Mon, 27 Jul 2026 18:07:37 +0530 Subject: [PATCH] Fix job seeker document submission: hide raw storage URL, fix error masking Two issues in the job seeker (and shared profile) dashboard: - The uploaded document's full Backblaze URL was rendered as visible text and linked directly; view-document now resolves a short-lived signed URL on demand instead of exposing the permanent storage link. - "Submit for Verification" always showed a generic "Network error" message on any failure because request() throws on non-2xx responses, making the destructured status/data unreachable in the catch-free path (e.g. a 409 "verification already in progress" looked identical to a network failure). Now surfaces the real backend error message. Co-Authored-By: Claude Sonnet 5 --- src/components/dashboard/ProfilePage.tsx | 16 ++++++++-------- .../dashboard/VerificationStatusPage.tsx | 19 +++++++++++++------ src/lib/api.ts | 13 +++++++++++++ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/components/dashboard/ProfilePage.tsx b/src/components/dashboard/ProfilePage.tsx index eff635a..a9b7f55 100644 --- a/src/components/dashboard/ProfilePage.tsx +++ b/src/components/dashboard/ProfilePage.tsx @@ -859,7 +859,7 @@ export default function ProfilePage(props: Props) { setSubmitting(true); setSubmitMsg(""); try { - const { data, status } = await request("/api/profile/submit-for-verification", { + const { status } = await request("/api/profile/submit-for-verification", { method: "POST", body: { roleKey: props.roleKey, profile_data: { ...form(), ...docUrls() } }, }); @@ -867,13 +867,13 @@ export default function ProfilePage(props: Props) { setVerificationStatus("PENDING"); props.onVerificationStatusChange?.("PENDING"); setSubmitMsg("Submitted! We will review your profile and notify you."); - } else if (status === 409) { - setSubmitMsg(data?.error ?? "A verification is already in progress."); - } else { - setSubmitMsg(data?.error ?? "Submission failed. Please try again."); } - } catch { - setSubmitMsg("Network error. Please try again."); + } catch (err: any) { + // request() throws on any non-2xx response with the backend's actual error + // message (e.g. "A verification is already in progress...") — surface that + // instead of a generic message, otherwise every failure looks identical and + // unactionable regardless of cause. + setSubmitMsg(err?.message || "Submission failed. Please try again."); } finally { setSubmitting(false); } @@ -1241,7 +1241,7 @@ export default function ProfilePage(props: Props) { "border-radius": "6px", }} > - ✓ {docUrls()[doc.key]} + ✓ Uploaded

{ return res?.data ?? []; } +/** + * Resolve a stored document reference into a short-lived, signed view URL. + * Never render a stored document URL directly (e.g. as an or ) + * — always exchange it for a fresh one through this endpoint first. + */ +export async function presignDocumentUrl(url: string): Promise { + const res = await apiFetch('/api/profile/documents/presign', { + method: 'POST', + body: JSON.stringify({ url }), + }); + return res?.url ?? url; +} + export async function submitProfileForVerification(rolePrefix: string): Promise { return apiFetch(`/api/${rolePrefix}/profile/submit`, { method: 'POST',