Permissions are a fixed list from plugin code; grant them on Users and Groups

This commit is contained in:
2026-08-05 14:29:15 +02:00
parent fb4382be9d
commit 29d654c012
35 changed files with 431 additions and 873 deletions
+13
View File
@@ -2,6 +2,7 @@ import assert from "node:assert/strict";
import { test } from "node:test";
import {
checkApiVersion,
declaredPermissions,
definePlugin,
findConflicts,
HOST_API_VERSION,
@@ -58,6 +59,18 @@ test("isValidPermissionName requires <resource>:<action> — a bare word names a
}
});
test("declaredPermissions is the catalog: every plugin's declarations, deduped by name and sorted", () => {
const a: Plugin = { apiVersion: "1.0.0", id: "a", permissions: [{ description: "Write things", name: "things:write" }, { description: "Read things", name: "things:read" }] };
const b: Plugin = { apiVersion: "1.0.0", id: "b", permissions: [{ description: "b's wording", name: "things:read" }, { name: "orders:read" }] };
const c: Plugin = { apiVersion: "1.0.0", id: "c" }; // declaring none is fine
const catalog = declaredPermissions([a, b, c]);
assert.deepEqual(catalog.map((p) => p.name), ["orders:read", "things:read", "things:write"]);
// A shared name is legitimate (findConflicts only warns); the first declaration wins its wording.
assert.equal(catalog.find((p) => p.name === "things:read")?.description, "Read things");
assert.deepEqual(declaredPermissions([]), []);
});
test("parseSemver follows the semver core, rejecting ranges, prefixes, leading zeros and missing parts", () => {
assert.deepEqual(parseSemver("1.2.3"), { major: 1, minor: 2, patch: 3 });
assert.deepEqual(parseSemver("1.2.3-rc.1+build.5"), { major: 1, minor: 2, patch: 3 }); // prerelease/build tolerated, ignored