225 行
6.1 KiB
TypeScript
225 行
6.1 KiB
TypeScript
const EXPENSE_SELF_SERVICE_PERMISSIONS = [
|
|
"expense.create",
|
|
"expense.view_own",
|
|
"expense.edit_own",
|
|
"expense.delete_own",
|
|
"expense.submit",
|
|
"expense.withdraw",
|
|
"invoice.upload",
|
|
"invoice.view_own",
|
|
"expense.proxy_manage",
|
|
] as const;
|
|
|
|
const LEAVE_SELF_SERVICE_PERMISSIONS = [
|
|
"leave.create",
|
|
"leave.view_own",
|
|
"leave.submit",
|
|
] as const;
|
|
|
|
const ATTENDANCE_SELF_SERVICE_PERMISSIONS = [
|
|
"attendance.create",
|
|
"attendance.view_own",
|
|
"attendance.submit",
|
|
] as const;
|
|
|
|
const PROCUREMENT_SELF_SERVICE_PERMISSIONS = [
|
|
"procurement.create",
|
|
"procurement.view_own",
|
|
"procurement.submit",
|
|
] as const;
|
|
|
|
const ASSET_SELF_SERVICE_PERMISSIONS = ["asset.view_own"] as const;
|
|
const PROJECT_SELF_SERVICE_PERMISSIONS = ["project.view_own"] as const;
|
|
|
|
const MASTERDATA_VIEW_PERMISSIONS = ["masterdata.view"] as const;
|
|
const MASTERDATA_MANAGE_PERMISSIONS = ["masterdata.manage"] as const;
|
|
|
|
const EMPLOYEE_BASE_PERMISSIONS = [
|
|
...EXPENSE_SELF_SERVICE_PERMISSIONS,
|
|
...LEAVE_SELF_SERVICE_PERMISSIONS,
|
|
...ATTENDANCE_SELF_SERVICE_PERMISSIONS,
|
|
...PROJECT_SELF_SERVICE_PERMISSIONS,
|
|
] as const;
|
|
|
|
const ROLE_PERMISSIONS: Record<string, readonly string[]> = {
|
|
employee: [
|
|
...EMPLOYEE_BASE_PERMISSIONS,
|
|
...PROCUREMENT_SELF_SERVICE_PERMISSIONS,
|
|
...ASSET_SELF_SERVICE_PERMISSIONS,
|
|
],
|
|
manager: [
|
|
...EMPLOYEE_BASE_PERMISSIONS,
|
|
...PROCUREMENT_SELF_SERVICE_PERMISSIONS,
|
|
"expense.approve",
|
|
"expense.transfer",
|
|
"expense.view_all",
|
|
"leave.approve",
|
|
"leave.view_all",
|
|
"attendance.approve",
|
|
"attendance.view_all",
|
|
"procurement.approve",
|
|
"procurement.view_all",
|
|
"asset.view_all",
|
|
"report.dashboard.view",
|
|
"project.view_all",
|
|
"project.manage",
|
|
"budget.view",
|
|
"budget.manage",
|
|
],
|
|
ceo: [
|
|
...EMPLOYEE_BASE_PERMISSIONS,
|
|
...PROCUREMENT_SELF_SERVICE_PERMISSIONS,
|
|
...MASTERDATA_VIEW_PERMISSIONS,
|
|
"expense.approve",
|
|
"expense.transfer",
|
|
"expense.view_all",
|
|
"leave.approve",
|
|
"leave.view_all",
|
|
"attendance.approve",
|
|
"attendance.view_all",
|
|
"procurement.approve",
|
|
"procurement.view_all",
|
|
"asset.view_all",
|
|
"report.dashboard.view",
|
|
"budget.view",
|
|
],
|
|
finance: [
|
|
...EMPLOYEE_BASE_PERMISSIONS,
|
|
...MASTERDATA_VIEW_PERMISSIONS,
|
|
"invoice.manage",
|
|
"invoice.verify",
|
|
"report.dashboard.view",
|
|
"budget.view",
|
|
"expense.approve",
|
|
"expense.finance.pay",
|
|
"payment.batch.manage",
|
|
"expense.view_all",
|
|
"procurement.view_all",
|
|
"asset.view_all",
|
|
"attendance.view_all",
|
|
],
|
|
finance_mgr: [
|
|
...EMPLOYEE_BASE_PERMISSIONS,
|
|
...MASTERDATA_MANAGE_PERMISSIONS,
|
|
"invoice.manage",
|
|
"invoice.verify",
|
|
"report.dashboard.view",
|
|
"budget.view",
|
|
"budget.manage",
|
|
"integration.manage",
|
|
"notification.channel.manage",
|
|
"ai.assist",
|
|
"expense.approve",
|
|
"expense.finance.pay",
|
|
"payment.batch.manage",
|
|
"expense.view_all",
|
|
"expense.finance.override_duplicate",
|
|
"procurement.view_all",
|
|
"procurement.manage",
|
|
"asset.view_all",
|
|
"asset.manage",
|
|
"asset.inventory",
|
|
"system.settings",
|
|
"system.audit.view",
|
|
"payment.batch.manage",
|
|
"risk.review.manage",
|
|
"project.view_all",
|
|
"attendance.view_all",
|
|
"attendance.manage",
|
|
"attendance.sync",
|
|
],
|
|
administration: [
|
|
"expense.proxy_submit",
|
|
...EMPLOYEE_BASE_PERMISSIONS,
|
|
"procurement.view_all",
|
|
"procurement.manage",
|
|
"asset.view_all",
|
|
"asset.manage",
|
|
"asset.transfer",
|
|
"project.view_all",
|
|
"project.manage",
|
|
"attendance.view_all",
|
|
"attendance.manage",
|
|
],
|
|
hr: [
|
|
...LEAVE_SELF_SERVICE_PERMISSIONS,
|
|
...ATTENDANCE_SELF_SERVICE_PERMISSIONS,
|
|
"leave.view_all",
|
|
"leave.manage",
|
|
"attendance.approve",
|
|
"attendance.view_all",
|
|
"attendance.manage",
|
|
"attendance.sync",
|
|
"system.users",
|
|
"system.users_sensitive",
|
|
"expense.view_all",
|
|
"report.dashboard.view",
|
|
],
|
|
admin: ["*"],
|
|
};
|
|
|
|
export const BUSINESS_APPROVAL_PERMISSIONS = [
|
|
"expense.approve",
|
|
"leave.approve",
|
|
"attendance.approve",
|
|
"procurement.approve",
|
|
"travel.approve",
|
|
] as const;
|
|
|
|
const BUSINESS_APPROVER_ROLE_CODES = ["manager", "ceo", "finance", "finance_mgr", "hr"] as const;
|
|
const FINANCE_ROLE_CODES = ["finance", "finance_mgr"] as const;
|
|
const FINANCE_PORTAL_PERMISSIONS = ["payment.batch.manage", "risk.review.manage", "expense.finance.pay"] as const;
|
|
|
|
function rolePermissions(roleCode: string): readonly string[] {
|
|
return ROLE_PERMISSIONS[roleCode] ?? [];
|
|
}
|
|
|
|
export function resolvePermissionsForRoles(roleCodes: string[]) {
|
|
const permissions = new Set<string>();
|
|
|
|
for (const roleCode of roleCodes) {
|
|
for (const permission of rolePermissions(roleCode)) {
|
|
permissions.add(permission);
|
|
}
|
|
}
|
|
|
|
return Array.from(permissions);
|
|
}
|
|
|
|
export function hasPermission(permissionCodes: string[], permissionCode: string) {
|
|
return permissionCodes.includes("*") || permissionCodes.includes(permissionCode);
|
|
}
|
|
|
|
export function hasAnyPermission(permissionCodes: string[], candidates: string[]) {
|
|
if (candidates.length === 0) {
|
|
return true;
|
|
}
|
|
|
|
return candidates.some((candidate) => hasPermission(permissionCodes, candidate));
|
|
}
|
|
|
|
export function hasBusinessApproverRole(roleCodes: string[] | undefined, permissionCodes: string[]) {
|
|
const hasBusinessRole = (roleCodes ?? []).some((roleCode) =>
|
|
(BUSINESS_APPROVER_ROLE_CODES as readonly string[]).includes(roleCode),
|
|
);
|
|
|
|
return hasBusinessRole && hasAnyPermission(permissionCodes, [...BUSINESS_APPROVAL_PERMISSIONS]);
|
|
}
|
|
|
|
export function hasFinanceRole(roleCodes: string[] | undefined, permissionCodes: string[]) {
|
|
const hasRole = (roleCodes ?? []).some((roleCode) => (FINANCE_ROLE_CODES as readonly string[]).includes(roleCode));
|
|
return hasRole && hasAnyPermission(permissionCodes, [...FINANCE_PORTAL_PERMISSIONS]);
|
|
}
|
|
|
|
export function isManagerRole(permissionCodes: string[]) {
|
|
if (hasPermission(permissionCodes, "*") || hasPermission(permissionCodes, "system.users")) {
|
|
return true;
|
|
}
|
|
|
|
return permissionCodes.some(
|
|
(permission) =>
|
|
permission.endsWith(".approve") ||
|
|
(permission.endsWith(".manage") && !permission.endsWith(".view_all")),
|
|
);
|
|
}
|