127 lines
7.0 KiB
TypeScript
127 lines
7.0 KiB
TypeScript
import { describe, expect, test, vi } from "vitest";
|
|
|
|
vi.mock("~/utils/db/entities/entities.db.server", () => ({ getAllEntities: vi.fn() }));
|
|
vi.mock("~/utils/db/permissions/permissions.db.server", () => ({ createPermissions: vi.fn(), getAllPermissions: vi.fn() }));
|
|
vi.mock("~/utils/db/permissions/rolePermissions.db.server", () => ({ createRolePermission: vi.fn() }));
|
|
vi.mock("~/utils/db/permissions/roles.db.server", () => ({ createRole: vi.fn(), getAllRoles: vi.fn(), getRoleByName: vi.fn() }));
|
|
vi.mock("~/utils/db/permissions/userRoles.db.server", () => ({ createUserRole: vi.fn() }));
|
|
vi.mock("~/utils/db/tenants.db.server", () => ({ adminGetAllTenants: vi.fn() }));
|
|
vi.mock("~/utils/db/users.db.server", () => ({ adminGetAllUsers: vi.fn() }));
|
|
vi.mock("~/utils/helpers/PermissionsHelper", () => ({ getEntityPermissions: vi.fn() }));
|
|
|
|
import { DefaultAdminRoles } from "~/application/dtos/shared/DefaultAdminRoles";
|
|
import { DefaultAppRoles } from "~/application/dtos/shared/DefaultAppRoles";
|
|
import { DefaultPermission, DefaultPermissions } from "~/application/dtos/shared/DefaultPermissions";
|
|
import { defaultAdminRoles, defaultAppRoles, defaultPermissions } from "./rolesAndPermissionsService";
|
|
|
|
function duplicates(values: string[]) {
|
|
const seen = new Set<string>();
|
|
const duplicateValues = new Set<string>();
|
|
|
|
values.forEach((value) => {
|
|
if (seen.has(value)) {
|
|
duplicateValues.add(value);
|
|
}
|
|
seen.add(value);
|
|
});
|
|
|
|
return Array.from(duplicateValues).sort();
|
|
}
|
|
|
|
describe("default roles matrix", () => {
|
|
test("seeded admin roles are unique, typed as admin, and are not assigned to new users", () => {
|
|
const adminRoleNames = defaultAdminRoles.map((role) => role.name);
|
|
|
|
expect(duplicates(adminRoleNames), "duplicate default admin role names").toEqual([]);
|
|
expect(adminRoleNames.sort(), "seeded admin roles must match DefaultAdminRoles").toEqual(Object.values(DefaultAdminRoles).sort());
|
|
expect(
|
|
defaultAdminRoles.filter((role) => role.type !== "admin").map((role) => `${role.name}:${role.type}`),
|
|
"admin roles with unexpected type"
|
|
).toEqual([]);
|
|
expect(
|
|
defaultAdminRoles.filter((role) => role.assignToNewUsers).map((role) => role.name),
|
|
"operator admin roles must be assigned intentionally"
|
|
).toEqual([]);
|
|
});
|
|
|
|
test("seeded app roles are unique, typed as app, and only User is assigned to new users", () => {
|
|
const appRoleNames = defaultAppRoles.map((role) => role.name);
|
|
|
|
expect(duplicates(appRoleNames), "duplicate default app role names").toEqual([]);
|
|
expect(appRoleNames.sort(), "seeded app roles must match DefaultAppRoles").toEqual(Object.values(DefaultAppRoles).sort());
|
|
expect(
|
|
defaultAppRoles.filter((role) => role.type !== "app").map((role) => `${role.name}:${role.type}`),
|
|
"app roles with unexpected type"
|
|
).toEqual([]);
|
|
expect(
|
|
defaultAppRoles.filter((role) => role.assignToNewUsers).map((role) => role.name),
|
|
"only User should be assigned to new app users"
|
|
).toEqual([DefaultAppRoles.User]);
|
|
});
|
|
});
|
|
|
|
describe("default permissions matrix", () => {
|
|
const defaultRoleNames = new Set([...defaultAdminRoles.map((role) => role.name), ...defaultAppRoles.map((role) => role.name)]);
|
|
|
|
function seedDefinitionsFor(permissionName: DefaultPermission) {
|
|
return defaultPermissions.filter((permission) => permission.name === permissionName);
|
|
}
|
|
|
|
test("permission names are unique and every inRoles target exists in default roles", () => {
|
|
const permissionNames = defaultPermissions.map((permission) => permission.name);
|
|
const orphanRoleTargets = defaultPermissions.flatMap((permission) =>
|
|
permission.inRoles.filter((roleName) => !defaultRoleNames.has(roleName)).map((roleName) => `${permission.name} -> ${roleName}`)
|
|
);
|
|
|
|
expect(duplicates(permissionNames), "duplicate default permission names").toEqual([]);
|
|
expect(orphanRoleTargets, "permissions targeting missing default roles").toEqual([]);
|
|
});
|
|
|
|
test("every DefaultPermissions entry has exactly one seed definition", () => {
|
|
const seedCounts = new Map(defaultPermissions.map((permission) => [permission.name, 0]));
|
|
|
|
defaultPermissions.forEach((permission) => {
|
|
seedCounts.set(permission.name, (seedCounts.get(permission.name) ?? 0) + 1);
|
|
});
|
|
|
|
const missingSeedDefinitions = DefaultPermissions.filter((permissionName) => !seedCounts.has(permissionName));
|
|
const duplicateSeedDefinitions = Array.from(seedCounts.entries())
|
|
.filter(([, count]) => count !== 1)
|
|
.map(([permissionName, count]) => `${permissionName}:${count}`);
|
|
const nonEnumSeedDefinitions = defaultPermissions
|
|
.map((permission) => permission.name)
|
|
.filter((permissionName) => !DefaultPermissions.includes(permissionName));
|
|
|
|
expect(missingSeedDefinitions, "DefaultPermissions entries missing from defaultPermissions seeds").toEqual([]);
|
|
expect(duplicateSeedDefinitions, "DefaultPermissions entries with duplicate seed definitions").toEqual([]);
|
|
expect(nonEnumSeedDefinitions, "defaultPermissions seed definitions missing from DefaultPermissions").toEqual([]);
|
|
});
|
|
|
|
test("audit permissions are seeded once and assigned only to intended default roles", () => {
|
|
const adminAuditPermissionName = "admin.auditTrails.view";
|
|
const appAuditPermissionName = "app.settings.auditTrails.view";
|
|
const expectedAdminAuditRoles = [DefaultAdminRoles.SuperAdmin];
|
|
const expectedAppAuditRoles = [DefaultAppRoles.SuperUser, DefaultAppRoles.Admin];
|
|
|
|
const adminAuditSeedDefinitions = seedDefinitionsFor(adminAuditPermissionName);
|
|
const appAuditSeedDefinitions = seedDefinitionsFor(appAuditPermissionName);
|
|
const adminAuditEnumEntries = DefaultPermissions.filter((permissionName) => permissionName === adminAuditPermissionName);
|
|
const appAuditEnumEntries = DefaultPermissions.filter((permissionName) => permissionName === appAuditPermissionName);
|
|
|
|
expect(adminAuditSeedDefinitions, `${adminAuditPermissionName} must have exactly one defaultPermissions seed definition`).toHaveLength(1);
|
|
expect(adminAuditEnumEntries, `${adminAuditPermissionName} must exist exactly once in DefaultPermissions`).toHaveLength(1);
|
|
expect(
|
|
[...(adminAuditSeedDefinitions[0]?.inRoles ?? [])].sort(),
|
|
`${adminAuditPermissionName} must target SuperAdmin only`
|
|
).toEqual([...expectedAdminAuditRoles].sort());
|
|
|
|
expect(appAuditSeedDefinitions, `${appAuditPermissionName} must have exactly one defaultPermissions seed definition`).toHaveLength(1);
|
|
expect(appAuditEnumEntries, `${appAuditPermissionName} must exist exactly once in DefaultPermissions`).toHaveLength(1);
|
|
expect([...(appAuditSeedDefinitions[0]?.inRoles ?? [])].sort(), `${appAuditPermissionName} must target SuperUser and Admin only`).toEqual(
|
|
[...expectedAppAuditRoles].sort()
|
|
);
|
|
expect(appAuditSeedDefinitions[0]?.inRoles, `${appAuditPermissionName} must not target User`).not.toContain(DefaultAppRoles.User);
|
|
expect(appAuditSeedDefinitions[0]?.inRoles, `${appAuditPermissionName} must not target Billing Admin`).not.toContain(DefaultAppRoles.BillingAdmin);
|
|
});
|
|
});
|