86 lines
5.3 KiB
JavaScript
86 lines
5.3 KiB
JavaScript
// Capability catalog — the granular permissions the application understands. Routes are
|
|
// guarded by these keys (see middleware/auth requireCapability); roles are sets of them.
|
|
// This is pure data (no DB) so it can be required anywhere without circular dependencies.
|
|
|
|
const CAPABILITIES = [
|
|
// Assets
|
|
{ key: 'assets.view', label: 'View assets', group: 'Assets' },
|
|
{ key: 'assets.edit', label: 'Create & edit assets (files, photos, warranties, tasks, notes)', group: 'Assets' },
|
|
{ key: 'assets.delete', label: 'Delete assets', group: 'Assets' },
|
|
{ key: 'assets.bulk', label: 'Import, export, mass-update & CMDB sync', group: 'Assets' },
|
|
{ key: 'assets.assign', label: 'Assign assets & manage employees', group: 'Assets' },
|
|
// Maintenance
|
|
{ key: 'pm.view', label: 'View maintenance', group: 'Maintenance' },
|
|
{ key: 'pm.manage', label: 'Create & edit PM plans and defaults', group: 'Maintenance' },
|
|
{ key: 'pm.complete', label: 'Attach & complete PM on assets', group: 'Maintenance' },
|
|
{ key: 'parts.manage', label: 'Manage parts inventory', group: 'Maintenance' },
|
|
{ key: 'alerts.manage', label: 'Work alerts (scan, acknowledge, dismiss, ticket)', group: 'Maintenance' },
|
|
// Contacts
|
|
{ key: 'contacts.manage', label: 'Manage contacts & CRM', group: 'Contacts' },
|
|
// Finance
|
|
{ key: 'finance.view', label: 'View reports, books & tax rules', group: 'Finance' },
|
|
{ key: 'finance.manage', label: 'Manage books, tax rules, disposals & leases', group: 'Finance' },
|
|
{ key: 'finance.close', label: 'Run month-end / year-end close & reopen periods', group: 'Finance' },
|
|
{ key: 'reports.save', label: 'Save & delete reports', group: 'Finance' },
|
|
// Configuration
|
|
{ key: 'config.manage', label: 'Manage templates, categories & ID templates', group: 'Configuration' },
|
|
// Administration
|
|
{ key: 'admin.users', label: 'Manage users & teams', group: 'Administration' },
|
|
{ key: 'admin.roles', label: 'Manage roles', group: 'Administration' },
|
|
{ key: 'admin.security', label: 'Manage password & lockout policy', group: 'Administration' },
|
|
{ key: 'admin.audit', label: 'View activity & audit trail', group: 'Administration' },
|
|
{ key: 'admin.logs', label: 'View application logs', group: 'Administration' },
|
|
{ key: 'admin.settings', label: 'Manage application settings', group: 'Administration' },
|
|
{ key: 'admin.integrations', label: 'Manage integrations (email, webhook, ServiceNow, Workday)', group: 'Administration' }
|
|
];
|
|
|
|
const CAPABILITY_KEYS = CAPABILITIES.map((c) => c.key);
|
|
|
|
// '*' is a wildcard granting every capability (used by the admin role and future-proofs new ones).
|
|
const WILDCARD = '*';
|
|
|
|
const FINANCE_CAPS = [
|
|
'assets.view', 'assets.edit', 'assets.delete', 'assets.bulk', 'assets.assign',
|
|
'pm.view', 'pm.manage', 'pm.complete', 'parts.manage', 'alerts.manage',
|
|
'contacts.manage', 'finance.view', 'finance.manage', 'finance.close', 'reports.save', 'config.manage'
|
|
];
|
|
|
|
const OPERATIONS_CAPS = [
|
|
'assets.view', 'assets.edit', 'assets.assign',
|
|
'pm.view', 'pm.manage', 'pm.complete', 'parts.manage', 'alerts.manage',
|
|
'contacts.manage', 'reports.save'
|
|
];
|
|
|
|
// Built-in roles. is_system roles cannot be deleted (admin/built-ins) but their
|
|
// capabilities can be edited, except admin which always keeps the wildcard.
|
|
const DEFAULT_ROLES = [
|
|
{ key: 'admin', name: 'Administrator', description: 'Full system access, including users, roles, settings, and integrations.', capabilities: [WILDCARD], is_system: 1, locked: 1, sort_order: 0 },
|
|
{ key: 'finance', name: 'Finance', description: 'Full asset, maintenance, and financial management; no system administration.', capabilities: FINANCE_CAPS, is_system: 1, locked: 0, sort_order: 1 },
|
|
{ key: 'operations', name: 'Operations', description: 'Day-to-day asset, maintenance, parts, contacts, and alert work.', capabilities: OPERATIONS_CAPS, is_system: 1, locked: 0, sort_order: 2 },
|
|
{ key: 'pm_admin', name: 'PM Admin', description: 'Manages preventative maintenance: plans, defaults, completion, parts, and alerts.', capabilities: ['assets.view', 'pm.view', 'pm.manage', 'pm.complete', 'parts.manage', 'alerts.manage', 'reports.save'], is_system: 1, locked: 0, sort_order: 3 },
|
|
{ key: 'pm_user', name: 'PM User', description: 'Completes preventative maintenance and views assets, parts, and alerts.', capabilities: ['assets.view', 'pm.view', 'pm.complete', 'alerts.manage'], is_system: 1, locked: 0, sort_order: 4 },
|
|
{ key: 'viewer', name: 'Viewer', description: 'Read-only access to assets, maintenance, and reports.', capabilities: ['assets.view', 'pm.view', 'finance.view'], is_system: 1, locked: 0, sort_order: 5 }
|
|
];
|
|
|
|
// Does a capability set satisfy a required capability? Honors the wildcard.
|
|
function capabilitySetIncludes(capabilities, required) {
|
|
if (!Array.isArray(capabilities)) return false;
|
|
return capabilities.includes(WILDCARD) || capabilities.includes(required);
|
|
}
|
|
|
|
// Normalize an arbitrary capability list to known keys (admin/wildcard preserved).
|
|
function sanitizeCapabilities(list) {
|
|
if (Array.isArray(list) && list.includes(WILDCARD)) return [WILDCARD];
|
|
const set = new Set((Array.isArray(list) ? list : []).filter((key) => CAPABILITY_KEYS.includes(key)));
|
|
return CAPABILITY_KEYS.filter((key) => set.has(key));
|
|
}
|
|
|
|
module.exports = {
|
|
CAPABILITIES,
|
|
CAPABILITY_KEYS,
|
|
DEFAULT_ROLES,
|
|
WILDCARD,
|
|
capabilitySetIncludes,
|
|
sanitizeCapabilities
|
|
};
|