Catalyst / admin/Synapse-Sonar 14.8 GB / 57.8 GB 40.0 GB free
Help Sign in

admin / Synapse-Sonar

public

Attack Surface Simulation

Code Issues Pull requests Pipelines Packages Security Insights Wiki Settings
Synapse-Sonar / synapse-sonar / lib / rbac.ts 1325 B · main
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { Role } from "@prisma/client";

/**
 * Coarse-grained permission catalog for the MVP. A permission is granted to a
 * role if it appears in that role's set. TENANT_ADMIN is a superset.
 */
export type Permission =
  | "asset:read"
  | "asset:write"
  | "graph:simulate" // run blast-radius
  | "integration:read"
  | "integration:write"
  | "user:read"
  | "user:manage" // invite / change role / disable
  | "rule:write";

const MATRIX: Record<Role, Permission[]> = {
  READ_ONLY_VIEWER: ["asset:read", "integration:read", "user:read"],
  SECURITY_ANALYST: [
    "asset:read",
    "asset:write",
    "graph:simulate",
    "integration:read",
    "user:read",
    "rule:write",
  ],
  TENANT_ADMIN: [
    "asset:read",
    "asset:write",
    "graph:simulate",
    "integration:read",
    "integration:write",
    "user:read",
    "user:manage",
    "rule:write",
  ],
};

export function can(role: Role, permission: Permission): boolean {
  return MATRIX[role]?.includes(permission) ?? false;
}

/** Throws a 403-shaped error when the role lacks the permission. */
export function assertCan(role: Role, permission: Permission): void {
  if (!can(role, permission)) {
    const err = new Error(`Forbidden: role ${role} lacks ${permission}`);
    (err as Error & { status?: number }).status = 403;
    throw err;
  }
}