2 * Copyright 2014 IBM Corp.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 var util = require("util");
18 var when = require("when");
20 var credentialCache = {};
22 var credentialsDef = {};
26 * Adds an HTTP endpoint to allow look up of credentials for a given node id.
28 function registerEndpoint(type) {
29 redApp.get('/credentials/' + type + '/:id', function (req, res) {
30 // TODO: This could be a generic endpoint with the type value
33 // TODO: It should verify the given node id is of the type specified -
34 // but that would add a dependency from this module to the
35 // registry module that knows about node types.
37 var nodeID = req.params.id;
39 var credentials = credentialCache[nodeID];
40 if (credentials === undefined) {
44 var definition = credentialsDef[nodeType];
46 var sendCredentials = {};
47 for (var cred in definition) {
48 if (definition.hasOwnProperty(cred)) {
49 if (definition[cred].type == "password") {
50 var key = 'has_' + cred;
51 sendCredentials[key] = credentials[cred] != null && credentials[cred] !== '';
54 sendCredentials[cred] = credentials[cred] || '';
57 res.json(sendCredentials);
64 init: function (_storage) {
66 // TODO: this should get passed in init function call rather than
68 redApp = require("../server").app;
72 * Loads the credentials from storage.
75 return storage.getCredentials().then(function (creds) {
76 credentialCache = creds;
77 }).otherwise(function (err) {
78 util.log("[red] Error loading credentials : " + err);
83 * Adds a set of credentials for the given node id.
84 * @param id the node id for the credentials
85 * @param creds an object of credential key/value pairs
86 * @return a promise for the saving of credentials to storage
88 add: function (id, creds) {
89 credentialCache[id] = creds;
90 return storage.saveCredentials(credentialCache);
94 * Gets the credentials for the given node id.
95 * @param id the node id for the credentials
96 * @return the credentials
99 return credentialCache[id];
103 * Deletes the credentials for the given node id.
104 * @param id the node id for the credentials
105 * @return a promise for the saving of credentials to storage
107 delete: function (id) {
108 delete credentialCache[id];
109 storage.saveCredentials(credentialCache);
113 * Deletes any credentials for nodes that no longer exist
114 * @param getNode a function that can return a node for a given id
115 * @return a promise for the saving of credentials to storage
117 clean: function (getNode) {
118 var deletedCredentials = false;
119 for (var c in credentialCache) {
120 if (credentialCache.hasOwnProperty(c)) {
123 deletedCredentials = true;
124 delete credentialCache[c];
128 if (deletedCredentials) {
129 return storage.saveCredentials(credentialCache);
131 return when.resolve();
136 * Registers a node credential definition.
137 * @param type the node type
138 * @param definition the credential definition
140 register: function (type, definition) {
141 var dashedType = type.replace(/\s+/g, '-');
142 credentialsDef[dashedType] = definition;
143 registerEndpoint(dashedType);
147 * Extracts and stores any credential updates in the provided node.
148 * The provided node may have a .credentials property that contains
149 * new credentials for the node.
150 * This function loops through the credentials in the definition for
151 * the node-type and applies any of the updates provided in the node.
153 * This function does not save the credentials to disk as it is expected
154 * to be called multiple times when a new flow is deployed.
156 * @param node the node to extract credentials from
158 extract: function(node) {
159 var nodeID = node.id;
160 var nodeType = node.type;
161 var newCreds = node.credentials;
163 var savedCredentials = credentialCache[nodeID] || {};
165 var dashedType = nodeType.replace(/\s+/g, '-');
166 var definition = credentialsDef[dashedType];
169 util.log('Credential Type ' + nodeType + ' is not registered.');
173 for (var cred in definition) {
174 if (definition.hasOwnProperty(cred)) {
175 if (newCreds[cred] === undefined) {
178 if (definition[cred].type == "password" && newCreds[cred] == '__PWRD__') {
181 if (0 === newCreds[cred].length || /^\s*$/.test(newCreds[cred])) {
182 delete savedCredentials[cred];
185 savedCredentials[cred] = newCreds[cred];
188 credentialCache[nodeID] = savedCredentials;
193 * Saves the credentials to storage
194 * @return a promise for the saving of credentials to storage
197 return storage.saveCredentials(credentialCache);
201 * Gets the credential definition for the given node type
202 * @param type the node type
203 * @return the credential definition
205 getDefinition: function (type) {
206 return credentialsDef[type];