mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Move credential http API handling to api component
This commit is contained in:
		
							
								
								
									
										46
									
								
								red/api/credentials.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								red/api/credentials.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | /** | ||||||
|  |  * Copyright 2015 IBM Corp. | ||||||
|  |  * | ||||||
|  |  * 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. | ||||||
|  |  **/ | ||||||
|  |  | ||||||
|  | var api = require("../nodes"); | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  |     get: function (req, res) { | ||||||
|  |         // 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 = req.params.type; | ||||||
|  |         var nodeID = req.params.id; | ||||||
|  |         var credentials = api.getCredentials(nodeID); | ||||||
|  |         if (!credentials) { | ||||||
|  |             res.json({}); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         var definition = api.getCredentialDefinition(nodeType); | ||||||
|  |  | ||||||
|  |         var sendCredentials = {}; | ||||||
|  |         for (var cred in definition) { | ||||||
|  |             if (definition.hasOwnProperty(cred)) { | ||||||
|  |                 if (definition[cred].type == "password") { | ||||||
|  |                     var key = 'has_' + cred; | ||||||
|  |                     sendCredentials[key] = credentials[cred] != null && credentials[cred] !== ''; | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 sendCredentials[cred] = credentials[cred] || ''; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         res.json(sendCredentials); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -27,6 +27,7 @@ var library = require("./library"); | |||||||
| var info = require("./info"); | var info = require("./info"); | ||||||
| var theme = require("./theme"); | var theme = require("./theme"); | ||||||
| var locales = require("./locales"); | var locales = require("./locales"); | ||||||
|  | var credentials = require("./credentials"); | ||||||
|  |  | ||||||
| var log = require("../log"); | var log = require("../log"); | ||||||
|  |  | ||||||
| @@ -48,7 +49,6 @@ var errorHandler = function(err,req,res,next) { | |||||||
| function init(adminApp,storage) { | function init(adminApp,storage) { | ||||||
|  |  | ||||||
|     auth.init(settings,storage); |     auth.init(settings,storage); | ||||||
|  |  | ||||||
|     // Editor |     // Editor | ||||||
|     if (!settings.disableEditor) { |     if (!settings.disableEditor) { | ||||||
|         ui.init(settings); |         ui.init(settings); | ||||||
| @@ -94,6 +94,8 @@ function init(adminApp,storage) { | |||||||
|     adminApp.get("/nodes/:mod/:set",needsPermission("nodes.read"),nodes.getSet); |     adminApp.get("/nodes/:mod/:set",needsPermission("nodes.read"),nodes.getSet); | ||||||
|     adminApp.put("/nodes/:mod/:set",needsPermission("nodes.write"),nodes.putSet); |     adminApp.put("/nodes/:mod/:set",needsPermission("nodes.write"),nodes.putSet); | ||||||
|  |  | ||||||
|  |     adminApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get); | ||||||
|  |  | ||||||
|     adminApp.get(/locales\/(.+)\/?$/,locales.get); |     adminApp.get(/locales\/(.+)\/?$/,locales.get); | ||||||
|  |  | ||||||
|     // Library |     // Library | ||||||
|   | |||||||
| @@ -23,50 +23,10 @@ var needsPermission = require("../api/auth").needsPermission; | |||||||
| var credentialCache = {}; | var credentialCache = {}; | ||||||
| var storage = null; | var storage = null; | ||||||
| var credentialsDef = {}; | var credentialsDef = {}; | ||||||
| var redApp = null; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Adds an HTTP endpoint to allow look up of credentials for a given node id. |  | ||||||
|  */ |  | ||||||
| function registerEndpoint(type) { |  | ||||||
|     redApp.get('/credentials/' + type + '/:id', needsPermission(type+".read"), 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 = credentialCache[nodeID]; |  | ||||||
|         if (credentials === undefined) { |  | ||||||
|             res.json({}); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         var definition = credentialsDef[nodeType]; |  | ||||||
|  |  | ||||||
|         var sendCredentials = {}; |  | ||||||
|         for (var cred in definition) { |  | ||||||
|             if (definition.hasOwnProperty(cred)) { |  | ||||||
|                 if (definition[cred].type == "password") { |  | ||||||
|                     var key = 'has_' + cred; |  | ||||||
|                     sendCredentials[key] = credentials[cred] != null && credentials[cred] !== ''; |  | ||||||
|                     continue; |  | ||||||
|                 } |  | ||||||
|                 sendCredentials[cred] = credentials[cred] || ''; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         res.json(sendCredentials); |  | ||||||
|  |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     init: function (_storage,_app) { |     init: function (_storage) { | ||||||
|         storage = _storage; |         storage = _storage; | ||||||
|         redApp = _app; |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -144,7 +104,6 @@ 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; | ||||||
|         registerEndpoint(dashedType); |  | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|   | |||||||
| @@ -53,8 +53,8 @@ function createNode(node,def) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| function init(_settings,storage,app) { | function init(_settings,storage) { | ||||||
|     credentials.init(storage,app); |     credentials.init(storage); | ||||||
|     flows.init(_settings,storage); |     flows.init(_settings,storage); | ||||||
|     registry.init(_settings); |     registry.init(_settings); | ||||||
| } | } | ||||||
| @@ -148,5 +148,6 @@ module.exports = { | |||||||
|     // Credentials |     // Credentials | ||||||
|     addCredentials: credentials.add, |     addCredentials: credentials.add, | ||||||
|     getCredentials: credentials.get, |     getCredentials: credentials.get, | ||||||
|     deleteCredentials: credentials.delete |     deleteCredentials: credentials.delete, | ||||||
|  |     getCredentialDefinition: credentials.getDefinition | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ function start() { | |||||||
|             } |             } | ||||||
|             log.info(log._("runtime.version",{component:"Node.js ",version:process.version})); |             log.info(log._("runtime.version",{component:"Node.js ",version:process.version})); | ||||||
|             log.info(log._("server.loading")); |             log.info(log._("server.loading")); | ||||||
|             redNodes.init(settings,storage,app); |             redNodes.init(settings,storage); | ||||||
|             return redNodes.load().then(function() { |             return redNodes.load().then(function() { | ||||||
|  |  | ||||||
|                 var i; |                 var i; | ||||||
|   | |||||||
							
								
								
									
										108
									
								
								test/red/api/credentials_spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								test/red/api/credentials_spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | |||||||
|  | /** | ||||||
|  |  * Copyright 2015 IBM Corp. | ||||||
|  |  * | ||||||
|  |  * 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. | ||||||
|  |  **/ | ||||||
|  |  | ||||||
|  | var should = require("should"); | ||||||
|  | var request = require('supertest'); | ||||||
|  | var express = require('express'); | ||||||
|  | var sinon = require('sinon'); | ||||||
|  | var when = require('when'); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | var nodeApi = require("../../../red/nodes"); | ||||||
|  | var credentials = require("../../../red/api/credentials"); | ||||||
|  |  | ||||||
|  | describe('credentials api', function() { | ||||||
|  |     var app; | ||||||
|  |  | ||||||
|  |     before(function() { | ||||||
|  |         app = express(); | ||||||
|  |         app.get('/credentials/:type/:id',credentials.get); | ||||||
|  |  | ||||||
|  |         sinon.stub(nodeApi,"getCredentials",function(id) { | ||||||
|  |             if (id === "n1") { | ||||||
|  |                 return {user1:"abc",password1:"123"}; | ||||||
|  |             } else { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |         sinon.stub(nodeApi,"getCredentialDefinition",function(type) { | ||||||
|  |             if (type === "known-type") { | ||||||
|  |                 return {user1:{type:"text"},password1:{type:"password"}}; | ||||||
|  |             } else { | ||||||
|  |                 return null; | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |     after(function() { | ||||||
|  |         nodeApi.getCredentials.restore(); | ||||||
|  |         nodeApi.getCredentialDefinition.restore(); | ||||||
|  |     }) | ||||||
|  |     it('returns empty credentials if unknown type',function(done) { | ||||||
|  |         request(app) | ||||||
|  |             .get("/credentials/unknown-type/n1") | ||||||
|  |             .expect(200) | ||||||
|  |             .expect("Content-Type",/json/) | ||||||
|  |             .end(function(err,res) { | ||||||
|  |                 if (err) { | ||||||
|  |                     done(err); | ||||||
|  |                 } else { | ||||||
|  |                     try { | ||||||
|  |                         res.body.should.eql({}); | ||||||
|  |                         done(); | ||||||
|  |                     } catch(e) { | ||||||
|  |                         done(e); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |     }); | ||||||
|  |     it('returns empty credentials if none are stored',function(done) { | ||||||
|  |         request(app) | ||||||
|  |             .get("/credentials/known-type/n2") | ||||||
|  |             .expect("Content-Type",/json/) | ||||||
|  |             .end(function(err,res) { | ||||||
|  |                 if (err) { | ||||||
|  |                     done(err); | ||||||
|  |                 } else { | ||||||
|  |                     try { | ||||||
|  |                         res.body.should.eql({}); | ||||||
|  |                         done(); | ||||||
|  |                     } catch(e) { | ||||||
|  |                         done(e); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |     }); | ||||||
|  |     it('returns stored credentials',function(done) { | ||||||
|  |         request(app) | ||||||
|  |             .get("/credentials/known-type/n1") | ||||||
|  |             .expect("Content-Type",/json/) | ||||||
|  |             .end(function(err,res) { | ||||||
|  |                 if (err) { | ||||||
|  |                     done(err); | ||||||
|  |                 } else { | ||||||
|  |                     try { | ||||||
|  |                         res.body.should.have.a.property("user1","abc"); | ||||||
|  |                         res.body.should.not.have.a.property("password1"); | ||||||
|  |                         res.body.should.have.a.property("has_password1",true); | ||||||
|  |                         done(); | ||||||
|  |                     } catch(e) { | ||||||
|  |                         done(e); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  | }); | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Copyright 2014 IBM Corp. |  * Copyright 2014, 2015 IBM Corp. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @@ -261,76 +261,4 @@ describe('Credentials', function() { | |||||||
|  |  | ||||||
|         done(); |         done(); | ||||||
|     }); |     }); | ||||||
|      |  | ||||||
|     describe('registerEndpoint',function() { |  | ||||||
|         it('returns empty credentials if none are stored',function(done) { |  | ||||||
|             auth.init({}); |  | ||||||
|             var app = express(); |  | ||||||
|             credentials.init({saveCredentials:function(){}},app); |  | ||||||
|             credentials.register("test",{ |  | ||||||
|                 user1:{type:"text"}, |  | ||||||
|                 password1:{type:"password"}, |  | ||||||
|                 user2:{type:"text"}, |  | ||||||
|                 password2:{type:"password"}, |  | ||||||
|                 user3:{type:"text"}, |  | ||||||
|                 password3:{type:"password"} |  | ||||||
|                  |  | ||||||
|             }); |  | ||||||
|             request(app) |  | ||||||
|                 .get("/credentials/test/123") |  | ||||||
|                 .expect("Content-Type",/json/) |  | ||||||
|                 .end(function(err,res) { |  | ||||||
|                     if (err) { |  | ||||||
|                         done(err); |  | ||||||
|                     } else { |  | ||||||
|                         try { |  | ||||||
|                             res.body.should.eql({}); |  | ||||||
|                             done(); |  | ||||||
|                         } catch(e) { |  | ||||||
|                             done(e); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 }) |  | ||||||
|         }); |  | ||||||
|         it('returns stored credentials',function(done) { |  | ||||||
|             auth.init({}); |  | ||||||
|             var app = express(); |  | ||||||
|             credentials.init({saveCredentials:function(){}},app); |  | ||||||
|             credentials.register("test",{ |  | ||||||
|                 user1:{type:"text"}, |  | ||||||
|                 password1:{type:"password"}, |  | ||||||
|                 user2:{type:"text"}, |  | ||||||
|                 password2:{type:"password"}, |  | ||||||
|                 user3:{type:"text"}, |  | ||||||
|                 password3:{type:"password"} |  | ||||||
|                  |  | ||||||
|             }); |  | ||||||
|             credentials.add("node",{user1:"abc",password1:"123",user2:"def",password2:"456",user3:"ghi",password3:"789"}); |  | ||||||
|             request(app) |  | ||||||
|                 .get("/credentials/test/node") |  | ||||||
|                 .expect("Content-Type",/json/) |  | ||||||
|                 .end(function(err,res) { |  | ||||||
|                     if (err) { |  | ||||||
|                         done(err); |  | ||||||
|                     } else { |  | ||||||
|                         try { |  | ||||||
|                             res.body.should.have.a.property("user1","abc"); |  | ||||||
|                             res.body.should.have.a.property("user2","def"); |  | ||||||
|                             res.body.should.have.a.property("user3","ghi"); |  | ||||||
|                             res.body.should.have.a.property("has_password1",true); |  | ||||||
|                             res.body.should.have.a.property("has_password2",true); |  | ||||||
|                             res.body.should.have.a.property("has_password3",true); |  | ||||||
|                             res.body.should.not.have.a.property("password1"); |  | ||||||
|                             res.body.should.not.have.a.property("password2"); |  | ||||||
|                             res.body.should.not.have.a.property("password3"); |  | ||||||
|                             done(); |  | ||||||
|                         } catch(e) { |  | ||||||
|                             done(e); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 }) |  | ||||||
|         }); |  | ||||||
|              |  | ||||||
|     }); |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -134,7 +134,7 @@ describe("red/nodes/index", function() { | |||||||
|                } |                } | ||||||
|            }); |            }); | ||||||
|            var testnode = new TestNode({id:'tab1',type:'test',name:'barney', '_alias':'tab1'}); |            var testnode = new TestNode({id:'tab1',type:'test',name:'barney', '_alias':'tab1'}); | ||||||
|            credentials.getDefinition("test").should.have.property('foo'); |            index.getCredentialDefinition("test").should.have.property('foo'); | ||||||
|            done(); |            done(); | ||||||
|        }); |        }); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user