Files
api/src/auth/permissions.ts
T

152 lines
5.0 KiB
TypeScript
Raw Normal View History

/** Permission codes for SuperAdmin panel RBAC */
export const PERMISSIONS = [
'sms:read',
'sms:write',
'servers:read',
'servers:write',
'plugins:read',
'plugins:write',
'support:read',
'support:write',
'hamkar:read',
'hamkar:write',
'hamkar.ui:read',
'hamkar.ui:write',
'khanegi:read',
'khanegi:write',
'khanegi.settings:read',
'khanegi.settings:write',
'khanegi.ui:read',
'khanegi.ui:write',
'others:read',
'others:write',
'admins:read',
'admins:write',
'audit:read',
'settings:write',
] as const;
export type PermissionCode = (typeof PERMISSIONS)[number];
export const PERMISSION_SET = new Set<string>(PERMISSIONS);
export type PermissionModule = {
key: string;
label: string;
read?: PermissionCode;
write?: PermissionCode;
};
export const PERMISSION_MODULES: PermissionModule[] = [
{ key: 'sms', label: 'پیامک', read: 'sms:read', write: 'sms:write' },
{ key: 'servers', label: 'سرور', read: 'servers:read', write: 'servers:write' },
{ key: 'plugins', label: 'افزونه', read: 'plugins:read', write: 'plugins:write' },
{ key: 'support', label: 'پشتیبانی', read: 'support:read', write: 'support:write' },
{ key: 'hamkar', label: 'همکار — مدیریت', read: 'hamkar:read', write: 'hamkar:write' },
{ key: 'hamkar.ui', label: 'همکار — ظاهر', read: 'hamkar.ui:read', write: 'hamkar.ui:write' },
{ key: 'khanegi', label: 'خانگی — مدیریت', read: 'khanegi:read', write: 'khanegi:write' },
{
key: 'khanegi.settings',
label: 'خانگی — تنظیمات',
read: 'khanegi.settings:read',
write: 'khanegi.settings:write',
},
{ key: 'khanegi.ui', label: 'خانگی — ظاهر', read: 'khanegi.ui:read', write: 'khanegi.ui:write' },
{ key: 'others', label: 'سایت‌های دیگر', read: 'others:read', write: 'others:write' },
{ key: 'admins', label: 'مدیران', read: 'admins:read', write: 'admins:write' },
{ key: 'audit', label: 'لاگ', read: 'audit:read' },
{ key: 'settings', label: 'تنظیمات حساس', write: 'settings:write' },
];
export function parsePermissions(raw: unknown): PermissionCode[] {
if (!Array.isArray(raw)) return [];
const out: PermissionCode[] = [];
for (const item of raw) {
const code = String(item || '').trim();
if (PERMISSION_SET.has(code)) out.push(code as PermissionCode);
}
return [...new Set(out)];
}
/** write implies matching read for the same module */
export function normalizePermissionList(codes: string[]): PermissionCode[] {
const set = new Set<PermissionCode>();
for (const code of parsePermissions(codes)) {
set.add(code);
if (code.endsWith(':write')) {
const read = code.replace(/:write$/, ':read');
if (PERMISSION_SET.has(read)) set.add(read as PermissionCode);
}
}
return [...set];
}
export function isFullAccessRole(role: string | null | undefined) {
return role === 'super_admin';
}
export function userHasPermission(
user: { role?: string | null; permissions?: unknown },
code: PermissionCode | string,
): boolean {
if (isFullAccessRole(user.role)) return true;
const list = parsePermissions(user.permissions);
return list.includes(code as PermissionCode);
}
export function userHasAnyPermission(
user: { role?: string | null; permissions?: unknown },
codes: Array<PermissionCode | string>,
): boolean {
if (isFullAccessRole(user.role)) return true;
return codes.some((code) => userHasPermission(user, code));
}
export function userHasAllPermissions(
user: { role?: string | null; permissions?: unknown },
codes: Array<PermissionCode | string>,
): boolean {
if (isFullAccessRole(user.role)) return true;
return codes.every((code) => userHasPermission(user, code));
}
export function productReadPermission(product: string): PermissionCode {
if (product === 'hamkar') return 'hamkar:read';
if (product === 'other') return 'others:read';
return 'khanegi:read';
}
export function productWritePermission(product: string): PermissionCode {
if (product === 'hamkar') return 'hamkar:write';
if (product === 'other') return 'others:write';
return 'khanegi:write';
}
export function productUiReadPermission(product: string): PermissionCode | null {
if (product === 'hamkar') return 'hamkar.ui:read';
if (product === 'khanegi') return 'khanegi.ui:read';
return null;
}
export function productUiWritePermission(product: string): PermissionCode | null {
if (product === 'hamkar') return 'hamkar.ui:write';
if (product === 'khanegi') return 'khanegi.ui:write';
return null;
}
/** Any read access to a product section (list / manage / ui / settings). */
export function productAnyReadPermissions(product: string): PermissionCode[] {
if (product === 'hamkar') return ['hamkar:read', 'hamkar.ui:read'];
if (product === 'other') return ['others:read'];
return ['khanegi:read', 'khanegi.ui:read', 'khanegi.settings:read'];
}
export const ANY_TENANT_READ: PermissionCode[] = [
'hamkar:read',
'hamkar.ui:read',
'khanegi:read',
'khanegi.ui:read',
'khanegi.settings:read',
'others:read',
];