feat(rbac): hide unauthorized menu sections and enforce route guards
This commit is contained in:
103
frontend/src/lib/auth/__tests__/permissions.test.js
Normal file
103
frontend/src/lib/auth/__tests__/permissions.test.js
Normal file
@@ -0,0 +1,103 @@
|
||||
// [DEF:frontend.src.lib.auth.__tests__.permissions:Module]
|
||||
// @TIER: STANDARD
|
||||
// @SEMANTICS: tests, auth, permissions, rbac
|
||||
// @PURPOSE: Verifies frontend RBAC permission parsing and access checks.
|
||||
// @LAYER: UI (Tests)
|
||||
// @RELATION: TESTS -> frontend/src/lib/auth/permissions.js
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
normalizePermissionRequirement,
|
||||
isAdminUser,
|
||||
hasPermission,
|
||||
} from "../permissions.js";
|
||||
|
||||
describe("auth.permissions", () => {
|
||||
it("normalizes resource-only requirement with default READ action", () => {
|
||||
expect(normalizePermissionRequirement("admin:settings")).toEqual({
|
||||
resource: "admin:settings",
|
||||
action: "READ",
|
||||
});
|
||||
});
|
||||
|
||||
it("normalizes explicit resource:action requirement", () => {
|
||||
expect(normalizePermissionRequirement("admin:settings:write")).toEqual({
|
||||
resource: "admin:settings",
|
||||
action: "WRITE",
|
||||
});
|
||||
});
|
||||
|
||||
it("detects admin role case-insensitively", () => {
|
||||
const user = {
|
||||
roles: [{ name: "ADMIN" }],
|
||||
};
|
||||
expect(isAdminUser(user)).toBe(true);
|
||||
});
|
||||
|
||||
it("denies when user is absent and permission is required", () => {
|
||||
expect(hasPermission(null, "tasks", "READ")).toBe(false);
|
||||
});
|
||||
|
||||
it("grants when permission object matches resource and action", () => {
|
||||
const user = {
|
||||
roles: [
|
||||
{
|
||||
name: "Operator",
|
||||
permissions: [{ resource: "tasks", action: "READ" }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(hasPermission(user, "tasks", "READ")).toBe(true);
|
||||
});
|
||||
|
||||
it("grants when requirement is provided as resource:action", () => {
|
||||
const user = {
|
||||
roles: [
|
||||
{
|
||||
name: "Operator",
|
||||
permissions: [{ resource: "admin:settings", action: "READ" }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(hasPermission(user, "admin:settings:READ")).toBe(true);
|
||||
});
|
||||
|
||||
it("grants when string permission entry matches", () => {
|
||||
const user = {
|
||||
roles: [
|
||||
{
|
||||
name: "Operator",
|
||||
permissions: ["plugin:migration:READ"],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(hasPermission(user, "plugin:migration", "READ")).toBe(true);
|
||||
});
|
||||
|
||||
it("denies when action does not match", () => {
|
||||
const user = {
|
||||
roles: [
|
||||
{
|
||||
name: "Operator",
|
||||
permissions: [{ resource: "tasks", action: "READ" }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(hasPermission(user, "tasks", "WRITE")).toBe(false);
|
||||
});
|
||||
|
||||
it("always grants for admin role regardless of explicit permissions", () => {
|
||||
const adminUser = {
|
||||
roles: [{ name: "Admin", permissions: [] }],
|
||||
};
|
||||
|
||||
expect(hasPermission(adminUser, "admin:users", "READ")).toBe(true);
|
||||
expect(hasPermission(adminUser, "plugin:migration", "EXECUTE")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
// [/DEF:frontend.src.lib.auth.__tests__.permissions:Module]
|
||||
Reference in New Issue
Block a user