2014-05-03 23:26:35 +02:00
|
|
|
/**
|
2015-02-03 23:02:26 +01:00
|
|
|
* Copyright 2014, 2015 IBM Corp.
|
2014-05-03 23:26:35 +02:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
**/
|
|
|
|
|
2014-06-24 12:13:19 +02:00
|
|
|
var when = require("when");
|
2014-05-03 23:26:35 +02:00
|
|
|
|
2015-02-03 23:02:26 +01:00
|
|
|
var log = require("../log");
|
2015-02-06 14:57:15 +01:00
|
|
|
var needsPermission = require("../api/auth").needsPermission;
|
2015-02-03 23:02:26 +01:00
|
|
|
|
2014-07-21 16:56:38 +02:00
|
|
|
var credentialCache = {};
|
2014-05-03 23:26:35 +02:00
|
|
|
var storage = null;
|
2014-05-07 20:19:08 +02:00
|
|
|
var credentialsDef = {};
|
|
|
|
var redApp = null;
|
|
|
|
|
2014-07-21 16:56:38 +02:00
|
|
|
/**
|
|
|
|
* Adds an HTTP endpoint to allow look up of credentials for a given node id.
|
|
|
|
*/
|
|
|
|
function registerEndpoint(type) {
|
2015-02-06 14:57:15 +01:00
|
|
|
redApp.get('/credentials/' + type + '/:id', needsPermission(type+".read"), function (req, res) {
|
2014-07-21 16:56:38 +02:00
|
|
|
// 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.
|
2014-05-07 20:19:08 +02:00
|
|
|
var nodeType = type;
|
|
|
|
var nodeID = req.params.id;
|
|
|
|
|
2014-07-21 16:56:38 +02:00
|
|
|
var credentials = credentialCache[nodeID];
|
2014-07-02 00:46:25 +02:00
|
|
|
if (credentials === undefined) {
|
2014-05-07 20:19:08 +02:00
|
|
|
res.json({});
|
|
|
|
return;
|
|
|
|
}
|
2014-07-21 16:56:38 +02:00
|
|
|
var definition = credentialsDef[nodeType];
|
2014-05-07 20:19:08 +02:00
|
|
|
|
|
|
|
var sendCredentials = {};
|
|
|
|
for (var cred in definition) {
|
2014-07-02 00:46:25 +02:00
|
|
|
if (definition.hasOwnProperty(cred)) {
|
|
|
|
if (definition[cred].type == "password") {
|
2014-07-20 21:42:41 +02:00
|
|
|
var key = 'has_' + cred;
|
2014-07-02 00:46:25 +02:00
|
|
|
sendCredentials[key] = credentials[cred] != null && credentials[cred] !== '';
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
sendCredentials[cred] = credentials[cred] || '';
|
2014-05-07 20:19:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
res.json(sendCredentials);
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
2014-05-03 23:26:35 +02:00
|
|
|
|
2014-07-21 16:56:38 +02:00
|
|
|
|
2014-05-03 23:26:35 +02:00
|
|
|
module.exports = {
|
2015-03-13 22:26:50 +01:00
|
|
|
init: function (_storage,_app) {
|
2014-05-03 23:26:35 +02:00
|
|
|
storage = _storage;
|
2015-03-13 22:26:50 +01:00
|
|
|
redApp = _app;
|
2014-05-03 23:26:35 +02:00
|
|
|
},
|
2014-07-21 16:56:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads the credentials from storage.
|
|
|
|
*/
|
2014-05-07 20:19:08 +02:00
|
|
|
load: function () {
|
|
|
|
return storage.getCredentials().then(function (creds) {
|
2014-07-21 16:56:38 +02:00
|
|
|
credentialCache = creds;
|
2014-05-07 20:19:08 +02:00
|
|
|
}).otherwise(function (err) {
|
2015-02-03 23:02:26 +01:00
|
|
|
log.warn("Error loading credentials : " + err);
|
2014-05-03 23:26:35 +02:00
|
|
|
});
|
|
|
|
},
|
2014-07-21 16:56:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2014-05-07 20:19:08 +02:00
|
|
|
add: function (id, creds) {
|
2014-07-21 16:56:38 +02:00
|
|
|
credentialCache[id] = creds;
|
|
|
|
return storage.saveCredentials(credentialCache);
|
2014-05-03 23:26:35 +02:00
|
|
|
},
|
|
|
|
|
2014-07-21 16:56:38 +02:00
|
|
|
/**
|
|
|
|
* Gets the credentials for the given node id.
|
|
|
|
* @param id the node id for the credentials
|
|
|
|
* @return the credentials
|
|
|
|
*/
|
2014-05-07 20:19:08 +02:00
|
|
|
get: function (id) {
|
2014-07-21 16:56:38 +02:00
|
|
|
return credentialCache[id];
|
2014-05-03 23:26:35 +02:00
|
|
|
},
|
2014-05-07 20:19:08 +02:00
|
|
|
|
2014-07-21 16:56:38 +02:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2014-05-07 20:19:08 +02:00
|
|
|
delete: function (id) {
|
2014-07-21 16:56:38 +02:00
|
|
|
delete credentialCache[id];
|
|
|
|
storage.saveCredentials(credentialCache);
|
2014-05-03 23:26:35 +02:00
|
|
|
},
|
2014-05-07 20:19:08 +02:00
|
|
|
|
2014-07-21 16:56:38 +02:00
|
|
|
/**
|
|
|
|
* Deletes any credentials for nodes that no longer exist
|
2015-01-08 23:34:26 +01:00
|
|
|
* @param config a flow config
|
2014-07-21 16:56:38 +02:00
|
|
|
* @return a promise for the saving of credentials to storage
|
|
|
|
*/
|
2015-01-08 23:34:26 +01:00
|
|
|
clean: function (config) {
|
|
|
|
var existingIds = {};
|
|
|
|
config.forEach(function(n) {
|
|
|
|
existingIds[n.id] = true;
|
|
|
|
});
|
2014-05-03 23:26:35 +02:00
|
|
|
var deletedCredentials = false;
|
2014-07-21 16:56:38 +02:00
|
|
|
for (var c in credentialCache) {
|
|
|
|
if (credentialCache.hasOwnProperty(c)) {
|
2015-01-08 23:34:26 +01:00
|
|
|
if (!existingIds[c]) {
|
2014-07-02 00:46:25 +02:00
|
|
|
deletedCredentials = true;
|
2014-07-21 16:56:38 +02:00
|
|
|
delete credentialCache[c];
|
2014-07-02 00:46:25 +02:00
|
|
|
}
|
2014-05-03 23:26:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (deletedCredentials) {
|
2014-07-21 16:56:38 +02:00
|
|
|
return storage.saveCredentials(credentialCache);
|
|
|
|
} else {
|
|
|
|
return when.resolve();
|
2014-05-03 23:26:35 +02:00
|
|
|
}
|
2014-05-07 20:19:08 +02:00
|
|
|
},
|
2014-07-21 16:56:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers a node credential definition.
|
|
|
|
* @param type the node type
|
|
|
|
* @param definition the credential definition
|
|
|
|
*/
|
2014-05-07 20:19:08 +02:00
|
|
|
register: function (type, definition) {
|
|
|
|
var dashedType = type.replace(/\s+/g, '-');
|
|
|
|
credentialsDef[dashedType] = definition;
|
2014-07-21 16:56:38 +02:00
|
|
|
registerEndpoint(dashedType);
|
2014-06-24 12:13:19 +02:00
|
|
|
},
|
2014-07-21 16:56:38 +02:00
|
|
|
|
2014-06-24 12:13:19 +02:00
|
|
|
/**
|
2014-07-21 16:56:38 +02:00
|
|
|
* 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
|
2014-06-24 12:13:19 +02:00
|
|
|
*/
|
2014-07-21 16:56:38 +02:00
|
|
|
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) {
|
2015-02-03 23:02:26 +01:00
|
|
|
log.warn('Credential Type ' + nodeType + ' is not registered.');
|
2014-07-21 16:56:38 +02:00
|
|
|
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];
|
2014-06-24 12:13:19 +02:00
|
|
|
}
|
|
|
|
}
|
2014-07-21 16:56:38 +02:00
|
|
|
credentialCache[nodeID] = savedCredentials;
|
2015-02-24 23:02:39 +01:00
|
|
|
delete node.credentials;
|
2014-06-24 12:13:19 +02:00
|
|
|
}
|
|
|
|
},
|
2014-07-21 16:56:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Saves the credentials to storage
|
|
|
|
* @return a promise for the saving of credentials to storage
|
|
|
|
*/
|
2014-06-24 12:13:19 +02:00
|
|
|
save: function () {
|
2014-07-21 16:56:38 +02:00
|
|
|
return storage.saveCredentials(credentialCache);
|
2014-07-29 15:58:49 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the credential definition for the given node type
|
|
|
|
* @param type the node type
|
|
|
|
* @return the credential definition
|
|
|
|
*/
|
|
|
|
getDefinition: function (type) {
|
|
|
|
return credentialsDef[type];
|
2014-05-03 23:26:35 +02:00
|
|
|
}
|
|
|
|
}
|