mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Use npm info to check pending install version
This commit is contained in:
parent
af19536222
commit
8a87f93741
@ -37,7 +37,8 @@ const localtgzRe = /^([a-zA-Z]:|\/).+tgz$/;
|
|||||||
// Default allow/deny lists
|
// Default allow/deny lists
|
||||||
let installAllowList = ['*'];
|
let installAllowList = ['*'];
|
||||||
let installDenyList = [];
|
let installDenyList = [];
|
||||||
|
let installAllAllowed = true;
|
||||||
|
let installVersionRestricted = false;
|
||||||
|
|
||||||
function init(_settings) {
|
function init(_settings) {
|
||||||
settings = _settings;
|
settings = _settings;
|
||||||
@ -51,6 +52,18 @@ function init(_settings) {
|
|||||||
}
|
}
|
||||||
installAllowList = registryUtil.parseModuleList(installAllowList);
|
installAllowList = registryUtil.parseModuleList(installAllowList);
|
||||||
installDenyList = registryUtil.parseModuleList(installDenyList);
|
installDenyList = registryUtil.parseModuleList(installDenyList);
|
||||||
|
installAllAllowed = installDenyList.length === 0;
|
||||||
|
if (!installAllAllowed) {
|
||||||
|
installAllowList.forEach(function(rule) {
|
||||||
|
installVersionRestricted = installVersionRestricted || (!!rule.version);
|
||||||
|
})
|
||||||
|
if (!installVersionRestricted) {
|
||||||
|
installDenyList.forEach(function(rule) {
|
||||||
|
installVersionRestricted = installVersionRestricted || (!!rule.version);
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var activePromise = Promise.resolve();
|
var activePromise = Promise.resolve();
|
||||||
@ -95,99 +108,101 @@ function checkExistingModule(module,version) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function installModule(module,version,url) {
|
async function installModule(module,version,url) {
|
||||||
if (Buffer.isBuffer(module)) {
|
if (Buffer.isBuffer(module)) {
|
||||||
return installTarball(module)
|
return installTarball(module)
|
||||||
}
|
}
|
||||||
module = module || "";
|
module = module || "";
|
||||||
activePromise = activePromise.then(() => {
|
activePromise = activePromise.then(async function() {
|
||||||
//TODO: ensure module is 'safe'
|
//TODO: ensure module is 'safe'
|
||||||
return new Promise((resolve,reject) => {
|
var installName = module;
|
||||||
var installName = module;
|
let isRegistryPackage = true;
|
||||||
var isUpgrade = false;
|
var isUpgrade = false;
|
||||||
try {
|
if (url) {
|
||||||
if (url) {
|
if (pkgurlRe.test(url) || localtgzRe.test(url)) {
|
||||||
if (pkgurlRe.test(url) || localtgzRe.test(url)) {
|
// Git remote url or Tarball url - check the valid package url
|
||||||
// Git remote url or Tarball url - check the valid package url
|
installName = url;
|
||||||
installName = url;
|
isRegistryPackage = false;
|
||||||
} else {
|
|
||||||
log.warn(log._("server.install.install-failed-url",{name:module,url:url}));
|
|
||||||
const e = new Error("Invalid url");
|
|
||||||
e.code = "invalid_module_url";
|
|
||||||
reject(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (moduleRe.test(module)) {
|
|
||||||
// Simple module name - assume it can be npm installed
|
|
||||||
if (version) {
|
|
||||||
installName += "@"+version;
|
|
||||||
}
|
|
||||||
} else if (slashRe.test(module)) {
|
|
||||||
// A path - check if there's a valid package.json
|
|
||||||
installName = module;
|
|
||||||
let info = checkModulePath(module);
|
|
||||||
module = info.name;
|
|
||||||
} else {
|
|
||||||
log.warn(log._("server.install.install-failed-name",{name:module}));
|
|
||||||
const e = new Error("Invalid module name");
|
|
||||||
e.code = "invalid_module_name";
|
|
||||||
reject(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!registryUtil.checkModuleAllowed(module,version,installAllowList,installDenyList)) {
|
|
||||||
const e = new Error("Install not allowed");
|
|
||||||
e.code = "install_not_allowed";
|
|
||||||
reject(e);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
isUpgrade = checkExistingModule(module,version);
|
|
||||||
} catch(err) {
|
|
||||||
return reject(err);
|
|
||||||
}
|
|
||||||
if (!isUpgrade) {
|
|
||||||
log.info(log._("server.install.installing",{name: module,version: version||"latest"}));
|
|
||||||
} else {
|
} else {
|
||||||
log.info(log._("server.install.upgrading",{name: module,version: version||"latest"}));
|
log.warn(log._("server.install.install-failed-url",{name:module,url:url}));
|
||||||
|
const e = new Error("Invalid url");
|
||||||
|
e.code = "invalid_module_url";
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
} else if (moduleRe.test(module)) {
|
||||||
|
// Simple module name - assume it can be npm installed
|
||||||
|
if (version) {
|
||||||
|
installName += "@"+version;
|
||||||
|
}
|
||||||
|
} else if (slashRe.test(module)) {
|
||||||
|
// A path - check if there's a valid package.json
|
||||||
|
installName = module;
|
||||||
|
let info = checkModulePath(module);
|
||||||
|
module = info.name;
|
||||||
|
isRegistryPackage = false;
|
||||||
|
} else {
|
||||||
|
log.warn(log._("server.install.install-failed-name",{name:module}));
|
||||||
|
const e = new Error("Invalid module name");
|
||||||
|
e.code = "invalid_module_name";
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
if (!installAllAllowed) {
|
||||||
|
let installVersion = version;
|
||||||
|
if (installVersionRestricted && isRegistryPackage) {
|
||||||
|
installVersion = await getModuleVersionFromNPM(module, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
|
if (!registryUtil.checkModuleAllowed(module,installVersion,installAllowList,installDenyList)) {
|
||||||
var args = ['install','--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production',installName];
|
const e = new Error("Install not allowed");
|
||||||
log.trace(npmCommand + JSON.stringify(args));
|
e.code = "install_not_allowed";
|
||||||
exec.run(npmCommand,args,{
|
throw e;
|
||||||
cwd: installDir
|
}
|
||||||
}, true).then(result => {
|
}
|
||||||
if (!isUpgrade) {
|
isUpgrade = checkExistingModule(module,version);
|
||||||
log.info(log._("server.install.installed",{name:module}));
|
|
||||||
resolve(require("./index").addModule(module).then(reportAddedModules));
|
if (!isUpgrade) {
|
||||||
} else {
|
log.info(log._("server.install.installing",{name: module,version: version||"latest"}));
|
||||||
log.info(log._("server.install.upgraded",{name:module, version:version}));
|
} else {
|
||||||
events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
|
log.info(log._("server.install.upgrading",{name: module,version: version||"latest"}));
|
||||||
resolve(require("./registry").setModulePendingUpdated(module,version));
|
}
|
||||||
}
|
|
||||||
}).catch(result => {
|
var installDir = settings.userDir || process.env.NODE_RED_HOME || ".";
|
||||||
var output = result.stderr;
|
var args = ['install','--no-audit','--no-update-notifier','--no-fund','--save','--save-prefix=~','--production',installName];
|
||||||
var e;
|
log.trace(npmCommand + JSON.stringify(args));
|
||||||
var lookFor404 = new RegExp(" 404 .*"+module,"m");
|
return exec.run(npmCommand,args,{
|
||||||
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
|
cwd: installDir
|
||||||
if (lookFor404.test(output)) {
|
}, true).then(result => {
|
||||||
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
if (!isUpgrade) {
|
||||||
e = new Error("Module not found");
|
log.info(log._("server.install.installed",{name:module}));
|
||||||
e.code = 404;
|
return require("./index").addModule(module).then(reportAddedModules);
|
||||||
reject(e);
|
} else {
|
||||||
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
|
log.info(log._("server.install.upgraded",{name:module, version:version}));
|
||||||
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
|
events.emit("runtime-event",{id:"restart-required",payload:{type:"warning",text:"notification.warnings.restartRequired"},retain:true});
|
||||||
e = new Error("Module not found");
|
return require("./registry").setModulePendingUpdated(module,version);
|
||||||
e.code = 404;
|
}
|
||||||
reject(e);
|
}).catch(result => {
|
||||||
} else {
|
var output = result.stderr;
|
||||||
log.warn(log._("server.install.install-failed-long",{name:module}));
|
var e;
|
||||||
log.warn("------------------------------------------");
|
var lookFor404 = new RegExp(" 404 .*"+module,"m");
|
||||||
log.warn(output);
|
var lookForVersionNotFound = new RegExp("version not found: "+module+"@"+version,"m");
|
||||||
log.warn("------------------------------------------");
|
if (lookFor404.test(output)) {
|
||||||
reject(new Error(log._("server.install.install-failed")));
|
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
||||||
}
|
e = new Error("Module not found");
|
||||||
})
|
e.code = 404;
|
||||||
});
|
throw e;
|
||||||
|
} else if (isUpgrade && lookForVersionNotFound.test(output)) {
|
||||||
|
log.warn(log._("server.install.upgrade-failed-not-found",{name:module}));
|
||||||
|
e = new Error("Module not found");
|
||||||
|
e.code = 404;
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
log.warn(log._("server.install.install-failed-long",{name:module}));
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
log.warn(output);
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
throw new Error(log._("server.install.install-failed"));
|
||||||
|
}
|
||||||
|
})
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
// In case of error, reset activePromise to be resolvable
|
// In case of error, reset activePromise to be resolvable
|
||||||
activePromise = Promise.resolve();
|
activePromise = Promise.resolve();
|
||||||
@ -236,6 +251,58 @@ async function getExistingPackageVersion(moduleName) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getModuleVersionFromNPM(module, version) {
|
||||||
|
let installName = module;
|
||||||
|
if (version) {
|
||||||
|
installName += "@" + version;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
child_process.execFile(npmCommand,['info','--json',installName],function(err,stdout,stderr) {
|
||||||
|
try {
|
||||||
|
if (!stdout) {
|
||||||
|
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
||||||
|
e = new Error("Version not found");
|
||||||
|
e.code = 404;
|
||||||
|
reject(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const response = JSON.parse(stdout);
|
||||||
|
if (response.error) {
|
||||||
|
if (response.error.code === "E404") {
|
||||||
|
log.warn(log._("server.install.install-failed-not-found",{name:module}));
|
||||||
|
e = new Error("Module not found");
|
||||||
|
e.code = 404;
|
||||||
|
reject(e);
|
||||||
|
} else {
|
||||||
|
log.warn(log._("server.install.install-failed-long",{name:module}));
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
log.warn(response.error.summary);
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
reject(new Error(log._("server.install.install-failed")));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
resolve(response.version);
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
log.warn(log._("server.install.install-failed-long",{name:module}));
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
if (stdout) {
|
||||||
|
log.warn(stdout);
|
||||||
|
}
|
||||||
|
if (stderr) {
|
||||||
|
log.warn(stderr);
|
||||||
|
}
|
||||||
|
log.warn(err);
|
||||||
|
log.warn("------------------------------------------");
|
||||||
|
reject(new Error(log._("server.install.install-failed")));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function installTarball(tarball) {
|
async function installTarball(tarball) {
|
||||||
if (settings.externalModules && settings.externalModules.palette && settings.externalModules.palette.allowUpload === false) {
|
if (settings.externalModules && settings.externalModules.palette && settings.externalModules.palette.allowUpload === false) {
|
||||||
throw new Error("Module upload disabled")
|
throw new Error("Module upload disabled")
|
||||||
|
Loading…
Reference in New Issue
Block a user