From e70b69aaf0175a72e4fdfa27ce02f939a4d9ced0 Mon Sep 17 00:00:00 2001 From: Maximiliano Korp Date: Thu, 23 Feb 2017 14:55:54 -0700 Subject: [PATCH 1/4] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8055e0e..3027d8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "secure-storage", - "version": "0.2.0", + "version": "0.2.1", "description": "", "main": "lib/main.js", "scripts": { From 4da1cf4efc29940b30678478ac7f98b16d254aa5 Mon Sep 17 00:00:00 2001 From: Maximiliano Korp Date: Mon, 27 Feb 2017 10:32:14 -0700 Subject: [PATCH 2/4] Add istanbul for coverage --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3027d8e..b7e33ac 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "lib/main.js", "scripts": { "lint": "eslint lib spec/spec.js", - "test": "mocha spec/spec.js" + "test": "nyc mocha spec/spec.js" }, "author": "Maximiliano Korp Date: Mon, 27 Feb 2017 10:32:51 -0700 Subject: [PATCH 3/4] Fixup coverage --- lib/io.js | 2 +- lib/main.js | 10 +++++----- lib/operateOnData.js | 15 +++++++-------- spec/spec.js | 22 +++++++++++----------- 4 files changed, 24 insertions(+), 25 deletions(-) diff --git a/lib/io.js b/lib/io.js index 84914ae..5f37ab4 100644 --- a/lib/io.js +++ b/lib/io.js @@ -47,7 +47,7 @@ module.exports = (encPath, _password, _algorithm) => { .then(() => JSON.stringify(inputJson, null, 2)) .then((input) => doCrypto(input, false)) .then((output) => fse.writeFileAsync(actualPath, output)) - .catch((e) => { + .catch(/* istanbul ignore next */ (e) => { debug('failed to save:'); debug(e); throw e; diff --git a/lib/main.js b/lib/main.js index 3a92c19..584de40 100644 --- a/lib/main.js +++ b/lib/main.js @@ -25,7 +25,7 @@ module.exports = (encPath, password, algorithm) => { .then((data) => { return operate.getPassword(data, service, account); }) - .catch((e) => { + .catch(/* istanbul ignore next */(e) => { debug(e); return null; }); @@ -47,7 +47,7 @@ module.exports = (encPath, password, algorithm) => { .then((_success) => { success = _success; }) .then(() => success && ioImpl.save(data)) .then(() => success) - .catch(() => false); + .catch(/* istanbul ignore next */() => false); corePromise = newPromise; return newPromise; @@ -65,7 +65,7 @@ module.exports = (encPath, password, algorithm) => { .then((_success) => { success = _success; }) .then(() => success && ioImpl.save(data)) .then(() => success) - .catch(() => false); + .catch(/* istanbul ignore next */() => false); corePromise = newPromise; return newPromise; @@ -84,7 +84,7 @@ module.exports = (encPath, password, algorithm) => { .then((_success) => { success = _success; }) .then(() => success && ioImpl.save(data)) .then(() => success) - .catch(() => false); + .catch(/* istanbul ignore next */() => false); corePromise = newPromise; return newPromise; @@ -95,7 +95,7 @@ module.exports = (encPath, password, algorithm) => { .then(() => guard('service', service)) .then(() => ioImpl.load()) .then((data) => operate.findPassword(data, service)) - .catch(() => null); + .catch(/* istanbul ignore next */() => null); corePromise = newPromise; return newPromise; diff --git a/lib/operateOnData.js b/lib/operateOnData.js index f454ed3..8ca8d7e 100644 --- a/lib/operateOnData.js +++ b/lib/operateOnData.js @@ -5,7 +5,7 @@ const debug = require('debug')('secure-storage:operateOnData'); module.exports.getPassword = (data, service, account) => { debug('getting password: %s %s %s', JSON.stringify(data), service, account); try { - return data[service][account]; + return data[service][account] || null; } catch (e) { return null; @@ -33,17 +33,16 @@ module.exports.deletePassword = (data, service, account) => { let password = false; try { - if (data[service]) { - if (data[service][account]) { - password = data[service][account]; - delete data[service][account]; // eslint-disable-line no-param-reassign - if (!Object.keys(data[service])) { - delete data[service]; // eslint-disable-line no-param-reassign - } + if (data[service][account]) { + password = data[service][account]; + delete data[service][account]; // eslint-disable-line no-param-reassign + if (!Object.keys(data[service])) { + delete data[service]; // eslint-disable-line no-param-reassign } } } catch (e) { + /* istanbul ignore next */ password = false; } diff --git a/spec/spec.js b/spec/spec.js index 16963fe..77e0bd3 100644 --- a/spec/spec.js +++ b/spec/spec.js @@ -51,17 +51,17 @@ const encryptWithOpenSSL = (inputFile, outputFile, algo) => { }; // disabled linter for this as another test will use it -const decryptWithOpenSSL = (inputFile, algo) => { // eslint-disable-line no-unused-vars - const cmd = [ - 'openssl', - algo, - '-e', - '-in', - inputFile, - '-nosalt' - ].join(' '); - return cp.execSync(cmd); -}; +// const decryptWithOpenSSL = (inputFile, algo) => { // eslint-disable-line no-unused-vars +// const cmd = [ +// 'openssl', +// algo, +// '-e', +// '-in', +// inputFile, +// '-nosalt' +// ].join(' '); +// return cp.execSync(cmd); +// }; describe(`secure-storage (Using password: ${password})`, () => { beforeEach(() => { From f4f6b4da4f5c74fd22b41f3f12c544df2bcd271a Mon Sep 17 00:00:00 2001 From: Maximiliano Korp Date: Mon, 27 Feb 2017 10:32:56 -0700 Subject: [PATCH 4/4] Add more tests --- lib/operateOnData.js | 3 +- spec/spec.js | 97 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/lib/operateOnData.js b/lib/operateOnData.js index 8ca8d7e..d7eeff6 100644 --- a/lib/operateOnData.js +++ b/lib/operateOnData.js @@ -36,13 +36,12 @@ module.exports.deletePassword = (data, service, account) => { if (data[service][account]) { password = data[service][account]; delete data[service][account]; // eslint-disable-line no-param-reassign - if (!Object.keys(data[service])) { + if (!Object.keys(data[service]).length) { delete data[service]; // eslint-disable-line no-param-reassign } } } catch (e) { - /* istanbul ignore next */ password = false; } diff --git a/spec/spec.js b/spec/spec.js index 77e0bd3..f2cef86 100644 --- a/spec/spec.js +++ b/spec/spec.js @@ -194,4 +194,101 @@ describe(`secure-storage (Using password: ${password})`, () => { expect(pass).toEqual('c'); }); }); + + it('can find a password', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return Promise.all([ + ss.setPassword('serv1', 'acct1', 'condo'), + ss.setPassword('serv1', 'acct2', 'hondo'), + ss.setPassword('serv2', 'acct1111', 'janefondo') + ]) + .then(() => + ss.findPassword('serv1') + .then((pass) => expect(['condo', 'hondo'].includes(pass)).toEqual(true)) + .then(() => ss.findPassword('serv2')) + .then((pass) => expect(['janefondo'].includes(pass)).toEqual(true)) + ); + }); + + it('gets null when getting a non-existing password', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.getPassword('serv1', 'acct1') + .then((pass) => expect(pass).toEqual(null)); + }); + + it('gets null when finding a non-existing password', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.findPassword('serv1', 'acct1') + .then((pass) => expect(pass).toEqual(null)); + }); + + it('can replace an existing password', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.setPassword('serv1', 'acct1', 'condo') + .then(() => ss.replacePassword('serv1', 'acct1', 'hondo')) + .then(() => ss.getPassword('serv1', 'acct1')) + .then((pass) => expect(pass).toEqual('hondo')); + }); + + it('can replace a non-existing password', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.setPassword('serv1', 'acct1', 'condo') + .then(() => ss.replacePassword('serv1', 'acct2', 'hondo')) + .then(() => ss.getPassword('serv1', 'acct1')) + .then((pass) => expect(pass).toEqual('condo')) + .then(() => ss.getPassword('serv1', 'acct2')) + .then((pass) => expect(pass).toEqual('hondo')); + }); + + it('does not replace an existing password when using setPassword', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.setPassword('serv1', 'acct1', 'condo') + .then(() => ss.setPassword('serv1', 'acct1', 'hondo')) + .then(() => ss.getPassword('serv1', 'acct1')) + .then((pass) => expect(pass).toEqual('condo')); + }); + + it('returns when getting a non existing password', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.setPassword('serv1', 'acct1', 'condo') + .then(() => ss.getPassword('poyo', 'fundido')) + .then((pass) => expect(pass).toEqual(null)); + }); + + it('can delete a password', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.setPassword('serv1', 'acct1', 'condo') + .then(() => ss.getPassword('serv1', 'acct1')) + .then((pass) => expect(pass).toEqual('condo')) + .then(() => ss.deletePassword('serv1', 'acct1')) + .then((pass) => expect(pass).toEqual('condo')) + .then(() => ss.getPassword('serv1', 'acct1')) + .then((pass) => expect(pass).toEqual(null)) + .then(() => ss.deletePassword('serv2', 'cactusAccount')) + .then((pass) => expect(pass).toEqual(false)); + }); + + it('can properly guard', () => { + const filePath = path.join(__dirname, 'tmp', 'secure.enc'); + const algo = Object.keys(algos)[0]; + const ss = secureStorage(filePath, password, algo); + return ss.setPassword('serv1', 'acct1') + .then((set) => expect(set).toEqual(false)); + }); });