fix(panel): 本人与所有者账户的禁用和删除按钮提前锁定并说明原因,角色改为只读,后端拒绝改用专用错误码 self_protected 与 owner_protected
This commit is contained in:
13 files changed
+269
-27
No files matched your search
@@ -392,6 +392,16 @@ describe("api access-control wire shapes", () => {
|
||||
expect(humanizeError({ code: "console_unavailable" })).toMatch(/console/i);
|
||||
});
|
||||
|
||||
it("says why a user change was refused for the caller's own or the owner account", async () => {
|
||||
const { humanizeError } = await import("./api");
|
||||
expect(humanizeError({ status: 403, code: "self_protected" })).toBe(
|
||||
"You can't do that to the account you're signed in with.",
|
||||
);
|
||||
expect(humanizeError({ status: 403, code: "owner_protected" })).toBe(
|
||||
"The owner account can't be demoted, disabled or deleted from the panel. Only the host's break-glass console (sudo felis breakGlass) manages it.",
|
||||
);
|
||||
});
|
||||
|
||||
it("maps the backup rationing codes to their own copy", async () => {
|
||||
const { humanizeError } = await import("./api");
|
||||
expect(humanizeError({ code: "backup_cooldown" })).toMatch(/cooldown/i);
|
||||
|
||||
@@ -822,6 +822,12 @@ export function humanizeError(e: unknown): string {
|
||||
return t("passkey_unavailable");
|
||||
case "last_passkey":
|
||||
return t("last_passkey");
|
||||
// User admin (internal/api/handlers_users.go): the caller's own account and
|
||||
// the owner account are refused, each for its own reason.
|
||||
case "self_protected":
|
||||
return t("self_protected");
|
||||
case "owner_protected":
|
||||
return t("owner_protected");
|
||||
case "quota_exceeded":
|
||||
return t("quota_exceeded");
|
||||
case "already_claimed":
|
||||
|
||||
@@ -5205,7 +5205,15 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
401: components["responses"]["Unauthorized"];
|
||||
403: components["responses"]["Forbidden"];
|
||||
/** @description Not an owner (forbidden); the caller's own account (self_protected); or the owner account (owner_protected), which only the host's break-glass console (sudo felis breakGlass) may remove. */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["Error"];
|
||||
};
|
||||
};
|
||||
404: components["responses"]["NotFound"];
|
||||
};
|
||||
};
|
||||
@@ -5241,7 +5249,15 @@ export interface operations {
|
||||
};
|
||||
400: components["responses"]["BadRequest"];
|
||||
401: components["responses"]["Unauthorized"];
|
||||
403: components["responses"]["Forbidden"];
|
||||
/** @description Not an owner (forbidden); a change to the caller's own role (self_protected); or a role change on the owner account (owner_protected), which only the host's break-glass console (sudo felis breakGlass) may make. */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["Error"];
|
||||
};
|
||||
};
|
||||
404: components["responses"]["NotFound"];
|
||||
/** @description Username conflict. */
|
||||
409: {
|
||||
@@ -5284,7 +5300,15 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
401: components["responses"]["Unauthorized"];
|
||||
403: components["responses"]["Forbidden"];
|
||||
/** @description Not an owner (forbidden); the caller's own account (self_protected); or disabling the owner account (owner_protected). Re-enabling the owner is allowed. */
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["Error"];
|
||||
};
|
||||
};
|
||||
404: components["responses"]["NotFound"];
|
||||
};
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user