From 10207d04f4ff77a5cb92cb6c2e682de40588ce84 Mon Sep 17 00:00:00 2001 From: TotallyNotElite <1yourexperiment@protonmail.com> Date: Sat, 25 Jan 2020 16:58:44 +0100 Subject: [PATCH] Improve the way dynamic dependencies work Properly verify the version without using hacks. Allows mc to ensure exact versions are installed. Also added otplib as a normal dependency. --- meshcentral.js | 23 +++++++++++++++-------- package.json | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/meshcentral.js b/meshcentral.js index 63d4fa42..b254f83f 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -2168,20 +2168,27 @@ function getConfig(createSampleConfig) { function InstallModules(modules, func) { var missingModules = []; if (modules.length > 0) { + var dependencies = require("./package.json").dependencies; for (var i in modules) { // Modules may contain a version tag (foobar@1.0.0), remove it so the module can be found using require - var moduleName = modules[i].split("@", 1)[0]; + var moduleInfo = modules[i].split("@", 2); + var moduleName = moduleInfo[0]; + var moduleVersion = moduleInfo[1]; try { - if (moduleName == 'greenlock') { - // Check if we have GreenLock v3 - delete require.cache[require.resolve('greenlock')]; // Clear the require cache - if (typeof require('greenlock').challengeType == 'string') { missingModules.push(modules[i]); } - } else { + // Does the module need a specific version? + if (moduleVersion) { + if (require(`${moduleName}/package.json`).version != moduleVersion) + throw new Error(); + } + else { // For all other modules, do the check here. + // Is the module in package.json? Install exact version. + if (typeof dependencies[moduleName] != undefined) + moduleVersion = dependencies[moduleName]; require(moduleName); } } catch (e) { - if (previouslyInstalledModules[modules[i]] !== true) { missingModules.push(modules[i]); } + if (previouslyInstalledModules[modules[i]] !== true) { missingModules.push(`${moduleName}${moduleVersion ? `@${moduleVersion}` : ""}`); } } } if (missingModules.length > 0) { InstallModule(missingModules.shift(), InstallModules, modules, func); } else { func(); } @@ -2197,7 +2204,7 @@ function InstallModule(modulename, func, tag1, tag2) { // Get the working directory if ((__dirname.endsWith('/node_modules/meshcentral')) || (__dirname.endsWith('\\node_modules\\meshcentral')) || (__dirname.endsWith('/node_modules/meshcentral/')) || (__dirname.endsWith('\\node_modules\\meshcentral\\'))) { parentpath = require('path').join(__dirname, '../..'); } - child_process.exec(`npm install --no-optional ${modulename}`, { maxBuffer: 512000, timeout: 120000, cwd: parentpath }, function (error, stdout, stderr) { + child_process.exec(`npm install --no-save --no-optional ${modulename}`, { maxBuffer: 512000, timeout: 120000, cwd: parentpath }, function (error, stdout, stderr) { if ((error != null) && (error != '')) { console.log('ERROR: Unable to install required module "' + modulename + '". MeshCentral may not have access to npm, or npm may not have suffisent rights to load the new module. Try "npm install ' + modulename + '" to manualy install this module.\r\n'); process.exit(); diff --git a/package.json b/package.json index c2688378..9e9da302 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,11 @@ "express-handlebars": "^3.1.0", "express-ws": "^4.0.0", "ipcheck": "^0.1.0", - "meshcentral": "*", "minimist": "^1.2.0", "multiparty": "^4.2.1", "nedb": "^1.8.0", "node-forge": "^0.8.4", + "otplib": "^12.0.1", "ws": "^6.2.1", "xmldom": "^0.1.27", "yauzl": "^2.10.0"