const { exec } = require('child_process'); const path = require('path'); const { dirname } = require('path'); const { File: HotReload } = require(`@services/hotReload.js`); const { service } = require(`@root/server.js`); const { localPath, cache, runtimeFile } = require('@root/globalize.js'); module.exports = startMenuItems = async function (app, objectGuid) { const debug = runtimeFile.configuration.live.debug.startMenuItems; let logContent = []; function safeClone(obj) { return JSON.parse(JSON.stringify(obj)); } const log = (...args) => { if (debug) logContent.push(...args); }; // ========================= // Load menu sources // ========================= const integratedStartmenuItems = runtimeFile.startMenuItems.live; const plugins = service .get('pluginManager') .getStatus() .map(({ config, ...plugin }) => ({ ...safeClone(plugin), section: 'Plugin' })); let allPlugins = [...plugins, ...integratedStartmenuItems]; // ========================= // Load user permissions // ========================= const rbacManager = service.get('rbacManager'); const userPermissions = objectGuid === undefined ? [] : (await rbacManager.resolvePermissions(objectGuid))?.permissions; const normalizedPermissions = userPermissions.map(p => ({ scope: p.scope, action: p.action, resource: p.resource || null })); // ========================= // SUPER ADMIN CHECK // ========================= const isSuperAdmin = normalizedPermissions.some(p => p.scope === 'SYSTEM' && p.resource === 'ALL' && p.action === 'ALL' ); log(`PERMISSIONS: ${JSON.stringify(normalizedPermissions)} - IS SUPER ADMIN: ${isSuperAdmin}`); // ========================= // BUILD MENU // ========================= for (const plugin of allPlugins) { plugin.menu.items = (plugin.menu.items || []).map(item => { const resource = item.label; const requiredPermissions = item.permissions || []; const debugTrace = []; const authorized = isSuperAdmin ? (debugTrace.push('SUPERADMIN OVERRIDE'), true) : normalizedPermissions.some(userPerm => { return requiredPermissions.some(required => { const scopeMatch = userPerm.scope === required.scope; const actionMatch = userPerm.action === 'ALL' || userPerm.action === required.action || required.action === 'ALL'; const resourceMatch = !userPerm.resource || userPerm.resource === 'ALL' || userPerm.resource === resource; const result = scopeMatch && actionMatch && resourceMatch; if (debug) { debugTrace.push({ userPerm, required, scopeMatch, actionMatch, resourceMatch, result }); } return result; }); }); if (debug) { log(`\nMENU ITEM: ${item.label} - AUTHORIZED:', ${authorized} - TRACE:', ${debugTrace}`); } return { ...safeClone(item), authorized }; }); plugin.onlyAdministration = plugin.menu.items.every(i => !i.authorized); if (debug) { log(`PLUGIN: ${plugin.name} - VISIBLE:', ${!plugin.onlyAdministration}`); } } // ========================= // FILTER FINAL MENU // ========================= allPlugins = allPlugins .filter(p => !p.onlyAdministration) .filter(p => p.active); cache.startMenuItems = allPlugins; if(debug) { service.get('eventManager').writeLog(objectGuid, 0, 'StartMenuItems', logContent); } return allPlugins; }; /** * Convert date into custom dateformat * @param {any} date - Valid date as datetype or string * @param {string} [format] - (optional) date characters are lowercase, time characters are uppercase; If is null, format will be "dd.mm.yyyy HH:MM:SS" */ module.exports = dateFormat = function(date, format = null) { format = (format == null ? "dd.mm.yyyy HH:MM:SS" : format); const finish_date = new Date(date); return format .replace('yyyy', finish_date.getFullYear()) .replace('yy', finish_date.getFullYear().toString().slice(-2)) .replace('mm', ("0" + (finish_date.getMonth() + 1)).slice(-2)) .replace('dd', ("0" + finish_date.getDate()).slice(-2)) .replace('HH', ("0" + finish_date.getHours()).slice(-2)) .replace('MM', ("0" + finish_date.getMinutes()).slice(-2)) .replace('SS', ("0" + finish_date.getSeconds()).slice(-2)); } /** * Limits the number of functions that can be executed in parallel. */ // module.exports = createLimiter = function(max) { // let active = 0; // const queue = []; // const runNext = () => { // if (active >= max || queue.length === 0) return; // active++; // const { fn, resolve, reject } = queue.shift(); // fn() // .then(resolve) // .catch(reject) // .finally(() => { // active--; // runNext(); // }); // }; // return fn => // new Promise((resolve, reject) => { // queue.push({ fn, resolve, reject }); // runNext(); // }); // } /** * try to call an existing host by name or ip adress * @param {string} hostname - Valid hostname or ip adress * @param {string} [format] - (optional) date characters are lowercase, time characters are uppercase; If is null, format will be "dd.mm.yyyy HH:MM:SS" */ module.exports = ping = function(hostname, cbErr, cb, ttl = 1) { exec(`ping ${hostname} -c 1 -W ${ttl}`, function (err, stdout, stderr) { if(err) { cbErr(err); } else { cb(stdout); } }); } module.exports = isObject = function(param) { return param !== null && typeof param === 'object' && !Array.isArray(param); }