diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/keyderive.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/keyderive.js | 18 |
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 = { |