mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge remote-tracking branch 'upstream/dev' into fix-mqtt-keep-subscription-4132
This commit is contained in:
commit
0528c12782
18
package.json
18
package.json
@ -44,8 +44,8 @@
|
|||||||
"express": "4.18.2",
|
"express": "4.18.2",
|
||||||
"express-session": "1.17.3",
|
"express-session": "1.17.3",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "11.1.1",
|
||||||
"got": "11.8.6",
|
"got": "12.6.0",
|
||||||
"hash-sum": "2.0.0",
|
"hash-sum": "2.0.0",
|
||||||
"hpagent": "1.2.0",
|
"hpagent": "1.2.0",
|
||||||
"https-proxy-agent": "5.0.1",
|
"https-proxy-agent": "5.0.1",
|
||||||
@ -60,7 +60,7 @@
|
|||||||
"memorystore": "1.6.7",
|
"memorystore": "1.6.7",
|
||||||
"mime": "3.0.0",
|
"mime": "3.0.0",
|
||||||
"moment": "2.29.4",
|
"moment": "2.29.4",
|
||||||
"moment-timezone": "0.5.41",
|
"moment-timezone": "0.5.43",
|
||||||
"mqtt": "4.3.7",
|
"mqtt": "4.3.7",
|
||||||
"multer": "1.4.5-lts.1",
|
"multer": "1.4.5-lts.1",
|
||||||
"mustache": "4.2.0",
|
"mustache": "4.2.0",
|
||||||
@ -73,13 +73,13 @@
|
|||||||
"passport-http-bearer": "1.0.1",
|
"passport-http-bearer": "1.0.1",
|
||||||
"passport-oauth2-client-password": "0.1.2",
|
"passport-oauth2-client-password": "0.1.2",
|
||||||
"raw-body": "2.5.2",
|
"raw-body": "2.5.2",
|
||||||
"semver": "7.3.8",
|
"semver": "7.5.0",
|
||||||
"tar": "6.1.13",
|
"tar": "6.1.13",
|
||||||
"tough-cookie": "4.1.2",
|
"tough-cookie": "4.1.2",
|
||||||
"uglify-js": "3.17.4",
|
"uglify-js": "3.17.4",
|
||||||
"uuid": "9.0.0",
|
"uuid": "9.0.0",
|
||||||
"ws": "7.5.6",
|
"ws": "7.5.6",
|
||||||
"xml2js": "0.4.23"
|
"xml2js": "0.5.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"bcrypt": "5.1.0"
|
"bcrypt": "5.1.0"
|
||||||
@ -108,14 +108,14 @@
|
|||||||
"i18next-http-backend": "1.4.1",
|
"i18next-http-backend": "1.4.1",
|
||||||
"jquery-i18next": "1.2.1",
|
"jquery-i18next": "1.2.1",
|
||||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||||
"marked": "4.2.12",
|
"marked": "4.3.0",
|
||||||
"mermaid": "^9.3.0",
|
"mermaid": "^9.4.3",
|
||||||
"minami": "1.2.3",
|
"minami": "1.2.3",
|
||||||
"mocha": "9.2.2",
|
"mocha": "9.2.2",
|
||||||
"node-red-node-test-helper": "^0.3.0",
|
"node-red-node-test-helper": "^0.3.1",
|
||||||
"nodemon": "2.0.20",
|
"nodemon": "2.0.20",
|
||||||
"proxy": "^1.0.2",
|
"proxy": "^1.0.2",
|
||||||
"sass": "1.58.3",
|
"sass": "1.62.1",
|
||||||
"should": "13.2.3",
|
"should": "13.2.3",
|
||||||
"sinon": "11.1.2",
|
"sinon": "11.1.2",
|
||||||
"stoppable": "^1.1.0",
|
"stoppable": "^1.1.0",
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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 = {
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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": "中国語(繁体)"
|
||||||
|
@ -263,6 +263,7 @@ var RED = (function() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
RED.view.reveal(nodeToShow.id)
|
RED.view.reveal(nodeToShow.id)
|
||||||
window.location.hash = currentHash
|
window.location.hash = currentHash
|
||||||
|
RED.view.select(nodeToShow.id)
|
||||||
if (showEditDialog) {
|
if (showEditDialog) {
|
||||||
RED.editor.edit(nodeToShow)
|
RED.editor.edit(nodeToShow)
|
||||||
}
|
}
|
||||||
@ -273,6 +274,7 @@ var RED = (function() {
|
|||||||
if (nodeToShow) {
|
if (nodeToShow) {
|
||||||
RED.view.reveal(nodeToShow.id)
|
RED.view.reveal(nodeToShow.id)
|
||||||
window.location.hash = currentHash
|
window.location.hash = currentHash
|
||||||
|
RED.view.select(nodeToShow.id)
|
||||||
if (showEditDialog) {
|
if (showEditDialog) {
|
||||||
RED.editor.editGroup(nodeToShow)
|
RED.editor.editGroup(nodeToShow)
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -401,7 +401,7 @@ RED.group = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var existingGroup;
|
var existingGroup;
|
||||||
|
var mergedEnv = {}
|
||||||
// Second pass, ungroup any groups in the selection and add their contents
|
// Second pass, ungroup any groups in the selection and add their contents
|
||||||
// to the selection
|
// to the selection
|
||||||
for (var i=0; i<selection.nodes.length; i++) {
|
for (var i=0; i<selection.nodes.length; i++) {
|
||||||
@ -410,6 +410,11 @@ RED.group = (function() {
|
|||||||
if (!existingGroup) {
|
if (!existingGroup) {
|
||||||
existingGroup = n;
|
existingGroup = n;
|
||||||
}
|
}
|
||||||
|
if (n.env && n.env.length > 0) {
|
||||||
|
n.env.forEach(env => {
|
||||||
|
mergedEnv[env.name] = env
|
||||||
|
})
|
||||||
|
}
|
||||||
ungroupHistoryEvent.groups.push(n);
|
ungroupHistoryEvent.groups.push(n);
|
||||||
nodes = nodes.concat(ungroup(n));
|
nodes = nodes.concat(ungroup(n));
|
||||||
} else {
|
} else {
|
||||||
@ -427,6 +432,7 @@ RED.group = (function() {
|
|||||||
group.style = existingGroup.style;
|
group.style = existingGroup.style;
|
||||||
group.name = existingGroup.name;
|
group.name = existingGroup.name;
|
||||||
}
|
}
|
||||||
|
group.env = Object.values(mergedEnv)
|
||||||
RED.view.select({nodes:[group]})
|
RED.view.select({nodes:[group]})
|
||||||
}
|
}
|
||||||
historyEvent.events.push({
|
historyEvent.events.push({
|
||||||
|
@ -46,7 +46,9 @@ RED.subflow = (function() {
|
|||||||
'</script>';
|
'</script>';
|
||||||
|
|
||||||
function findAvailableSubflowIOPosition(subflow,isInput) {
|
function findAvailableSubflowIOPosition(subflow,isInput) {
|
||||||
var pos = {x:50,y:30};
|
const scrollPos = RED.view.scroll()
|
||||||
|
const scaleFactor = RED.view.scale()
|
||||||
|
var pos = { x: (scrollPos[0]/scaleFactor)+50, y: (scrollPos[1]/scaleFactor)+30 };
|
||||||
if (!isInput) {
|
if (!isInput) {
|
||||||
pos.x += 110;
|
pos.x += 110;
|
||||||
}
|
}
|
||||||
|
@ -232,6 +232,63 @@ RED.view = (function() {
|
|||||||
return api
|
return api
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
const selectedGroups = (function() {
|
||||||
|
let groups = new Set()
|
||||||
|
const api = {
|
||||||
|
add: function(g, includeNodes, addToMovingSet) {
|
||||||
|
groups.add(g)
|
||||||
|
if (!g.selected) {
|
||||||
|
g.selected = true;
|
||||||
|
g.dirty = true;
|
||||||
|
}
|
||||||
|
if (addToMovingSet !== false) {
|
||||||
|
movingSet.add(g);
|
||||||
|
}
|
||||||
|
if (includeNodes) {
|
||||||
|
var currentSet = new Set(movingSet.nodes());
|
||||||
|
var allNodes = RED.group.getNodes(g,true);
|
||||||
|
allNodes.forEach(function(n) {
|
||||||
|
if (!currentSet.has(n)) {
|
||||||
|
movingSet.add(n)
|
||||||
|
}
|
||||||
|
n.dirty = true;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
selectedLinks.clearUnselected()
|
||||||
|
},
|
||||||
|
remove: function(g) {
|
||||||
|
groups.delete(g)
|
||||||
|
if (g.selected) {
|
||||||
|
g.selected = false;
|
||||||
|
g.dirty = true;
|
||||||
|
}
|
||||||
|
const allNodes = RED.group.getNodes(g,true);
|
||||||
|
const nodeSet = new Set(allNodes);
|
||||||
|
nodeSet.add(g);
|
||||||
|
for (let i = movingSet.length()-1; i >= 0; i -= 1) {
|
||||||
|
const msn = movingSet.get(i);
|
||||||
|
if (nodeSet.has(msn.n) || msn.n === g) {
|
||||||
|
msn.n.selected = false;
|
||||||
|
msn.n.dirty = true;
|
||||||
|
movingSet.remove(msn.n,i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedLinks.clearUnselected()
|
||||||
|
},
|
||||||
|
length: () => groups.length,
|
||||||
|
forEach: (func) => { groups.forEach(func) },
|
||||||
|
toArray: () => [...groups],
|
||||||
|
clear: function () {
|
||||||
|
groups.forEach(g => {
|
||||||
|
g.selected = false
|
||||||
|
g.dirty = true
|
||||||
|
})
|
||||||
|
groups.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return api
|
||||||
|
})()
|
||||||
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
@ -1136,7 +1193,7 @@ RED.view = (function() {
|
|||||||
var touchTrigger = options.touchTrigger;
|
var touchTrigger = options.touchTrigger;
|
||||||
|
|
||||||
if (targetGroup) {
|
if (targetGroup) {
|
||||||
selectGroup(targetGroup,false);
|
selectedGroups.add(targetGroup,false);
|
||||||
RED.view.redraw();
|
RED.view.redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1462,7 +1519,7 @@ RED.view = (function() {
|
|||||||
clearSelection();
|
clearSelection();
|
||||||
nn.selected = true;
|
nn.selected = true;
|
||||||
if (targetGroup) {
|
if (targetGroup) {
|
||||||
selectGroup(targetGroup,false);
|
selectedGroups.add(targetGroup,false);
|
||||||
}
|
}
|
||||||
movingSet.add(nn);
|
movingSet.add(nn);
|
||||||
updateActiveNodes();
|
updateActiveNodes();
|
||||||
@ -1926,7 +1983,7 @@ RED.view = (function() {
|
|||||||
if (!movingSet.has(n) && !n.selected) {
|
if (!movingSet.has(n) && !n.selected) {
|
||||||
// group entirely within lasso
|
// group entirely within lasso
|
||||||
if (n.x > x && n.y > y && n.x + n.w < x2 && n.y + n.h < y2) {
|
if (n.x > x && n.y > y && n.x + n.w < x2 && n.y + n.h < y2) {
|
||||||
selectGroup(n, true)
|
selectedGroups.add(n, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -2276,7 +2333,7 @@ RED.view = (function() {
|
|||||||
clearSelection();
|
clearSelection();
|
||||||
activeGroups.forEach(function(g) {
|
activeGroups.forEach(function(g) {
|
||||||
if (!g.g) {
|
if (!g.g) {
|
||||||
selectGroup(g, true);
|
selectedGroups.add(g, true);
|
||||||
if (!g.selected) {
|
if (!g.selected) {
|
||||||
g.selected = true;
|
g.selected = true;
|
||||||
g.dirty = true;
|
g.dirty = true;
|
||||||
@ -2346,10 +2403,7 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
movingSet.clear();
|
movingSet.clear();
|
||||||
selectedLinks.clear();
|
selectedLinks.clear();
|
||||||
activeGroups.forEach(function(g) {
|
selectedGroups.clear();
|
||||||
g.selected = false;
|
|
||||||
g.dirty = true;
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastSelection = null;
|
var lastSelection = null;
|
||||||
@ -2606,6 +2660,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);
|
||||||
@ -3428,7 +3492,7 @@ RED.view = (function() {
|
|||||||
if (!groupNodeSelectPrimed && !d.selected && d.g && RED.nodes.group(d.g).selected) {
|
if (!groupNodeSelectPrimed && !d.selected && d.g && RED.nodes.group(d.g).selected) {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
|
||||||
selectGroup(RED.nodes.group(d.g), false);
|
selectedGroups.add(RED.nodes.group(d.g), false);
|
||||||
|
|
||||||
mousedown_node.selected = true;
|
mousedown_node.selected = true;
|
||||||
movingSet.add(mousedown_node);
|
movingSet.add(mousedown_node);
|
||||||
@ -3849,14 +3913,14 @@ RED.view = (function() {
|
|||||||
lastClickNode = g;
|
lastClickNode = g;
|
||||||
|
|
||||||
if (g.selected && (d3.event.ctrlKey||d3.event.metaKey)) {
|
if (g.selected && (d3.event.ctrlKey||d3.event.metaKey)) {
|
||||||
deselectGroup(g);
|
selectedGroups.remove(g);
|
||||||
d3.event.stopPropagation();
|
d3.event.stopPropagation();
|
||||||
} else {
|
} else {
|
||||||
if (!g.selected) {
|
if (!g.selected) {
|
||||||
if (!d3.event.ctrlKey && !d3.event.metaKey) {
|
if (!d3.event.ctrlKey && !d3.event.metaKey) {
|
||||||
clearSelection();
|
clearSelection();
|
||||||
}
|
}
|
||||||
selectGroup(g,true);//!wasSelected);
|
selectedGroups.add(g,true);//!wasSelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d3.event.button != 2) {
|
if (d3.event.button != 2) {
|
||||||
@ -3872,45 +3936,6 @@ RED.view = (function() {
|
|||||||
d3.event.stopPropagation();
|
d3.event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectGroup(g, includeNodes, addToMovingSet) {
|
|
||||||
if (!g.selected) {
|
|
||||||
g.selected = true;
|
|
||||||
g.dirty = true;
|
|
||||||
}
|
|
||||||
if (addToMovingSet !== false) {
|
|
||||||
movingSet.add(g);
|
|
||||||
}
|
|
||||||
if (includeNodes) {
|
|
||||||
var currentSet = new Set(movingSet.nodes());
|
|
||||||
var allNodes = RED.group.getNodes(g,true);
|
|
||||||
allNodes.forEach(function(n) {
|
|
||||||
if (!currentSet.has(n)) {
|
|
||||||
movingSet.add(n)
|
|
||||||
}
|
|
||||||
n.dirty = true;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
selectedLinks.clearUnselected()
|
|
||||||
}
|
|
||||||
|
|
||||||
function deselectGroup(g) {
|
|
||||||
if (g.selected) {
|
|
||||||
g.selected = false;
|
|
||||||
g.dirty = true;
|
|
||||||
}
|
|
||||||
const allNodes = RED.group.getNodes(g,true);
|
|
||||||
const nodeSet = new Set(allNodes);
|
|
||||||
nodeSet.add(g);
|
|
||||||
for (let i = movingSet.length()-1; i >= 0; i -= 1) {
|
|
||||||
const msn = movingSet.get(i);
|
|
||||||
if (nodeSet.has(msn.n) || msn.n === g) {
|
|
||||||
msn.n.selected = false;
|
|
||||||
msn.n.dirty = true;
|
|
||||||
movingSet.remove(msn.n,i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selectedLinks.clearUnselected()
|
|
||||||
}
|
|
||||||
function getGroupAt(x, y, ignoreSelected) {
|
function getGroupAt(x, y, ignoreSelected) {
|
||||||
// x,y expected to be in node-co-ordinate space
|
// x,y expected to be in node-co-ordinate space
|
||||||
var candidateGroups = {};
|
var candidateGroups = {};
|
||||||
@ -4349,6 +4374,7 @@ RED.view = (function() {
|
|||||||
this.__port__.setAttribute("transform","translate(-5,"+((d.h/2)-5)+")");
|
this.__port__.setAttribute("transform","translate(-5,"+((d.h/2)-5)+")");
|
||||||
this.__outputOutput__.setAttribute("transform","translate(20,"+((d.h/2)-8)+")");
|
this.__outputOutput__.setAttribute("transform","translate(20,"+((d.h/2)-8)+")");
|
||||||
this.__outputNumber__.setAttribute("transform","translate(20,"+((d.h/2)+7)+")");
|
this.__outputNumber__.setAttribute("transform","translate(20,"+((d.h/2)+7)+")");
|
||||||
|
this.__outputNumber__.textContent = d.i+1;
|
||||||
}
|
}
|
||||||
d.dirty = false;
|
d.dirty = false;
|
||||||
}
|
}
|
||||||
@ -5891,11 +5917,10 @@ RED.view = (function() {
|
|||||||
if (movingSet.length() > 0) {
|
if (movingSet.length() > 0) {
|
||||||
movingSet.forEach(function(n) {
|
movingSet.forEach(function(n) {
|
||||||
if (n.n.type !== 'group') {
|
if (n.n.type !== 'group') {
|
||||||
allNodes.add(n.n);
|
allNodes.add(n.n);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var selectedGroups = activeGroups.filter(function(g) { return g.selected });
|
|
||||||
selectedGroups.forEach(function(g) {
|
selectedGroups.forEach(function(g) {
|
||||||
var groupNodes = RED.group.getNodes(g,true);
|
var groupNodes = RED.group.getNodes(g,true);
|
||||||
groupNodes.forEach(function(n) {
|
groupNodes.forEach(function(n) {
|
||||||
@ -6089,6 +6114,13 @@ RED.view = (function() {
|
|||||||
selectedNode.dirty = true;
|
selectedNode.dirty = true;
|
||||||
movingSet.clear();
|
movingSet.clear();
|
||||||
movingSet.add(selectedNode);
|
movingSet.add(selectedNode);
|
||||||
|
} else {
|
||||||
|
selectedNode = RED.nodes.group(selection);
|
||||||
|
if (selectedNode) {
|
||||||
|
movingSet.clear();
|
||||||
|
selectedGroups.clear()
|
||||||
|
selectedGroups.add(selectedNode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (selection) {
|
} else if (selection) {
|
||||||
if (selection.nodes) {
|
if (selection.nodes) {
|
||||||
@ -6104,7 +6136,7 @@ RED.view = (function() {
|
|||||||
n.dirty = true;
|
n.dirty = true;
|
||||||
movingSet.add(n);
|
movingSet.add(n);
|
||||||
} else {
|
} else {
|
||||||
selectGroup(n,true);
|
selectedGroups.add(n,true);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -6272,8 +6304,12 @@ RED.view = (function() {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
scroll: function(x,y) {
|
scroll: function(x,y) {
|
||||||
chart.scrollLeft(chart.scrollLeft()+x);
|
if (x !== undefined && y !== undefined) {
|
||||||
chart.scrollTop(chart.scrollTop()+y)
|
chart.scrollLeft(chart.scrollLeft()+x);
|
||||||
|
chart.scrollTop(chart.scrollTop()+y)
|
||||||
|
} else {
|
||||||
|
return [chart.scrollLeft(), chart.scrollTop()]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
clickNodeButton: function(n) {
|
clickNodeButton: function(n) {
|
||||||
if (n._def.button) {
|
if (n._def.button) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<label style="width: auto" for="node-input-scope" data-i18n="catch.label.source"></label>
|
<label style="width: auto" for="node-input-scope" data-i18n="catch.label.source"></label>
|
||||||
<select id="node-input-scope-select">
|
<select id="node-input-scope-select">
|
||||||
<option value="all" data-i18n="catch.scope.all"></option>
|
<option value="all" data-i18n="catch.scope.all"></option>
|
||||||
|
<option value="group" data-i18n="catch.scope.group"></option>
|
||||||
<option value="target" data-i18n="catch.scope.selected"></option>
|
<option value="target" data-i18n="catch.scope.selected"></option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -170,6 +171,8 @@
|
|||||||
});
|
});
|
||||||
if (this.scope === null) {
|
if (this.scope === null) {
|
||||||
$("#node-input-scope-select").val("all");
|
$("#node-input-scope-select").val("all");
|
||||||
|
} else if(this.scope === "group"){
|
||||||
|
$("#node-input-scope-select").val("group");
|
||||||
} else {
|
} else {
|
||||||
$("#node-input-scope-select").val("target");
|
$("#node-input-scope-select").val("target");
|
||||||
}
|
}
|
||||||
@ -179,6 +182,8 @@
|
|||||||
var scope = $("#node-input-scope-select").val();
|
var scope = $("#node-input-scope-select").val();
|
||||||
if (scope === 'all') {
|
if (scope === 'all') {
|
||||||
this.scope = null;
|
this.scope = null;
|
||||||
|
} else if(scope === 'group') {
|
||||||
|
this.scope = "group";
|
||||||
} else {
|
} else {
|
||||||
$("#node-input-uncaught").prop("checked",false);
|
$("#node-input-uncaught").prop("checked",false);
|
||||||
this.scope = $("#node-input-catch-target-container-div").treeList('selected').map(function(i) { return i.node.id})
|
this.scope = $("#node-input-catch-target-container-div").treeList('selected').map(function(i) { return i.node.id})
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<label style="width: auto" for="node-input-scope" data-i18n="status.label.source"></label>
|
<label style="width: auto" for="node-input-scope" data-i18n="status.label.source"></label>
|
||||||
<select id="node-input-scope-select">
|
<select id="node-input-scope-select">
|
||||||
<option value="all" data-i18n="status.scope.all"></option>
|
<option value="all" data-i18n="status.scope.all"></option>
|
||||||
|
<option value="group" data-i18n="status.scope.group"></option>
|
||||||
<option value="target" data-i18n="status.scope.selected"></option>
|
<option value="target" data-i18n="status.scope.selected"></option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@ -157,6 +158,8 @@
|
|||||||
});
|
});
|
||||||
if (this.scope === null) {
|
if (this.scope === null) {
|
||||||
$("#node-input-scope-select").val("all");
|
$("#node-input-scope-select").val("all");
|
||||||
|
} else if(this.scope === "group"){
|
||||||
|
$("#node-input-scope-select").val("group");
|
||||||
} else {
|
} else {
|
||||||
$("#node-input-scope-select").val("target");
|
$("#node-input-scope-select").val("target");
|
||||||
}
|
}
|
||||||
@ -166,6 +169,8 @@
|
|||||||
var scope = $("#node-input-scope-select").val();
|
var scope = $("#node-input-scope-select").val();
|
||||||
if (scope === 'all') {
|
if (scope === 'all') {
|
||||||
this.scope = null;
|
this.scope = null;
|
||||||
|
} else if(scope === 'group') {
|
||||||
|
this.scope = "group";
|
||||||
} else {
|
} else {
|
||||||
this.scope = $("#node-input-status-target-container-div").treeList('selected').map(function(i) { return i.node.id})
|
this.scope = $("#node-input-status-target-container-div").treeList('selected').map(function(i) { return i.node.id})
|
||||||
}
|
}
|
||||||
|
@ -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; }
|
||||||
|
@ -14,9 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = async function(RED) {
|
||||||
"use strict";
|
"use strict";
|
||||||
const got = require("got");
|
const { got } = await import('got')
|
||||||
const {CookieJar} = require("tough-cookie");
|
const {CookieJar} = require("tough-cookie");
|
||||||
const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent');
|
const { HttpProxyAgent, HttpsProxyAgent } = require('hpagent');
|
||||||
const FormData = require('form-data');
|
const FormData = require('form-data');
|
||||||
@ -210,24 +210,24 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
// set defaultport, else when using HttpsProxyAgent, it's defaultPort of 443 will be used :(.
|
// set defaultport, else when using HttpsProxyAgent, it's defaultPort of 443 will be used :(.
|
||||||
// Had to remove this to get http->https redirect to work
|
// Had to remove this to get http->https redirect to work
|
||||||
// opts.defaultPort = isHttps?443:80;
|
// opts.defaultPort = isHttps?443:80;
|
||||||
opts.timeout = node.reqTimeout;
|
opts.timeout = { request: node.reqTimeout || 5000 };
|
||||||
opts.throwHttpErrors = false;
|
opts.throwHttpErrors = false;
|
||||||
// TODO: add UI option to auto decompress. Setting to false for 1.x compatibility
|
// TODO: add UI option to auto decompress. Setting to false for 1.x compatibility
|
||||||
opts.decompress = false;
|
opts.decompress = false;
|
||||||
opts.method = method;
|
opts.method = method;
|
||||||
opts.retry = 0;
|
opts.retry = { limit: 0 };
|
||||||
opts.responseType = 'buffer';
|
opts.responseType = 'buffer';
|
||||||
opts.maxRedirects = 21;
|
opts.maxRedirects = 21;
|
||||||
opts.cookieJar = new CookieJar();
|
opts.cookieJar = new CookieJar();
|
||||||
opts.ignoreInvalidCookies = true;
|
opts.ignoreInvalidCookies = true;
|
||||||
opts.forever = nodeHTTPPersistent;
|
// opts.forever = nodeHTTPPersistent;
|
||||||
if (msg.requestTimeout !== undefined) {
|
if (msg.requestTimeout !== undefined) {
|
||||||
if (isNaN(msg.requestTimeout)) {
|
if (isNaN(msg.requestTimeout)) {
|
||||||
node.warn(RED._("httpin.errors.timeout-isnan"));
|
node.warn(RED._("httpin.errors.timeout-isnan"));
|
||||||
} else if (msg.requestTimeout < 1) {
|
} else if (msg.requestTimeout < 1) {
|
||||||
node.warn(RED._("httpin.errors.timeout-isnegative"));
|
node.warn(RED._("httpin.errors.timeout-isnegative"));
|
||||||
} else {
|
} else {
|
||||||
opts.timeout = msg.requestTimeout;
|
opts.timeout = { request: msg.requestTimeout };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const originalHeaderMap = {};
|
const originalHeaderMap = {};
|
||||||
@ -245,9 +245,12 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
delete options.headers[h];
|
delete options.headers[h];
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (node.insecureHTTPParser) {
|
if (node.insecureHTTPParser) {
|
||||||
options.insecureHTTPParser = true
|
// Setting the property under _unixOptions as pretty
|
||||||
|
// much the only hack available to get got to apply
|
||||||
|
// a core http option it doesn't think we should be
|
||||||
|
// allowed to set
|
||||||
|
options._unixOptions = { ...options.unixOptions, insecureHTTPParser: true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -403,15 +406,16 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
const requestUrl = new URL(response.request.requestUrl);
|
const requestUrl = new URL(response.request.requestUrl);
|
||||||
const options = response.request.options;
|
const options = { headers: {} }
|
||||||
const normalisedHeaders = {};
|
const normalisedHeaders = {};
|
||||||
Object.keys(response.headers).forEach(k => {
|
Object.keys(response.headers).forEach(k => {
|
||||||
normalisedHeaders[k.toLowerCase()] = response.headers[k]
|
normalisedHeaders[k.toLowerCase()] = response.headers[k]
|
||||||
})
|
})
|
||||||
if (normalisedHeaders['www-authenticate']) {
|
if (normalisedHeaders['www-authenticate']) {
|
||||||
let authHeader = buildDigestHeader(digestCreds.user,digestCreds.password, options.method, requestUrl.pathname, normalisedHeaders['www-authenticate'])
|
let authHeader = buildDigestHeader(digestCreds.user,digestCreds.password, response.request.options.method, requestUrl.pathname, normalisedHeaders['www-authenticate'])
|
||||||
options.headers.Authorization = authHeader;
|
options.headers.Authorization = authHeader;
|
||||||
}
|
}
|
||||||
|
// response.request.options.merge(options)
|
||||||
sentCreds = true;
|
sentCreds = true;
|
||||||
return retry(options);
|
return retry(options);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,13 @@ module.exports = function(RED) {
|
|||||||
parseString(value, options, function (err, result) {
|
parseString(value, options, function (err, result) {
|
||||||
if (err) { done(err); }
|
if (err) { done(err); }
|
||||||
else {
|
else {
|
||||||
value = result;
|
// TODO: With xml2js@0.5.0, they return an object with
|
||||||
|
// a null prototype. This could cause unexpected
|
||||||
|
// issues. So for now, we have to reconstruct
|
||||||
|
// the object with a proper prototype.
|
||||||
|
// Once https://github.com/Leonidas-from-XIV/node-xml2js/pull/674
|
||||||
|
// is merged, we can revisit and hopefully remove this hack
|
||||||
|
value = fixObj(result)
|
||||||
RED.util.setMessageProperty(msg,node.property,value);
|
RED.util.setMessageProperty(msg,node.property,value);
|
||||||
send(msg);
|
send(msg);
|
||||||
done();
|
done();
|
||||||
@ -46,4 +52,18 @@ module.exports = function(RED) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("xml",XMLNode);
|
RED.nodes.registerType("xml",XMLNode);
|
||||||
|
|
||||||
|
|
||||||
|
function fixObj(obj) {
|
||||||
|
const res = {}
|
||||||
|
const keys = Object.keys(obj)
|
||||||
|
keys.forEach(k => {
|
||||||
|
if (typeof obj[k] === 'object' && obj[k]) {
|
||||||
|
res[k] = fixObj(obj[k])
|
||||||
|
} else {
|
||||||
|
res[k] = obj[k]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,7 @@
|
|||||||
},
|
},
|
||||||
"scope": {
|
"scope": {
|
||||||
"all": "allen Nodes",
|
"all": "allen Nodes",
|
||||||
|
"group": "in gleicher Gruppe",
|
||||||
"selected": "ausgewählten Nodes"
|
"selected": "ausgewählten Nodes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -110,6 +111,7 @@
|
|||||||
},
|
},
|
||||||
"scope": {
|
"scope": {
|
||||||
"all": "allen Nodes",
|
"all": "allen Nodes",
|
||||||
|
"group": "in gleicher Gruppe",
|
||||||
"selected": "ausgewählten Nodes"
|
"selected": "ausgewählten Nodes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -103,6 +103,7 @@
|
|||||||
},
|
},
|
||||||
"scope": {
|
"scope": {
|
||||||
"all": "all nodes",
|
"all": "all nodes",
|
||||||
|
"group": "in same group",
|
||||||
"selected": "selected nodes"
|
"selected": "selected nodes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -115,6 +116,7 @@
|
|||||||
},
|
},
|
||||||
"scope": {
|
"scope": {
|
||||||
"all": "all nodes",
|
"all": "all nodes",
|
||||||
|
"group": "in same group",
|
||||||
"selected": "selected nodes"
|
"selected": "selected nodes"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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設定",
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
"cronosjs": "1.7.1",
|
"cronosjs": "1.7.1",
|
||||||
"denque": "2.1.0",
|
"denque": "2.1.0",
|
||||||
"form-data": "4.0.0",
|
"form-data": "4.0.0",
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "11.1.1",
|
||||||
"got": "11.8.6",
|
"got": "12.6.0",
|
||||||
"hash-sum": "2.0.0",
|
"hash-sum": "2.0.0",
|
||||||
"hpagent": "1.2.0",
|
"hpagent": "1.2.0",
|
||||||
"https-proxy-agent": "5.0.1",
|
"https-proxy-agent": "5.0.1",
|
||||||
@ -44,7 +44,7 @@
|
|||||||
"tough-cookie": "4.1.2",
|
"tough-cookie": "4.1.2",
|
||||||
"uuid": "9.0.0",
|
"uuid": "9.0.0",
|
||||||
"ws": "7.5.6",
|
"ws": "7.5.6",
|
||||||
"xml2js": "0.4.23",
|
"xml2js": "0.5.0",
|
||||||
"iconv-lite": "0.6.3"
|
"iconv-lite": "0.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,63 +242,68 @@ async function ensureModuleDir() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let installLock = Promise.resolve()
|
||||||
async function installModule(moduleDetails) {
|
async function installModule(moduleDetails) {
|
||||||
let installSpec = moduleDetails.module;
|
const result = installLock.then(async () => {
|
||||||
if (!registryUtil.checkModuleAllowed( moduleDetails.module, moduleDetails.version,installAllowList,installDenyList)) {
|
let installSpec = moduleDetails.module;
|
||||||
const e = new Error("Install not allowed");
|
if (!registryUtil.checkModuleAllowed( moduleDetails.module, moduleDetails.version,installAllowList,installDenyList)) {
|
||||||
e.code = "install_not_allowed";
|
const e = new Error("Install not allowed");
|
||||||
throw e;
|
e.code = "install_not_allowed";
|
||||||
}
|
|
||||||
if (moduleDetails.version) {
|
|
||||||
installSpec = installSpec+"@"+moduleDetails.version;
|
|
||||||
}
|
|
||||||
log.info(log._("server.install.installing",{name: moduleDetails.module,version: moduleDetails.version||"latest"}));
|
|
||||||
const installDir = getInstallDir();
|
|
||||||
|
|
||||||
await ensureModuleDir();
|
|
||||||
|
|
||||||
let triggerPayload = {
|
|
||||||
"module": moduleDetails.module,
|
|
||||||
"version": moduleDetails.version,
|
|
||||||
"dir": installDir,
|
|
||||||
"args": ["--production","--engine-strict"]
|
|
||||||
}
|
|
||||||
return hooks.trigger("preInstall", triggerPayload).then((result) => {
|
|
||||||
// preInstall passed
|
|
||||||
// - run install
|
|
||||||
if (result !== false) {
|
|
||||||
let extraArgs = triggerPayload.args || [];
|
|
||||||
let args = ['install', ...extraArgs, installSpec]
|
|
||||||
log.trace(NPM_COMMAND + JSON.stringify(args));
|
|
||||||
return exec.run(NPM_COMMAND, args, { cwd: installDir },true)
|
|
||||||
} else {
|
|
||||||
log.trace("skipping npm install");
|
|
||||||
}
|
|
||||||
}).then(() => {
|
|
||||||
return hooks.trigger("postInstall", triggerPayload)
|
|
||||||
}).then(() => {
|
|
||||||
log.info(log._("server.install.installed", { name: installSpec }));
|
|
||||||
const runtimeInstalledModules = settings.get("modules") || {};
|
|
||||||
runtimeInstalledModules[moduleDetails.module] = moduleDetails;
|
|
||||||
settings.set("modules",runtimeInstalledModules)
|
|
||||||
}).catch(result => {
|
|
||||||
var output = result.stderr || result.toString();
|
|
||||||
var e;
|
|
||||||
if (/E404/.test(output) || /ETARGET/.test(output)) {
|
|
||||||
log.error(log._("server.install.install-failed-not-found",{name:installSpec}));
|
|
||||||
e = new Error("Module not found");
|
|
||||||
e.code = 404;
|
|
||||||
throw e;
|
|
||||||
} else {
|
|
||||||
log.error(log._("server.install.install-failed-long",{name:installSpec}));
|
|
||||||
log.error("------------------------------------------");
|
|
||||||
log.error(output);
|
|
||||||
log.error("------------------------------------------");
|
|
||||||
e = new Error(log._("server.install.install-failed"));
|
|
||||||
e.code = "unexpected_error";
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
if (moduleDetails.version) {
|
||||||
|
installSpec = installSpec+"@"+moduleDetails.version;
|
||||||
|
}
|
||||||
|
log.info(log._("server.install.installing",{name: moduleDetails.module,version: moduleDetails.version||"latest"}));
|
||||||
|
const installDir = getInstallDir();
|
||||||
|
|
||||||
|
await ensureModuleDir();
|
||||||
|
|
||||||
|
let triggerPayload = {
|
||||||
|
"module": moduleDetails.module,
|
||||||
|
"version": moduleDetails.version,
|
||||||
|
"dir": installDir,
|
||||||
|
"args": ["--production","--engine-strict"]
|
||||||
|
}
|
||||||
|
return hooks.trigger("preInstall", triggerPayload).then((result) => {
|
||||||
|
// preInstall passed
|
||||||
|
// - run install
|
||||||
|
if (result !== false) {
|
||||||
|
let extraArgs = triggerPayload.args || [];
|
||||||
|
let args = ['install', ...extraArgs, installSpec]
|
||||||
|
log.trace(NPM_COMMAND + JSON.stringify(args));
|
||||||
|
return exec.run(NPM_COMMAND, args, { cwd: installDir },true)
|
||||||
|
} else {
|
||||||
|
log.trace("skipping npm install");
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
return hooks.trigger("postInstall", triggerPayload)
|
||||||
|
}).then(() => {
|
||||||
|
log.info(log._("server.install.installed", { name: installSpec }));
|
||||||
|
const runtimeInstalledModules = settings.get("modules") || {};
|
||||||
|
runtimeInstalledModules[moduleDetails.module] = moduleDetails;
|
||||||
|
settings.set("modules",runtimeInstalledModules)
|
||||||
|
}).catch(result => {
|
||||||
|
var output = result.stderr || result.toString();
|
||||||
|
var e;
|
||||||
|
if (/E404/.test(output) || /ETARGET/.test(output)) {
|
||||||
|
log.error(log._("server.install.install-failed-not-found",{name:installSpec}));
|
||||||
|
e = new Error("Module not found");
|
||||||
|
e.code = 404;
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
log.error(log._("server.install.install-failed-long",{name:installSpec}));
|
||||||
|
log.error("------------------------------------------");
|
||||||
|
log.error(output);
|
||||||
|
log.error("------------------------------------------");
|
||||||
|
e = new Error(log._("server.install.install-failed"));
|
||||||
|
e.code = "unexpected_error";
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
installLock = result.catch(() => {})
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@node-red/util": "3.1.0-beta.2",
|
"@node-red/util": "3.1.0-beta.2",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "11.1.1",
|
||||||
"semver": "7.3.8",
|
"semver": "7.5.0",
|
||||||
"tar": "6.1.13",
|
"tar": "6.1.13",
|
||||||
"uglify-js": "3.17.4"
|
"uglify-js": "3.17.4"
|
||||||
}
|
}
|
||||||
|
@ -606,10 +606,36 @@ class Flow {
|
|||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
} else {
|
} else {
|
||||||
this.statusNodes.forEach(function(targetStatusNode) {
|
const candidateNodes = [];
|
||||||
if (targetStatusNode.scope && targetStatusNode.scope.indexOf(reportingNode.id) === -1) {
|
this.statusNodes.forEach(targetStatusNode => {
|
||||||
|
if (targetStatusNode.g && targetStatusNode.scope === 'group' && !reportingNode.g) {
|
||||||
|
// Status node inside a group, reporting node not in a group - skip it
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Array.isArray(targetStatusNode.scope) && targetStatusNode.scope.indexOf(reportingNode.id) === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let distance = 0
|
||||||
|
if (reportingNode.g) {
|
||||||
|
// Reporting node inside a group. Calculate the distance between it and the status node
|
||||||
|
let containingGroup = this.global.groups[reportingNode.g]
|
||||||
|
while (containingGroup && containingGroup.id !== targetStatusNode.g) {
|
||||||
|
distance++
|
||||||
|
containingGroup = this.global.groups[containingGroup.g]
|
||||||
|
}
|
||||||
|
if (!containingGroup && targetStatusNode.g && targetStatusNode.scope === 'group') {
|
||||||
|
// This status node is in a group, but not in the same hierachy
|
||||||
|
// the reporting node is in
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
candidateNodes.push({ d: distance, n: targetStatusNode })
|
||||||
|
})
|
||||||
|
candidateNodes.sort((A,B) => {
|
||||||
|
return A.d - B.d
|
||||||
|
})
|
||||||
|
candidateNodes.forEach(candidate => {
|
||||||
|
const targetStatusNode = candidate.n
|
||||||
var message = {
|
var message = {
|
||||||
status: clone(statusMessage)
|
status: clone(statusMessage)
|
||||||
}
|
}
|
||||||
@ -667,21 +693,46 @@ class Flow {
|
|||||||
}
|
}
|
||||||
handled = true;
|
handled = true;
|
||||||
} else {
|
} else {
|
||||||
var handledByUncaught = false;
|
const candidateNodes = [];
|
||||||
|
this.catchNodes.forEach(targetCatchNode => {
|
||||||
this.catchNodes.forEach(function(targetCatchNode) {
|
if (targetCatchNode.g && targetCatchNode.scope === 'group' && !reportingNode.g) {
|
||||||
if (targetCatchNode.scope && targetCatchNode.scope.indexOf(reportingNode.id) === -1) {
|
// Catch node inside a group, reporting node not in a group - skip it
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (Array.isArray(targetCatchNode.scope) && targetCatchNode.scope.indexOf(reportingNode.id) === -1) {
|
||||||
|
// Catch node has a scope set and it doesn't include the reporting node
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!targetCatchNode.scope && targetCatchNode.uncaught && !handledByUncaught) {
|
let distance = 0
|
||||||
if (handled) {
|
if (reportingNode.g) {
|
||||||
// This has been handled by a !uncaught catch node
|
// Reporting node inside a group. Calculate the distance between it and the catch node
|
||||||
return;
|
let containingGroup = this.global.groups[reportingNode.g]
|
||||||
|
while (containingGroup && containingGroup.id !== targetCatchNode.g) {
|
||||||
|
distance++
|
||||||
|
containingGroup = this.global.groups[containingGroup.g]
|
||||||
|
}
|
||||||
|
if (!containingGroup && targetCatchNode.g && targetCatchNode.scope === 'group') {
|
||||||
|
// This catch node is in a group, but not in the same hierachy
|
||||||
|
// the reporting node is in
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// This is an uncaught error
|
|
||||||
handledByUncaught = true;
|
|
||||||
}
|
}
|
||||||
var errorMessage;
|
candidateNodes.push({ d: distance, n: targetCatchNode })
|
||||||
|
})
|
||||||
|
candidateNodes.sort((A,B) => {
|
||||||
|
return A.d - B.d
|
||||||
|
})
|
||||||
|
let handledByUncaught = false
|
||||||
|
candidateNodes.forEach(candidate => {
|
||||||
|
const targetCatchNode = candidate.n
|
||||||
|
if (targetCatchNode.uncaught && !handledByUncaught) {
|
||||||
|
// This node only wants errors that haven't already been handled
|
||||||
|
if (handled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
handledByUncaught = true
|
||||||
|
}
|
||||||
|
let errorMessage;
|
||||||
if (msg) {
|
if (msg) {
|
||||||
errorMessage = redUtil.cloneMessage(msg);
|
errorMessage = redUtil.cloneMessage(msg);
|
||||||
} else {
|
} else {
|
||||||
|
@ -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;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"async-mutex": "0.4.0",
|
"async-mutex": "0.4.0",
|
||||||
"clone": "2.1.2",
|
"clone": "2.1.2",
|
||||||
"express": "4.18.2",
|
"express": "4.18.2",
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "11.1.1",
|
||||||
"json-stringify-safe": "5.0.1"
|
"json-stringify-safe": "5.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "11.1.1",
|
||||||
"i18next": "21.10.0",
|
"i18next": "21.10.0",
|
||||||
"json-stringify-safe": "5.0.1",
|
"json-stringify-safe": "5.0.1",
|
||||||
"jsonata": "1.8.6",
|
"jsonata": "1.8.6",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"moment": "2.29.4",
|
"moment": "2.29.4",
|
||||||
"moment-timezone": "0.5.41"
|
"moment-timezone": "0.5.43"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
packages/node_modules/node-red/package.json
vendored
4
packages/node_modules/node-red/package.json
vendored
@ -38,10 +38,10 @@
|
|||||||
"basic-auth": "2.0.1",
|
"basic-auth": "2.0.1",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"express": "4.18.2",
|
"express": "4.18.2",
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "11.1.1",
|
||||||
"node-red-admin": "^3.0.0",
|
"node-red-admin": "^3.0.0",
|
||||||
"nopt": "5.0.0",
|
"nopt": "5.0.0",
|
||||||
"semver": "7.3.8"
|
"semver": "7.5.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"bcrypt": "5.1.0"
|
"bcrypt": "5.1.0"
|
||||||
|
11
packages/node_modules/node-red/red.js
vendored
11
packages/node_modules/node-red/red.js
vendored
@ -148,7 +148,7 @@ try {
|
|||||||
} else {
|
} else {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
process.exit();
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedArgs.define) {
|
if (parsedArgs.define) {
|
||||||
@ -182,7 +182,7 @@ if (parsedArgs.define) {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Error processing -D option: "+e.message);
|
console.log("Error processing -D option: "+e.message);
|
||||||
process.exit();
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,10 +316,10 @@ httpsPromise.then(function(startupHttps) {
|
|||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sp.subRoot = formatRoot(sp.root);
|
sp.subRoot = formatRoot(sp.root || "/");
|
||||||
sp.root = formatRoot(path.posix.join(settings.httpStaticRoot,sp.subRoot));
|
sp.root = formatRoot(path.posix.join(settings.httpStaticRoot,sp.subRoot));
|
||||||
}
|
}
|
||||||
settings.httpStatic = sanitised.length ? sanitised : false;
|
settings.httpStatic = sanitised.length ? sanitised : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we got a port from command line, use it (even if 0)
|
// if we got a port from command line, use it (even if 0)
|
||||||
@ -427,6 +427,7 @@ httpsPromise.then(function(startupHttps) {
|
|||||||
const sp = settings.httpStatic[si];
|
const sp = settings.httpStatic[si];
|
||||||
const filePath = sp.path;
|
const filePath = sp.path;
|
||||||
const thisRoot = sp.root || "/";
|
const thisRoot = sp.root || "/";
|
||||||
|
const options = sp.options;
|
||||||
if(appUseMem[filePath + "::" + thisRoot]) {
|
if(appUseMem[filePath + "::" + thisRoot]) {
|
||||||
continue;// this path and root already registered!
|
continue;// this path and root already registered!
|
||||||
}
|
}
|
||||||
@ -434,7 +435,7 @@ httpsPromise.then(function(startupHttps) {
|
|||||||
if (settings.httpStaticAuth) {
|
if (settings.httpStaticAuth) {
|
||||||
app.use(thisRoot, basicAuthMiddleware(settings.httpStaticAuth.user, settings.httpStaticAuth.pass));
|
app.use(thisRoot, basicAuthMiddleware(settings.httpStaticAuth.user, settings.httpStaticAuth.pass));
|
||||||
}
|
}
|
||||||
app.use(thisRoot, express.static(filePath));
|
app.use(thisRoot, express.static(filePath, options));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
9
packages/node_modules/node-red/settings.js
vendored
9
packages/node_modules/node-red/settings.js
vendored
@ -223,10 +223,15 @@ module.exports = {
|
|||||||
* to move httpAdminRoot
|
* to move httpAdminRoot
|
||||||
*/
|
*/
|
||||||
//httpStatic: '/home/nol/node-red-static/', //single static source
|
//httpStatic: '/home/nol/node-red-static/', //single static source
|
||||||
/* OR multiple static sources can be created using an array of objects... */
|
/**
|
||||||
|
* OR multiple static sources can be created using an array of objects...
|
||||||
|
* Each object can also contain an options object for further configuration.
|
||||||
|
* See https://expressjs.com/en/api.html#express.static for available options.
|
||||||
|
*/
|
||||||
//httpStatic: [
|
//httpStatic: [
|
||||||
// {path: '/home/nol/pics/', root: "/img/"},
|
// {path: '/home/nol/pics/', root: "/img/"},
|
||||||
// {path: '/home/nol/reports/', root: "/doc/"},
|
// {path: '/home/nol/reports/', root: "/doc/"},
|
||||||
|
// {path: '/home/nol/videos/', root: "/vid/", options: {maxAge: '1d'}}
|
||||||
//],
|
//],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -431,7 +436,7 @@ module.exports = {
|
|||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -223,7 +223,7 @@ describe('HTTP Request Node', function() {
|
|||||||
}
|
}
|
||||||
authFields[match[1]] = match[2] || match[3];
|
authFields[match[1]] = match[2] || match[3];
|
||||||
}
|
}
|
||||||
console.log(JSON.stringify(authFields));
|
// console.log(JSON.stringify(authFields));
|
||||||
|
|
||||||
if (qop && authFields['qop'] != qop) {
|
if (qop && authFields['qop'] != qop) {
|
||||||
console.log('test1');
|
console.log('test1');
|
||||||
@ -250,7 +250,7 @@ describe('HTTP Request Node', function() {
|
|||||||
req, algorithm, sess, realm, username, nonce, nc, cnonce, qop
|
req, algorithm, sess, realm, username, nonce, nc, cnonce, qop
|
||||||
);
|
);
|
||||||
if (!response || expectedResponse.toLowerCase() !== response.toLowerCase()) {
|
if (!response || expectedResponse.toLowerCase() !== response.toLowerCase()) {
|
||||||
console.log('test3');
|
console.log('test3', response, expectedResponse);
|
||||||
res.status(401).end();
|
res.status(401).end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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") {
|
||||||
|
@ -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());
|
||||||
|
@ -686,6 +686,44 @@ describe('Flow', function() {
|
|||||||
},50);
|
},50);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.only("passes a status event to the group scoped status node",function(done) {
|
||||||
|
var config = flowUtils.parseConfig([
|
||||||
|
{id:"t1",type:"tab"},
|
||||||
|
{id: "g1", type: "group", g: "g3" },
|
||||||
|
{id: "g2", type: "group" },
|
||||||
|
{id: "g3", type: "group" },
|
||||||
|
{id:"1",x:10,y:10,z:"t1",g:"g1", type:"test",name:"a",wires:["2"]},
|
||||||
|
// sn - in the same group as source node
|
||||||
|
{id:"sn",x:10,y:10,z:"t1",g:"g1", type:"status",scope:"group",wires:[]},
|
||||||
|
// sn2 - in a different group hierarchy to the source node
|
||||||
|
{id:"sn2",x:10,y:10,z:"t1", g:"g2", type:"status",scope:"group",wires:[]},
|
||||||
|
// sn3 - in a higher-level group to the source node
|
||||||
|
{id:"sn3",x:10,y:10,z:"t1", g:"g3", type:"status",scope:"group",wires:[]},
|
||||||
|
// sn2 - in a different group hierarchy, but not scope to the group
|
||||||
|
{id:"sn4",x:10,y:10,z:"t1", g:"g2", type:"status",wires:[]},
|
||||||
|
|
||||||
|
]);
|
||||||
|
var flow = Flow.create({},config,config.flows["t1"]);
|
||||||
|
|
||||||
|
flow.start();
|
||||||
|
|
||||||
|
var activeNodes = flow.getActiveNodes();
|
||||||
|
flow.handleStatus(config.flows["t1"].nodes["1"],{text:"my-status"});
|
||||||
|
setTimeout(function() {
|
||||||
|
try {
|
||||||
|
currentNodes["sn"].should.have.a.property("handled",1);
|
||||||
|
currentNodes["sn2"].should.have.a.property("handled",0);
|
||||||
|
currentNodes["sn3"].should.have.a.property("handled",1);
|
||||||
|
currentNodes["sn3"].should.have.a.property("handled",1);
|
||||||
|
done()
|
||||||
|
} catch(err) {
|
||||||
|
done(err)
|
||||||
|
}
|
||||||
|
},50);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("#handleError",function() {
|
describe("#handleError",function() {
|
||||||
@ -796,6 +834,42 @@ describe('Flow', function() {
|
|||||||
},50);
|
},50);
|
||||||
},50);
|
},50);
|
||||||
});
|
});
|
||||||
|
it("passes an error event to the group scoped catch node",function(done) {
|
||||||
|
var config = flowUtils.parseConfig([
|
||||||
|
{id:"t1",type:"tab"},
|
||||||
|
{id: "g1", type: "group", g: "g3" },
|
||||||
|
{id: "g2", type: "group" },
|
||||||
|
{id: "g3", type: "group" },
|
||||||
|
{id:"1",x:10,y:10,z:"t1",g:"g1", type:"test",name:"a",wires:["2"]},
|
||||||
|
// sn - in the same group as source node
|
||||||
|
{id:"sn",x:10,y:10,z:"t1",g:"g1", type:"catch",scope:"group",wires:[]},
|
||||||
|
// sn2 - in a different group hierarchy to the source node
|
||||||
|
{id:"sn2",x:10,y:10,z:"t1", g:"g2", type:"catch",scope:"group",wires:[]},
|
||||||
|
// sn3 - in a higher-level group to the source node
|
||||||
|
{id:"sn3",x:10,y:10,z:"t1", g:"g3", type:"catch",scope:"group",wires:[]},
|
||||||
|
// sn2 - in a different group hierarchy, but not scope to the group
|
||||||
|
{id:"sn4",x:10,y:10,z:"t1", g:"g2", type:"catch",wires:[]},
|
||||||
|
|
||||||
|
]);
|
||||||
|
var flow = Flow.create({},config,config.flows["t1"]);
|
||||||
|
|
||||||
|
flow.start();
|
||||||
|
|
||||||
|
var activeNodes = flow.getActiveNodes();
|
||||||
|
|
||||||
|
flow.handleError(config.flows["t1"].nodes["1"],"my-error",{a:"foo"});
|
||||||
|
setTimeout(function() {
|
||||||
|
try {
|
||||||
|
currentNodes["sn"].should.have.a.property("handled",1);
|
||||||
|
currentNodes["sn2"].should.have.a.property("handled",0);
|
||||||
|
currentNodes["sn3"].should.have.a.property("handled",1);
|
||||||
|
currentNodes["sn3"].should.have.a.property("handled",1);
|
||||||
|
done()
|
||||||
|
} catch(err) {
|
||||||
|
done(err)
|
||||||
|
}
|
||||||
|
},50);
|
||||||
|
});
|
||||||
it("moves any existing error object sideways",function(done){
|
it("moves any existing error object sideways",function(done){
|
||||||
var config = flowUtils.parseConfig([
|
var config = flowUtils.parseConfig([
|
||||||
{id:"t1",type:"tab"},
|
{id:"t1",type:"tab"},
|
||||||
|
Loading…
Reference in New Issue
Block a user