import { ok, err } from "@tailor-platform/erp-kit/core"; import type { Transaction } from "../generated/kysely-tailordb"; import { InvalidPermissionError, RoleNotActiveError, RoleNotFoundError, } from "../lib/errors.generated"; import { validatePermissionKey } from "../lib/validatePermissionKey"; export interface GrantPermissionToRoleInput { roleId: string; permission: string; } /** Function: grantPermissionToRole * Adds a permission key to a role's permissions array. Idempotent. */ export async function run(db: Transaction, input: GrantPermissionToRoleInput) { if (!validatePermissionKey(input.permission)) { return err(new InvalidPermissionError(input.permission)); } const role = await db .selectFrom("Role") .selectAll() .where("id", "=", input.roleId) .forUpdate() .executeTakeFirst(); if (!role) { return err(new RoleNotFoundError(input.roleId)); } if (role.status !== "ACTIVE") { return err(new RoleNotActiveError(input.roleId)); } const currentPermissions = role.permissions ?? []; // Idempotent: if permission already exists, return success if (currentPermissions.includes(input.permission)) { return ok({ role }); } const updatedRole = await db .updateTable("Role") .set({ permissions: [...currentPermissions, input.permission], }) .where("id", "=", input.roleId) .returningAll() .executeTakeFirstOrThrow(); return ok({ role: updatedRole }); }