diff --git a/web/packages/accounts/components/two-factor/VerifyTwoFactor.tsx b/web/packages/accounts/components/two-factor/VerifyTwoFactor.tsx index 9f37cc52a3..0633a35060 100644 --- a/web/packages/accounts/components/two-factor/VerifyTwoFactor.tsx +++ b/web/packages/accounts/components/two-factor/VerifyTwoFactor.tsx @@ -38,7 +38,7 @@ export function VerifyTwoFactor(props: Props) { } catch (e) { resetForm(); const message = e instanceof Error ? e.message : ""; - setFieldError("otp", `${t("generic_error_retry")} ${message}`); + setFieldError("otp", `${t("generic_error_retry")} (${message})`); // Workaround (toggling shouldAutoFocus) to reset the focus back to // the first input field in case of errors. // https://github.com/devfolioco/react-otp-input/issues/420 diff --git a/web/packages/accounts/services/srp-remote.ts b/web/packages/accounts/services/srp-remote.ts index 1aad4ddb2a..4d860d2de3 100644 --- a/web/packages/accounts/services/srp-remote.ts +++ b/web/packages/accounts/services/srp-remote.ts @@ -1,3 +1,4 @@ +import { ensureOk, publicRequestHeaders } from "@/base/http"; import log from "@/base/log"; import { apiURL } from "@/base/origins"; import { ApiError, CustomError } from "@ente/shared/error"; @@ -131,19 +132,15 @@ export const completeSRPSetup = async ( }; export const createSRPSession = async (srpUserID: string, srpA: string) => { - try { - const resp = await HTTPService.post( - await apiURL("/users/srp/create-session"), - { - srpUserID, - srpA, - }, - ); - return resp.data as CreateSRPSessionResponse; - } catch (e) { - log.error("createSRPSession failed", e); - throw e; - } + const res = await fetch(await apiURL("/users/srp/create-session"), { + method: "POST", + headers: publicRequestHeaders(), + body: JSON.stringify({ srpUserID, srpA }), + }); + ensureOk(res); + const data = await res.json(); + // TODO: Use zod + return data as CreateSRPSessionResponse; }; export const verifySRPSession = async ( diff --git a/web/packages/base/http.ts b/web/packages/base/http.ts index 91f9b412dd..3eb98d9bae 100644 --- a/web/packages/base/http.ts +++ b/web/packages/base/http.ts @@ -72,6 +72,7 @@ export const authenticatedPublicAlbumsRequestHeaders = ({ */ export class HTTPError extends Error { res: Response; + details: Record; constructor(res: Response) { // Trim off any query parameters from the URL before logging, it may @@ -81,9 +82,10 @@ export class HTTPError extends Error { // necessarily the same as the request's URL. const url = new URL(res.url); url.search = ""; - super( - `Fetch failed: ${url.href}: HTTP ${res.status} ${res.statusText}`, - ); + super(`HTTP ${res.status} ${res.statusText} (${url.pathname})`); + + const requestID = res.headers.get("x-request-id"); + const details = { url: url.href, ...(requestID ? { requestID } : {}) }; // Cargo culted from // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#custom_error_types @@ -92,6 +94,7 @@ export class HTTPError extends Error { this.name = this.constructor.name; this.res = res; + this.details = details; } } @@ -100,7 +103,11 @@ export class HTTPError extends Error { * {@link Response} does not have a HTTP 2xx status. */ export const ensureOk = (res: Response) => { - if (!res.ok) throw new HTTPError(res); + if (!res.ok) { + const e = new HTTPError(res); + log.error(`${e.message} ${JSON.stringify(e.details)}`); + throw e; + } }; /** diff --git a/web/packages/shared/components/VerifyMasterPasswordForm.tsx b/web/packages/shared/components/VerifyMasterPasswordForm.tsx index 7e07cffa1d..76c52ee2fe 100644 --- a/web/packages/shared/components/VerifyMasterPasswordForm.tsx +++ b/web/packages/shared/components/VerifyMasterPasswordForm.tsx @@ -100,9 +100,7 @@ export default function VerifyMasterPasswordForm({ setFieldError(t("incorrect_password")); break; default: - setFieldError( - `${t("generic_error_retry")} ${e.message}`, - ); + setFieldError(t("generic_error")); } } }