mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #3143 from node-red/upgrade-deny-list
Add allowUpdate feature to externalModules.palette
This commit is contained in:
commit
f3312a6403
@ -333,7 +333,10 @@ RED.palette.editor = (function() {
|
|||||||
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
|
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
|
||||||
nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').css('display', 'inline-block');
|
nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').css('display', 'inline-block');
|
||||||
} else if (loadedIndex.hasOwnProperty(module)) {
|
} else if (loadedIndex.hasOwnProperty(module)) {
|
||||||
if (semVerCompare(loadedIndex[module].version,moduleInfo.version) > 0) {
|
if (updateAllowed &&
|
||||||
|
semVerCompare(loadedIndex[module].version,moduleInfo.version) > 0 &&
|
||||||
|
RED.utils.checkModuleAllowed(module,null,updateAllowList,updateDenyList)
|
||||||
|
) {
|
||||||
nodeEntry.updateButton.show();
|
nodeEntry.updateButton.show();
|
||||||
nodeEntry.updateButton.text(RED._('palette.editor.update',{version:loadedIndex[module].version}));
|
nodeEntry.updateButton.text(RED._('palette.editor.update',{version:loadedIndex[module].version}));
|
||||||
} else {
|
} else {
|
||||||
@ -484,6 +487,9 @@ RED.palette.editor = (function() {
|
|||||||
|
|
||||||
var installAllowList = ['*'];
|
var installAllowList = ['*'];
|
||||||
var installDenyList = [];
|
var installDenyList = [];
|
||||||
|
var updateAllowed = true;
|
||||||
|
var updateAllowList = ['*'];
|
||||||
|
var updateDenyList = [];
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||||
@ -498,6 +504,17 @@ RED.palette.editor = (function() {
|
|||||||
installAllowList = RED.utils.parseModuleList(installAllowList);
|
installAllowList = RED.utils.parseModuleList(installAllowList);
|
||||||
installDenyList = RED.utils.parseModuleList(installDenyList);
|
installDenyList = RED.utils.parseModuleList(installDenyList);
|
||||||
|
|
||||||
|
var settingsUpdateAllowList = RED.settings.get("externalModules.palette.allowUpdateList")
|
||||||
|
var settingsUpdateDenyList = RED.settings.get("externalModules.palette.denyUpdateList")
|
||||||
|
if (settingsUpdateAllowList || settingsUpdateDenyList) {
|
||||||
|
updateAllowList = settingsUpdateAllowList;
|
||||||
|
updateDenyList = settingsUpdateDenyList;
|
||||||
|
}
|
||||||
|
updateAllowList = RED.utils.parseModuleList(updateAllowList);
|
||||||
|
updateDenyList = RED.utils.parseModuleList(updateDenyList);
|
||||||
|
updateAllowed = RED.settings.get("externalModules.palette.allowUpdate",true);
|
||||||
|
|
||||||
|
|
||||||
createSettingsPane();
|
createSettingsPane();
|
||||||
|
|
||||||
RED.userSettings.add({
|
RED.userSettings.add({
|
||||||
|
@ -40,15 +40,42 @@ let installDenyList = [];
|
|||||||
let installAllAllowed = true;
|
let installAllAllowed = true;
|
||||||
let installVersionRestricted = false;
|
let installVersionRestricted = false;
|
||||||
|
|
||||||
|
let updateAllowed = true;
|
||||||
|
let updateAllowList = ['*'];
|
||||||
|
let updateDenyList = [];
|
||||||
|
let updateAllAllowed = true;
|
||||||
|
|
||||||
function init(_settings) {
|
function init(_settings) {
|
||||||
settings = _settings;
|
settings = _settings;
|
||||||
// TODO: This is duplicated in localfilesystem.js
|
// TODO: This is duplicated in localfilesystem.js
|
||||||
// Should it *all* be managed by util?
|
// Should it *all* be managed by util?
|
||||||
|
|
||||||
|
installAllowList = ['*'];
|
||||||
|
installDenyList = [];
|
||||||
|
installAllAllowed = true;
|
||||||
|
installVersionRestricted = false;
|
||||||
|
|
||||||
|
updateAllowed = true;
|
||||||
|
updateAllowList = ['*'];
|
||||||
|
updateDenyList = [];
|
||||||
|
updateAllAllowed = true;
|
||||||
|
|
||||||
if (settings.externalModules && settings.externalModules.palette) {
|
if (settings.externalModules && settings.externalModules.palette) {
|
||||||
|
|
||||||
if (settings.externalModules.palette.allowList || settings.externalModules.palette.denyList) {
|
if (settings.externalModules.palette.allowList || settings.externalModules.palette.denyList) {
|
||||||
installAllowList = settings.externalModules.palette.allowList;
|
installAllowList = settings.externalModules.palette.allowList;
|
||||||
installDenyList = settings.externalModules.palette.denyList;
|
installDenyList = settings.externalModules.palette.denyList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.externalModules.palette.hasOwnProperty('allowUpdate')) {
|
||||||
|
updateAllowed = !!settings.externalModules.palette.allowUpdate;
|
||||||
|
}
|
||||||
|
if (settings.externalModules.palette.allowUpdateList || settings.externalModules.palette.denyUpdateList) {
|
||||||
|
updateAllowList = settings.externalModules.palette.allowUpdateList;
|
||||||
|
updateDenyList = settings.externalModules.palette.denyUpdateList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
installAllowList = registryUtil.parseModuleList(installAllowList);
|
installAllowList = registryUtil.parseModuleList(installAllowList);
|
||||||
installDenyList = registryUtil.parseModuleList(installDenyList);
|
installDenyList = registryUtil.parseModuleList(installDenyList);
|
||||||
@ -64,6 +91,10 @@ function init(_settings) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateAllowList = registryUtil.parseModuleList(updateAllowList);
|
||||||
|
updateDenyList = registryUtil.parseModuleList(updateDenyList);
|
||||||
|
updateAllAllowed = updateAllowed ? updateDenyList.length === 0 : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var activePromise = Promise.resolve();
|
var activePromise = Promise.resolve();
|
||||||
@ -161,6 +192,15 @@ async function installModule(module,version,url) {
|
|||||||
isUpgrade = false;
|
isUpgrade = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isUpgrade && !updateAllAllowed) {
|
||||||
|
// Check this module is allowed to be upgraded...
|
||||||
|
if (!updateAllowed || !registryUtil.checkModuleAllowed(module,null,updateAllowList,updateDenyList)) {
|
||||||
|
const e = new Error("Update not allowed");
|
||||||
|
e.code = "update_not_allowed";
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!isUpgrade) {
|
if (!isUpgrade) {
|
||||||
log.info(log._("server.install.installing",{name: module,version: version||"latest"}));
|
log.info(log._("server.install.installing",{name: module,version: version||"latest"}));
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,7 +63,9 @@ describe('nodes/registry/installer', function() {
|
|||||||
if (typeRegistry.getModuleInfo.restore) {
|
if (typeRegistry.getModuleInfo.restore) {
|
||||||
typeRegistry.getModuleInfo.restore();
|
typeRegistry.getModuleInfo.restore();
|
||||||
}
|
}
|
||||||
|
if (typeRegistry.setModulePendingUpdated.restore) {
|
||||||
|
typeRegistry.setModulePendingUpdated.restore();
|
||||||
|
}
|
||||||
if (fs.statSync.restore) {
|
if (fs.statSync.restore) {
|
||||||
fs.statSync.restore();
|
fs.statSync.restore();
|
||||||
}
|
}
|
||||||
@ -298,8 +300,11 @@ describe('nodes/registry/installer', function() {
|
|||||||
hooks.add("preInstall", function(event) { return false })
|
hooks.add("preInstall", function(event) { return false })
|
||||||
hooks.add("postInstall", function(event) { receivedEvent = event; })
|
hooks.add("postInstall", function(event) { receivedEvent = event; })
|
||||||
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
var nodeInfo = {nodes:{module:"foo",types:["a"]}};
|
||||||
|
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
|
||||||
installer.installModule("this_wont_exist","1.2.3").catch(function(err) {
|
installer.installModule("this_wont_exist","1.2.3").then(function() {
|
||||||
exec.run.called.should.be.false();
|
exec.run.called.should.be.false();
|
||||||
should.exist(receivedEvent);
|
should.exist(receivedEvent);
|
||||||
done();
|
done();
|
||||||
@ -316,6 +321,147 @@ describe('nodes/registry/installer', function() {
|
|||||||
}).catch(done);
|
}).catch(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("allowUpdate lists", function() {
|
||||||
|
it("rejects when update requested with allowUpdate set to false", function(done) {
|
||||||
|
installer.init({ externalModules: { palette: { allowUpdate: false } } })
|
||||||
|
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||||
|
return {
|
||||||
|
user: true,
|
||||||
|
version: "0.1.1"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||||
|
err.code.should.be.eql('update_not_allowed');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
it("succeeds when update requested with module not on denyUpdateList", function(done) {
|
||||||
|
installer.init({ externalModules: { palette: { denyUpdateList: ['this_wont_exist'] } } })
|
||||||
|
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||||
|
return {
|
||||||
|
user: true,
|
||||||
|
version: "0.1.1"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var res = {
|
||||||
|
code: 0,
|
||||||
|
stdout:"",
|
||||||
|
stderr:""
|
||||||
|
}
|
||||||
|
var p = Promise.resolve(res);
|
||||||
|
p.catch((err)=>{});
|
||||||
|
execResponse = p;
|
||||||
|
|
||||||
|
var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
|
||||||
|
|
||||||
|
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
installer.installModule("this_is_allowed","0.1.2").then(function() {
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
it("rejects when update requested with module on denyUpdateList", function(done) {
|
||||||
|
installer.init({ externalModules: { palette: { denyUpdateList: ['this_wont_exist'] } } })
|
||||||
|
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||||
|
return {
|
||||||
|
user: true,
|
||||||
|
version: "0.1.1"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var res = {
|
||||||
|
code: 0,
|
||||||
|
stdout:"",
|
||||||
|
stderr:""
|
||||||
|
}
|
||||||
|
var p = Promise.resolve(res);
|
||||||
|
p.catch((err)=>{});
|
||||||
|
execResponse = p;
|
||||||
|
|
||||||
|
var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
|
||||||
|
|
||||||
|
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||||
|
err.code.should.be.eql('update_not_allowed');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
it("succeeds when update requested with module on allowUpdateList", function(done) {
|
||||||
|
installer.init({ externalModules: { palette: { allowUpdateList: ['this_is_allowed'] } } })
|
||||||
|
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||||
|
return {
|
||||||
|
user: true,
|
||||||
|
version: "0.1.1"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var res = {
|
||||||
|
code: 0,
|
||||||
|
stdout:"",
|
||||||
|
stderr:""
|
||||||
|
}
|
||||||
|
var p = Promise.resolve(res);
|
||||||
|
p.catch((err)=>{});
|
||||||
|
execResponse = p;
|
||||||
|
|
||||||
|
var nodeInfo = {nodes:{module:"this_is_allowed",types:["a"]}};
|
||||||
|
|
||||||
|
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
installer.installModule("this_is_allowed","0.1.2").then(function() {
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
it("rejects when update requested with module not on allowUpdateList", function(done) {
|
||||||
|
installer.init({ externalModules: { palette: { allowUpdateList: ['this_is_allowed'] } } })
|
||||||
|
sinon.stub(typeRegistry,"getModuleInfo").callsFake(function() {
|
||||||
|
return {
|
||||||
|
user: true,
|
||||||
|
version: "0.1.1"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var res = {
|
||||||
|
code: 0,
|
||||||
|
stdout:"",
|
||||||
|
stderr:""
|
||||||
|
}
|
||||||
|
var p = Promise.resolve(res);
|
||||||
|
p.catch((err)=>{});
|
||||||
|
execResponse = p;
|
||||||
|
|
||||||
|
var nodeInfo = {nodes:{module:"this_wont_exist",types:["a"]}};
|
||||||
|
|
||||||
|
var addModule = sinon.stub(registry,"addModule").callsFake(function(md) {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
sinon.stub(typeRegistry,"setModulePendingUpdated").callsFake(function() {
|
||||||
|
return Promise.resolve(nodeInfo);
|
||||||
|
});
|
||||||
|
|
||||||
|
installer.installModule("this_wont_exist","0.1.2").catch(function(err) {
|
||||||
|
err.code.should.be.eql('update_not_allowed');
|
||||||
|
done();
|
||||||
|
}).catch(done);
|
||||||
|
})
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe("uninstalls module", function() {
|
describe("uninstalls module", function() {
|
||||||
it("rejects invalid module names", function(done) {
|
it("rejects invalid module names", function(done) {
|
||||||
|
Loading…
Reference in New Issue
Block a user