aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/keyderive.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/keyderive.js18
1 files changed, 17 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js b/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
index a540a94..918ade3 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
@@ -368,7 +368,23 @@ async function loginAndRecover(username, password) {
body: JSON.stringify({ username, auth_key: authKey }),
});
- if (!resp.ok) throw new Error(`Login failed: ${await resp.text()}`);
+ if (!resp.ok) {
+ // The hub's `detail`, not the raw body: the sign-in page matches on it
+ // (`email_verification_required`, `account_locked`), and a message wrapped
+ // as "Login failed: {json}" matched nothing, so neither was ever shown.
+ const body = await resp.text();
+ let detail = body;
+ // `error` is the per-IP rate limiter's field (slowapi), `detail` everyone else's.
+ try {
+ const j = JSON.parse(body);
+ detail = j.detail || j.error || body;
+ } catch { /* not JSON */ }
+ const err = new Error(String(detail));
+ err.status = resp.status;
+ err.retryAfter = Number(resp.headers && resp.headers.get
+ ? resp.headers.get('Retry-After') : 0) || 0;
+ throw err;
+ }
const data = await resp.json();
const result = {