mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Reorganise red/api layout to better componentise
This commit is contained in:
		
							
								
								
									
										12
									
								
								Gruntfile.js
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Gruntfile.js
									
									
									
									
									
								
							@@ -47,10 +47,12 @@ module.exports = function(grunt) {
 | 
			
		||||
                timeout: 3000,
 | 
			
		||||
                ignoreLeaks: false,
 | 
			
		||||
                ui: 'bdd',
 | 
			
		||||
                reportFormats: ['lcov'],
 | 
			
		||||
                reportFormats: ['lcov','html'],
 | 
			
		||||
                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: {
 | 
			
		||||
            options: {
 | 
			
		||||
@@ -466,7 +468,7 @@ module.exports = function(grunt) {
 | 
			
		||||
 | 
			
		||||
    grunt.registerTask('test-core',
 | 
			
		||||
        'Runs code style check and unit tests on core runtime code',
 | 
			
		||||
        ['jshint:core','simplemocha:core']);
 | 
			
		||||
        ['build','mocha_istanbul:core']);
 | 
			
		||||
 | 
			
		||||
    grunt.registerTask('test-editor',
 | 
			
		||||
        'Runs code style check on editor code',
 | 
			
		||||
@@ -474,7 +476,7 @@ module.exports = function(grunt) {
 | 
			
		||||
 | 
			
		||||
    grunt.registerTask('test-nodes',
 | 
			
		||||
        'Runs unit tests on core nodes',
 | 
			
		||||
        ['simplemocha:nodes']);
 | 
			
		||||
        ['build','mocha_istanbul:nodes']);
 | 
			
		||||
 | 
			
		||||
    grunt.registerTask('build',
 | 
			
		||||
        'Builds editor content',
 | 
			
		||||
@@ -490,5 +492,5 @@ module.exports = function(grunt) {
 | 
			
		||||
 | 
			
		||||
    grunt.registerTask('coverage',
 | 
			
		||||
        '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
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 **/
 | 
			
		||||
var theme = require("./theme");
 | 
			
		||||
var theme = require("../editor/theme");
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var runtime;
 | 
			
		||||
var settings;
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    init: function(_runtime) {
 | 
			
		||||
        console.log("info.init");
 | 
			
		||||
        runtime = _runtime;
 | 
			
		||||
        settings = runtime.settings;
 | 
			
		||||
    },
 | 
			
		||||
@@ -50,7 +51,6 @@ module.exports = {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        settings.exportNodeSettings(safeSettings);
 | 
			
		||||
 | 
			
		||||
        res.json(safeSettings);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
var when = require("when");
 | 
			
		||||
var locales = require("./locales");
 | 
			
		||||
var apiUtils = require("../util");
 | 
			
		||||
var redNodes;
 | 
			
		||||
var log;
 | 
			
		||||
var i18n;
 | 
			
		||||
@@ -35,7 +35,7 @@ module.exports = {
 | 
			
		||||
            log.audit({event: "nodes.list.get"},req);
 | 
			
		||||
            res.json(redNodes.getNodeList());
 | 
			
		||||
        } else {
 | 
			
		||||
            var lang = locales.determineLangFromHeaders(req.acceptsLanguages());
 | 
			
		||||
            var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
 | 
			
		||||
            log.audit({event: "nodes.configs.get"},req);
 | 
			
		||||
            res.send(redNodes.getNodeConfigs(lang));
 | 
			
		||||
        }
 | 
			
		||||
@@ -141,7 +141,7 @@ module.exports = {
 | 
			
		||||
                res.status(404).end();
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            var lang = locales.determineLangFromHeaders(req.acceptsLanguages());
 | 
			
		||||
            var lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
 | 
			
		||||
            result = redNodes.getNodeConfig(id,lang);
 | 
			
		||||
            if (result) {
 | 
			
		||||
                log.audit({event: "nodes.config.get",id:id},req);
 | 
			
		||||
@@ -22,7 +22,7 @@ var Tokens = require("./tokens");
 | 
			
		||||
var Users = require("./users");
 | 
			
		||||
var permissions = require("./permissions");
 | 
			
		||||
 | 
			
		||||
var theme = require("../theme");
 | 
			
		||||
var theme = require("../editor/theme");
 | 
			
		||||
 | 
			
		||||
var settings = null;
 | 
			
		||||
var log = null
 | 
			
		||||
 
 | 
			
		||||
@@ -48,9 +48,9 @@ function init(_server,runtime) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function start() {
 | 
			
		||||
    var Tokens = require("./auth/tokens");
 | 
			
		||||
    var Users = require("./auth/users");
 | 
			
		||||
    var Permissions = require("./auth/permissions");
 | 
			
		||||
    var Tokens = require("../auth/tokens");
 | 
			
		||||
    var Users = require("../auth/users");
 | 
			
		||||
    var Permissions = require("../auth/permissions");
 | 
			
		||||
    if (!settings.disableEditor) {
 | 
			
		||||
        Users.default().then(function(anonymousUser) {
 | 
			
		||||
            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 log;
 | 
			
		||||
var redNodes;
 | 
			
		||||
var needsPermission = require("./auth").needsPermission;
 | 
			
		||||
var needsPermission = require("../auth").needsPermission;
 | 
			
		||||
 | 
			
		||||
function createLibrary(type) {
 | 
			
		||||
    if (redApp) {
 | 
			
		||||
@@ -15,17 +15,10 @@
 | 
			
		||||
 **/
 | 
			
		||||
var fs = require('fs');
 | 
			
		||||
var path = require('path');
 | 
			
		||||
//var apiUtil = require('../util');
 | 
			
		||||
var i18n;
 | 
			
		||||
var redNodes;
 | 
			
		||||
 | 
			
		||||
function determineLangFromHeaders(acceptedLanguages){
 | 
			
		||||
    var lang = i18n.defaultLang;
 | 
			
		||||
    acceptedLanguages = acceptedLanguages || [];
 | 
			
		||||
    if (acceptedLanguages.length >= 1) {
 | 
			
		||||
        lang = acceptedLanguages[0];
 | 
			
		||||
    }
 | 
			
		||||
    return lang;
 | 
			
		||||
}
 | 
			
		||||
module.exports = {
 | 
			
		||||
    init: function(runtime) {
 | 
			
		||||
        i18n = runtime.i18n;
 | 
			
		||||
@@ -35,7 +28,7 @@ module.exports = {
 | 
			
		||||
        var namespace = req.params[0];
 | 
			
		||||
        var lngs = req.query.lng;
 | 
			
		||||
        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();
 | 
			
		||||
        // Trigger a load from disk of the language if it is not the default
 | 
			
		||||
        i18n.i.setLng(lang, function(){
 | 
			
		||||
@@ -55,6 +48,5 @@ module.exports = {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        res.json(result);
 | 
			
		||||
    },
 | 
			
		||||
    determineLangFromHeaders: determineLangFromHeaders
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,7 +22,7 @@ var theme = require("./theme");
 | 
			
		||||
 | 
			
		||||
var redNodes;
 | 
			
		||||
 | 
			
		||||
var templateDir = path.resolve(__dirname+"/../../editor/templates");
 | 
			
		||||
var templateDir = path.resolve(__dirname+"/../../../editor/templates");
 | 
			
		||||
var editorTemplate;
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
@@ -52,5 +52,5 @@ module.exports = {
 | 
			
		||||
    editor: function(req,res) {
 | 
			
		||||
        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 bodyParser = require("body-parser");
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var path = require('path');
 | 
			
		||||
var passport = require('passport');
 | 
			
		||||
var when = require('when');
 | 
			
		||||
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 needsPermission = auth.needsPermission;
 | 
			
		||||
var apiUtil = require("./util");
 | 
			
		||||
 | 
			
		||||
var i18n;
 | 
			
		||||
var log;
 | 
			
		||||
var adminApp;
 | 
			
		||||
var server;
 | 
			
		||||
var runtime;
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
var editor;
 | 
			
		||||
 | 
			
		||||
function init(_server,_runtime) {
 | 
			
		||||
    server = _server;
 | 
			
		||||
@@ -68,45 +38,22 @@ function init(_server,_runtime) {
 | 
			
		||||
    i18n = runtime.i18n;
 | 
			
		||||
    log = runtime.log;
 | 
			
		||||
    if (settings.httpAdminRoot !== false) {
 | 
			
		||||
        comms.init(server,runtime);
 | 
			
		||||
        apiUtil.init(runtime);
 | 
			
		||||
        adminApp = express();
 | 
			
		||||
        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';
 | 
			
		||||
        adminApp.use(bodyParser.json({limit:maxApiRequestSize}));
 | 
			
		||||
        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.type === "strategy") {
 | 
			
		||||
                auth.genericStrategy(adminApp,settings.adminAuth.strategy);
 | 
			
		||||
@@ -119,62 +66,31 @@ function init(_server,_runtime) {
 | 
			
		||||
                    auth.errorHandler
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            adminApp.post("/auth/revoke",needsPermission(""),auth.revoke,errorHandler);
 | 
			
		||||
            adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (settings.httpAdminCors) {
 | 
			
		||||
            var corsHandler = cors(settings.httpAdminCors);
 | 
			
		||||
            adminApp.use(corsHandler);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Flows
 | 
			
		||||
        adminApp.get("/flows",needsPermission("flows.read"),flows.get,errorHandler);
 | 
			
		||||
        adminApp.post("/flows",needsPermission("flows.write"),flows.post,errorHandler);
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        var adminApiApp = require("./admin").init(runtime);
 | 
			
		||||
        adminApp.use(adminApiApp);
 | 
			
		||||
    } else {
 | 
			
		||||
        adminApp = null;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
function start() {
 | 
			
		||||
    var catalogPath = path.resolve(path.join(__dirname,"locales"));
 | 
			
		||||
    return 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();
 | 
			
		||||
    });
 | 
			
		||||
    if (editor) {
 | 
			
		||||
        return editor.start();
 | 
			
		||||
    } else {
 | 
			
		||||
        return when.resolve();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
function stop() {
 | 
			
		||||
    comms.stop();
 | 
			
		||||
    if (editor) {
 | 
			
		||||
        editor.stop();
 | 
			
		||||
    }
 | 
			
		||||
    return when.resolve();
 | 
			
		||||
}
 | 
			
		||||
module.exports = {
 | 
			
		||||
@@ -182,13 +98,21 @@ module.exports = {
 | 
			
		||||
    start: start,
 | 
			
		||||
    stop: stop,
 | 
			
		||||
    library: {
 | 
			
		||||
        register: library.register
 | 
			
		||||
        register: function(type) {
 | 
			
		||||
            if (editor) {
 | 
			
		||||
                editor.registerLibrary(type);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    auth: {
 | 
			
		||||
        needsPermission: auth.needsPermission
 | 
			
		||||
    },
 | 
			
		||||
    comms: {
 | 
			
		||||
        publish: comms.publish
 | 
			
		||||
        publish: function(topic,data,retain) {
 | 
			
		||||
            if (editor) {
 | 
			
		||||
                editor.publish(topic,data,retain);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    get adminApp() { return adminApp; },
 | 
			
		||||
    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 flows = require("../../red/runtime/nodes/flows");
 | 
			
		||||
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 context = require("../../red/runtime/nodes/context.js");
 | 
			
		||||
var events = require("../../red/runtime/events.js");
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ var bodyParser = require('body-parser');
 | 
			
		||||
var sinon = require('sinon');
 | 
			
		||||
var when = require('when');
 | 
			
		||||
 | 
			
		||||
var flow = require("../../../red/api/flow");
 | 
			
		||||
var flow = require("../../../../red/api/admin/flow");
 | 
			
		||||
 | 
			
		||||
describe("flow api", function() {
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +21,7 @@ var bodyParser = require('body-parser');
 | 
			
		||||
var sinon = require('sinon');
 | 
			
		||||
var when = require('when');
 | 
			
		||||
 | 
			
		||||
var flows = require("../../../red/api/flows");
 | 
			
		||||
var flows = require("../../../../red/api/admin/flows");
 | 
			
		||||
 | 
			
		||||
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 app = express();
 | 
			
		||||
var info = require("../../../red/api/info");
 | 
			
		||||
var theme = require("../../../red/api/theme");
 | 
			
		||||
var info = require("../../../../red/api/admin/info");
 | 
			
		||||
var theme = require("../../../../red/api/editor/theme");
 | 
			
		||||
 | 
			
		||||
describe("info api", function() {
 | 
			
		||||
    describe("settings handler", function() {
 | 
			
		||||
@@ -21,8 +21,8 @@ var bodyParser = require('body-parser');
 | 
			
		||||
var sinon = require('sinon');
 | 
			
		||||
var when = require('when');
 | 
			
		||||
 | 
			
		||||
var nodes = require("../../../red/api/nodes");
 | 
			
		||||
var locales = require("../../../red/api/locales");
 | 
			
		||||
var nodes = require("../../../../red/api/admin/nodes");
 | 
			
		||||
var apiUtil = require("../../../../red/api/util");
 | 
			
		||||
 | 
			
		||||
describe("nodes api", function() {
 | 
			
		||||
 | 
			
		||||
@@ -51,11 +51,13 @@ describe("nodes api", function() {
 | 
			
		||||
        app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
 | 
			
		||||
        app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
 | 
			
		||||
        app.delete("/nodes/:id",nodes.delete);
 | 
			
		||||
        sinon.stub(locales,"determineLangFromHeaders", function() {
 | 
			
		||||
        sinon.stub(apiUtil,"determineLangFromHeaders", function() {
 | 
			
		||||
            return "en-US";
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    after(function() {
 | 
			
		||||
        apiUtil.determineLangFromHeaders.restore();
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    describe('get nodes', function() {
 | 
			
		||||
        it('returns node list', function(done) {
 | 
			
		||||
@@ -23,14 +23,14 @@ var express = require('express');
 | 
			
		||||
var app = express();
 | 
			
		||||
var WebSocket = require('ws');
 | 
			
		||||
 | 
			
		||||
var comms = require("../../../red/api/comms");
 | 
			
		||||
var Users = require("../../../red/api/auth/users");
 | 
			
		||||
var Tokens = require("../../../red/api/auth/tokens");
 | 
			
		||||
var comms = require("../../../../red/api/editor/comms");
 | 
			
		||||
var Users = require("../../../../red/api/auth/users");
 | 
			
		||||
var Tokens = require("../../../../red/api/auth/tokens");
 | 
			
		||||
 | 
			
		||||
var address = '127.0.0.1';
 | 
			
		||||
var listenPort = 0; // use ephemeral port
 | 
			
		||||
 | 
			
		||||
describe("api/comms", function() {
 | 
			
		||||
describe("api/editor/comms", function() {
 | 
			
		||||
    describe("with default keepalive", function() {
 | 
			
		||||
        var server;
 | 
			
		||||
        var url;
 | 
			
		||||
@@ -327,7 +327,7 @@ describe("api/comms", function() {
 | 
			
		||||
            ws.on('message', function(data) {
 | 
			
		||||
                var msg = JSON.parse(data);
 | 
			
		||||
                msg.should.have.property('topic','hb');
 | 
			
		||||
                msg.should.have.property('data').be.a.Number;
 | 
			
		||||
                msg.should.have.property('data').be.a.Number();
 | 
			
		||||
                count++;
 | 
			
		||||
                if (count == 3) {
 | 
			
		||||
                    ws.close();
 | 
			
		||||
@@ -20,9 +20,9 @@ var express = require('express');
 | 
			
		||||
var sinon = require('sinon');
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
    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 app;
 | 
			
		||||
var library = require("../../../red/api/library");
 | 
			
		||||
var auth = require("../../../red/api/auth");
 | 
			
		||||
var library = require("../../../../red/api/editor/library");
 | 
			
		||||
var auth = require("../../../../red/api/auth");
 | 
			
		||||
 | 
			
		||||
describe("library api", function() {
 | 
			
		||||
describe("api/editor/library", function() {
 | 
			
		||||
 | 
			
		||||
    function initLibrary(_flows,_libraryEntries,_examples) {
 | 
			
		||||
        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 request = require('supertest');
 | 
			
		||||
var express = require('express');
 | 
			
		||||
var sinon = require('sinon');
 | 
			
		||||
var when = require('when');
 | 
			
		||||
@@ -23,9 +22,9 @@ var fs = require("fs");
 | 
			
		||||
 | 
			
		||||
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() {
 | 
			
		||||
        sinon.stub(fs,"statSync",function() { return true; });
 | 
			
		||||
    });
 | 
			
		||||
@@ -22,10 +22,10 @@ var path = require("path");
 | 
			
		||||
 | 
			
		||||
var EventEmitter = require('events').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;
 | 
			
		||||
 | 
			
		||||
    before(function() {
 | 
			
		||||
@@ -33,7 +33,7 @@ describe("ui api", function() {
 | 
			
		||||
            events:events,
 | 
			
		||||
            nodes: {
 | 
			
		||||
                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) {
 | 
			
		||||
            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)
 | 
			
		||||
                .get("/icons/module/icon.png")
 | 
			
		||||
                .expect("Content-Type", /image\/png/)
 | 
			
		||||
@@ -23,164 +23,83 @@ var fs = require("fs");
 | 
			
		||||
var path = require("path");
 | 
			
		||||
var api = require("../../../red/api");
 | 
			
		||||
 | 
			
		||||
describe("api index", function() {
 | 
			
		||||
    var app;
 | 
			
		||||
var apiUtil = require("../../../red/api/util");
 | 
			
		||||
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() {
 | 
			
		||||
            beforeEach();
 | 
			
		||||
            api.init({},{
 | 
			
		||||
                settings:{httpNodeRoot:true, httpAdminRoot: true,disableEditor:true, exportNodeSettings: function() {}},
 | 
			
		||||
                events: {on:function(){},removeListener: function(){}},
 | 
			
		||||
                log: {info:function(){},_:function(){}},
 | 
			
		||||
                nodes: {paletteEditorEnabled: function(){return true}}
 | 
			
		||||
                settings: { }
 | 
			
		||||
            });
 | 
			
		||||
            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() {
 | 
			
		||||
        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();
 | 
			
		||||
            })
 | 
			
		||||
        });
 | 
			
		||||
    describe('initalises admin api without editor', function(done) {
 | 
			
		||||
        before(function() {
 | 
			
		||||
            beforeEach();
 | 
			
		||||
            api.init({},{
 | 
			
		||||
                settings:{httpNodeRoot:true, httpAdminRoot: true, adminAuth:{type: "credentials",users:[],default:{permissions:"read"}}},
 | 
			
		||||
                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(){});
 | 
			
		||||
                settings: { disableEditor: true }
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
        after(function() {
 | 
			
		||||
            mockList.forEach(function(m) {
 | 
			
		||||
                require("../../../red/api/"+m).init.restore();
 | 
			
		||||
            })
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('serves the editor', function(done) {
 | 
			
		||||
            var errorLog = sinon.spy();
 | 
			
		||||
            api.init({},{
 | 
			
		||||
                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)
 | 
			
		||||
        });
 | 
			
		||||
        after(afterEach);
 | 
			
		||||
        it('does not expose the editor',function() {
 | 
			
		||||
            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('exposes the auth api',function(done) {
 | 
			
		||||
            request(api.adminApp).get("/auth/login").expect(200).end(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");
 | 
			
		||||
        })
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
		Reference in New Issue
	
	Block a user