From 7040aaa179fcea4074d2105f2a47f7b12bdafbe6 Mon Sep 17 00:00:00 2001 From: Nicholas O'Leary Date: Mon, 25 Nov 2013 22:50:08 +0000 Subject: [PATCH] Add clientid/username/password to MQTT nodes Alternative implementation, closes #42 The username/password as not stored in the main flow file for security reasons; they are stored in the adjacent credentials file. This does mean an extra step to importing an MQTT node, as the user has to manually edit it to re-add username and password if needed. --- nodes/core/io/10-mqtt.html | 58 +++++++++++++++++++++++-- nodes/core/io/10-mqtt.js | 49 ++++++++++++++++++++- nodes/core/io/lib/mqttConnectionPool.js | 9 ++-- 3 files changed, 108 insertions(+), 8 deletions(-) diff --git a/nodes/core/io/10-mqtt.html b/nodes/core/io/10-mqtt.html index da3c5e347..96ff22053 100644 --- a/nodes/core/io/10-mqtt.html +++ b/nodes/core/io/10-mqtt.html @@ -30,8 +30,9 @@ diff --git a/nodes/core/io/10-mqtt.js b/nodes/core/io/10-mqtt.js index af3d77e94..f729d286b 100644 --- a/nodes/core/io/10-mqtt.js +++ b/nodes/core/io/10-mqtt.js @@ -22,9 +22,54 @@ function MQTTBrokerNode(n) { RED.nodes.createNode(this,n); this.broker = n.broker; this.port = n.port; + this.clientid = n.clientid; + var credentials = RED.nodes.getCredentials(n.id); + if (credentials) { + this.username = credentials.user; + this.password = credentials.password; + } } RED.nodes.registerType("mqtt-broker",MQTTBrokerNode); +var querystring = require('querystring'); + +RED.app.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!="")})); + } else { + res.send(JSON.stringify({})); + } +}); + +RED.app.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) { + 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 MQTTInNode(n) { RED.nodes.createNode(this,n); @@ -32,7 +77,7 @@ function MQTTInNode(n) { this.broker = n.broker; this.brokerConfig = RED.nodes.getNode(this.broker); if (this.brokerConfig) { - this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port); + this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); var node = this; this.client.subscribe(this.topic,2,function(topic,payload,qos,retain) { var msg = {topic:topic,payload:payload,qos:qos,retain:retain}; @@ -65,7 +110,7 @@ function MQTTOutNode(n) { this.brokerConfig = RED.nodes.getNode(this.broker); if (this.brokerConfig) { - this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port); + this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); this.on("input",function(msg) { if (msg != null) { if (this.topic) { diff --git a/nodes/core/io/lib/mqttConnectionPool.js b/nodes/core/io/lib/mqttConnectionPool.js index 1e4b681d4..6b31dea65 100644 --- a/nodes/core/io/lib/mqttConnectionPool.js +++ b/nodes/core/io/lib/mqttConnectionPool.js @@ -25,13 +25,16 @@ function matchTopic(ts,t) { } module.exports = { - get: function(broker,port) { - var id = broker+":"+port; + get: function(broker,port,clientid,username,password) { + var id = "["+(username||"")+":"+(password||"")+"]["+(clientid||"")+"]@"+broker+":"+port; if (!connections[id]) { connections[id] = function() { var client = mqtt.createClient(port,broker); client.setMaxListeners(0); - var options = {keepalive:15,clientId:'mqtt_' + (1+Math.random()*4294967295).toString(16)}; + var options = {keepalive:15}; + options.clientId = clientid || 'mqtt_' + (1+Math.random()*4294967295).toString(16); + options.username = username; + options.password = password; var queue = []; var subscriptions = []; var connecting = false;