mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Tidy up runtime credentials
This commit is contained in:
parent
7687cf6661
commit
fea6280bff
@ -17,33 +17,31 @@
|
||||
var util = require("util");
|
||||
var when = require("when");
|
||||
|
||||
var credentials = {};
|
||||
var credentialCache = {};
|
||||
var storage = null;
|
||||
var credentialsDef = {};
|
||||
var redApp = null;
|
||||
var querystring = require('querystring');
|
||||
var Credentials;
|
||||
|
||||
function getCredDef(type) {
|
||||
var dashedType = type.replace(/\s+/g, '-');
|
||||
return credentialsDef[dashedType];
|
||||
}
|
||||
|
||||
function isRegistered(type) {
|
||||
return getCredDef(type) !== undefined;
|
||||
}
|
||||
|
||||
function restGET(type) {
|
||||
/**
|
||||
* Adds an HTTP endpoint to allow look up of credentials for a given node id.
|
||||
*/
|
||||
function registerEndpoint(type) {
|
||||
redApp.get('/credentials/' + type + '/:id', function (req, res) {
|
||||
// TODO: This could be a generic endpoint with the type value
|
||||
// parameterised.
|
||||
//
|
||||
// TODO: It should verify the given node id is of the type specified -
|
||||
// but that would add a dependency from this module to the
|
||||
// registry module that knows about node types.
|
||||
var nodeType = type;
|
||||
var nodeID = req.params.id;
|
||||
|
||||
var credentials = Credentials.get(nodeID);
|
||||
var credentials = credentialCache[nodeID];
|
||||
if (credentials === undefined) {
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
var definition = getCredDef(nodeType);
|
||||
var definition = credentialsDef[nodeType];
|
||||
|
||||
var sendCredentials = {};
|
||||
for (var cred in definition) {
|
||||
@ -61,87 +59,141 @@ function restGET(type) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
init: function (_storage) {
|
||||
storage = _storage;
|
||||
// TODO: this should get passed in init function call rather than
|
||||
// required directly.
|
||||
redApp = require("../server").app;
|
||||
Credentials = this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Loads the credentials from storage.
|
||||
*/
|
||||
load: function () {
|
||||
return storage.getCredentials().then(function (creds) {
|
||||
credentials = creds;
|
||||
credentialCache = creds;
|
||||
}).otherwise(function (err) {
|
||||
util.log("[red] Error loading credentials : " + err);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a set of credentials for the given node id.
|
||||
* @param id the node id for the credentials
|
||||
* @param creds an object of credential key/value pairs
|
||||
* @return a promise for the saving of credentials to storage
|
||||
*/
|
||||
add: function (id, creds) {
|
||||
credentials[id] = creds;
|
||||
storage.saveCredentials(credentials);
|
||||
credentialCache[id] = creds;
|
||||
return storage.saveCredentials(credentialCache);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the credentials for the given node id.
|
||||
* @param id the node id for the credentials
|
||||
* @return the credentials
|
||||
*/
|
||||
get: function (id) {
|
||||
return credentials[id];
|
||||
return credentialCache[id];
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes the credentials for the given node id.
|
||||
* @param id the node id for the credentials
|
||||
* @return a promise for the saving of credentials to storage
|
||||
*/
|
||||
delete: function (id) {
|
||||
delete credentials[id];
|
||||
storage.saveCredentials(credentials);
|
||||
delete credentialCache[id];
|
||||
storage.saveCredentials(credentialCache);
|
||||
},
|
||||
|
||||
/**
|
||||
* Deletes any credentials for nodes that no longer exist
|
||||
* @param getNode a function that can return a node for a given id
|
||||
* @return a promise for the saving of credentials to storage
|
||||
*/
|
||||
clean: function (getNode) {
|
||||
var deletedCredentials = false;
|
||||
for (var c in credentials) {
|
||||
if (credentials.hasOwnProperty(c)) {
|
||||
for (var c in credentialCache) {
|
||||
if (credentialCache.hasOwnProperty(c)) {
|
||||
var n = getNode(c);
|
||||
if (!n) {
|
||||
deletedCredentials = true;
|
||||
delete credentials[c];
|
||||
delete credentialCache[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (deletedCredentials) {
|
||||
storage.saveCredentials(credentials);
|
||||
return storage.saveCredentials(credentialCache);
|
||||
} else {
|
||||
return when.resolve();
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers a node credential definition.
|
||||
* @param type the node type
|
||||
* @param definition the credential definition
|
||||
*/
|
||||
register: function (type, definition) {
|
||||
var dashedType = type.replace(/\s+/g, '-');
|
||||
credentialsDef[dashedType] = definition;
|
||||
restGET(dashedType);
|
||||
registerEndpoint(dashedType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Merge the new credentials with the existings one
|
||||
* @param nodeID
|
||||
* @param nodeType
|
||||
* @param newCreds
|
||||
* Extracts and stores any credential updates in the provided node.
|
||||
* The provided node may have a .credentials property that contains
|
||||
* new credentials for the node.
|
||||
* This function loops through the credentials in the definition for
|
||||
* the node-type and applies any of the updates provided in the node.
|
||||
*
|
||||
* This function does not save the credentials to disk as it is expected
|
||||
* to be called multiple times when a new flow is deployed.
|
||||
*
|
||||
* @param node the node to extract credentials from
|
||||
*/
|
||||
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];
|
||||
extract: function(node) {
|
||||
var nodeID = node.id;
|
||||
var nodeType = node.type;
|
||||
var newCreds = node.credentials;
|
||||
if (newCreds) {
|
||||
var savedCredentials = credentialCache[nodeID] || {};
|
||||
|
||||
var dashedType = nodeType.replace(/\s+/g, '-');
|
||||
var definition = credentialsDef[dashedType];
|
||||
|
||||
if (!definition) {
|
||||
util.log('Credential Type ' + nodeType + ' is not registered.');
|
||||
return;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
credentialCache[nodeID] = savedCredentials;
|
||||
}
|
||||
credentials[nodeID] = savedCredentials;
|
||||
},
|
||||
|
||||
/**
|
||||
* Saves the credentials to storage
|
||||
* @return a promise for the saving of credentials to storage
|
||||
*/
|
||||
save: function () {
|
||||
return storage.saveCredentials(credentials);
|
||||
return storage.saveCredentials(credentialCache);
|
||||
}
|
||||
}
|
||||
|
@ -40,25 +40,6 @@ 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.credentials) {
|
||||
var type = node.type;
|
||||
credentials.merge(node.id, type, node.credentials);
|
||||
delete node.credentials;
|
||||
}
|
||||
}
|
||||
}
|
||||
credentials.save().then(function () {
|
||||
resolve(config);
|
||||
}).otherwise(function (err) {
|
||||
defect(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var parseConfig = function() {
|
||||
var i;
|
||||
@ -173,16 +154,22 @@ var flowNodes = module.exports = {
|
||||
getFlows: function() {
|
||||
return activeConfig;
|
||||
},
|
||||
setFlows: function (conf) {
|
||||
return parseCredentials(conf).then(function (confCredsRemoved) {
|
||||
return storage.saveFlows(confCredsRemoved).then(function () {
|
||||
return stopFlows().then(function () {
|
||||
activeConfig = confCredsRemoved;
|
||||
parseConfig();
|
||||
});
|
||||
})
|
||||
|
||||
})
|
||||
setFlows: function (config) {
|
||||
// Extract any credential updates
|
||||
for (var i=0; i<config.length; i++) {
|
||||
var node = config[i];
|
||||
if (node.credentials) {
|
||||
credentials.extract(node);
|
||||
delete node.credentials;
|
||||
}
|
||||
}
|
||||
return credentials.save()
|
||||
.then(function() { return storage.saveFlows(config);})
|
||||
.then(function() { return stopFlows();})
|
||||
.then(function () {
|
||||
activeConfig = config;
|
||||
parseConfig();
|
||||
});
|
||||
},
|
||||
stopFlows: stopFlows
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user