fix(panel): 收到角色拒绝的 403 时限频重读身份,被降权的管理员随即失去管理页

This commit is contained in:
Lemon-miaow committed 2026-09-27 15:57:31 +08:00
1 parent 5282d55214
commit 2c6e29fa0d
4 files changed
+89 -7

No files matched your search

+16 -1
View File
@@ -12,7 +12,7 @@ vi.mock("./config", () => ({
}));
// Imported after the mock so api.ts picks up the mocked loadConfig.
const { api, SETUP_REQUIRED_EVENT, SESSION_EXPIRED_EVENT, CONNECTION_EVENT, humanizeError, isConnectionLost, clientError } =
const { api, SETUP_REQUIRED_EVENT, SESSION_EXPIRED_EVENT, ACCESS_REFUSED_EVENT, CONNECTION_EVENT, humanizeError, isConnectionLost, clientError } =
await import("./api");
function fakeFetch(body: unknown, init?: { ok?: boolean; status?: number }) {
@@ -1099,6 +1099,21 @@ describe("session and connection signals", () => {
expect(seen).toHaveLength(0);
});
it("announces a role refusal, and no other 403", async () => {
const seen = listen(ACCESS_REFUSED_EVENT);
const refuse = async (status: number, code: string) => {
vi.stubGlobal("fetch", fakeFetch({ error: { code, message: "x" } }, { ok: false, status }));
await expect(api.myServers()).rejects.toMatchObject({ status, code });
};
for (const code of ["reauth_required", "setup_required", "quota_exceeded", "local_auth_disabled"]) await refuse(403, code);
await refuse(409, "forbidden");
expect(seen).toHaveLength(0);
await refuse(403, "forbidden");
await refuse(403, "not_admin");
expect(seen).toHaveLength(2);
});
it("reports a fetch that got no response, and the next one that did", async () => {
const seen = listen(CONNECTION_EVENT);
vi.stubGlobal(