mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Reorganise red/api layout to better componentise
This commit is contained in:
parent
96a0dbea2d
commit
41af5187aa
12
Gruntfile.js
12
Gruntfile.js
@ -47,10 +47,12 @@ module.exports = function(grunt) {
|
|||||||
timeout: 3000,
|
timeout: 3000,
|
||||||
ignoreLeaks: false,
|
ignoreLeaks: false,
|
||||||
ui: 'bdd',
|
ui: 'bdd',
|
||||||
reportFormats: ['lcov'],
|
reportFormats: ['lcov','html'],
|
||||||
print: 'both'
|
print: 'both'
|
||||||
},
|
},
|
||||||
coverage: { src: ['test/**/*_spec.js'] }
|
all: { src: ['test/**/*_spec.js'] },
|
||||||
|
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
|
||||||
|
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||||
},
|
},
|
||||||
jshint: {
|
jshint: {
|
||||||
options: {
|
options: {
|
||||||
@ -466,7 +468,7 @@ module.exports = function(grunt) {
|
|||||||
|
|
||||||
grunt.registerTask('test-core',
|
grunt.registerTask('test-core',
|
||||||
'Runs code style check and unit tests on core runtime code',
|
'Runs code style check and unit tests on core runtime code',
|
||||||
['jshint:core','simplemocha:core']);
|
['build','mocha_istanbul:core']);
|
||||||
|
|
||||||
grunt.registerTask('test-editor',
|
grunt.registerTask('test-editor',
|
||||||
'Runs code style check on editor code',
|
'Runs code style check on editor code',
|
||||||
@ -474,7 +476,7 @@ module.exports = function(grunt) {
|
|||||||
|
|
||||||
grunt.registerTask('test-nodes',
|
grunt.registerTask('test-nodes',
|
||||||
'Runs unit tests on core nodes',
|
'Runs unit tests on core nodes',
|
||||||
['simplemocha:nodes']);
|
['build','mocha_istanbul:nodes']);
|
||||||
|
|
||||||
grunt.registerTask('build',
|
grunt.registerTask('build',
|
||||||
'Builds editor content',
|
'Builds editor content',
|
||||||
@ -490,5 +492,5 @@ module.exports = function(grunt) {
|
|||||||
|
|
||||||
grunt.registerTask('coverage',
|
grunt.registerTask('coverage',
|
||||||
'Run Istanbul code test coverage task',
|
'Run Istanbul code test coverage task',
|
||||||
['build','mocha_istanbul']);
|
['build','mocha_istanbul:all']);
|
||||||
};
|
};
|
||||||
|
62
red/api/admin/index.js
Normal file
62
red/api/admin/index.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var express = require("express");
|
||||||
|
|
||||||
|
var nodes = require("./nodes");
|
||||||
|
var flows = require("./flows");
|
||||||
|
var flow = require("./flow");
|
||||||
|
var info = require("./info");
|
||||||
|
var auth = require("../auth");
|
||||||
|
|
||||||
|
var apiUtil = require("../util");
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function(runtime) {
|
||||||
|
flows.init(runtime);
|
||||||
|
flow.init(runtime);
|
||||||
|
info.init(runtime);
|
||||||
|
nodes.init(runtime);
|
||||||
|
|
||||||
|
var needsPermission = auth.needsPermission;
|
||||||
|
|
||||||
|
var adminApp = express();
|
||||||
|
|
||||||
|
// Flows
|
||||||
|
adminApp.get("/flows",needsPermission("flows.read"),flows.get,apiUtil.errorHandler);
|
||||||
|
adminApp.post("/flows",needsPermission("flows.write"),flows.post,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
// Flow
|
||||||
|
adminApp.get("/flow/:id",needsPermission("flows.read"),flow.get,apiUtil.errorHandler);
|
||||||
|
adminApp.post("/flow",needsPermission("flows.write"),flow.post,apiUtil.errorHandler);
|
||||||
|
adminApp.delete("/flow/:id",needsPermission("flows.write"),flow.delete,apiUtil.errorHandler);
|
||||||
|
adminApp.put("/flow/:id",needsPermission("flows.write"),flow.put,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
// Nodes
|
||||||
|
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler);
|
||||||
|
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler);
|
||||||
|
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler);
|
||||||
|
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler);
|
||||||
|
adminApp.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler);
|
||||||
|
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler);
|
||||||
|
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
adminApp.get("/settings",needsPermission("settings.read"),info.settings,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
return adminApp;
|
||||||
|
}
|
||||||
|
}
|
@ -13,13 +13,14 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
var theme = require("./theme");
|
var theme = require("../editor/theme");
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var runtime;
|
var runtime;
|
||||||
var settings;
|
var settings;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(_runtime) {
|
init: function(_runtime) {
|
||||||
|
console.log("info.init");
|
||||||
runtime = _runtime;
|
runtime = _runtime;
|
||||||
settings = runtime.settings;
|
settings = runtime.settings;
|
||||||
},
|
},
|
||||||
@ -50,7 +51,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
settings.exportNodeSettings(safeSettings);
|
settings.exportNodeSettings(safeSettings);
|
||||||
|
|
||||||
res.json(safeSettings);
|
res.json(safeSettings);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,7 +15,7 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
var when = require("when");
|
var when = require("when");
|
||||||
var locales = require("./locales");
|
var apiUtils = require("../util");
|
||||||
var redNodes;
|
var redNodes;
|
||||||
var log;
|
var log;
|
||||||
var i18n;
|
var i18n;
|
||||||
@ -35,7 +35,7 @@ module.exports = {
|
|||||||
log.audit({event: "nodes.list.get"},req);
|
log.audit({event: "nodes.list.get"},req);
|
||||||
res.json(redNodes.getNodeList());
|
res.json(redNodes.getNodeList());
|
||||||
} else {
|
} else {
|
||||||
var lang = locales.determineLangFromHeaders(req.acceptsLanguages());
|
var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||||
log.audit({event: "nodes.configs.get"},req);
|
log.audit({event: "nodes.configs.get"},req);
|
||||||
res.send(redNodes.getNodeConfigs(lang));
|
res.send(redNodes.getNodeConfigs(lang));
|
||||||
}
|
}
|
||||||
@ -141,7 +141,7 @@ module.exports = {
|
|||||||
res.status(404).end();
|
res.status(404).end();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var lang = locales.determineLangFromHeaders(req.acceptsLanguages());
|
var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||||
result = redNodes.getNodeConfig(id,lang);
|
result = redNodes.getNodeConfig(id,lang);
|
||||||
if (result) {
|
if (result) {
|
||||||
log.audit({event: "nodes.config.get",id:id},req);
|
log.audit({event: "nodes.config.get",id:id},req);
|
@ -22,7 +22,7 @@ var Tokens = require("./tokens");
|
|||||||
var Users = require("./users");
|
var Users = require("./users");
|
||||||
var permissions = require("./permissions");
|
var permissions = require("./permissions");
|
||||||
|
|
||||||
var theme = require("../theme");
|
var theme = require("../editor/theme");
|
||||||
|
|
||||||
var settings = null;
|
var settings = null;
|
||||||
var log = null
|
var log = null
|
||||||
|
@ -48,9 +48,9 @@ function init(_server,runtime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
var Tokens = require("./auth/tokens");
|
var Tokens = require("../auth/tokens");
|
||||||
var Users = require("./auth/users");
|
var Users = require("../auth/users");
|
||||||
var Permissions = require("./auth/permissions");
|
var Permissions = require("../auth/permissions");
|
||||||
if (!settings.disableEditor) {
|
if (!settings.disableEditor) {
|
||||||
Users.default().then(function(anonymousUser) {
|
Users.default().then(function(anonymousUser) {
|
||||||
var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000;
|
var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000;
|
108
red/api/editor/index.js
Normal file
108
red/api/editor/index.js
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var express = require("express");
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var comms = require("./comms");
|
||||||
|
var library = require("./library");
|
||||||
|
|
||||||
|
var auth = require("../auth");
|
||||||
|
var needsPermission = auth.needsPermission;
|
||||||
|
var runtime;
|
||||||
|
var log;
|
||||||
|
var apiUtil = require("../util");
|
||||||
|
|
||||||
|
var ensureRuntimeStarted = function(req,res,next) {
|
||||||
|
if (!runtime.isStarted()) {
|
||||||
|
log.error("Node-RED runtime not started");
|
||||||
|
res.status(503).send("Not started");
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function(server, _runtime) {
|
||||||
|
runtime = _runtime;
|
||||||
|
log = runtime.log;
|
||||||
|
var settings = runtime.settings;
|
||||||
|
if (!settings.disableEditor) {
|
||||||
|
|
||||||
|
comms.init(server,runtime);
|
||||||
|
|
||||||
|
var ui = require("./ui");
|
||||||
|
ui.init(runtime);
|
||||||
|
var editorApp = express();
|
||||||
|
if (settings.requireHttps === true) {
|
||||||
|
editorApp.enable('trust proxy');
|
||||||
|
editorApp.use(function (req, res, next) {
|
||||||
|
if (req.secure) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
res.redirect('https://' + req.headers.host + req.originalUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor);
|
||||||
|
editorApp.get("/icons/:module/:icon",ui.icon);
|
||||||
|
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
||||||
|
|
||||||
|
var theme = require("./theme");
|
||||||
|
theme.init(runtime);
|
||||||
|
editorApp.use("/theme",theme.app());
|
||||||
|
editorApp.use("/",ui.editorResources);
|
||||||
|
|
||||||
|
// //Projects
|
||||||
|
// var projects = require("./projects");
|
||||||
|
// projects.init(runtime);
|
||||||
|
// editorApp.get("/projects",projects.app());
|
||||||
|
|
||||||
|
// Locales
|
||||||
|
var locales = require("./locales");
|
||||||
|
locales.init(runtime);
|
||||||
|
editorApp.get('/locales/nodes',locales.getAllNodes,apiUtil.errorHandler);
|
||||||
|
editorApp.get(/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
// Library
|
||||||
|
var library = require("./library");
|
||||||
|
library.init(editorApp,runtime);
|
||||||
|
editorApp.post(new RegExp("/library/flows\/(.*)"),needsPermission("library.write"),library.post,apiUtil.errorHandler);
|
||||||
|
editorApp.get("/library/flows",needsPermission("library.read"),library.getAll,apiUtil.errorHandler);
|
||||||
|
editorApp.get(new RegExp("/library/flows\/(.*)"),needsPermission("library.read"),library.get,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
// Credentials
|
||||||
|
var credentials = require("./credentials");
|
||||||
|
credentials.init(runtime);
|
||||||
|
editorApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get,apiUtil.errorHandler);
|
||||||
|
|
||||||
|
return editorApp;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
start: function() {
|
||||||
|
var catalogPath = path.resolve(path.join(__dirname,"locales"));
|
||||||
|
return runtime.i18n.registerMessageCatalogs([
|
||||||
|
{namespace: "editor", dir: catalogPath, file:"editor.json"},
|
||||||
|
{namespace: "jsonata", dir: catalogPath, file:"jsonata.json"},
|
||||||
|
{namespace: "infotips", dir: catalogPath, file:"infotips.json"}
|
||||||
|
]).then(function(){
|
||||||
|
comms.start();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
stop: comms.stop,
|
||||||
|
publish: comms.publish,
|
||||||
|
registerLibrary: library.register
|
||||||
|
}
|
@ -21,7 +21,7 @@ var redApp = null;
|
|||||||
var storage;
|
var storage;
|
||||||
var log;
|
var log;
|
||||||
var redNodes;
|
var redNodes;
|
||||||
var needsPermission = require("./auth").needsPermission;
|
var needsPermission = require("../auth").needsPermission;
|
||||||
|
|
||||||
function createLibrary(type) {
|
function createLibrary(type) {
|
||||||
if (redApp) {
|
if (redApp) {
|
@ -15,17 +15,10 @@
|
|||||||
**/
|
**/
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
//var apiUtil = require('../util');
|
||||||
var i18n;
|
var i18n;
|
||||||
var redNodes;
|
var redNodes;
|
||||||
|
|
||||||
function determineLangFromHeaders(acceptedLanguages){
|
|
||||||
var lang = i18n.defaultLang;
|
|
||||||
acceptedLanguages = acceptedLanguages || [];
|
|
||||||
if (acceptedLanguages.length >= 1) {
|
|
||||||
lang = acceptedLanguages[0];
|
|
||||||
}
|
|
||||||
return lang;
|
|
||||||
}
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function(runtime) {
|
init: function(runtime) {
|
||||||
i18n = runtime.i18n;
|
i18n = runtime.i18n;
|
||||||
@ -35,7 +28,7 @@ module.exports = {
|
|||||||
var namespace = req.params[0];
|
var namespace = req.params[0];
|
||||||
var lngs = req.query.lng;
|
var lngs = req.query.lng;
|
||||||
namespace = namespace.replace(/\.json$/,"");
|
namespace = namespace.replace(/\.json$/,"");
|
||||||
var lang = req.query.lng; //determineLangFromHeaders(req.acceptsLanguages() || []);
|
var lang = req.query.lng; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []);
|
||||||
var prevLang = i18n.i.lng();
|
var prevLang = i18n.i.lng();
|
||||||
// Trigger a load from disk of the language if it is not the default
|
// Trigger a load from disk of the language if it is not the default
|
||||||
i18n.i.setLng(lang, function(){
|
i18n.i.setLng(lang, function(){
|
||||||
@ -55,6 +48,5 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
res.json(result);
|
res.json(result);
|
||||||
},
|
}
|
||||||
determineLangFromHeaders: determineLangFromHeaders
|
|
||||||
}
|
}
|
@ -22,7 +22,7 @@ var theme = require("./theme");
|
|||||||
|
|
||||||
var redNodes;
|
var redNodes;
|
||||||
|
|
||||||
var templateDir = path.resolve(__dirname+"/../../editor/templates");
|
var templateDir = path.resolve(__dirname+"/../../../editor/templates");
|
||||||
var editorTemplate;
|
var editorTemplate;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -52,5 +52,5 @@ module.exports = {
|
|||||||
editor: function(req,res) {
|
editor: function(req,res) {
|
||||||
res.send(Mustache.render(editorTemplate,theme.context()));
|
res.send(Mustache.render(editorTemplate,theme.context()));
|
||||||
},
|
},
|
||||||
editorResources: express.static(__dirname + '/../../public')
|
editorResources: express.static(__dirname + '/../../../public')
|
||||||
};
|
};
|
144
red/api/index.js
144
red/api/index.js
@ -17,49 +17,19 @@
|
|||||||
var express = require("express");
|
var express = require("express");
|
||||||
var bodyParser = require("body-parser");
|
var bodyParser = require("body-parser");
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var path = require('path');
|
|
||||||
var passport = require('passport');
|
var passport = require('passport');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
var cors = require('cors');
|
var cors = require('cors');
|
||||||
|
|
||||||
var ui = require("./ui");
|
|
||||||
var nodes = require("./nodes");
|
|
||||||
var flows = require("./flows");
|
|
||||||
var flow = require("./flow");
|
|
||||||
var library = require("./library");
|
|
||||||
var info = require("./info");
|
|
||||||
var theme = require("./theme");
|
|
||||||
var locales = require("./locales");
|
|
||||||
var credentials = require("./credentials");
|
|
||||||
var comms = require("./comms");
|
|
||||||
|
|
||||||
var auth = require("./auth");
|
var auth = require("./auth");
|
||||||
var needsPermission = auth.needsPermission;
|
var apiUtil = require("./util");
|
||||||
|
|
||||||
var i18n;
|
var i18n;
|
||||||
var log;
|
var log;
|
||||||
var adminApp;
|
var adminApp;
|
||||||
var server;
|
var server;
|
||||||
var runtime;
|
var runtime;
|
||||||
|
var editor;
|
||||||
var errorHandler = function(err,req,res,next) {
|
|
||||||
if (err.message === "request entity too large") {
|
|
||||||
log.error(err);
|
|
||||||
} else {
|
|
||||||
console.log(err.stack);
|
|
||||||
}
|
|
||||||
log.audit({event: "api.error",error:err.code||"unexpected_error",message:err.toString()},req);
|
|
||||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
|
||||||
};
|
|
||||||
|
|
||||||
var ensureRuntimeStarted = function(req,res,next) {
|
|
||||||
if (!runtime.isStarted()) {
|
|
||||||
log.error("Node-RED runtime not started");
|
|
||||||
res.status(503).send("Not started");
|
|
||||||
} else {
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function init(_server,_runtime) {
|
function init(_server,_runtime) {
|
||||||
server = _server;
|
server = _server;
|
||||||
@ -68,45 +38,22 @@ function init(_server,_runtime) {
|
|||||||
i18n = runtime.i18n;
|
i18n = runtime.i18n;
|
||||||
log = runtime.log;
|
log = runtime.log;
|
||||||
if (settings.httpAdminRoot !== false) {
|
if (settings.httpAdminRoot !== false) {
|
||||||
comms.init(server,runtime);
|
apiUtil.init(runtime);
|
||||||
adminApp = express();
|
adminApp = express();
|
||||||
auth.init(runtime);
|
auth.init(runtime);
|
||||||
credentials.init(runtime);
|
|
||||||
flows.init(runtime);
|
|
||||||
flow.init(runtime);
|
|
||||||
info.init(runtime);
|
|
||||||
library.init(adminApp,runtime);
|
|
||||||
locales.init(runtime);
|
|
||||||
nodes.init(runtime);
|
|
||||||
|
|
||||||
// Editor
|
|
||||||
if (!settings.disableEditor) {
|
|
||||||
ui.init(runtime);
|
|
||||||
var editorApp = express();
|
|
||||||
if (settings.requireHttps === true) {
|
|
||||||
editorApp.enable('trust proxy');
|
|
||||||
editorApp.use(function (req, res, next) {
|
|
||||||
if (req.secure) {
|
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
res.redirect('https://' + req.headers.host + req.originalUrl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor);
|
|
||||||
editorApp.get("/icons/:module/:icon",ui.icon);
|
|
||||||
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
|
||||||
theme.init(runtime);
|
|
||||||
editorApp.use("/theme",theme.app());
|
|
||||||
editorApp.use("/",ui.editorResources);
|
|
||||||
adminApp.use(editorApp);
|
|
||||||
}
|
|
||||||
var maxApiRequestSize = settings.apiMaxLength || '5mb';
|
var maxApiRequestSize = settings.apiMaxLength || '5mb';
|
||||||
adminApp.use(bodyParser.json({limit:maxApiRequestSize}));
|
adminApp.use(bodyParser.json({limit:maxApiRequestSize}));
|
||||||
adminApp.use(bodyParser.urlencoded({limit:maxApiRequestSize,extended:true}));
|
adminApp.use(bodyParser.urlencoded({limit:maxApiRequestSize,extended:true}));
|
||||||
|
|
||||||
adminApp.get("/auth/login",auth.login,errorHandler);
|
// Editor
|
||||||
|
if (!settings.disableEditor) {
|
||||||
|
editor = require("./editor");
|
||||||
|
var editorApp = editor.init(server, runtime);
|
||||||
|
adminApp.use(editorApp);
|
||||||
|
}
|
||||||
|
|
||||||
|
adminApp.get("/auth/login",auth.login,apiUtil.errorHandler);
|
||||||
if (settings.adminAuth) {
|
if (settings.adminAuth) {
|
||||||
if (settings.adminAuth.type === "strategy") {
|
if (settings.adminAuth.type === "strategy") {
|
||||||
auth.genericStrategy(adminApp,settings.adminAuth.strategy);
|
auth.genericStrategy(adminApp,settings.adminAuth.strategy);
|
||||||
@ -119,62 +66,31 @@ function init(_server,_runtime) {
|
|||||||
auth.errorHandler
|
auth.errorHandler
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
adminApp.post("/auth/revoke",needsPermission(""),auth.revoke,errorHandler);
|
adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.httpAdminCors) {
|
if (settings.httpAdminCors) {
|
||||||
var corsHandler = cors(settings.httpAdminCors);
|
var corsHandler = cors(settings.httpAdminCors);
|
||||||
adminApp.use(corsHandler);
|
adminApp.use(corsHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flows
|
var adminApiApp = require("./admin").init(runtime);
|
||||||
adminApp.get("/flows",needsPermission("flows.read"),flows.get,errorHandler);
|
adminApp.use(adminApiApp);
|
||||||
adminApp.post("/flows",needsPermission("flows.write"),flows.post,errorHandler);
|
} else {
|
||||||
|
adminApp = null;
|
||||||
adminApp.get("/flow/:id",needsPermission("flows.read"),flow.get,errorHandler);
|
|
||||||
adminApp.post("/flow",needsPermission("flows.write"),flow.post,errorHandler);
|
|
||||||
adminApp.delete("/flow/:id",needsPermission("flows.write"),flow.delete,errorHandler);
|
|
||||||
adminApp.put("/flow/:id",needsPermission("flows.write"),flow.put,errorHandler);
|
|
||||||
|
|
||||||
// Nodes
|
|
||||||
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,errorHandler);
|
|
||||||
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,errorHandler);
|
|
||||||
|
|
||||||
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,errorHandler);
|
|
||||||
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,errorHandler);
|
|
||||||
adminApp.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,errorHandler);
|
|
||||||
|
|
||||||
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,errorHandler);
|
|
||||||
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,errorHandler);
|
|
||||||
|
|
||||||
adminApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get,errorHandler);
|
|
||||||
|
|
||||||
adminApp.get('/locales/nodes',locales.getAllNodes,errorHandler);
|
|
||||||
adminApp.get(/locales\/(.+)\/?$/,locales.get,errorHandler);
|
|
||||||
|
|
||||||
// Library
|
|
||||||
adminApp.post(new RegExp("/library/flows\/(.*)"),needsPermission("library.write"),library.post,errorHandler);
|
|
||||||
adminApp.get("/library/flows",needsPermission("library.read"),library.getAll,errorHandler);
|
|
||||||
adminApp.get(new RegExp("/library/flows\/(.*)"),needsPermission("library.read"),library.get,errorHandler);
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
adminApp.get("/settings",needsPermission("settings.read"),info.settings,errorHandler);
|
|
||||||
|
|
||||||
// Error Handler
|
|
||||||
//adminApp.use(errorHandler);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function start() {
|
function start() {
|
||||||
var catalogPath = path.resolve(path.join(__dirname,"locales"));
|
if (editor) {
|
||||||
return i18n.registerMessageCatalogs([
|
return editor.start();
|
||||||
{namespace: "editor", dir: catalogPath, file:"editor.json"},
|
} else {
|
||||||
{namespace: "jsonata", dir: catalogPath, file:"jsonata.json"},
|
return when.resolve();
|
||||||
{namespace: "infotips", dir: catalogPath, file:"infotips.json"}
|
}
|
||||||
]).then(function(){
|
|
||||||
comms.start();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
function stop() {
|
function stop() {
|
||||||
comms.stop();
|
if (editor) {
|
||||||
|
editor.stop();
|
||||||
|
}
|
||||||
return when.resolve();
|
return when.resolve();
|
||||||
}
|
}
|
||||||
module.exports = {
|
module.exports = {
|
||||||
@ -182,13 +98,21 @@ module.exports = {
|
|||||||
start: start,
|
start: start,
|
||||||
stop: stop,
|
stop: stop,
|
||||||
library: {
|
library: {
|
||||||
register: library.register
|
register: function(type) {
|
||||||
|
if (editor) {
|
||||||
|
editor.registerLibrary(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
auth: {
|
auth: {
|
||||||
needsPermission: auth.needsPermission
|
needsPermission: auth.needsPermission
|
||||||
},
|
},
|
||||||
comms: {
|
comms: {
|
||||||
publish: comms.publish
|
publish: function(topic,data,retain) {
|
||||||
|
if (editor) {
|
||||||
|
editor.publish(topic,data,retain);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
get adminApp() { return adminApp; },
|
get adminApp() { return adminApp; },
|
||||||
get server() { return server; }
|
get server() { return server; }
|
||||||
|
47
red/api/util.js
Normal file
47
red/api/util.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
var i18n;
|
||||||
|
var log;
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
init: function(_runtime) {
|
||||||
|
log = _runtime.log;
|
||||||
|
i18n = _runtime.i18n;
|
||||||
|
},
|
||||||
|
errorHandler: function(err,req,res,next) {
|
||||||
|
if (err.message === "request entity too large") {
|
||||||
|
log.error(err);
|
||||||
|
} else {
|
||||||
|
log.error(err.stack);
|
||||||
|
}
|
||||||
|
log.audit({event: "api.error",error:err.code||"unexpected_error",message:err.toString()},req);
|
||||||
|
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||||
|
},
|
||||||
|
|
||||||
|
determineLangFromHeaders: function(acceptedLanguages){
|
||||||
|
console.log("GOT",acceptedLanguages)
|
||||||
|
var lang = i18n.defaultLang;
|
||||||
|
acceptedLanguages = acceptedLanguages || [];
|
||||||
|
if (acceptedLanguages.length >= 1) {
|
||||||
|
console.log("WE HAVE SOMETHING");
|
||||||
|
lang = acceptedLanguages[0];
|
||||||
|
}
|
||||||
|
console.log("RETURNING",lang);
|
||||||
|
return lang;
|
||||||
|
}
|
||||||
|
}
|
@ -33,7 +33,7 @@ var RED = require("../../red/red.js");
|
|||||||
var redNodes = require("../../red/runtime/nodes");
|
var redNodes = require("../../red/runtime/nodes");
|
||||||
var flows = require("../../red/runtime/nodes/flows");
|
var flows = require("../../red/runtime/nodes/flows");
|
||||||
var credentials = require("../../red/runtime/nodes/credentials");
|
var credentials = require("../../red/runtime/nodes/credentials");
|
||||||
var comms = require("../../red/api/comms.js");
|
var comms = require("../../red/api/editor/comms.js");
|
||||||
var log = require("../../red/runtime/log.js");
|
var log = require("../../red/runtime/log.js");
|
||||||
var context = require("../../red/runtime/nodes/context.js");
|
var context = require("../../red/runtime/nodes/context.js");
|
||||||
var events = require("../../red/runtime/events.js");
|
var events = require("../../red/runtime/events.js");
|
||||||
|
@ -21,7 +21,7 @@ var bodyParser = require('body-parser');
|
|||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
|
|
||||||
var flow = require("../../../red/api/flow");
|
var flow = require("../../../../red/api/admin/flow");
|
||||||
|
|
||||||
describe("flow api", function() {
|
describe("flow api", function() {
|
||||||
|
|
@ -21,7 +21,7 @@ var bodyParser = require('body-parser');
|
|||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
|
|
||||||
var flows = require("../../../red/api/flows");
|
var flows = require("../../../../red/api/admin/flows");
|
||||||
|
|
||||||
describe("flows api", function() {
|
describe("flows api", function() {
|
||||||
|
|
299
test/red/api/admin/index_spec.js
Normal file
299
test/red/api/admin/index_spec.js
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
var request = require("supertest");
|
||||||
|
var express = require("express");
|
||||||
|
var adminApi = require("../../../../red/api/admin");
|
||||||
|
var auth = require("../../../../red/api/auth");
|
||||||
|
|
||||||
|
var nodes = require("../../../../red/api/admin/nodes");
|
||||||
|
var flows = require("../../../../red/api/admin/flows");
|
||||||
|
var flow = require("../../../../red/api/admin/flow");
|
||||||
|
var info = require("../../../../red/api/admin/info");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure all API routes are correctly mounted, with the expected permissions checks
|
||||||
|
*/
|
||||||
|
describe("api/admin/index", function() {
|
||||||
|
describe("Ensure all API routes are correctly mounted, with the expected permissions checks", function() {
|
||||||
|
var app;
|
||||||
|
var mockList = [
|
||||||
|
flows,flow,info,nodes
|
||||||
|
]
|
||||||
|
var permissionChecks = {};
|
||||||
|
var lastRequest;
|
||||||
|
var stubApp = function(req,res,next) {
|
||||||
|
lastRequest = req;
|
||||||
|
res.status(200).end();
|
||||||
|
};
|
||||||
|
before(function() {
|
||||||
|
mockList.forEach(function(m) {
|
||||||
|
sinon.stub(m,"init",function(){});
|
||||||
|
});
|
||||||
|
sinon.stub(auth,"needsPermission", function(permission) {
|
||||||
|
return function(req,res,next) {
|
||||||
|
permissionChecks[permission] = (permissionChecks[permission]||0)+1;
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
sinon.stub(flows,"get",stubApp);
|
||||||
|
sinon.stub(flows,"post",stubApp);
|
||||||
|
|
||||||
|
sinon.stub(flow,"get",stubApp);
|
||||||
|
sinon.stub(flow,"post",stubApp);
|
||||||
|
sinon.stub(flow,"delete",stubApp);
|
||||||
|
sinon.stub(flow,"put",stubApp);
|
||||||
|
|
||||||
|
sinon.stub(nodes,"getAll",stubApp);
|
||||||
|
sinon.stub(nodes,"post",stubApp);
|
||||||
|
sinon.stub(nodes,"getModule",stubApp);
|
||||||
|
sinon.stub(nodes,"putModule",stubApp);
|
||||||
|
sinon.stub(nodes,"delete",stubApp);
|
||||||
|
sinon.stub(nodes,"getSet",stubApp);
|
||||||
|
sinon.stub(nodes,"putSet",stubApp);
|
||||||
|
|
||||||
|
sinon.stub(info,"settings",stubApp);
|
||||||
|
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
mockList.forEach(function(m) {
|
||||||
|
m.init.restore();
|
||||||
|
});
|
||||||
|
auth.needsPermission.restore();
|
||||||
|
|
||||||
|
flows.get.restore();
|
||||||
|
flows.post.restore();
|
||||||
|
flow.get.restore();
|
||||||
|
flow.post.restore();
|
||||||
|
flow.delete.restore();
|
||||||
|
flow.put.restore();
|
||||||
|
nodes.getAll.restore();
|
||||||
|
nodes.post.restore();
|
||||||
|
nodes.getModule.restore();
|
||||||
|
nodes.putModule.restore();
|
||||||
|
nodes.delete.restore();
|
||||||
|
nodes.getSet.restore();
|
||||||
|
nodes.putSet.restore();
|
||||||
|
|
||||||
|
info.settings.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
app = adminApi.init({});
|
||||||
|
});
|
||||||
|
beforeEach(function() {
|
||||||
|
permissionChecks = {};
|
||||||
|
})
|
||||||
|
it('GET /flows', function(done) {
|
||||||
|
request(app).get("/flows").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('flows.read',1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('POST /flows', function(done) {
|
||||||
|
request(app).post("/flows").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('flows.write',1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /flow/1234', function(done) {
|
||||||
|
request(app).get("/flow/1234").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('flows.read',1);
|
||||||
|
lastRequest.params.should.have.property('id','1234')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('POST /flow', function(done) {
|
||||||
|
request(app).post("/flow").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('flows.write',1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('DELETE /flow/1234', function(done) {
|
||||||
|
request(app).del("/flow/1234").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('flows.write',1);
|
||||||
|
lastRequest.params.should.have.property('id','1234')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('PUT /flow/1234', function(done) {
|
||||||
|
request(app).put("/flow/1234").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('flows.write',1);
|
||||||
|
lastRequest.params.should.have.property('id','1234')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /nodes', function(done) {
|
||||||
|
request(app).get("/nodes").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.read',1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('POST /nodes', function(done) {
|
||||||
|
request(app).post("/nodes").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.write',1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('GET /nodes/module', function(done) {
|
||||||
|
request(app).get("/nodes/module").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.read',1);
|
||||||
|
lastRequest.params.should.have.property(0,'module')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('GET /nodes/@scope/module', function(done) {
|
||||||
|
request(app).get("/nodes/@scope/module").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.read',1);
|
||||||
|
lastRequest.params.should.have.property(0,'@scope/module')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('PUT /nodes/module', function(done) {
|
||||||
|
request(app).put("/nodes/module").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.write',1);
|
||||||
|
lastRequest.params.should.have.property(0,'module')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('PUT /nodes/@scope/module', function(done) {
|
||||||
|
request(app).put("/nodes/@scope/module").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.write',1);
|
||||||
|
lastRequest.params.should.have.property(0,'@scope/module')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('DELETE /nodes/module', function(done) {
|
||||||
|
request(app).del("/nodes/module").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.write',1);
|
||||||
|
lastRequest.params.should.have.property(0,'module')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('DELETE /nodes/@scope/module', function(done) {
|
||||||
|
request(app).del("/nodes/@scope/module").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.write',1);
|
||||||
|
lastRequest.params.should.have.property(0,'@scope/module')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /nodes/module/set', function(done) {
|
||||||
|
request(app).get("/nodes/module/set").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.read',1);
|
||||||
|
lastRequest.params.should.have.property(0,'module')
|
||||||
|
lastRequest.params.should.have.property(2,'set')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('GET /nodes/@scope/module/set', function(done) {
|
||||||
|
request(app).get("/nodes/@scope/module/set").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.read',1);
|
||||||
|
lastRequest.params.should.have.property(0,'@scope/module')
|
||||||
|
lastRequest.params.should.have.property(2,'set')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('PUT /nodes/module/set', function(done) {
|
||||||
|
request(app).put("/nodes/module/set").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.write',1);
|
||||||
|
lastRequest.params.should.have.property(0,'module')
|
||||||
|
lastRequest.params.should.have.property(2,'set')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
it('PUT /nodes/@scope/module/set', function(done) {
|
||||||
|
request(app).put("/nodes/@scope/module/set").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('nodes.write',1);
|
||||||
|
lastRequest.params.should.have.property(0,'@scope/module')
|
||||||
|
lastRequest.params.should.have.property(2,'set')
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it('GET /settings', function(done) {
|
||||||
|
request(app).get("/settings").expect(200).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
permissionChecks.should.have.property('settings.read',1);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -21,8 +21,8 @@ var sinon = require('sinon');
|
|||||||
var when = require('when');
|
var when = require('when');
|
||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
var info = require("../../../red/api/info");
|
var info = require("../../../../red/api/admin/info");
|
||||||
var theme = require("../../../red/api/theme");
|
var theme = require("../../../../red/api/editor/theme");
|
||||||
|
|
||||||
describe("info api", function() {
|
describe("info api", function() {
|
||||||
describe("settings handler", function() {
|
describe("settings handler", function() {
|
@ -21,8 +21,8 @@ var bodyParser = require('body-parser');
|
|||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
|
|
||||||
var nodes = require("../../../red/api/nodes");
|
var nodes = require("../../../../red/api/admin/nodes");
|
||||||
var locales = require("../../../red/api/locales");
|
var apiUtil = require("../../../../red/api/util");
|
||||||
|
|
||||||
describe("nodes api", function() {
|
describe("nodes api", function() {
|
||||||
|
|
||||||
@ -51,11 +51,13 @@ describe("nodes api", function() {
|
|||||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
|
||||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
||||||
app.delete("/nodes/:id",nodes.delete);
|
app.delete("/nodes/:id",nodes.delete);
|
||||||
sinon.stub(locales,"determineLangFromHeaders", function() {
|
sinon.stub(apiUtil,"determineLangFromHeaders", function() {
|
||||||
return "en-US";
|
return "en-US";
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
after(function() {
|
||||||
|
apiUtil.determineLangFromHeaders.restore();
|
||||||
|
})
|
||||||
|
|
||||||
describe('get nodes', function() {
|
describe('get nodes', function() {
|
||||||
it('returns node list', function(done) {
|
it('returns node list', function(done) {
|
@ -23,14 +23,14 @@ var express = require('express');
|
|||||||
var app = express();
|
var app = express();
|
||||||
var WebSocket = require('ws');
|
var WebSocket = require('ws');
|
||||||
|
|
||||||
var comms = require("../../../red/api/comms");
|
var comms = require("../../../../red/api/editor/comms");
|
||||||
var Users = require("../../../red/api/auth/users");
|
var Users = require("../../../../red/api/auth/users");
|
||||||
var Tokens = require("../../../red/api/auth/tokens");
|
var Tokens = require("../../../../red/api/auth/tokens");
|
||||||
|
|
||||||
var address = '127.0.0.1';
|
var address = '127.0.0.1';
|
||||||
var listenPort = 0; // use ephemeral port
|
var listenPort = 0; // use ephemeral port
|
||||||
|
|
||||||
describe("api/comms", function() {
|
describe("api/editor/comms", function() {
|
||||||
describe("with default keepalive", function() {
|
describe("with default keepalive", function() {
|
||||||
var server;
|
var server;
|
||||||
var url;
|
var url;
|
||||||
@ -327,7 +327,7 @@ describe("api/comms", function() {
|
|||||||
ws.on('message', function(data) {
|
ws.on('message', function(data) {
|
||||||
var msg = JSON.parse(data);
|
var msg = JSON.parse(data);
|
||||||
msg.should.have.property('topic','hb');
|
msg.should.have.property('topic','hb');
|
||||||
msg.should.have.property('data').be.a.Number;
|
msg.should.have.property('data').be.a.Number();
|
||||||
count++;
|
count++;
|
||||||
if (count == 3) {
|
if (count == 3) {
|
||||||
ws.close();
|
ws.close();
|
@ -20,9 +20,9 @@ var express = require('express');
|
|||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
|
|
||||||
var credentials = require("../../../red/api/credentials");
|
var credentials = require("../../../../red/api/editor/credentials");
|
||||||
|
|
||||||
describe('credentials api', function() {
|
describe('api/editor/credentials', function() {
|
||||||
var app;
|
var app;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
109
test/red/api/editor/index_spec.js
Normal file
109
test/red/api/editor/index_spec.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var sinon = require("sinon");
|
||||||
|
var request = require("supertest");
|
||||||
|
var express = require("express");
|
||||||
|
var editorApi = require("../../../../red/api/editor");
|
||||||
|
var comms = require("../../../../red/api/editor/comms");
|
||||||
|
|
||||||
|
|
||||||
|
describe("api/editor/index", function() {
|
||||||
|
var app;
|
||||||
|
describe("disabled the editor", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
sinon.stub(comms,'init', function(){});
|
||||||
|
});
|
||||||
|
afterEach(function() {
|
||||||
|
comms.init.restore();
|
||||||
|
});
|
||||||
|
it("disables the editor", function() {
|
||||||
|
var editorApp = editorApi.init({},{
|
||||||
|
settings:{disableEditor:true}
|
||||||
|
});
|
||||||
|
should.not.exist(editorApp);
|
||||||
|
comms.init.called.should.be.false();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe("enables the editor", function() {
|
||||||
|
var mockList = [
|
||||||
|
'library','theme','locales','credentials','comms'
|
||||||
|
]
|
||||||
|
var isStarted = true;
|
||||||
|
var errors = [];
|
||||||
|
before(function() {
|
||||||
|
mockList.forEach(function(m) {
|
||||||
|
sinon.stub(require("../../../../red/api/editor/"+m),"init",function(){});
|
||||||
|
});
|
||||||
|
sinon.stub(require("../../../../red/api/editor/theme"),"app",function(){ return express()});
|
||||||
|
});
|
||||||
|
after(function() {
|
||||||
|
mockList.forEach(function(m) {
|
||||||
|
require("../../../../red/api/editor/"+m).init.restore();
|
||||||
|
})
|
||||||
|
require("../../../../red/api/editor/theme").app.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
app = editorApi.init({},{
|
||||||
|
log:{audit:function(){},error:function(msg){errors.push(msg)}},
|
||||||
|
settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false},
|
||||||
|
events:{on:function(){},removeListener:function(){}},
|
||||||
|
isStarted: function() { return isStarted; }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('serves the editor', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get("/")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
// Index page should probably mention Node-RED somewhere
|
||||||
|
res.text.indexOf("Node-RED").should.not.eql(-1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('serves icons', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get("/icons/inject.png")
|
||||||
|
.expect("Content-Type", /image\/png/)
|
||||||
|
.expect(200,done)
|
||||||
|
});
|
||||||
|
it('handles page not there', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get("/foo")
|
||||||
|
.expect(404,done)
|
||||||
|
});
|
||||||
|
it('warns if runtime not started', function(done) {
|
||||||
|
isStarted = false;
|
||||||
|
request(app)
|
||||||
|
.get("/")
|
||||||
|
.expect(503)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.text.should.eql("Not started");
|
||||||
|
errors.should.have.lengthOf(1);
|
||||||
|
errors[0].should.eql("Node-RED runtime not started");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -22,10 +22,10 @@ var bodyParser = require('body-parser');
|
|||||||
var when = require('when');
|
var when = require('when');
|
||||||
|
|
||||||
var app;
|
var app;
|
||||||
var library = require("../../../red/api/library");
|
var library = require("../../../../red/api/editor/library");
|
||||||
var auth = require("../../../red/api/auth");
|
var auth = require("../../../../red/api/auth");
|
||||||
|
|
||||||
describe("library api", function() {
|
describe("api/editor/library", function() {
|
||||||
|
|
||||||
function initLibrary(_flows,_libraryEntries,_examples) {
|
function initLibrary(_flows,_libraryEntries,_examples) {
|
||||||
var flows = _flows;
|
var flows = _flows;
|
122
test/red/api/editor/locales_spec.js
Normal file
122
test/red/api/editor/locales_spec.js
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var request = require('supertest');
|
||||||
|
var express = require('express');
|
||||||
|
var sinon = require('sinon');
|
||||||
|
|
||||||
|
var locales = require("../../../../red/api/editor/locales");
|
||||||
|
|
||||||
|
describe("api/editor/locales", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
})
|
||||||
|
afterEach(function() {
|
||||||
|
})
|
||||||
|
describe('get named resource catalog',function() {
|
||||||
|
var app;
|
||||||
|
before(function() {
|
||||||
|
// bit of a mess of internal workings
|
||||||
|
locales.init({
|
||||||
|
i18n: {
|
||||||
|
i: {
|
||||||
|
lng: function() { return 'en-US'},
|
||||||
|
setLng: function(lang,callback) {
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
catalog: function(namespace, lang) {
|
||||||
|
return {namespace:namespace, lang:lang};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app = express();
|
||||||
|
app.get(/locales\/(.+)\/?$/,locales.get);
|
||||||
|
});
|
||||||
|
it('returns with default language', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get("/locales/message-catalog")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('namespace','message-catalog');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns with selected language', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get("/locales/message-catalog?lng=fr-FR")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property('namespace','message-catalog');
|
||||||
|
res.body.should.have.property('lang','fr-FR');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('get all node resource catalogs',function() {
|
||||||
|
var app;
|
||||||
|
before(function() {
|
||||||
|
// bit of a mess of internal workings
|
||||||
|
locales.init({
|
||||||
|
i18n: {
|
||||||
|
catalog: function(namespace, lang) {
|
||||||
|
return {
|
||||||
|
"node-red": "should not return",
|
||||||
|
"test-module-a-id": "test-module-a-catalog",
|
||||||
|
"test-module-b-id": "test-module-b-catalog",
|
||||||
|
"test-module-c-id": "test-module-c-catalog"
|
||||||
|
}[namespace]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
nodes: {
|
||||||
|
getNodeList: function() {
|
||||||
|
return [
|
||||||
|
{module:"node-red",id:"node-red-id"},
|
||||||
|
{module:"test-module-a",id:"test-module-a-id"},
|
||||||
|
{module:"test-module-b",id:"test-module-b-id"}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app = express();
|
||||||
|
app.get("/locales/nodes",locales.getAllNodes);
|
||||||
|
});
|
||||||
|
it('returns with the node catalogs', function(done) {
|
||||||
|
request(app)
|
||||||
|
.get("/locales/nodes")
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.eql({
|
||||||
|
'test-module-a-id': 'test-module-a-catalog',
|
||||||
|
'test-module-b-id': 'test-module-b-catalog'
|
||||||
|
});
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -15,7 +15,6 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
var should = require("should");
|
var should = require("should");
|
||||||
var request = require('supertest');
|
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
@ -23,9 +22,9 @@ var fs = require("fs");
|
|||||||
|
|
||||||
var app = express();
|
var app = express();
|
||||||
|
|
||||||
var theme = require("../../../red/api/theme");
|
var theme = require("../../../../red/api/editor/theme");
|
||||||
|
|
||||||
describe("theme handler", function() {
|
describe("api/editor/theme", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
sinon.stub(fs,"statSync",function() { return true; });
|
sinon.stub(fs,"statSync",function() { return true; });
|
||||||
});
|
});
|
@ -22,10 +22,10 @@ var path = require("path");
|
|||||||
|
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var events = new EventEmitter();
|
var events = new EventEmitter();
|
||||||
var ui = require("../../../red/api/ui");
|
var ui = require("../../../../red/api/editor/ui");
|
||||||
|
|
||||||
|
|
||||||
describe("ui api", function() {
|
describe("api/editor/ui", function() {
|
||||||
var app;
|
var app;
|
||||||
|
|
||||||
before(function() {
|
before(function() {
|
||||||
@ -33,7 +33,7 @@ describe("ui api", function() {
|
|||||||
events:events,
|
events:events,
|
||||||
nodes: {
|
nodes: {
|
||||||
getNodeIconPath: function(module,icon) {
|
getNodeIconPath: function(module,icon) {
|
||||||
return path.resolve(__dirname+'/../../../public/icons/arrow-in.png');
|
return path.resolve(__dirname+'/../../../../public/icons/arrow-in.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -91,7 +91,7 @@ describe("ui api", function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
it('returns the requested icon', function(done) {
|
it('returns the requested icon', function(done) {
|
||||||
var defaultIcon = fs.readFileSync(path.resolve(__dirname+'/../../../public/icons/arrow-in.png'));
|
var defaultIcon = fs.readFileSync(path.resolve(__dirname+'/../../../../public/icons/arrow-in.png'));
|
||||||
request(app)
|
request(app)
|
||||||
.get("/icons/module/icon.png")
|
.get("/icons/module/icon.png")
|
||||||
.expect("Content-Type", /image\/png/)
|
.expect("Content-Type", /image\/png/)
|
@ -23,164 +23,83 @@ var fs = require("fs");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
var api = require("../../../red/api");
|
var api = require("../../../red/api");
|
||||||
|
|
||||||
describe("api index", function() {
|
var apiUtil = require("../../../red/api/util");
|
||||||
var app;
|
var apiAuth = require("../../../red/api/auth");
|
||||||
|
var apiEditor = require("../../../red/api/editor");
|
||||||
|
var apiAdmin = require("../../../red/api/admin");
|
||||||
|
|
||||||
describe("disables editor", function() {
|
|
||||||
|
describe("api/index", function() {
|
||||||
|
var beforeEach = function() {
|
||||||
|
sinon.stub(apiUtil,"init",function(){});
|
||||||
|
sinon.stub(apiAuth,"init",function(){});
|
||||||
|
sinon.stub(apiEditor,"init",function(){
|
||||||
|
var app = express();
|
||||||
|
app.get("/editor",function(req,res) { res.status(200).end(); });
|
||||||
|
return app;
|
||||||
|
});
|
||||||
|
sinon.stub(apiAdmin,"init",function(){
|
||||||
|
var app = express();
|
||||||
|
app.get("/admin",function(req,res) { res.status(200).end(); });
|
||||||
|
return app;
|
||||||
|
});
|
||||||
|
sinon.stub(apiAuth,"login",function(req,res){
|
||||||
|
res.status(200).end();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var afterEach = function() {
|
||||||
|
apiUtil.init.restore();
|
||||||
|
apiAuth.init.restore();
|
||||||
|
apiAuth.login.restore();
|
||||||
|
apiEditor.init.restore();
|
||||||
|
apiAdmin.init.restore();
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(beforeEach);
|
||||||
|
afterEach(afterEach);
|
||||||
|
|
||||||
|
it("does not setup admin api if httpAdminRoot is false", function(done) {
|
||||||
|
api.init({},{
|
||||||
|
settings: { httpAdminRoot: false }
|
||||||
|
});
|
||||||
|
should.not.exist(api.adminApp);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
describe('initalises admin api without adminAuth', function(done) {
|
||||||
before(function() {
|
before(function() {
|
||||||
|
beforeEach();
|
||||||
api.init({},{
|
api.init({},{
|
||||||
settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:true, exportNodeSettings: function() {}},
|
settings: { }
|
||||||
events: {on:function(){},removeListener: function(){}},
|
|
||||||
log: {info:function(){},_:function(){}},
|
|
||||||
nodes: {paletteEditorEnabled: function(){return true}}
|
|
||||||
});
|
});
|
||||||
app = api.adminApp;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('does not serve the editor', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/")
|
|
||||||
.expect(404,done)
|
|
||||||
});
|
|
||||||
it('does not serve icons', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/icons/default.png")
|
|
||||||
.expect(404,done)
|
|
||||||
});
|
|
||||||
it('serves settings', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/settings")
|
|
||||||
.expect(200,done)
|
|
||||||
});
|
});
|
||||||
|
after(afterEach);
|
||||||
|
it('exposes the editor',function() {
|
||||||
|
request(api.adminApp).get("/editor").expect(200).end(done);
|
||||||
|
})
|
||||||
|
it('exposes the admin api',function() {
|
||||||
|
request(api.adminApp).get("/admin").expect(200).end(done);
|
||||||
|
})
|
||||||
|
it('exposes the auth api',function(done) {
|
||||||
|
request(api.adminApp).get("/auth/login").expect(200).end(done);
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("can serve auth", function() {
|
describe('initalises admin api without editor', function(done) {
|
||||||
var mockList = [
|
|
||||||
'ui','nodes','flows','library','info','locales','credentials'
|
|
||||||
]
|
|
||||||
before(function() {
|
|
||||||
mockList.forEach(function(m) {
|
|
||||||
sinon.stub(require("../../../red/api/"+m),"init",function(){});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
after(function() {
|
|
||||||
mockList.forEach(function(m) {
|
|
||||||
require("../../../red/api/"+m).init.restore();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
before(function() {
|
before(function() {
|
||||||
|
beforeEach();
|
||||||
api.init({},{
|
api.init({},{
|
||||||
settings:{httpNodeRoot:true, httpAdminRoot: true, adminAuth:{type: "credentials",users:[],default:{permissions:"read"}}},
|
settings: { disableEditor: true }
|
||||||
storage:{getSessions:function(){return when.resolve({})}},
|
|
||||||
events:{on:function(){},removeListener:function(){}}
|
|
||||||
});
|
|
||||||
app = api.adminApp;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('it now serves auth', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/auth/login")
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) { return done(err); }
|
|
||||||
res.body.type.should.equal("credentials");
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("editor warns if runtime not started", function() {
|
|
||||||
var mockList = [
|
|
||||||
'nodes','flows','library','info','theme','locales','credentials'
|
|
||||||
]
|
|
||||||
before(function() {
|
|
||||||
mockList.forEach(function(m) {
|
|
||||||
sinon.stub(require("../../../red/api/"+m),"init",function(){});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
after(function() {
|
after(afterEach);
|
||||||
mockList.forEach(function(m) {
|
it('does not expose the editor',function() {
|
||||||
require("../../../red/api/"+m).init.restore();
|
request(api.adminApp).get("/editor").expect(404).end(done);
|
||||||
})
|
})
|
||||||
});
|
it('exposes the admin api',function() {
|
||||||
|
request(api.adminApp).get("/admin").expect(200).end(done);
|
||||||
it('serves the editor', function(done) {
|
})
|
||||||
var errorLog = sinon.spy();
|
it('exposes the auth api',function(done) {
|
||||||
api.init({},{
|
request(api.adminApp).get("/auth/login").expect(200).end(done)
|
||||||
log:{audit:function(){},error:errorLog},
|
})
|
||||||
settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false},
|
|
||||||
events:{on:function(){},removeListener:function(){}},
|
|
||||||
isStarted: function() { return false; } // <-----
|
|
||||||
});
|
|
||||||
app = api.adminApp;
|
|
||||||
request(app)
|
|
||||||
.get("/")
|
|
||||||
.expect(503)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
res.text.should.eql("Not started");
|
|
||||||
errorLog.calledOnce.should.be.true();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("enables editor", function() {
|
|
||||||
|
|
||||||
var mockList = [
|
|
||||||
'nodes','flows','library','info','theme','locales','credentials'
|
|
||||||
]
|
|
||||||
before(function() {
|
|
||||||
mockList.forEach(function(m) {
|
|
||||||
sinon.stub(require("../../../red/api/"+m),"init",function(){});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
after(function() {
|
|
||||||
mockList.forEach(function(m) {
|
|
||||||
require("../../../red/api/"+m).init.restore();
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
before(function() {
|
|
||||||
api.init({},{
|
|
||||||
log:{audit:function(){}},
|
|
||||||
settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:false},
|
|
||||||
events:{on:function(){},removeListener:function(){}},
|
|
||||||
isStarted: function() { return true; }
|
|
||||||
});
|
|
||||||
app = api.adminApp;
|
|
||||||
});
|
|
||||||
it('serves the editor', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/")
|
|
||||||
.expect(200)
|
|
||||||
.end(function(err,res) {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
// Index page should probably mention Node-RED somewhere
|
|
||||||
res.text.indexOf("Node-RED").should.not.eql(-1);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
it('serves icons', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/icons/inject.png")
|
|
||||||
.expect("Content-Type", /image\/png/)
|
|
||||||
.expect(200,done)
|
|
||||||
});
|
|
||||||
it('serves settings', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/settings")
|
|
||||||
.expect(200,done)
|
|
||||||
});
|
|
||||||
it('handles page not there', function(done) {
|
|
||||||
request(app)
|
|
||||||
.get("/foo")
|
|
||||||
.expect(404,done)
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
**/
|
|
||||||
|
|
||||||
describe("locales api", function() {
|
|
||||||
it.skip("works",function() {});
|
|
||||||
});
|
|
107
test/red/api/util_spec.js
Normal file
107
test/red/api/util_spec.js
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var should = require("should");
|
||||||
|
var request = require('supertest');
|
||||||
|
var express = require('express');
|
||||||
|
|
||||||
|
var apiUtil = require("../../../red/api/util");
|
||||||
|
|
||||||
|
describe("api/util", function() {
|
||||||
|
describe("errorHandler", function() {
|
||||||
|
var loggedError = null;
|
||||||
|
var loggedEvent = null;
|
||||||
|
var app;
|
||||||
|
before(function() {
|
||||||
|
app = express();
|
||||||
|
apiUtil.init({
|
||||||
|
log:{
|
||||||
|
error: function(msg) {
|
||||||
|
loggedError = msg;
|
||||||
|
},
|
||||||
|
audit: function(event) {
|
||||||
|
loggedEvent = event;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
i18n:{}
|
||||||
|
})
|
||||||
|
app.get("/tooLarge", function(req,res) {
|
||||||
|
var err = new Error();
|
||||||
|
err.message = "request entity too large";
|
||||||
|
throw err;
|
||||||
|
},apiUtil.errorHandler)
|
||||||
|
app.get("/stack", function(req,res) {
|
||||||
|
var err = new Error();
|
||||||
|
err.message = "stacktrace";
|
||||||
|
throw err;
|
||||||
|
},apiUtil.errorHandler)
|
||||||
|
});
|
||||||
|
beforeEach(function() {
|
||||||
|
loggedError = null;
|
||||||
|
loggedEvent = null;
|
||||||
|
})
|
||||||
|
it("logs an error for request entity too large", function(done) {
|
||||||
|
request(app).get("/tooLarge").expect(400).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property("error","unexpected_error");
|
||||||
|
res.body.should.have.property("message","Error: request entity too large");
|
||||||
|
|
||||||
|
loggedError.should.have.property("message","request entity too large");
|
||||||
|
|
||||||
|
loggedEvent.should.have.property("event","api.error");
|
||||||
|
loggedEvent.should.have.property("error","unexpected_error");
|
||||||
|
loggedEvent.should.have.property("message","Error: request entity too large");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it("logs an error plus stack for other errors", function(done) {
|
||||||
|
request(app).get("/stack").expect(400).end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
return done(err);
|
||||||
|
}
|
||||||
|
res.body.should.have.property("error","unexpected_error");
|
||||||
|
res.body.should.have.property("message","Error: stacktrace");
|
||||||
|
|
||||||
|
/Error: stacktrace\s*at.*util_spec.js/m.test(loggedError).should.be.true();
|
||||||
|
|
||||||
|
loggedEvent.should.have.property("event","api.error");
|
||||||
|
loggedEvent.should.have.property("error","unexpected_error");
|
||||||
|
loggedEvent.should.have.property("message","Error: stacktrace");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('determineLangFromHeaders', function() {
|
||||||
|
before(function() {
|
||||||
|
apiUtil.init({
|
||||||
|
log:{},
|
||||||
|
i18n:{defaultLang:"en-US"}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
it('returns the default lang if non provided', function() {
|
||||||
|
apiUtil.determineLangFromHeaders(null).should.eql("en-US");
|
||||||
|
})
|
||||||
|
it('returns the first language accepted', function() {
|
||||||
|
apiUtil.determineLangFromHeaders(['fr-FR','en-GB']).should.eql("fr-FR");
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user