Merge branch 'dev' into update-deps

This commit is contained in:
Nick O'Leary 2023-05-22 13:57:47 +01:00 committed by GitHub
commit 69d643942c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 95 additions and 52 deletions

View File

@ -14,8 +14,6 @@
* limitations under the License. * limitations under the License.
**/ **/
var express = require("express");
var nodes = require("./nodes"); var nodes = require("./nodes");
var flows = require("./flows"); var flows = require("./flows");
var flow = require("./flow"); var flow = require("./flow");
@ -37,18 +35,9 @@ module.exports = {
plugins.init(runtimeAPI); plugins.init(runtimeAPI);
diagnostics.init(settings, runtimeAPI); diagnostics.init(settings, runtimeAPI);
var needsPermission = auth.needsPermission; const needsPermission = auth.needsPermission;
var adminApp = express();
var defaultServerSettings = {
"x-powered-by": false
}
var serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{});
for (var eOption in serverSettings) {
adminApp.set(eOption, serverSettings[eOption]);
}
const adminApp = apiUtil.createExpressApp(settings)
// Flows // Flows
adminApp.get("/flows",needsPermission("flows.read"),flows.get,apiUtil.errorHandler); adminApp.get("/flows",needsPermission("flows.read"),flows.get,apiUtil.errorHandler);

View File

@ -46,14 +46,15 @@ module.exports = {
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;
needsPermission = auth.needsPermission; needsPermission = auth.needsPermission;
if (!settings.disableEditor) { if (!settings.disableEditor) {
info.init(runtimeAPI); info.init(settings, runtimeAPI);
comms.init(server,settings,runtimeAPI); comms.init(server,settings,runtimeAPI);
var ui = require("./ui"); var ui = require("./ui");
ui.init(runtimeAPI); ui.init(runtimeAPI);
var editorApp = express(); const editorApp = apiUtil.createExpressApp(settings)
if (settings.requireHttps === true) { if (settings.requireHttps === true) {
editorApp.enable('trust proxy'); editorApp.enable('trust proxy');
editorApp.use(function (req, res, next) { editorApp.use(function (req, res, next) {
@ -86,7 +87,7 @@ module.exports = {
//Projects //Projects
var projects = require("./projects"); var projects = require("./projects");
projects.init(runtimeAPI); projects.init(settings, runtimeAPI);
editorApp.use("/projects",projects.app()); editorApp.use("/projects",projects.app());
// Locales // Locales

View File

@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
**/ **/
var express = require("express");
var apiUtils = require("../util"); var apiUtils = require("../util");
var settings;
var runtimeAPI; var runtimeAPI;
var needsPermission = require("../auth").needsPermission; var needsPermission = require("../auth").needsPermission;
@ -77,11 +77,12 @@ function getProjectRemotes(req,res) {
}) })
} }
module.exports = { module.exports = {
init: function(_runtimeAPI) { init: function(_settings, _runtimeAPI) {
settings = _settings;
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;
}, },
app: function() { app: function() {
var app = express(); var app = apiUtils.createExpressApp(settings)
app.use(function(req,res,next) { app.use(function(req,res,next) {
runtimeAPI.projects.available().then(function(available) { runtimeAPI.projects.available().then(function(available) {

View File

@ -18,9 +18,9 @@ var runtimeAPI;
var sshkeys = require("./sshkeys"); var sshkeys = require("./sshkeys");
module.exports = { module.exports = {
init: function(_runtimeAPI) { init: function(settings, _runtimeAPI) {
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;
sshkeys.init(runtimeAPI); sshkeys.init(settings, runtimeAPI);
}, },
userSettings: function(req, res) { userSettings: function(req, res) {
var opts = { var opts = {

View File

@ -17,13 +17,15 @@
var apiUtils = require("../util"); var apiUtils = require("../util");
var express = require("express"); var express = require("express");
var runtimeAPI; var runtimeAPI;
var settings;
module.exports = { module.exports = {
init: function(_runtimeAPI) { init: function(_settings, _runtimeAPI) {
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;
settings = _settings;
}, },
app: function() { app: function() {
var app = express(); const app = apiUtils.createExpressApp(settings);
// List all SSH keys // List all SSH keys
app.get("/", function(req,res) { app.get("/", function(req,res) {

View File

@ -19,6 +19,7 @@ var util = require("util");
var path = require("path"); var path = require("path");
var fs = require("fs"); var fs = require("fs");
var clone = require("clone"); var clone = require("clone");
const apiUtil = require("../util")
var defaultContext = { var defaultContext = {
page: { page: {
@ -27,8 +28,7 @@ var defaultContext = {
tabicon: { tabicon: {
icon: "red/images/node-red-icon-black.svg", icon: "red/images/node-red-icon-black.svg",
colour: "#8f0000" colour: "#8f0000"
}, }
version: require(path.join(__dirname,"../../package.json")).version
}, },
header: { header: {
title: "Node-RED", title: "Node-RED",
@ -40,6 +40,7 @@ var defaultContext = {
vendorMonaco: "" vendorMonaco: ""
} }
}; };
var settings;
var theme = null; var theme = null;
var themeContext = clone(defaultContext); var themeContext = clone(defaultContext);
@ -92,7 +93,8 @@ function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) {
} }
module.exports = { module.exports = {
init: function(settings, _runtimeAPI) { init: function(_settings, _runtimeAPI) {
settings = _settings;
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;
themeContext = clone(defaultContext); themeContext = clone(defaultContext);
if (process.env.NODE_ENV == "development") { if (process.env.NODE_ENV == "development") {
@ -113,7 +115,15 @@ module.exports = {
var url; var url;
themeSettings = {}; themeSettings = {};
themeApp = express(); themeApp = apiUtil.createExpressApp(settings);
const defaultServerSettings = {
"x-powered-by": false
}
const serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{});
for (const eOption in serverSettings) {
themeApp.set(eOption, serverSettings[eOption]);
}
if (theme.page) { if (theme.page) {

View File

@ -37,7 +37,6 @@ var adminApp;
var server; var server;
var editor; var editor;
/** /**
* Initialise the module. * Initialise the module.
* @param {Object} settings The runtime settings * @param {Object} settings The runtime settings
@ -49,7 +48,7 @@ var editor;
function init(settings,_server,storage,runtimeAPI) { function init(settings,_server,storage,runtimeAPI) {
server = _server; server = _server;
if (settings.httpAdminRoot !== false) { if (settings.httpAdminRoot !== false) {
adminApp = express(); adminApp = apiUtil.createExpressApp(settings);
var cors = require('cors'); var cors = require('cors');
var corsHandler = cors({ var corsHandler = cors({
@ -64,14 +63,6 @@ function init(settings,_server,storage,runtimeAPI) {
} }
} }
var defaultServerSettings = {
"x-powered-by": false
}
var serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{});
for (var eOption in serverSettings) {
adminApp.set(eOption, serverSettings[eOption]);
}
auth.init(settings,storage); auth.init(settings,storage);
var maxApiRequestSize = settings.apiMaxLength || '5mb'; var maxApiRequestSize = settings.apiMaxLength || '5mb';
@ -136,10 +127,11 @@ async function stop() {
editor.stop(); editor.stop();
} }
} }
module.exports = { module.exports = {
init: init, init,
start: start, start,
stop: stop, stop,
/** /**
* @memberof @node-red/editor-api * @memberof @node-red/editor-api

View File

@ -14,10 +14,9 @@
* limitations under the License. * limitations under the License.
**/ **/
const express = require("express");
var log = require("@node-red/util").log; // TODO: separate module const { log, i18n } = require("@node-red/util");
var i18n = require("@node-red/util").i18n; // TODO: separate module
module.exports = { module.exports = {
errorHandler: function(err,req,res,next) { errorHandler: function(err,req,res,next) {
@ -64,5 +63,17 @@ module.exports = {
path: req.path, path: req.path,
ip: (req.headers && req.headers['x-forwarded-for']) || (req.connection && req.connection.remoteAddress) || undefined ip: (req.headers && req.headers['x-forwarded-for']) || (req.connection && req.connection.remoteAddress) || undefined
} }
},
createExpressApp: function(settings) {
const app = express();
const defaultServerSettings = {
"x-powered-by": false
}
const serverSettings = Object.assign({},defaultServerSettings,settings.httpServerOptions||{});
for (let eOption in serverSettings) {
app.set(eOption, serverSettings[eOption]);
}
return app
} }
} }

View File

@ -504,6 +504,7 @@
"unassigned": "未割当", "unassigned": "未割当",
"global": "グローバル", "global": "グローバル",
"workspace": "ワークスペース", "workspace": "ワークスペース",
"editor": "編集ダイアログ",
"selectAll": "全てのノードを選択", "selectAll": "全てのノードを選択",
"selectNone": "選択を外す", "selectNone": "選択を外す",
"selectAllConnected": "接続されたノードを選択", "selectAllConnected": "接続されたノードを選択",
@ -1203,7 +1204,7 @@
"fr": "フランス語", "fr": "フランス語",
"ja": "日本語", "ja": "日本語",
"ko": "韓国語", "ko": "韓国語",
"pt-BR":"ポルトガル語", "pt-BR": "ポルトガル語",
"ru": "ロシア語", "ru": "ロシア語",
"zh-CN": "中国語(簡体)", "zh-CN": "中国語(簡体)",
"zh-TW": "中国語(繁体)" "zh-TW": "中国語(繁体)"

View File

@ -37,13 +37,13 @@ RED.clipboard = (function() {
// IE11 workaround // IE11 workaround
// IE does not support data uri scheme for downloading data // IE does not support data uri scheme for downloading data
var blob = new Blob([data], { var blob = new Blob([data], {
type: "data:text/plain;charset=utf-8" type: "data:application/json;charset=utf-8"
}); });
navigator.msSaveBlob(blob, file); navigator.msSaveBlob(blob, file);
} }
else { else {
var element = document.createElement('a'); var element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data)); element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(data));
element.setAttribute('download', file); element.setAttribute('download', file);
element.style.display = 'none'; element.style.display = 'none';
document.body.appendChild(element); document.body.appendChild(element);

View File

@ -50,7 +50,11 @@ RED.envVar = (function() {
var new_env = []; var new_env = [];
var items = list.editableList('items'); var items = list.editableList('items');
var credentials = gconf ? gconf.credentials : null; var credentials = gconf ? gconf.credentials : null;
if (!gconf && list.editableList('length') === 0) {
// No existing global-config node and nothing in the list,
// so no need to do anything more
return
}
if (!credentials) { if (!credentials) {
credentials = { credentials = {
_ : {}, _ : {},
@ -78,6 +82,12 @@ RED.envVar = (function() {
if (gconf === null) { if (gconf === null) {
gconf = getGlobalConf(true); gconf = getGlobalConf(true);
} }
if (!gconf.credentials) {
gconf.credentials = {
_ : {},
map: {}
};
}
if ((JSON.stringify(new_env) !== JSON.stringify(gconf.env)) || if ((JSON.stringify(new_env) !== JSON.stringify(gconf.env)) ||
(JSON.stringify(credentials) !== JSON.stringify(gconf.credentials))) { (JSON.stringify(credentials) !== JSON.stringify(gconf.credentials))) {
gconf.env = new_env; gconf.env = new_env;

View File

@ -2606,6 +2606,16 @@ RED.view = (function() {
var result = RED.nodes.removeJunction(node) var result = RED.nodes.removeJunction(node)
removedJunctions.push(node); removedJunctions.push(node);
removedLinks = removedLinks.concat(result.links); removedLinks = removedLinks.concat(result.links);
if (node.g) {
var group = RED.nodes.group(node.g);
if (selectedGroups.indexOf(group) === -1) {
// Don't use RED.group.removeFromGroup as that emits
// a change event on the node - but we're deleting it
var index = group.nodes.indexOf(node);
group.nodes.splice(index,1);
RED.group.markDirty(group);
}
}
} else { } else {
if (node.direction === "out") { if (node.direction === "out") {
removedSubflowOutputs.push(node); removedSubflowOutputs.push(node);

View File

@ -35,7 +35,11 @@ module.exports = function(RED) {
} }
else { node.previous = {}; } else { node.previous = {}; }
} }
var value = RED.util.getMessageProperty(msg,node.property); var value;
try {
value = RED.util.getMessageProperty(msg,node.property);
}
catch(e) { }
if (value !== undefined) { if (value !== undefined) {
var t = "_no_topic"; var t = "_no_topic";
if (node.septopics) { t = topic || t; } if (node.septopics) { t = topic || t; }

View File

@ -414,6 +414,7 @@
"port": "ポート", "port": "ポート",
"keepalive": "キープアライブ時間", "keepalive": "キープアライブ時間",
"cleansession": "セッションの初期化", "cleansession": "セッションの初期化",
"autoUnsubscribe": "切断時に購読を自動解除",
"cleanstart": "クリーンスタート", "cleanstart": "クリーンスタート",
"use-tls": "TLSを使用", "use-tls": "TLSを使用",
"tls-config": "TLS設定", "tls-config": "TLS設定",

View File

@ -89,6 +89,15 @@ function init(userSettings,httpServer,_adminApi) {
nodeApp = express(); nodeApp = express();
adminApp = express(); adminApp = express();
const defaultServerSettings = {
"x-powered-by": false
}
const serverSettings = Object.assign({},defaultServerSettings,userSettings.httpServerOptions||{});
for (let eOption in serverSettings) {
nodeApp.set(eOption, serverSettings[eOption]);
adminApp.set(eOption, serverSettings[eOption]);
}
if (_adminApi) { if (_adminApi) {
adminApi = _adminApi; adminApi = _adminApi;

View File

@ -854,7 +854,7 @@ describe('inject node', function() {
}); });
n1.on("call:error", function(err) { n1.on("call:error", function(err) {
count++; count++;
if (count == 2) { if (count == 1) {
done(); done();
} }
}); });

View File

@ -61,12 +61,14 @@ describe("api/editor/index", function() {
sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m),"init").callsFake(function(){}); sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m),"init").callsFake(function(){});
}); });
sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme"),"app").callsFake(function(){ return express()}); sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme"),"app").callsFake(function(){ return express()});
sinon.stub(NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/settings"),"sshkeys").callsFake(function(){ return express()});
}); });
after(function() { after(function() {
mockList.forEach(function(m) { mockList.forEach(function(m) {
NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m).init.restore(); NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/"+m).init.restore();
}) })
NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme").app.restore(); NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/theme").app.restore();
NR_TEST_UTILS.require("@node-red/editor-api/lib/editor/settings").sshkeys.restore();
auth.needsPermission.restore(); auth.needsPermission.restore();
log.error.restore(); log.error.restore();
}); });

View File

@ -41,7 +41,7 @@ describe("api/editor/settings", function() {
}); });
it('returns the user settings', function(done) { it('returns the user settings', function(done) {
info.init({ info.init({}, {
settings: { settings: {
getUserSettings: function(opts) { getUserSettings: function(opts) {
if (opts.user !== "fred") { if (opts.user !== "fred") {
@ -67,7 +67,7 @@ describe("api/editor/settings", function() {
}); });
it('updates the user settings', function(done) { it('updates the user settings', function(done) {
var update; var update;
info.init({ info.init({}, {
settings: { settings: {
updateUserSettings: function(opts) { updateUserSettings: function(opts) {
if (opts.user !== "fred") { if (opts.user !== "fred") {

View File

@ -34,7 +34,7 @@ describe("api/editor/sshkeys", function() {
} }
} }
before(function() { before(function() {
sshkeys.init(mockRuntime); sshkeys.init({}, mockRuntime);
app = express(); app = express();
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use("/settings/user/keys", sshkeys.app()); app.use("/settings/user/keys", sshkeys.app());