mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 19:30:57 +00:00
Muluhabt ERP modules
This commit is contained in:
109
apps/finance-api/src/common/finance-permission.util.ts
Normal file
109
apps/finance-api/src/common/finance-permission.util.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import { ForbiddenException } from "@nestjs/common";
|
||||
import type { TCurrentUser } from "@tria-plc/api-common/modules/auth/types/current-user.type";
|
||||
|
||||
const SUPER_ADMIN_ROLE = "super_admin";
|
||||
const ORGANIZATION_ADMIN_ROLE = "organization_admin";
|
||||
|
||||
type PermissionLike = { key?: string };
|
||||
type PositionLike = { permissions?: PermissionLike[] };
|
||||
|
||||
/**
|
||||
* The two token shapes IAM issues. `employee` is an object on a session token
|
||||
* (`TCurrentUser`) and an array on the raw payload (`TCurrentTokenUser`); both
|
||||
* reach controllers depending on how the session was minted, so every reader has
|
||||
* to handle both. Mirrors hr-api's `hr-permission.util.ts` and freight's
|
||||
* `collectPermissionKeys`.
|
||||
*/
|
||||
export type MeLikeUser = {
|
||||
id?: string;
|
||||
roles?: { key?: string }[];
|
||||
permissions?: PermissionLike[];
|
||||
employee?:
|
||||
| {
|
||||
id?: string;
|
||||
organizationId?: string;
|
||||
position?: PositionLike;
|
||||
delegatedPositions?: PositionLike[];
|
||||
}
|
||||
| { id?: string; organizationId?: string; positions?: PositionLike[] }[]
|
||||
| null;
|
||||
};
|
||||
|
||||
export function isSuperAdmin(user: MeLikeUser | null | undefined): boolean {
|
||||
return Boolean(user?.roles?.some((r) => r.key === SUPER_ADMIN_ROLE));
|
||||
}
|
||||
|
||||
export function isOrganizationAdmin(
|
||||
user: MeLikeUser | null | undefined,
|
||||
): boolean {
|
||||
return Boolean(user?.roles?.some((r) => r.key === ORGANIZATION_ADMIN_ROLE));
|
||||
}
|
||||
|
||||
/** Flat permission keys from roles and every position the token carries. */
|
||||
export function collectPermissionKeys(
|
||||
user: MeLikeUser | null | undefined,
|
||||
): string[] {
|
||||
if (!user) return [];
|
||||
|
||||
const keys = new Set<string>();
|
||||
for (const p of user.permissions ?? []) {
|
||||
if (p.key) keys.add(p.key);
|
||||
}
|
||||
|
||||
const employee = user.employee;
|
||||
if (!employee) return [...keys];
|
||||
|
||||
if (Array.isArray(employee)) {
|
||||
for (const emp of employee) {
|
||||
for (const pos of emp.positions ?? []) {
|
||||
for (const p of pos.permissions ?? []) {
|
||||
if (p.key) keys.add(p.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [...keys];
|
||||
}
|
||||
|
||||
for (const p of employee.position?.permissions ?? []) {
|
||||
if (p.key) keys.add(p.key);
|
||||
}
|
||||
for (const delegated of employee.delegatedPositions ?? []) {
|
||||
for (const p of delegated.permissions ?? []) {
|
||||
if (p.key) keys.add(p.key);
|
||||
}
|
||||
}
|
||||
return [...keys];
|
||||
}
|
||||
|
||||
export function hasFinancePermission(
|
||||
user: MeLikeUser | null | undefined,
|
||||
permissionKey: string,
|
||||
): boolean {
|
||||
if (!user) return false;
|
||||
if (isSuperAdmin(user)) return true;
|
||||
return collectPermissionKeys(user).includes(permissionKey);
|
||||
}
|
||||
|
||||
export function assertFinancePermission(
|
||||
user: TCurrentUser | MeLikeUser | null | undefined,
|
||||
permissionKey: string,
|
||||
): void {
|
||||
if (hasFinancePermission(user, permissionKey)) return;
|
||||
throw new ForbiddenException(`Missing permission: ${permissionKey}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* The caller's `iam.employees.id`.
|
||||
*
|
||||
* Finance records who prepared and who posted each entry, and that identity is
|
||||
* the employee — not the user — because it is the employee that carries the
|
||||
* organization. Returns null for a token with no employee.
|
||||
*/
|
||||
export function currentEmployeeId(
|
||||
user: MeLikeUser | null | undefined,
|
||||
): string | null {
|
||||
const employee = user?.employee;
|
||||
if (!employee) return null;
|
||||
if (Array.isArray(employee)) return employee[0]?.id ?? null;
|
||||
return employee.id ?? null;
|
||||
}
|
||||
Reference in New Issue
Block a user