1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #251 from Belphemur/credentials-pr

Rewrite credentials API to work with save on deploy.
This commit is contained in:
Nick O'Leary 2014-07-16 10:41:01 +01:00
commit d4919e27bd
5 changed files with 147 additions and 97 deletions

View File

@ -92,6 +92,14 @@ var RED = function() {
node.dirty = true; node.dirty = true;
node.changed = false; node.changed = false;
} }
if(node._creds) {
delete node._creds;
}
});
RED.nodes.eachConfig(function (confNode) {
if (confNode._creds) {
delete confNode._creds;
}
}); });
// Once deployed, cannot undo back to a clean state // Once deployed, cannot undo back to a clean state
RED.history.markAllDirty(); RED.history.markAllDirty();

View File

@ -175,13 +175,17 @@ RED.nodes = function() {
/** /**
* Converts a node to an exportable JSON Object * Converts a node to an exportable JSON Object
**/ **/
function convertNode(n) { function convertNode(n, exportCreds) {
exportCreds = exportCreds || false;
var node = {}; var node = {};
node.id = n.id; node.id = n.id;
node.type = n.type; node.type = n.type;
for (var d in n._def.defaults) { for (var d in n._def.defaults) {
node[d] = n[d]; node[d] = n[d];
} }
if(exportCreds && n._creds) {
node._creds = n._creds.send;
}
if (n._def.category != "config") { if (n._def.category != "config") {
node.x = n.x; node.x = n.x;
node.y = n.y; node.y = n.y;
@ -235,11 +239,11 @@ RED.nodes = function() {
nns.push(workspaces[i]); nns.push(workspaces[i]);
} }
for (var i in configNodes) { for (var i in configNodes) {
nns.push(convertNode(configNodes[i])); nns.push(convertNode(configNodes[i], true));
} }
for (var i in nodes) { for (var i in nodes) {
var node = nodes[i]; var node = nodes[i];
nns.push(convertNode(node)); nns.push(convertNode(node, true));
} }
return nns; return nns;
} }

View File

@ -22,25 +22,40 @@ RED.editor = function() {
return 'credentials/' + dashedType + "/" + nodeID; return 'credentials/' + dashedType + "/" + nodeID;
} }
function sendCredentials(node,credDefinition,prefix) { /**
var credentials = {}; * Assign the credentials to the node
* @param node - the node containing the credentials
* @param credDefinition - definition of the credentials
* @param prefix - prefix of the input fields
*/
function manageNodeCredentials(node, credDefinition, prefix) {
if(!node._creds) {
node._creds = {server: {}, send: {}, input: {}};
}
for (var cred in credDefinition) { for (var cred in credDefinition) {
var input = $("#" + prefix + '-' + cred); var input = $("#" + prefix + '-' + cred);
var value = input.val(); var value = input.val();
if (credDefinition[cred].type == 'password' && value == '__PWRD__') { if (credDefinition[cred].type == 'password') {
continue; if(value != '') {
node._creds.input['has' + cred] = true;
if (value == '__PWRD__') {
continue;
}
} else {
node._creds.input['has' + cred] = false;
}
} }
credentials[cred] = value; if (node._creds.server[cred] != value) {
} node._creds.send[cred] = value;
node._def._creds = credentials; } else {
$.ajax({ delete node._creds.send[cred];
url: getCredentialsURL(node.type, node.id), }
type: 'POST', if (credDefinition[cred].type != 'password') {
data: credentials, node._creds.input[cred] = value;
success: function (result) {
} }
});
}
} }
@ -222,7 +237,7 @@ RED.editor = function() {
if (editing_node._def.credentials) { if (editing_node._def.credentials) {
var prefix = 'node-input'; var prefix = 'node-input';
var credDefinition = editing_node._def.credentials; var credDefinition = editing_node._def.credentials;
sendCredentials(editing_node,credDefinition,prefix); manageNodeCredentials(editing_node,credDefinition,prefix);
} }
@ -357,6 +372,32 @@ RED.editor = function() {
}); });
} }
/**
* Assign the value to each credential field
* @param node
* @param credDef
* @param credData
* @param prefix
*/
function populateCredentialsInputs(node, credDef, credData, prefix) {
for (var cred in credDef) {
if (credDef[cred].type == 'password') {
if (credData['has' + cred]) {
$('#' + prefix + '-' + cred).val('__PWRD__');
}
else {
$('#' + prefix + '-' + cred).val('');
}
} else {
preparePropertyEditor(credData, cred, prefix);
}
attachPropertyChangeHandler(node, credDef, cred, prefix);
for (var cred in credDef) {
$("#" + prefix + "-" + cred).change();
}
}
}
/** /**
* Prepare all of the editor dialog fields * Prepare all of the editor dialog fields
* @param node - the node being edited * @param node - the node being edited
@ -373,25 +414,16 @@ RED.editor = function() {
attachPropertyChangeHandler(node,definition.defaults,d,prefix); attachPropertyChangeHandler(node,definition.defaults,d,prefix);
} }
if (definition.credentials) { if (definition.credentials) {
if (node._creds) {
$.getJSON(getCredentialsURL(node.type, node.id), function (data) { populateCredentialsInputs(node, definition.credentials, node._creds.input, prefix);
for (var cred in definition.credentials) { } else {
if (definition.credentials[cred].type == 'password') { node._creds = {server: {}, send: {}, input: {}};
if (data['has' + cred]) { $.getJSON(getCredentialsURL(node.type, node.id), function (data) {
$('#' + prefix + '-' + cred).val('__PWRD__'); node._creds.server = data;
} node._creds.input = jQuery.extend({}, data);
else { populateCredentialsInputs(node, definition.credentials, node._creds.input, prefix);
$('#' + prefix + '-' + cred).val(''); });
} }
} else {
preparePropertyEditor(data, cred, prefix);
}
attachPropertyChangeHandler(node, definition.credentials, cred, prefix);
for (var cred in definition.credentials) {
$("#" + prefix + "-" + cred).change();
}
}
});
} }
if (definition.oneditprepare) { if (definition.oneditprepare) {
definition.oneditprepare.call(node); definition.oneditprepare.call(node);
@ -449,14 +481,6 @@ RED.editor = function() {
var configNode = RED.nodes.node(configId); var configNode = RED.nodes.node(configId);
var configTypeDef = RED.nodes.getType(configType); var configTypeDef = RED.nodes.getType(configType);
if (configTypeDef.credentials) {
$.ajax({
url: getCredentialsURL(configType, configId),
type: 'DELETE',
success: function (result) {
}
});
}
if (configTypeDef.ondelete) { if (configTypeDef.ondelete) {
configTypeDef.ondelete.call(RED.nodes.node(configId)); configTypeDef.ondelete.call(RED.nodes.node(configId));
} }
@ -546,7 +570,7 @@ RED.editor = function() {
updateConfigNodeSelect(configProperty,configType,configId); updateConfigNodeSelect(configProperty,configType,configId);
} }
if (configTypeDef.credentials) { if (configTypeDef.credentials) {
sendCredentials(configNode,configTypeDef.credentials,"node-config-input"); manageNodeCredentials(configNode,configTypeDef.credentials,"node-config-input");
} }
if (configTypeDef.oneditsave) { if (configTypeDef.oneditsave) {
configTypeDef.oneditsave.call(RED.nodes.node(configId)); configTypeDef.oneditsave.call(RED.nodes.node(configId));

View File

@ -15,6 +15,7 @@
**/ **/
var util = require("util"); var util = require("util");
var when = require("when");
var credentials = {}; var credentials = {};
var storage = null; var storage = null;
@ -32,40 +33,6 @@ function isRegistered(type) {
return getCredDef(type) !== undefined; return getCredDef(type) !== undefined;
} }
function restPOST(type) {
redApp.post('/credentials/' + type + '/:id', function (req, res) {
var body = "";
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
var nodeType = type;
var nodeID = req.params.id;
var newCreds = querystring.parse(body);
var credentials = Credentials.get(nodeID) || {};
var definition = getCredDef(nodeType);
for (var cred in definition) {
if (definition.hasOwnProperty(cred)) {
if (newCreds[cred] === undefined) {
continue;
}
if (definition[cred].type == "password" && newCreds[cred] == '__PWRD__') {
continue;
}
if (newCreds[cred] === '') {
delete credentials[cred];
}
credentials[cred] = newCreds[cred];
}
}
Credentials.add(nodeID, credentials);
res.send(200);
});
});
}
function restGET(type) { function restGET(type) {
redApp.get('/credentials/' + type + '/:id', function (req, res) { redApp.get('/credentials/' + type + '/:id', function (req, res) {
var nodeType = type; var nodeType = type;
@ -93,14 +60,6 @@ function restGET(type) {
}); });
} }
function restDELETE(type) {
redApp.delete('/credentials/' + type + '/:id', function (req, res) {
var nodeID = req.params.id;
Credentials.delete(nodeID);
res.send(200);
});
}
module.exports = { module.exports = {
init: function (_storage) { init: function (_storage) {
@ -148,8 +107,41 @@ module.exports = {
register: function (type, definition) { register: function (type, definition) {
var dashedType = type.replace(/\s+/g, '-'); var dashedType = type.replace(/\s+/g, '-');
credentialsDef[dashedType] = definition; credentialsDef[dashedType] = definition;
restDELETE(dashedType);
restGET(dashedType); restGET(dashedType);
restPOST(dashedType); },
/**
* Merge the new credentials with the existings one
* @param nodeID
* @param nodeType
* @param newCreds
*/
merge: function (nodeID, nodeType, newCreds) {
var savedCredentials = Credentials.get(nodeID) || {};
if (!isRegistered(nodeType)) {
util.log('Credential Type ' + nodeType + ' is not registered.');
return;
}
var definition = getCredDef(nodeType);
for (var cred in definition) {
if (definition.hasOwnProperty(cred)) {
if (newCreds[cred] === undefined) {
continue;
}
if (definition[cred].type == "password" && newCreds[cred] == '__PWRD__') {
continue;
}
if (0 === newCreds[cred].length || /^\s*$/.test(newCreds[cred])) {
delete savedCredentials[cred];
continue;
}
savedCredentials[cred] = newCreds[cred];
}
}
credentials[nodeID] = savedCredentials;
},
save: function () {
return storage.saveCredentials(credentials);
} }
} }

View File

@ -40,7 +40,26 @@ events.on('type-registered',function(type) {
} }
} }
}); });
var parseCredentials = function (config) {
return when.promise(function (resolve, defect) {
for (var i in config) {
if (config.hasOwnProperty(i)) {
var node = config[i];
if (!node._creds) {
continue;
}
var type = node.type;
credentials.merge(node.id, type, node._creds);
delete node._creds;
}
}
credentials.save().then(function () {
resolve(config);
}).otherwise(function (err) {
defect(err);
});
});
}
var parseConfig = function() { var parseConfig = function() {
var i; var i;
@ -155,13 +174,16 @@ var flowNodes = module.exports = {
getFlows: function() { getFlows: function() {
return activeConfig; return activeConfig;
}, },
setFlows: function(conf) { setFlows: function (conf) {
return storage.saveFlows(conf).then(function() { return parseCredentials(conf).then(function (confCredsRemoved) {
return stopFlows().then(function() { return storage.saveFlows(confCredsRemoved).then(function () {
activeConfig = conf; return stopFlows().then(function () {
parseConfig(); activeConfig = confCredsRemoved;
}); parseConfig();
}); });
})
})
}, },
stopFlows: stopFlows stopFlows: stopFlows
}; };