import { assert, assertEquals } from "jsr:@std/assert@1"; import { ALL_PERMISSION_CODES, LEGACY_TO_V2, PROJECT_DOC_CATEGORIES, projectDocPerm, RESERVED_ROLE_CODES, ROLE_TEMPLATES, } from "./iam_catalog.ts"; import { filterSensitivePermissions } from "./permissions.ts"; import { assertProjectAccess, isOwnerAccountRow } from "./user_scope.ts"; Deno.test("IAM catálogo: permisos CRUD únicos", () => { const codes = new Set(ALL_PERMISSION_CODES); assertEquals(codes.size, ALL_PERMISSION_CODES.length); assert(codes.has("workers.view")); assert(codes.has("project_docs.tecnico.view")); assert(codes.has("users.view")); }); Deno.test("IAM: códigos de rol reservados", () => { assert(RESERVED_ROLE_CODES.has("tenant_admin")); assert(RESERVED_ROLE_CODES.has("user")); assert(!RESERVED_ROLE_CODES.has("supervisor_obra")); }); Deno.test("IAM: plantilla supervisor sin gastos ni IAM", () => { const sup = ROLE_TEMPLATES.supervisor_obra.permissions; assert(sup.includes("projects.view")); assert(sup.includes("project_docs.tecnico.view")); assert(!sup.some((p) => p.startsWith("expenses."))); assert(!sup.some((p) => p.startsWith("users."))); assert(!sup.some((p) => p.startsWith("settings."))); }); Deno.test("IAM: plantilla contador con gastos y costos", () => { const cont = ROLE_TEMPLATES.contador.permissions; assert(cont.includes("expenses.view")); assert(cont.includes("cost_control.view")); assert(!cont.some((p) => p.startsWith("project_docs."))); }); Deno.test("IAM: permisos sensibles filtrados para no propietario", () => { const input = ["workers.view", "users.create", "settings.update", "reports.view"]; const filtered = filterSensitivePermissions(input, false); assertEquals(filtered, ["workers.view", "reports.view"]); assertEquals(filterSensitivePermissions(input, true), input); }); Deno.test("IAM: alcance por obra", () => { const scope = { allProjects: false, projectIds: [10, 20], warehouseCentral: false, warehouseProjects: true }; assert(assertProjectAccess(scope, 10)); assert(!assertProjectAccess(scope, 99)); assert(assertProjectAccess({ ...scope, allProjects: true }, 99)); }); Deno.test("IAM: cuenta propietaria", () => { assert(isOwnerAccountRow({ is_owner: true })); assert(isOwnerAccountRow({ role_code: "tenant_admin" })); assert(!isOwnerAccountRow({ role_code: "supervisor" })); }); Deno.test("IAM: categorías documento obra", () => { for (const cat of PROJECT_DOC_CATEGORIES) { assertEquals(projectDocPerm(cat, "view"), `project_docs.${cat}.view`); } }); Deno.test("IAM: mapeo legacy a v2", () => { assert(LEGACY_TO_V2.manage_workers.includes("workers.view")); assert(LEGACY_TO_V2.manage_expenses.includes("cost_control.view")); });