From a9e07f8b7861e606d62240cdb7adcc4d4004809d Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Fri, 2 May 2014 14:35:51 +0100 Subject: [PATCH] Updated credentials storage so there is a .._cred.... file per flow. Allows swapping flows more easily without having to re-enter credentials. Thus also added *_cred* to .gitignore --- .gitignore | 1 + red/storage/localfilesystem.js | 51 ++++++++++++++++------------ test/storage_localfilesystem_spec.js | 50 ++++++++++++++------------- 3 files changed, 56 insertions(+), 46 deletions(-) diff --git a/.gitignore b/.gitignore index 5c55e0846..853218a39 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules credentials.json flows*.json +*_cred* nodes/node-red-nodes/ .npm diff --git a/red/storage/localfilesystem.js b/red/storage/localfilesystem.js index 07c7eb891..e7832a936 100644 --- a/red/storage/localfilesystem.js +++ b/red/storage/localfilesystem.js @@ -1,5 +1,5 @@ /** - * Copyright 2013 IBM Corp. + * Copyright 2013, 2014 IBM Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ var settings; var flowsFile; var flowsFullPath; var credentialsFile; - +var oldCredentialsFile; var userDir; var libDir; var libFlowsDir; @@ -56,7 +56,6 @@ function listFiles(dir) { function getFileMeta(root,path) { var fn = fspath.join(root,path); - var fd = fs.openSync(fn,"r"); var size = fs.fstatSync(fd).size; var meta = {}; @@ -84,6 +83,7 @@ function getFileMeta(root,path) { fs.closeSync(fd); return meta; } + function getFileBody(root,path) { var body = ""; var fn = fspath.join(root,path); @@ -130,9 +130,9 @@ function writeFile(root,path,meta,body,res) { } mkdirp(fspath.dirname(fn), function (err) { fs.writeFile(fn,headers+body,function(err) { - //TODO: handle error - res.writeHead(204, {'Content-Type': 'text/plain'}); - res.end(); + //TODO: handle error + res.writeHead(204, {'Content-Type': 'text/plain'}); + res.end(); }); }); } @@ -141,7 +141,7 @@ var localfilesystem = { init: function(_settings) { settings = _settings; userDir = settings.userDir || process.env.NODE_RED_HOME; - + if (settings.flowFile) { flowsFile = settings.flowFile; flowsFullPath = flowsFile; @@ -149,13 +149,16 @@ var localfilesystem = { flowsFile = 'flows_'+require('os').hostname()+'.json'; flowsFullPath = fspath.join(userDir,flowsFile); } - credentialsFile = fspath.join(userDir,"credentials.json"); - + var fsext = fspath.extname(flowsFile); + credentialsFile = fspath.join(userDir,fspath.basename(flowsFile,fsext)+"_cred"+fsext); + oldCredentialsFile = fspath.join(userDir,"credentials.json"); + libDir = fspath.join(userDir,"lib"); libFlowsDir = fspath.join(libDir,"flows"); return promiseDir(libFlowsDir); }, + getFlows: function() { var defer = when.defer(); fs.exists(flowsFullPath, function(exists) { @@ -171,10 +174,11 @@ var localfilesystem = { }); return defer.promise; }, + saveFlows: function(flows) { return nodeFn.call(fs.writeFile, flowsFullPath, JSON.stringify(flows)); }, - + getCredentials: function() { var defer = when.defer(); fs.exists(credentialsFile, function(exists) { @@ -183,23 +187,30 @@ var localfilesystem = { return JSON.parse(data) })); } else { - defer.resolve({}); + fs.exists(oldCredentialsFile, function(exists) { + if (exists) { + defer.resolve(nodeFn.call(fs.readFile, oldCredentialsFile, 'utf8').then(function(data) { + return JSON.parse(data) + })); + } else { + defer.resolve({}); + } + }); } }); return defer.promise; }, - + saveCredentials: function(credentials) { return nodeFn.call(fs.writeFile, credentialsFile, JSON.stringify(credentials)) }, - + getAllFlows: function() { return listFiles(libFlowsDir); }, - + getFlow: function(fn) { var defer = when.defer(); - var file = fspath.join(libFlowsDir,fn+".json"); fs.exists(file, function(exists) { if (exists) { @@ -208,24 +219,22 @@ var localfilesystem = { defer.reject(); } }); - return defer.promise; }, - + saveFlow: function(fn,data) { var file = fspath.join(libFlowsDir,fn+".json"); return promiseDir(fspath.dirname(file)).then(function () { return nodeFn.call(fs.writeFile, file, data); }); }, - + getLibraryEntry: function(type,path) { var root = fspath.join(libDir,type); var rootPath = fspath.join(libDir,type,path); return promiseDir(root).then(function () { return nodeFn.call(fs.lstat, rootPath).then(function(stats) { if (stats.isFile()) return getFileBody(root,path); - if (path.substr(-1) == '/') { path = path.substr(0,path.length-1); } @@ -245,21 +254,19 @@ var localfilesystem = { files.push(meta); } } - }); return dirs.concat(files); }); }); }); }, + saveLibraryEntry: function(type,path,meta,body) { var fn = fspath.join(libDir, type, path); - var headers = ""; for (var i in meta) { headers += "// "+i+": "+meta[i]+"\n"; } - return promiseDir(fspath.dirname(fn)).then(function () { nodeFn.call(fs.writeFile, fn, headers+body); }); diff --git a/test/storage_localfilesystem_spec.js b/test/storage_localfilesystem_spec.js index 2c47d18b3..045d7d436 100644 --- a/test/storage_localfilesystem_spec.js +++ b/test/storage_localfilesystem_spec.js @@ -23,7 +23,7 @@ describe('LocalFileSystem', function() { done(); }); }); - + it('should handle missing flow file',function(done) { localfilesystem.init({userDir:userDir}).then(function() { var flowFile = 'flows_'+require('os').hostname()+'.json'; @@ -37,7 +37,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should save flows to the default file',function(done) { localfilesystem.init({userDir:userDir}).then(function() { var flowFile = 'flows_'+require('os').hostname()+'.json'; @@ -56,7 +56,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should save flows to the specified file',function(done) { var defaultFlowFile = 'flows_'+require('os').hostname()+'.json'; var defaultFlowFilePath = path.join(userDir,defaultFlowFile); @@ -66,7 +66,7 @@ describe('LocalFileSystem', function() { localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() { fs.existsSync(defaultFlowFilePath).should.be.false; fs.existsSync(flowFilePath).should.be.false; - + localfilesystem.saveFlows(testFlow).then(function() { fs.existsSync(defaultFlowFilePath).should.be.false; fs.existsSync(flowFilePath).should.be.true; @@ -81,12 +81,14 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should handle missing credentials', function(done) { - var credFile = path.join(userDir,"credentials.json"); - localfilesystem.init({userDir:userDir}).then(function() { + var flowFile = 'test.json'; + var flowFilePath = path.join(userDir,flowFile); + var credFile = path.join(userDir,"test_cred.json"); + localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() { fs.existsSync(credFile).should.be.false; - + localfilesystem.getCredentials().then(function(creds) { creds.should.eql({}); done(); @@ -95,16 +97,16 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should handle credentials', function(done) { - var credFile = path.join(userDir,"credentials.json"); + var credFile = path.join(userDir,"test_cred.json"); localfilesystem.init({userDir:userDir}).then(function() { - + fs.existsSync(credFile).should.be.false; - + var credentials = {"abc":{"type":"creds"}}; - + localfilesystem.saveCredentials(credentials).then(function() { fs.existsSync(credFile).should.be.true; localfilesystem.getCredentials().then(function(creds) { @@ -118,7 +120,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should return an empty list of library flows',function(done) { localfilesystem.init({userDir:userDir}).then(function() { localfilesystem.getAllFlows().then(function(flows) { @@ -129,7 +131,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should return a valid list of library flows',function(done) { localfilesystem.init({userDir:userDir}).then(function() { var flowLib = path.join(userDir,"lib","flows"); @@ -138,7 +140,7 @@ describe('LocalFileSystem', function() { fs.mkdirSync(path.join(flowLib,"C")); fs.closeSync(fs.openSync(path.join(flowLib,"C","D.json"),"w")); var testFlowsList = {"d":{"C":{"f":["D"]}},"f":["A","B"]}; - + localfilesystem.getAllFlows().then(function(flows) { flows.should.eql(testFlowsList); done(); @@ -147,7 +149,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should fail a non-existent flow', function(done) { localfilesystem.init({userDir:userDir}).then(function() { localfilesystem.getFlow("a/b/c.json").then(function(flow) { @@ -158,7 +160,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should return a flow',function(done) { localfilesystem.init({userDir:userDir}).then(function() { var testflowString = JSON.stringify(testFlow); @@ -174,7 +176,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should return an empty list of library objects',function(done) { localfilesystem.init({userDir:userDir}).then(function() { localfilesystem.getLibraryEntry('object','').then(function(flows) { @@ -206,11 +208,11 @@ describe('LocalFileSystem', function() { fs.writeFileSync(path.join(objLib,"file1.js"),"// abc: def\n// not a metaline \n\n Hi",'utf8'); fs.writeFileSync(path.join(objLib,"B","file2.js"),"// ghi: jkl\n// not a metaline \n\n Hi",'utf8'); } - + it('should return a directory listing of library objects',function(done) { localfilesystem.init({userDir:userDir}).then(function() { createObjectLibrary(); - + localfilesystem.getLibraryEntry('object','').then(function(flows) { flows.should.eql([ 'A', 'B', { abc: 'def', fn: 'file1.js' } ]); localfilesystem.getLibraryEntry('object','B').then(function(flows) { @@ -229,7 +231,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should return a library object',function(done) { localfilesystem.init({userDir:userDir}).then(function() { createObjectLibrary(); @@ -241,7 +243,7 @@ describe('LocalFileSystem', function() { }); }); }); - + it('should return a newly saved library object',function(done) { localfilesystem.init({userDir:userDir}).then(function() { createObjectLibrary(); @@ -267,5 +269,5 @@ describe('LocalFileSystem', function() { }); }); }); - + });