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 util = require("util");
|
||||||
var when = require("when");
|
var when = require("when");
|
||||||
|
|
||||||
var credentials = {};
|
var credentialCache = {};
|
||||||
var storage = null;
|
var storage = null;
|
||||||
var credentialsDef = {};
|
var credentialsDef = {};
|
||||||
var redApp = null;
|
var redApp = null;
|
||||||
var querystring = require('querystring');
|
|
||||||
var Credentials;
|
|
||||||
|
|
||||||
function getCredDef(type) {
|
/**
|
||||||
var dashedType = type.replace(/\s+/g, '-');
|
* Adds an HTTP endpoint to allow look up of credentials for a given node id.
|
||||||
return credentialsDef[dashedType];
|
*/
|
||||||
}
|
function registerEndpoint(type) {
|
||||||
|
|
||||||
function isRegistered(type) {
|
|
||||||
return getCredDef(type) !== undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
function restGET(type) {
|
|
||||||
redApp.get('/credentials/' + type + '/:id', function (req, res) {
|
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 nodeType = type;
|
||||||
var nodeID = req.params.id;
|
var nodeID = req.params.id;
|
||||||
|
|
||||||
var credentials = Credentials.get(nodeID);
|
var credentials = credentialCache[nodeID];
|
||||||
if (credentials === undefined) {
|
if (credentials === undefined) {
|
||||||
res.json({});
|
res.json({});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var definition = getCredDef(nodeType);
|
var definition = credentialsDef[nodeType];
|
||||||
|
|
||||||
var sendCredentials = {};
|
var sendCredentials = {};
|
||||||
for (var cred in definition) {
|
for (var cred in definition) {
|
||||||
@ -61,69 +59,117 @@ function restGET(type) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: function (_storage) {
|
init: function (_storage) {
|
||||||
storage = _storage;
|
storage = _storage;
|
||||||
|
// TODO: this should get passed in init function call rather than
|
||||||
|
// required directly.
|
||||||
redApp = require("../server").app;
|
redApp = require("../server").app;
|
||||||
Credentials = this;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the credentials from storage.
|
||||||
|
*/
|
||||||
load: function () {
|
load: function () {
|
||||||
return storage.getCredentials().then(function (creds) {
|
return storage.getCredentials().then(function (creds) {
|
||||||
credentials = creds;
|
credentialCache = creds;
|
||||||
}).otherwise(function (err) {
|
}).otherwise(function (err) {
|
||||||
util.log("[red] Error loading credentials : " + 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) {
|
add: function (id, creds) {
|
||||||
credentials[id] = creds;
|
credentialCache[id] = creds;
|
||||||
storage.saveCredentials(credentials);
|
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) {
|
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: function (id) {
|
||||||
delete credentials[id];
|
delete credentialCache[id];
|
||||||
storage.saveCredentials(credentials);
|
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) {
|
clean: function (getNode) {
|
||||||
var deletedCredentials = false;
|
var deletedCredentials = false;
|
||||||
for (var c in credentials) {
|
for (var c in credentialCache) {
|
||||||
if (credentials.hasOwnProperty(c)) {
|
if (credentialCache.hasOwnProperty(c)) {
|
||||||
var n = getNode(c);
|
var n = getNode(c);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
deletedCredentials = true;
|
deletedCredentials = true;
|
||||||
delete credentials[c];
|
delete credentialCache[c];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (deletedCredentials) {
|
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) {
|
register: function (type, definition) {
|
||||||
var dashedType = type.replace(/\s+/g, '-');
|
var dashedType = type.replace(/\s+/g, '-');
|
||||||
credentialsDef[dashedType] = definition;
|
credentialsDef[dashedType] = definition;
|
||||||
restGET(dashedType);
|
registerEndpoint(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)) {
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
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.');
|
util.log('Credential Type ' + nodeType + ' is not registered.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = getCredDef(nodeType);
|
|
||||||
for (var cred in definition) {
|
for (var cred in definition) {
|
||||||
if (definition.hasOwnProperty(cred)) {
|
if (definition.hasOwnProperty(cred)) {
|
||||||
if (newCreds[cred] === undefined) {
|
if (newCreds[cred] === undefined) {
|
||||||
@ -139,9 +185,15 @@ module.exports = {
|
|||||||
savedCredentials[cred] = newCreds[cred];
|
savedCredentials[cred] = newCreds[cred];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
credentials[nodeID] = savedCredentials;
|
credentialCache[nodeID] = savedCredentials;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the credentials to storage
|
||||||
|
* @return a promise for the saving of credentials to storage
|
||||||
|
*/
|
||||||
save: function () {
|
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 parseConfig = function() {
|
||||||
var i;
|
var i;
|
||||||
@ -173,16 +154,22 @@ var flowNodes = module.exports = {
|
|||||||
getFlows: function() {
|
getFlows: function() {
|
||||||
return activeConfig;
|
return activeConfig;
|
||||||
},
|
},
|
||||||
setFlows: function (conf) {
|
setFlows: function (config) {
|
||||||
return parseCredentials(conf).then(function (confCredsRemoved) {
|
// Extract any credential updates
|
||||||
return storage.saveFlows(confCredsRemoved).then(function () {
|
for (var i=0; i<config.length; i++) {
|
||||||
return stopFlows().then(function () {
|
var node = config[i];
|
||||||
activeConfig = confCredsRemoved;
|
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();
|
parseConfig();
|
||||||
});
|
});
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
stopFlows: stopFlows
|
stopFlows: stopFlows
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user