mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
fix(api): read the error code before the status
A read-failure primitive decided from the status alone, so a 401 from a step-up or re-proof gate would have read as an ended session and sent the reader to sign-in. The code now decides first and the status is the fallback for codes it does not know. The two invitation routes answer an unknown name or e-mail with sharing.invite.no_account. Both have a second 404 with a different next step, and since every error now carries a code the clients match on it instead of on the status. The status defaults move into a module the client can import, and the contract text no longer says these arms carry no code.
This commit is contained in:
1 parent
0057b03699
commit
c300574a8e
20 files changed
+212
-128
No files matched your search
@@ -718,16 +718,17 @@ describe("every call the managed-profile card can make", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("answers an unknown identifier with a 404 carrying NO error code", async () => {
|
||||
// The asymmetry the client has to branch on status for. Four arms of this
|
||||
// route publish a code; this one and the rate limit do not.
|
||||
it("answers an unknown identifier with a 404 that names itself", async () => {
|
||||
// This route has a second 404 (`managed_profile.not_found`) with a
|
||||
// different next step, so the unknown name carries its own code and a
|
||||
// client never has to tell the two apart by status.
|
||||
const { creator, profile } = await profileWithPendingSecondGuardian();
|
||||
signIn(creator);
|
||||
const response = await inviteGuardian(profile.id, {
|
||||
identifier: "nobody-here",
|
||||
});
|
||||
expect(response.status).toBe(404);
|
||||
expect(await errorCodeOf(response)).toBeUndefined();
|
||||
expect(await errorCodeOf(response)).toBe("sharing.invite.no_account");
|
||||
});
|
||||
|
||||
it("refuses an invitation from somebody who is not a Guardian", async () => {
|
||||
@@ -947,9 +948,9 @@ describe("how many profiles one account may create in an hour", () => {
|
||||
timezone: "UTC",
|
||||
});
|
||||
expect(refused.status).toBe(429);
|
||||
// No error code, like every other rate-limit refusal in this family — the
|
||||
// client branches on status, which is recorded in the findings.
|
||||
expect(await errorCodeOf(refused)).toBeUndefined();
|
||||
// The status default. A 429 has one meaning in this family (wait), so the
|
||||
// client branches on the status and needs no code of its own.
|
||||
expect(await errorCodeOf(refused)).toBe("http.rate_limited");
|
||||
// And nothing was created by the refused call.
|
||||
expect(
|
||||
await getPrismaClient().user.count({
|
||||
|
||||
@@ -491,6 +491,8 @@ describe("who may do what to a grant", () => {
|
||||
|
||||
const response = await invite("nobody-here@example.test");
|
||||
expect(response.status).toBe(404);
|
||||
const body = (await response.json()) as { meta?: { errorCode?: string } };
|
||||
expect(body.meta?.errorCode).toBe("sharing.invite.no_account");
|
||||
expect(await getPrismaClient().accountGrant.count()).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user