mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master'
This commit is contained in:
		| @@ -83,7 +83,7 @@ InjectNode.prototype.close = function() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| RED.app.post("/inject/:id", function(req,res) { | ||||
| RED.httpAdmin.post("/inject/:id", function(req,res) { | ||||
|         var node = RED.nodes.getNode(req.params.id); | ||||
|         if (node != null) { | ||||
|             try { | ||||
|   | ||||
| @@ -80,7 +80,7 @@ DebugNode.send = function(msg) { | ||||
|  | ||||
| DebugNode.activeConnections = []; | ||||
|  | ||||
| var path = RED.settings.httpRoot || "/"; | ||||
| var path = RED.settings.httpAdminRoot || "/"; | ||||
| path = path + (path.slice(-1) == "/" ? "":"/") + "debug/ws"; | ||||
|  | ||||
| DebugNode.wsServer = new ws.Server({server:RED.server,path:path}); | ||||
| @@ -104,7 +104,7 @@ DebugNode.logHandler.on("log",function(msg) { | ||||
| }); | ||||
| RED.nodes.addLogHandler(DebugNode.logHandler); | ||||
|  | ||||
| RED.app.post("/debug/:id/:state", function(req,res) { | ||||
| RED.httpAdmin.post("/debug/:id/:state", function(req,res) { | ||||
| 	var node = RED.nodes.getNode(req.params.id); | ||||
| 	var state = req.params.state; | ||||
| 	if (node != null) { | ||||
|   | ||||
| @@ -132,7 +132,7 @@ | ||||
|  | ||||
|         }, | ||||
|         label: function() { | ||||
|             return this.broker+":"+this.port; | ||||
|             return (this.clientid?this.clientid+"@":"")+this.broker+":"+this.port; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             $.getJSON('mqtt-broker/'+this.id,function(data) { | ||||
|   | ||||
| @@ -33,7 +33,7 @@ RED.nodes.registerType("mqtt-broker",MQTTBrokerNode); | ||||
|  | ||||
| var querystring = require('querystring'); | ||||
|  | ||||
| RED.app.get('/mqtt-broker/:id',function(req,res) { | ||||
| RED.httpAdmin.get('/mqtt-broker/:id',function(req,res) { | ||||
|     var credentials = RED.nodes.getCredentials(req.params.id); | ||||
|     if (credentials) { | ||||
|         res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); | ||||
| @@ -42,12 +42,12 @@ RED.app.get('/mqtt-broker/:id',function(req,res) { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| RED.app.delete('/mqtt-broker/:id',function(req,res) { | ||||
| RED.httpAdmin.delete('/mqtt-broker/:id',function(req,res) { | ||||
|     RED.nodes.deleteCredentials(req.params.id); | ||||
|     res.send(200); | ||||
| }); | ||||
|  | ||||
| RED.app.post('/mqtt-broker/:id',function(req,res) { | ||||
| RED.httpAdmin.post('/mqtt-broker/:id',function(req,res) { | ||||
|     var body = ""; | ||||
|     req.on('data', function(chunk) { | ||||
|         body+=chunk; | ||||
|   | ||||
| @@ -80,7 +80,7 @@ | ||||
|             if (this.name) { | ||||
|                 return this.name; | ||||
|             } else if (this.url) { | ||||
|                 var root = document.location.pathname.slice(0,-1); | ||||
|                 var root = RED.settings.httpNodeRoot.slice(0,-1); | ||||
|                 root += this.url; | ||||
|                 return "["+this.method+"] "+root; | ||||
|             } else { | ||||
|   | ||||
| @@ -21,6 +21,7 @@ var https = require("follow-redirects").https; | ||||
| var urllib = require("url"); | ||||
| var express = require("express"); | ||||
| var getBody = require('raw-body'); | ||||
| var cors = require('cors'); | ||||
| var jsonParser = express.json(); | ||||
| var urlencParser = express.urlencoded(); | ||||
|  | ||||
| @@ -53,28 +54,49 @@ function HTTPIn(n) { | ||||
|     }; | ||||
|      | ||||
|     this.callback = function(req,res) { | ||||
|         if (node.method == "post") { node.send({req:req,res:res,payload:req.body}); } | ||||
|         else if (node.method == "get") { node.send({req:req,res:res,payload:req.query}); } | ||||
|         else node.send({req:req,res:res}); | ||||
|         if (node.method == "post") { | ||||
|             node.send({req:req,res:res,payload:req.body}); | ||||
|         } else if (node.method == "get") { | ||||
|             node.send({req:req,res:res,payload:req.query}); | ||||
|         } else { | ||||
|             node.send({req:req,res:res}); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     var corsHandler = function(req,res,next) { next(); } | ||||
|      | ||||
|     if (RED.settings.httpNodeCors) { | ||||
|         corsHandler = cors(RED.settings.httpNodeCors); | ||||
|         RED.httpNode.options(this.url,corsHandler); | ||||
|     } | ||||
|      | ||||
|     if (this.method == "get") { | ||||
|         RED.app.get(this.url,this.callback,errorHandler); | ||||
|         RED.httpNode.get(this.url,corsHandler,this.callback,this.errorHandler); | ||||
|     } else if (this.method == "post") { | ||||
|         RED.app.post(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); | ||||
|         RED.httpNode.post(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); | ||||
|     } else if (this.method == "put") { | ||||
|         RED.app.put(this.url,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); | ||||
|         RED.httpNode.put(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); | ||||
|     } else if (this.method == "delete") { | ||||
|         RED.app.delete(this.url,this.callback,errorHandler); | ||||
|         RED.httpNode.delete(this.url,corsHandler,this.callback,errorHandler); | ||||
|     } | ||||
|  | ||||
|     this.on("close",function() { | ||||
|             var routes = RED.app.routes[this.method]; | ||||
|             for (var i in routes) { | ||||
|         var routes = RED.httpNode.routes[this.method]; | ||||
|         for (var i = 0; i<routes.length; i++) { | ||||
|             if (routes[i].path == this.url) { | ||||
|                 routes.splice(i,1); | ||||
|                 //break; | ||||
|             } | ||||
|         } | ||||
|         if (RED.settings.httpNodeCors) { | ||||
|             var routes = RED.httpNode.routes['options']; | ||||
|             for (var i = 0; i<routes.length; i++) { | ||||
|                 if (routes[i].path == this.url) { | ||||
|                     routes.splice(i,1); | ||||
|                     //break; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| @@ -106,14 +128,14 @@ RED.nodes.registerType("http response",HTTPOut); | ||||
| function HTTPRequest(n) { | ||||
|     RED.nodes.createNode(this,n); | ||||
|     var nodeUrl = n.url; | ||||
|     var method = n.method || "GET"; | ||||
|     var nodeMethod = n.method || "GET"; | ||||
|     var node = this; | ||||
|     this.on("input",function(msg) { | ||||
|              | ||||
|             var url = msg.url||nodeUrl; | ||||
|  | ||||
|             var method = (msg.method||nodeMethod).toUpperCase(); | ||||
|             var opts = urllib.parse(url); | ||||
|             opts.method = (msg.method||method).toUpperCase(); | ||||
|             opts.method = method; | ||||
|             if (msg.headers) { | ||||
|                 opts.headers = msg.headers; | ||||
|             } | ||||
|   | ||||
| @@ -135,12 +135,12 @@ | ||||
|         inputs:0, | ||||
|         outputs:0, | ||||
|         label: function() { | ||||
|             var root = document.location.pathname.slice(0,-1); | ||||
|             var root = RED.settings.httpNodeRoot.slice(0,-1); | ||||
|             root += this.path; | ||||
|             return root; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             var root = document.location.pathname.slice(0,-1); | ||||
|             var root = RED.settings.httpNodeRoot.slice(0,-1); | ||||
|             if (root == "") { | ||||
|                 $("#node-config-ws-tip").hide(); | ||||
|             } else { | ||||
|   | ||||
| @@ -32,7 +32,7 @@ function WebSocketListenerNode(n) { | ||||
|      | ||||
|     node._inputNodes = [];    // collection of nodes that want to receive events | ||||
|  | ||||
|     var path = RED.settings.httpRoot || "/"; | ||||
|     var path = RED.settings.httpNodeRoot || "/"; | ||||
|     path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path); | ||||
|  | ||||
|     // Workaround https://github.com/einaros/ws/pull/253 | ||||
|   | ||||
| @@ -185,7 +185,7 @@ var serialPool = function() { | ||||
|     } | ||||
| }(); | ||||
|  | ||||
| RED.app.get("/serialports",function(req,res) { | ||||
| RED.httpAdmin.get("/serialports",function(req,res) { | ||||
|     serialp.list(function (err, ports) { | ||||
|         res.writeHead(200, {'Content-Type': 'text/plain'}); | ||||
|         res.write(JSON.stringify(ports)); | ||||
|   | ||||
| @@ -263,7 +263,7 @@ var oa = new OAuth( | ||||
|  | ||||
| var credentials = {}; | ||||
|  | ||||
| RED.app.get('/twitter/:id', function(req,res) { | ||||
| RED.httpAdmin.get('/twitter/:id', function(req,res) { | ||||
|     var credentials = RED.nodes.getCredentials(req.params.id); | ||||
|     if (credentials) { | ||||
|         res.send(JSON.stringify({sn:credentials.screen_name})); | ||||
| @@ -272,12 +272,12 @@ RED.app.get('/twitter/:id', function(req,res) { | ||||
|     } | ||||
| }); | ||||
|  | ||||
| RED.app.delete('/twitter/:id', function(req,res) { | ||||
| RED.httpAdmin.delete('/twitter/:id', function(req,res) { | ||||
|     RED.nodes.deleteCredentials(req.params.id); | ||||
|     res.send(200); | ||||
| }); | ||||
|  | ||||
| RED.app.get('/twitter/:id/auth', function(req, res){ | ||||
| RED.httpAdmin.get('/twitter/:id/auth', function(req, res){ | ||||
|     var credentials = {}; | ||||
|     oa.getOAuthRequestToken({ | ||||
|             oauth_callback: req.query.callback | ||||
| @@ -297,7 +297,7 @@ RED.app.get('/twitter/:id/auth', function(req, res){ | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| RED.app.get('/twitter/:id/auth/callback', function(req, res, next){ | ||||
| RED.httpAdmin.get('/twitter/:id/auth/callback', function(req, res, next){ | ||||
|     var credentials = RED.nodes.getCredentials(req.params.id); | ||||
|     credentials.oauth_verifier = req.query.oauth_verifier; | ||||
|  | ||||
|   | ||||
| @@ -29,6 +29,14 @@ | ||||
|         <label for="node-config-input-name"><i class="icon-tag"></i> Name</label> | ||||
|         <input type="text" id="node-config-input-name" placeholder="Name"> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-config-input-user"><i class="icon-user"></i> Username</label> | ||||
|         <input type="text" id="node-config-input-user"> | ||||
|     </div> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-config-input-pass"><i class="icon-lock"></i> Password</label> | ||||
|         <input type="password" id="node-config-input-pass"> | ||||
|     </div> | ||||
| </script> | ||||
|  | ||||
| <script type="text/javascript"> | ||||
| @@ -39,10 +47,47 @@ | ||||
|             hostname: { value:"127.0.0.1",required:true}, | ||||
|             port: { value: 27017,required:true}, | ||||
|             db: { value:"",required:true}, | ||||
|             name: { value:"" } | ||||
|             name: { value:"" }, | ||||
|             //user -> credentials | ||||
|             //pass -> credentials | ||||
|         }, | ||||
|         label: function() { | ||||
|             return this.name||this.hostname+":"+this.port+"//"+this.db; | ||||
|             return this.name||this.hostname+":"+this.port+"/"+this.db; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             $.getJSON('mongodb/'+this.id,function(data) { | ||||
|                 if (data.user) { | ||||
|                     $('#node-config-input-user').val(data.user); | ||||
|                 } | ||||
|                 if (data.hasPassword) { | ||||
|                     $('#node-config-input-pass').val('__PWRD__'); | ||||
|                 } else { | ||||
|                     $('#node-config-input-pass').val(''); | ||||
|                 } | ||||
|  | ||||
|             }); | ||||
|         }, | ||||
|         oneditsave: function() { | ||||
|             var newUser = $('#node-config-input-user').val(); | ||||
|             var newPass = $('#node-config-input-pass').val(); | ||||
|             var credentials = {}; | ||||
|             credentials.user = newUser; | ||||
|             if (newPass != '__PWRD__') { | ||||
|                 credentials.password = newPass; | ||||
|             } | ||||
|             $.ajax({ | ||||
|                 url: 'mongodb/'+this.id, | ||||
|                 type: 'POST', | ||||
|                 data: credentials, | ||||
|                 success:function(result){} | ||||
|             }); | ||||
|         }, | ||||
|         ondelete: function() { | ||||
|             $.ajax({ | ||||
|                 url: 'mongodb/'+this.id, | ||||
|                 type: 'DELETE', | ||||
|                 success: function(result) {} | ||||
|             }); | ||||
|         } | ||||
|     }); | ||||
| </script> | ||||
| @@ -110,7 +155,7 @@ | ||||
|         align: "right", | ||||
|         label: function() { | ||||
|             var mongoNode = RED.nodes.node(this.mongodb); | ||||
|             return this.name||(mongoNode?mongoNode.label()+"//"+this.collection:"mongodb"); | ||||
|             return this.name||(mongoNode?mongoNode.label()+" "+this.collection:"mongodb"); | ||||
|         }, | ||||
|         labelStyle: function() { | ||||
|             return this.name?"node_label_italic":""; | ||||
| @@ -154,7 +199,7 @@ | ||||
|         icon: "mongodb.png", | ||||
|         label: function() { | ||||
|             var mongoNode = RED.nodes.node(this.mongodb); | ||||
|             return this.name||(mongoNode?mongoNode.label()+"//"+this.collection:"mongodb"); | ||||
|             return this.name||(mongoNode?mongoNode.label()+" "+this.collection:"mongodb"); | ||||
|         }, | ||||
|         labelStyle: function() { | ||||
|             return this.name?"node_label_italic":""; | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
|  | ||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | ||||
| var mongo = require('mongodb'); | ||||
| var MongoClient = mongo.MongoClient; | ||||
|  | ||||
| function MongoNode(n) { | ||||
|     RED.nodes.createNode(this,n); | ||||
| @@ -23,9 +24,62 @@ function MongoNode(n) { | ||||
|     this.port = n.port; | ||||
|     this.db = n.db; | ||||
|     this.name = n.name; | ||||
|     var credentials = RED.nodes.getCredentials(n.id); | ||||
|     if (credentials) { | ||||
|         this.username = credentials.user; | ||||
|         this.password = credentials.password; | ||||
|     } | ||||
|      | ||||
|     var url = "mongodb://"; | ||||
|     if (this.username && this.password) { | ||||
|         url += this.username+":"+this.password+"@"; | ||||
|     } | ||||
|     url += this.hostname+":"+this.port+"/"+this.db; | ||||
|      | ||||
|     this.url = url; | ||||
| } | ||||
|  | ||||
| RED.nodes.registerType("mongodb",MongoNode); | ||||
|  | ||||
| var querystring = require('querystring'); | ||||
|  | ||||
| RED.httpAdmin.get('/mongodb/:id',function(req,res) { | ||||
|     var credentials = RED.nodes.getCredentials(req.params.id); | ||||
|     if (credentials) { | ||||
|         res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); | ||||
|     } else { | ||||
|         res.send(JSON.stringify({})); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| RED.httpAdmin.delete('/mongodb/:id',function(req,res) { | ||||
|     RED.nodes.deleteCredentials(req.params.id); | ||||
|     res.send(200); | ||||
| }); | ||||
|  | ||||
| RED.httpAdmin.post('/mongodb/:id',function(req,res) { | ||||
|     var body = ""; | ||||
|     req.on('data', function(chunk) { | ||||
|         body+=chunk; | ||||
|     }); | ||||
|     req.on('end', function(){ | ||||
|         var newCreds = querystring.parse(body); | ||||
|         var credentials = RED.nodes.getCredentials(req.params.id)||{}; | ||||
|         if (newCreds.user == null || newCreds.user == "") { | ||||
|             delete credentials.user; | ||||
|         } else { | ||||
|             credentials.user = newCreds.user; | ||||
|         } | ||||
|         if (newCreds.password == "") { | ||||
|             delete credentials.password; | ||||
|         } else { | ||||
|             credentials.password = newCreds.password||credentials.password; | ||||
|         } | ||||
|         RED.nodes.addCredentials(req.params.id,credentials); | ||||
|         res.send(200); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
|  | ||||
| function MongoOutNode(n) { | ||||
|     RED.nodes.createNode(this,n); | ||||
| @@ -37,34 +91,33 @@ function MongoOutNode(n) { | ||||
|  | ||||
|     if (this.mongoConfig) { | ||||
|         var node = this; | ||||
|         this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); | ||||
|         this.clientDb.open(function(err,cli) { | ||||
|             if (err) { node.error(err); } | ||||
|             else { | ||||
|                 node.clientDb.collection(node.collection,function(err,coll) { | ||||
|                     if (err) { node.error(err); } | ||||
|                     else { | ||||
|                         node.on("input",function(msg) { | ||||
|                             if (node.operation == "store") { | ||||
|                                 delete msg._topic; | ||||
|                                 if (node.payonly) { | ||||
|                                     if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } | ||||
|                                     coll.save(msg.payload,function(err,item){ if (err){node.error(err);} }); | ||||
|                                 } | ||||
|                                 else coll.save(msg,function(err,item){if (err){node.error(err);}}); | ||||
|                             } | ||||
|                             else if (node.operation == "insert") { | ||||
|                                 delete msg._topic; | ||||
|                                 if (node.payonly) { | ||||
|                                     if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } | ||||
|                                     coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); | ||||
|                                 } | ||||
|                                 else coll.insert(msg,function(err,item){if (err){node.error(err);}}); | ||||
|                             } | ||||
|                             if (node.operation == "delete") { | ||||
|                                 coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); | ||||
|                             } | ||||
|                         }); | ||||
|         MongoClient.connect(this.mongoConfig.url, function(err,db) { | ||||
|             if (err) { | ||||
|                 node.error(err); | ||||
|             } else { | ||||
|                 node.clientDb = db; | ||||
|                 var coll = db.collection(node.collection); | ||||
|                 node.on("input",function(msg) { | ||||
|                     if (node.operation == "store") { | ||||
|                         delete msg._topic; | ||||
|                         if (node.payonly) { | ||||
|                             if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } | ||||
|                             coll.save(msg.payload,function(err,item){ if (err){node.error(err);} }); | ||||
|                         } else { | ||||
|                             coll.save(msg,function(err,item){if (err){node.error(err);}}); | ||||
|                         } | ||||
|                     } | ||||
|                     else if (node.operation == "insert") { | ||||
|                         delete msg._topic; | ||||
|                         if (node.payonly) { | ||||
|                             if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } | ||||
|                             coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); | ||||
|                         } else { | ||||
|                             coll.insert(msg,function(err,item){if (err){node.error(err);}}); | ||||
|                         } | ||||
|                     } | ||||
|                     if (node.operation == "delete") { | ||||
|                         coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
| @@ -90,25 +143,25 @@ function MongoInNode(n) { | ||||
|  | ||||
|     if (this.mongoConfig) { | ||||
|         var node = this; | ||||
|         this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); | ||||
|         this.clientDb.open(function(err,cli) { | ||||
|             if (err) { node.error(err); } | ||||
|             else { | ||||
|                 node.clientDb.collection(node.collection,function(err,coll) { | ||||
|                     if (err) { node.error(err); } | ||||
|                     else { | ||||
|                         node.on("input",function(msg) { | ||||
|                             msg.projection = msg.projection || {}; | ||||
|                             coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { | ||||
|                                 if (err) { node.error(err); } | ||||
|                                 msg.payload = items; | ||||
|                                 delete msg.projection; | ||||
|                                 delete msg.sort; | ||||
|                                 delete msg.limit; | ||||
|                                 node.send(msg); | ||||
|                             }); | ||||
|                         }); | ||||
|                     } | ||||
|         MongoClient.connect(this.mongoConfig.url, function(err,db) { | ||||
|             if (err) { | ||||
|                 node.error(err); | ||||
|             } else { | ||||
|                 node.clientDb = db; | ||||
|                 var coll = db.collection(node.collection); | ||||
|                 node.on("input",function(msg) { | ||||
|                     msg.projection = msg.projection || {}; | ||||
|                     coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { | ||||
|                         if (err) { | ||||
|                             node.error(err); | ||||
|                         } else { | ||||
|                             msg.payload = items; | ||||
|                             delete msg.projection; | ||||
|                             delete msg.sort; | ||||
|                             delete msg.limit; | ||||
|                             node.send(msg); | ||||
|                         } | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|         }); | ||||
|   | ||||
| @@ -36,6 +36,7 @@ | ||||
|         "sentiment":"~0.2.1", | ||||
|         "irc":"~0.3.6", | ||||
|         "follow-redirects":"~0.0.3", | ||||
|         "cors":"~2.1.1", | ||||
|         "mkdirp":"~0.3.5" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|   | ||||
| @@ -122,6 +122,12 @@ var RED = function() { | ||||
|             ] | ||||
|     }); | ||||
|  | ||||
|     function loadSettings() { | ||||
|         $.get('settings', function(data) { | ||||
|                 RED.settings = data; | ||||
|                 loadNodes(); | ||||
|         }); | ||||
|     } | ||||
|     function loadNodes() { | ||||
|         $.get('nodes', function(data) { | ||||
|                 $("body").append(data); | ||||
| @@ -157,7 +163,7 @@ var RED = function() { | ||||
|  | ||||
|     $(function() { | ||||
|             RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); | ||||
|             loadNodes(); | ||||
|             loadSettings(); | ||||
|     }); | ||||
|  | ||||
|     return { | ||||
|   | ||||
							
								
								
									
										56
									
								
								red.js
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								red.js
									
									
									
									
									
								
							| @@ -48,31 +48,57 @@ if (settings.https) { | ||||
|     server = http.createServer(function(req,res){app(req,res);}); | ||||
| } | ||||
|  | ||||
| function formatRoot(root) { | ||||
|     if (root[0] != "/") { | ||||
|         root = "/" + root; | ||||
|     } | ||||
|     if (root.slice(-1) != "/") { | ||||
|         root = root + "/"; | ||||
|     } | ||||
|     return root; | ||||
| } | ||||
|  | ||||
| settings.httpRoot = settings.httpRoot||"/"; | ||||
|  | ||||
| if (settings.httpRoot[0] != "/") { | ||||
|     settings.httpRoot = "/"+settings.httpRoot; | ||||
| } | ||||
| if (settings.httpRoot.slice(-1) != "/") { | ||||
|     settings.httpRoot = settings.httpRoot + "/"; | ||||
| } | ||||
| settings.httpAdminRoot = formatRoot(settings.httpAdminRoot || settings.httpRoot || "/"); | ||||
| settings.httpAdminAuth = settings.httpAdminAuth || settings.httpAuth; | ||||
|  | ||||
| settings.httpNodeRoot = formatRoot(settings.httpNodeRoot || settings.httpRoot || "/"); | ||||
| settings.httpNodeAuth = settings.httpNodeAuth || settings.httpAuth; | ||||
|  | ||||
| settings.uiPort = settings.uiPort||1880; | ||||
| settings.uiHost = settings.uiHost||"0.0.0.0"; | ||||
|  | ||||
| if (settings.httpAuth) { | ||||
|     app.use(settings.httpRoot, | ||||
| settings.flowFile = flowFile || settings.flowFile; | ||||
|  | ||||
| RED.init(server,settings); | ||||
|  | ||||
| if (settings.httpAdminAuth) { | ||||
|     app.use(settings.httpAdminRoot, | ||||
|         express.basicAuth(function(user, pass) { | ||||
|             return user === settings.httpAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAuth.pass; | ||||
|             return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass; | ||||
|         }) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| settings.flowFile = flowFile || settings.flowFile; | ||||
|  | ||||
| var red = RED.init(server,settings); | ||||
| app.use(settings.httpRoot,red); | ||||
| if (settings.httpNodeAuth) { | ||||
|     app.use(settings.httpNodeRoot, | ||||
|         express.basicAuth(function(user, pass) { | ||||
|             return user === settings.httpNodeAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpNodeAuth.pass; | ||||
|         }) | ||||
|     ); | ||||
| } | ||||
| app.use(settings.httpAdminRoot,RED.httpAdmin); | ||||
| app.use(settings.httpNodeRoot,RED.httpNode); | ||||
|  | ||||
| if (settings.httpStatic) { | ||||
|     settings.httpStaticAuth = settings.httpStaticAuth || settings.httpAuth; | ||||
|     if (settings.httpStaticAuth) { | ||||
|         app.use("/", | ||||
|             express.basicAuth(function(user, pass) { | ||||
|                 return user === settings.httpStaticAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpStaticAuth.pass; | ||||
|             }) | ||||
|         ); | ||||
|     } | ||||
|     app.use("/",express.static(settings.httpStatic)); | ||||
| } | ||||
|  | ||||
| @@ -80,7 +106,7 @@ RED.start(); | ||||
|  | ||||
| var listenPath = 'http'+(settings.https?'s':'')+'://'+ | ||||
|                  (settings.uiHost == '0.0.0.0'?'127.0.0.1':settings.uiHost)+ | ||||
|                  ':'+settings.uiPort+settings.httpRoot; | ||||
|                  ':'+settings.uiPort+settings.httpAdminRoot; | ||||
|  | ||||
| server.listen(settings.uiPort,settings.uiHost,function() { | ||||
| 	util.log('[red] Server now running at '+listenPath); | ||||
|   | ||||
| @@ -42,7 +42,9 @@ var RED = { | ||||
|     events: events | ||||
| }; | ||||
|  | ||||
| RED.__defineGetter__("app", function() { return server.app }); | ||||
| RED.__defineGetter__("app", function() { console.log("Deprecated use of RED.app - use RED.httpAdmin instead"); return server.app }); | ||||
| RED.__defineGetter__("httpAdmin", function() { return server.app }); | ||||
| RED.__defineGetter__("httpNode", function() { return server.nodeApp }); | ||||
| RED.__defineGetter__("server", function() { return server.server }); | ||||
| RED.__defineGetter__("settings", function() { return settings }); | ||||
|  | ||||
|   | ||||
| @@ -14,11 +14,13 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
|  | ||||
| var express = require('express'); | ||||
| var util = require('util'); | ||||
| var createUI = require("./ui"); | ||||
| var redNodes = require("./nodes"); | ||||
|  | ||||
| var app = null; | ||||
| var nodeApp = null; | ||||
| var server = null; | ||||
| var settings = null; | ||||
| var storage = null; | ||||
| @@ -28,6 +30,7 @@ function createServer(_server,_settings) { | ||||
|     settings = _settings; | ||||
|     storage = require("./storage"); | ||||
|     app = createUI(settings); | ||||
|     nodeApp = express(); | ||||
|      | ||||
|     flowfile = settings.flowFile || 'flows_'+require('os').hostname()+'.json'; | ||||
|      | ||||
| @@ -103,4 +106,5 @@ module.exports = { | ||||
| } | ||||
|  | ||||
| module.exports.__defineGetter__("app", function() { return app }); | ||||
| module.exports.__defineGetter__("nodeApp", function() { return nodeApp }); | ||||
| module.exports.__defineGetter__("server", function() { return server }); | ||||
|   | ||||
							
								
								
									
										30
									
								
								red/ui.js
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								red/ui.js
									
									
									
									
									
								
							| @@ -34,24 +34,30 @@ function setupUI(settings) { | ||||
|     // Need to ensure the url ends with a '/' so the static serving works | ||||
|     // with relative paths | ||||
|     app.get("/",function(req,res) { | ||||
|             if (req.originalUrl.slice(-1) != "/") { | ||||
|                 res.redirect(req.originalUrl+"/"); | ||||
|             } else { | ||||
|                 req.next(); | ||||
|             } | ||||
|         if (req.originalUrl.slice(-1) != "/") { | ||||
|             res.redirect(req.originalUrl+"/"); | ||||
|         } else { | ||||
|             req.next(); | ||||
|         } | ||||
|     }); | ||||
|      | ||||
|     app.get("/icons/:icon",function(req,res) { | ||||
|             for (var p in icon_paths) { | ||||
|                 if (fs.existsSync(icon_paths[p]+'/'+req.params.icon)) { | ||||
|                     res.sendfile(icon_paths[p]+'/'+req.params.icon); | ||||
|                     return; | ||||
|                 } | ||||
|         for (var p in icon_paths) { | ||||
|             if (fs.existsSync(icon_paths[p]+'/'+req.params.icon)) { | ||||
|                 res.sendfile(icon_paths[p]+'/'+req.params.icon); | ||||
|                 return; | ||||
|             } | ||||
|             //TODO: create a default icon | ||||
|             res.sendfile(path.resolve(__dirname + '/../public/icons/arrow-in.png')); | ||||
|         } | ||||
|         //TODO: create a default icon | ||||
|         res.sendfile(path.resolve(__dirname + '/../public/icons/arrow-in.png')); | ||||
|     }); | ||||
|      | ||||
|     app.get("/settings", function(req,res) { | ||||
|         var safeSettings = { | ||||
|             httpNodeRoot: settings.httpNodeRoot | ||||
|         }; | ||||
|         res.json(safeSettings); | ||||
|     }); | ||||
|      | ||||
|     app.use("/",express.static(__dirname + '/../public')); | ||||
|      | ||||
|   | ||||
							
								
								
									
										43
									
								
								settings.js
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								settings.js
									
									
									
									
									
								
							| @@ -49,19 +49,41 @@ module.exports = { | ||||
|     // The following property can be used to specify an additional directory to scan. | ||||
|     //nodesDir: '/home/nol/.node-red/nodes', | ||||
|  | ||||
|     // You can protect the user interface with a userid and password by using the following property | ||||
|     // the password must be an md5 hash  eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') | ||||
|     //httpAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, | ||||
|  | ||||
|     // By default, the Node-RED UI is available at http://localhost:1880/ | ||||
|     // The following property can be used to specifiy a different root path. | ||||
|     //httpRoot: '/admin', | ||||
|     //httpAdminRoot: '/admin', | ||||
|  | ||||
|     // When httpRoot is used to move the UI to a different root path, the | ||||
|     // You can protect the user interface with a userid and password by using the following property. | ||||
|     // The password must be an md5 hash  eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') | ||||
|     //httpAdminAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, | ||||
|  | ||||
|     // Some nodes, such as HTTP In, can be used to listen for incoming http requests. | ||||
|     // By default, these are served relative to '/'. The following property | ||||
|     // can be used to specifiy a different root path. | ||||
|     //httpNodeRoot: '/nodes', | ||||
|      | ||||
|     // To password protect the node-defined HTTP endpoints, the following property | ||||
|     // can be used. | ||||
|     // The password must be an md5 hash  eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') | ||||
|     //httpNodeAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, | ||||
|      | ||||
|     // When httpAdminRoot is used to move the UI to a different root path, the | ||||
|     // following property can be used to identify a directory of static content | ||||
|     // that should be served at http://localhost:1880/. | ||||
|     //httpStatic: '/home/nol/node-red-dashboard/', | ||||
|  | ||||
|     // To password protect the static content, the following property can be used. | ||||
|     // The password must be an md5 hash  eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') | ||||
|     //httpStaticAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, | ||||
|      | ||||
|     // The following property can be used in place of 'httpAdminRoot' and 'httpNodeRoot', | ||||
|     // to apply the same root to both parts. | ||||
|     //httpRoot: '/red', | ||||
|      | ||||
|     // The following property can be used in place of 'httpAdminAuth' and 'httpNodeAuth', | ||||
|     // to apply the same authentication to both parts. | ||||
|     //httpAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, | ||||
|      | ||||
|     // The following property can be used to enable HTTPS | ||||
|     // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener | ||||
|     // for details on its contents. | ||||
| @@ -70,6 +92,15 @@ module.exports = { | ||||
|     //    cert: fs.readFileSync('certificate.pem') | ||||
|     //}, | ||||
|  | ||||
|     // The following property can be used to configure cross-origin resource sharing | ||||
|     // in the HTTP nodes. | ||||
|     // See https://github.com/troygoode/node-cors#configuration-options for | ||||
|     // details on its contents. The following is a basic permissive set of options: | ||||
|     //httpNodeCors: { | ||||
|     //    origin: "*", | ||||
|     //    methods: "GET,PUT,POST,DELETE" | ||||
|     //}, | ||||
|      | ||||
|     // Anything in this hash is globally available to all functions. | ||||
|     // It is accessed as context.global. | ||||
|     // eg: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user