first commit

This commit is contained in:
Matt Kane
2026-04-01 10:44:22 +01:00
commit 43fcb9a131
1789 changed files with 395041 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
import { describe, it, expect } from "vitest";
import {
hasPermission,
requirePermission,
canActOnOwn,
requirePermissionOnResource,
PermissionError,
} from "./rbac.js";
import { Role } from "./types.js";
describe("rbac", () => {
describe("hasPermission", () => {
it("returns false for null user", () => {
expect(hasPermission(null, "content:read")).toBe(false);
});
it("returns false for undefined user", () => {
expect(hasPermission(undefined, "content:read")).toBe(false);
});
it("allows subscriber to read content", () => {
expect(hasPermission({ role: Role.SUBSCRIBER }, "content:read")).toBe(true);
});
it("denies subscriber from creating content", () => {
expect(hasPermission({ role: Role.SUBSCRIBER }, "content:create")).toBe(false);
});
it("allows contributor to create content", () => {
expect(hasPermission({ role: Role.CONTRIBUTOR }, "content:create")).toBe(true);
});
it("allows admin to do anything", () => {
const admin = { role: Role.ADMIN };
expect(hasPermission(admin, "content:read")).toBe(true);
expect(hasPermission(admin, "content:create")).toBe(true);
expect(hasPermission(admin, "users:manage")).toBe(true);
expect(hasPermission(admin, "schema:manage")).toBe(true);
});
it("denies editor from managing users", () => {
expect(hasPermission({ role: Role.EDITOR }, "users:manage")).toBe(false);
});
it("allows author to edit own media", () => {
expect(hasPermission({ role: Role.AUTHOR }, "media:edit_own")).toBe(true);
});
it("denies contributor from editing media", () => {
expect(hasPermission({ role: Role.CONTRIBUTOR }, "media:edit_own")).toBe(false);
});
it("allows editor to edit any media", () => {
expect(hasPermission({ role: Role.EDITOR }, "media:edit_any")).toBe(true);
});
it("denies author from editing any media", () => {
expect(hasPermission({ role: Role.AUTHOR }, "media:edit_any")).toBe(false);
});
});
describe("requirePermission", () => {
it("throws for null user", () => {
expect(() => requirePermission(null, "content:read")).toThrow(PermissionError);
});
it("throws unauthorized for missing user", () => {
try {
requirePermission(null, "content:read");
} catch (e) {
expect(e).toBeInstanceOf(PermissionError);
expect((e as PermissionError).code).toBe("unauthorized");
}
});
it("throws forbidden for insufficient permissions", () => {
try {
requirePermission({ role: Role.SUBSCRIBER }, "content:create");
} catch (e) {
expect(e).toBeInstanceOf(PermissionError);
expect((e as PermissionError).code).toBe("forbidden");
}
});
it("does not throw for sufficient permissions", () => {
expect(() => requirePermission({ role: Role.ADMIN }, "content:create")).not.toThrow();
});
});
describe("canActOnOwn", () => {
const user = { role: Role.AUTHOR, id: "user-1" };
it("allows action on own resource with own permission", () => {
expect(canActOnOwn(user, "user-1", "content:edit_own", "content:edit_any")).toBe(true);
});
it("denies action on others resource without any permission", () => {
expect(canActOnOwn(user, "user-2", "content:edit_own", "content:edit_any")).toBe(false);
});
it("allows editor to edit any resource", () => {
const editor = { role: Role.EDITOR, id: "editor-1" };
expect(canActOnOwn(editor, "user-2", "content:edit_own", "content:edit_any")).toBe(true);
});
it("allows author to edit own media", () => {
expect(canActOnOwn(user, "user-1", "media:edit_own", "media:edit_any")).toBe(true);
});
it("denies author from editing others media", () => {
expect(canActOnOwn(user, "user-2", "media:edit_own", "media:edit_any")).toBe(false);
});
it("denies contributor from editing any media (including own)", () => {
const contributor = { role: Role.CONTRIBUTOR, id: "contrib-1" };
expect(canActOnOwn(contributor, "contrib-1", "media:edit_own", "media:edit_any")).toBe(false);
});
it("allows editor to edit any media", () => {
const editor = { role: Role.EDITOR, id: "editor-1" };
expect(canActOnOwn(editor, "user-2", "media:edit_own", "media:edit_any")).toBe(true);
});
});
describe("requirePermissionOnResource", () => {
it("allows author to edit own content", () => {
const user = { role: Role.AUTHOR, id: "user-1" };
expect(() =>
requirePermissionOnResource(user, "user-1", "content:edit_own", "content:edit_any"),
).not.toThrow();
});
it("throws for author editing others content", () => {
const user = { role: Role.AUTHOR, id: "user-1" };
expect(() =>
requirePermissionOnResource(user, "user-2", "content:edit_own", "content:edit_any"),
).toThrow(PermissionError);
});
});
});