pr_01m47d24b0e6n91zwymwxg0vpx/services/deployments/src/access.test.ts

60 lines2,873 bytesCodeBlame
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { Project, User } from "@g1t/contracts";
5
6import { can, needs, permission } from "../../../packages/contracts/src/access.ts";
7import { NEEDS, repoRef, type Method } from "./access.ts";
8
9const project = (isPrivate: boolean): Project => ({
10 id: "prj_1",
11 workspace: "acme",
12 slug: "web",
13 name: "web",
14 description: null,
15 source: { kind: "hosted", repoId: "repo_web", repo: { namespace: "acme", name: "web" }, rootDir: "", defaultBranch: "main" },
16 private: isPrivate,
17 archived: false,
18 primary: true,
19 createdBy: "ada",
20 createdAt: "2026-10-01T00:00:00Z",
21 updatedAt: "2026-10-01T00:00:00Z",
22});
23
24const person = (extra: Partial<User>): User => ({ id: "u", username: "u", kind: "user", verified: true, workspaces: [], ...extra }) as User;
25const collaborator = (role: "read" | "write" | "admin") => person({ grants: [{ repo_id: "repo_web", workspace: "acme", role }] });
26
27const allowed = (viewer: User | null, method: Method, isPrivate = true) => can(viewer, repoRef(project(isPrivate)), NEEDS[method]);
28
29test("a Read collaborator sees a project's deployments but cannot deploy or change them", () => {
30 const reader = collaborator("read");
31 for (const method of ["settings", "list", "get", "listDomains"] as const) assert.ok(allowed(reader, method), method);
32 for (const method of ["redeploy", "stack", "takeDown", "updateSettings", "addDomain"] as const) assert.ok(!allowed(reader, method), method);
33 assert.equal(needs(NEEDS.redeploy), "Needs the Write role or higher.");
34});
35
36test("an outside collaborator with Write can deploy, but settings and domains need Admin", () => {
37 const writer = collaborator("write");
38 assert.ok(allowed(writer, "redeploy"));
39 assert.ok(allowed(writer, "takeDown"));
40 assert.ok(!allowed(writer, "updateSettings"));
41 assert.ok(!allowed(writer, "addDomain"));
42 assert.equal(needs(NEEDS.addDomain), "Needs the Admin role or higher.");
43 assert.ok(allowed(collaborator("admin"), "addDomain"));
44});
45
46test("members follow the workspace's base permission; owners manage everything", () => {
47 const member = person({ workspaces: [{ slug: "acme", role: "member" }] });
48 assert.ok(allowed(member, "redeploy"), "Write by default");
49 assert.ok(!allowed(member, "updateSettings"));
50 const none = person({ workspaces: [{ slug: "acme", role: "member", base_permission: "none" }] });
51 assert.equal(permission(none, repoRef(project(true))), null, "a private project is not found");
52 const owner = person({ workspaces: [{ slug: "acme", role: "owner" }] });
53 assert.ok(allowed(owner, "updateSettings"));
54});
55
56test("anyone can see a public project's deployments, and no more", () => {
57 assert.ok(allowed(null, "list", false));
58 assert.ok(!allowed(null, "redeploy", false));
59 assert.equal(permission(null, repoRef(project(true))), null);
60});