mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
9dca13305f
* migration plus feature flag * show navigation route + inital roles migration * add a check permission use case to take in the feature flags for a team * bulk update script * inital frontend work for displaying roles * move to a more "anemic domain models" approach * update test to match new DDD strutcture * fix tests * update transaction call back types to include trx * align fe types after transaction to DDD * move away from usecases to a more domain tailored approach * get permissions per resource and map them to domain permission string * update permision logic * correctly get the logic for *.* permissions on owner * wip sheet logic for ssr * role list * use nuqs for sheet parsing on handle change * fox * improve hook usage * enable PBAC router * delete modal etc * i18n and inital rough layout of roles + permisions creating * add color to migrations * add colors and new method to tests * move hooks out of infra into client with provider * move hooks out of infra into client with provider * memo features and ensure render once * remove comment * seed color * use role colours * match i18n * add custom color picker to edit/create form * fix advanced mode toggle * more work on adv permission group * update migrations * abstract lots of core form logic to a custom hook * improve UX for selecting all and toggling all * improve code quality and use domain mappers in role repositoryu * call server action to revalidate cache * call invalidate cache on delete * fix re-render + improves update logic wip * fix txn for assinging role to member * wip on assigning users custom roles * fix repo * update logic for checking if users can update roles * remove member from permission check * check users permission and assign roles * move to factory approach * move default rolesIDs to constant * add facuted values to table * display custom role in table * fix type error * fix role filter * check pbac feature flag to see what column to filter on * push repo mocks and other mocks to fix unit tests * fix and add test for empty permissions when creating a role * pass updates to repo so we actually update roles * fix types * fix types * restore lock changes * fix role service test for new updates section * fix updated at types * update mocks to use feature repository mock * remove roletype from db in model * prevent multiple queries * fix typeof in role model * fix and migrate i18n to one registery * fix and update i18n to be in registery * fix type error + fall back in service instead of repo for BL * more type errors * update members faceted values to bennys refactor * fix types * remove the _resource from type conditionally * fix managment factory types to expose PBAC enbaled obol * narrow down types * wip fix for types * more fix types * cast role * fix tests * attempt of fixing _resoucre key access type * attempt of fixing _resoucre key access type * seperate migraations to batches * add invalidate time to team features * restore router to main * push main lock * Update packages/features/pbac/domain/types/permission-registry.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update packages/features/pbac/domain/mappers/PermissionMapper.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update packages/prisma/migrations/20250527091330_add_color_to_pbac_role/migration.sql Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update packages/prisma/migrations/20250617070118_update_memberships_one_time/migration.sql Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Update apps/web/app/(use-page-wrapper)/settings/(settings-layout)/organizations/roles/_components/AdvancedPermissionGroup.tsx Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * fix mapped type * restore migration * skip _resource * use partical * fix type errors in tests and hooks * Simplified the role field in the editSchema to use z.nativeEnum(MembershipRole) * fix type errors for editsheet * fix type errors for editsheet * Apply suggestion from comment 2151515295 * remove footer since we dont have docs yet * add i18n * lock all toggle chevron * use prisma * tidy up old manage permission * fix i18n * remove can manage from role permission check * auto select read * address benny feedback * fix type * fix type * update function name due to merge * fix types * update tests to match new membership method from merge * address cubic feedback --------- Co-authored-by: Eunjae Lee <[email protected]> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
145 lines
5.6 KiB
TypeScript
145 lines
5.6 KiB
TypeScript
import { describe, it, expect, beforeEach } from "vitest";
|
|
|
|
import type { PermissionString } from "../../domain/types/permission-registry";
|
|
import { CrudAction, PERMISSION_REGISTRY, Resource } from "../../domain/types/permission-registry";
|
|
import { PermissionService } from "../permission.service";
|
|
|
|
describe("PermissionService", () => {
|
|
let service: PermissionService;
|
|
|
|
beforeEach(() => {
|
|
service = new PermissionService();
|
|
});
|
|
|
|
describe("validatePermission", () => {
|
|
it("should validate a valid permission", () => {
|
|
const result = service.validatePermission("eventType.create" as PermissionString);
|
|
expect(result.isValid).toBe(true);
|
|
expect(result.error).toBeNull();
|
|
});
|
|
|
|
it("should reject an invalid permission", () => {
|
|
const result = service.validatePermission("invalid.action" as PermissionString);
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.error).toBe("Invalid permission: invalid.action");
|
|
});
|
|
|
|
it("should reject a malformed permission", () => {
|
|
const result = service.validatePermission("invalid-format" as PermissionString);
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.error).toBe("Invalid permission format: invalid-format");
|
|
});
|
|
});
|
|
|
|
describe("validatePermissions", () => {
|
|
it("should validate multiple valid permissions", () => {
|
|
const permissions = [
|
|
"eventType.create",
|
|
"team.invite",
|
|
"organization.manageBilling",
|
|
] as PermissionString[];
|
|
const result = service.validatePermissions(permissions);
|
|
expect(result.isValid).toBe(true);
|
|
expect(result.error).toBeNull();
|
|
});
|
|
|
|
it("should reject if any permission is invalid", () => {
|
|
const permissions = [
|
|
"eventType.create",
|
|
"invalid.action",
|
|
"organization.manageBilling",
|
|
] as PermissionString[];
|
|
const result = service.validatePermissions(permissions);
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.error).toBe("Invalid permission: invalid.action");
|
|
});
|
|
|
|
it("should reject if any permission is malformed", () => {
|
|
const permissions = ["eventType.create", "invalid-format", "team.invite"] as PermissionString[];
|
|
const result = service.validatePermissions(permissions);
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.error).toBe("Invalid permission format: invalid-format");
|
|
});
|
|
});
|
|
|
|
describe("getAllPermissions", () => {
|
|
it("should return all permissions from registry as domain objects", () => {
|
|
const permissions = service.getAllPermissions();
|
|
const expectedCount = Object.values(PERMISSION_REGISTRY).reduce(
|
|
(count, resource) => count + Object.keys(resource).filter((key) => key !== "_resource").length,
|
|
0
|
|
);
|
|
expect(permissions).toHaveLength(expectedCount);
|
|
expect(permissions[0]).toHaveProperty("resource");
|
|
expect(permissions[0]).toHaveProperty("action");
|
|
expect(permissions[0]).toHaveProperty("description");
|
|
expect(permissions[0]).toHaveProperty("category");
|
|
});
|
|
});
|
|
|
|
describe("getPermissionsByCategory", () => {
|
|
it("should return permissions for a specific category as domain objects", () => {
|
|
const eventPermissions = service.getPermissionsByCategory("event");
|
|
expect(eventPermissions.every((p) => p.category === "event")).toBe(true);
|
|
expect(eventPermissions[0]).toMatchObject({
|
|
resource: expect.any(String),
|
|
action: expect.any(String),
|
|
category: "event",
|
|
});
|
|
});
|
|
|
|
it("should return empty array for non-existent category", () => {
|
|
const permissions = service.getPermissionsByCategory("nonexistent");
|
|
expect(permissions).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
describe("getPermissionCategories", () => {
|
|
it("should return all unique categories", () => {
|
|
const categories = service.getPermissionCategories();
|
|
const uniqueCategories = new Set(
|
|
Object.values(PERMISSION_REGISTRY).flatMap((resource) =>
|
|
Object.entries(resource)
|
|
.filter(([key]) => key !== "_resource")
|
|
.map(([_, p]) => p?.category)
|
|
.filter(Boolean)
|
|
)
|
|
);
|
|
expect(categories).toHaveLength(uniqueCategories.size);
|
|
expect(categories.every((category) => typeof category === "string")).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("getPermissionsByResource", () => {
|
|
it("should return permissions for a specific resource as domain objects", () => {
|
|
const eventTypePermissions = service.getPermissionsByResource(Resource.EventType);
|
|
expect(eventTypePermissions.every((p) => p.resource === Resource.EventType)).toBe(true);
|
|
expect(eventTypePermissions[0]).toMatchObject({
|
|
resource: Resource.EventType,
|
|
action: expect.any(String),
|
|
});
|
|
});
|
|
|
|
it("should return empty array for non-existent resource", () => {
|
|
const permissions = service.getPermissionsByResource("nonexistent" as Resource);
|
|
expect(permissions).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
describe("getPermissionsByAction", () => {
|
|
it("should return permissions for a specific action as domain objects", () => {
|
|
const createPermissions = service.getPermissionsByAction(CrudAction.Create);
|
|
expect(createPermissions.every((p) => p.action === CrudAction.Create)).toBe(true);
|
|
expect(createPermissions[0]).toMatchObject({
|
|
action: CrudAction.Create,
|
|
resource: expect.any(String),
|
|
});
|
|
});
|
|
|
|
it("should return empty array for non-existent action", () => {
|
|
const permissions = service.getPermissionsByAction("nonexistent" as CrudAction);
|
|
expect(permissions).toHaveLength(0);
|
|
});
|
|
});
|
|
});
|