From 2acbffa2f2c622a73830c5b0165105f8891e8e94 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Tue, 7 Jun 2016 14:56:55 +0200 Subject: [PATCH] Simplify configuration for different environments --- .gitignore | 1 - .travis.yml | 2 +- README.md | 16 ++++----------- config/default.js | 31 +++++++++++++++++++++++++---- config/integration.js | 6 +++--- config/production.js | 6 +++--- package.json | 4 ++-- res/credentials.json | 20 ------------------- src/app.js | 31 ++--------------------------- src/dao/mongo.js | 8 ++++---- src/email/email.js | 6 +++--- src/service/util.js | 13 ++++++++++++ test/integration/app-test.js | 15 +------------- test/integration/email-test.js | 26 ++---------------------- test/integration/mongo-test.js | 14 ++----------- test/integration/public-key-test.js | 15 +------------- test/integration/user-id-test.js | 14 ++----------- test/unit/util-test.js | 24 ++++++++++++++++++++++ 18 files changed, 94 insertions(+), 158 deletions(-) delete mode 100644 res/credentials.json diff --git a/.gitignore b/.gitignore index 1fac4aa..7d33200 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .DS_Store -credentials.json .vscode # Logs diff --git a/.travis.yml b/.travis.yml index 6a1fc7b..d7eb346 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ notifications: services: - mongodb env: - - MONGO_URI=127.0.0.1:27017/test_db MONGO_USER=travis MONGO_PASS=test \ No newline at end of file + - NODE_ENV=integration MONGO_URI=127.0.0.1:27017/test_db MONGO_USER=travis MONGO_PASS=test \ No newline at end of file diff --git a/README.md b/README.md index 0aebaac..fd64403 100644 --- a/README.md +++ b/README.md @@ -146,19 +146,11 @@ GET /api/v1/verifyRemove?keyid=0123456789ABCDEF&nonce=123e4567-e89b-12d3-a456-42 ``` + # Development -Copy the `credentials.json` file into the git repo root directory. This file can be changed to configure a local development installation: - -```shell -cp ./res/credentials.json . -``` - -## Requirements - The server is written is in JavaScript ES6 and runs on [Node.js](https://nodejs.org/) v4+. It uses [MongoDB](https://www.mongodb.com/) v2.4+ as its database. - ## Install Node.js (Mac OS) This is how to install node on Mac OS using [homebrew](http://brew.sh/). For other operating systems, please refer to the [Node.js download page](https://nodejs.org/en/download/). @@ -184,7 +176,7 @@ Now the mongo daemon should be running in the background. To have mongo start au brew services start mongodb ``` -Now you can use the `mongo` CLI client to create a new test database. **The username and password used here match the ones in the `credentials.json` file. Be sure to change them for production use**: +Now you can use the `mongo` CLI client to create a new test database. **The username and password used here match the ones in the `config/development.js` file. Be sure to change them for production use**: ```shell mongo @@ -194,7 +186,7 @@ db.createUser({ user:"keyserver-user", pwd:"trfepCpjhVrqgpXFWsEF", roles:[{ role ## Setup SMTP user -The key server uses [nodemailer](https://nodemailer.com) to send out emails upon public key upload to verify email address ownership. To test this feature locally, open the `credentials.json` file and change the `smtp.user` and `smtp.pass` attributes to your Gmail test account. Make sure that `smtp.user` and `sender.email` match. Otherwise the Gmail SMTP server will block any emails you try to send. Also, make sure to enable `Allow less secure apps` in the [Gmail security settings](https://myaccount.google.com/security#connectedapps). You can read more on this in the [Nodemailer documentation](https://nodemailer.com/using-gmail/). +The key server uses [nodemailer](https://nodemailer.com) to send out emails upon public key upload to verify email address ownership. To test this feature locally, open the `config/development.js` file and change the `email.auth.user` and `email.auth.pass` attributes to your Gmail test account. Make sure that `email.auth.user` and `email.sender.email` match. Otherwise the Gmail SMTP server will block any emails you try to send. Also, make sure to enable `Allow less secure apps` in the [Gmail security settings](https://myaccount.google.com/security#connectedapps). You can read more on this in the [Nodemailer documentation](https://nodemailer.com/using-gmail/). For production you should use a service like [Amazon SES](https://aws.amazon.com/ses/), [Mailgun](https://www.mailgun.com/) or [Sendgrid](https://sendgrid.com/solutions/transactional-email/). Nodemailer supports all of these out of the box. @@ -214,7 +206,7 @@ npm start # Production -The `credentials.json` file can be used to configure a local development installation. For production use, the following environment variables need to be set: +The `config/development.js` file can be used to configure a local development installation. For production use, the following environment variables need to be set: * NODE_ENV=production * MONGO_URI=127.0.0.1:27017/test_db diff --git a/config/default.js b/config/default.js index db0b55f..ee38db3 100644 --- a/config/default.js +++ b/config/default.js @@ -1,10 +1,33 @@ -'use strict'; - module.exports = { + + log: { + level: 'silly' + }, + server: { port: process.env.PORT || 8888, }, - log: { - level: "silly" + + mongo: { + uri: process.env.MONGO_URI, + user: process.env.MONGO_USER, + pass: process.env.MONGO_PASS + }, + + email: { + host: process.env.SMTP_HOST, + port: process.env.SMTP_PORT, + tls: process.env.SMTP_TLS, + starttls: process.env.SMTP_STARTTLS, + pgp: process.env.SMTP_PGP, + auth: { + user: process.env.SMTP_USER, + pass: process.env.SMTP_PASS + }, + sender: { + name: process.env.SENDER_NAME, + email: process.env.SENDER_EMAIL + } } + }; \ No newline at end of file diff --git a/config/integration.js b/config/integration.js index 9069a04..c4537d6 100644 --- a/config/integration.js +++ b/config/integration.js @@ -1,7 +1,7 @@ -'use strict'; - module.exports = { + log: { - level: "warn" + level: 'warn' } + }; \ No newline at end of file diff --git a/config/production.js b/config/production.js index c3b288d..a8dba5b 100644 --- a/config/production.js +++ b/config/production.js @@ -1,7 +1,7 @@ -'use strict'; - module.exports = { + log: { - level: "error" + level: 'error' } + }; \ No newline at end of file diff --git a/package.json b/package.json index f664212..542682d 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "node": ">=4" }, "scripts": { - "start": "node index.js", - "test": "export NODE_ENV=integration && grunt test" + "start": ": ${NODE_ENV=development} && node index.js", + "test": ": ${NODE_ENV=development} && grunt test" }, "dependencies": { "addressparser": "^1.0.1", diff --git a/res/credentials.json b/res/credentials.json deleted file mode 100644 index 05bd932..0000000 --- a/res/credentials.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "mongo": { - "uri": "127.0.0.1:27017/keyserver-test", - "user": "keyserver-user", - "pass": "trfepCpjhVrqgpXFWsEF" - }, - "smtp": { - "host": "smtp.gmail.com", - "port": "465", - "tls": "true", - "starttls": "true", - "pgp": "true", - "user": "user@gmail.com", - "pass": "password" - }, - "sender": { - "name": "OpenPGP Key Server", - "email": "user@gmail.com" - } -} \ No newline at end of file diff --git a/src/app.js b/src/app.js index 14cdcc1..5e58fd3 100644 --- a/src/app.js +++ b/src/app.js @@ -95,42 +95,15 @@ app.on('error', (error, ctx) => { // function injectDependencies() { - let credentials = readCredentials(); - mongo = new Mongo({ - uri: process.env.MONGO_URI || credentials.mongo.uri, - user: process.env.MONGO_USER || credentials.mongo.user, - password: process.env.MONGO_PASS || credentials.mongo.pass - }); + mongo = new Mongo(config.mongo); email = new Email(nodemailer, openpgpEncrypt); - email.init({ - host: process.env.SMTP_HOST || credentials.smtp.host, - port: process.env.SMTP_PORT || credentials.smtp.port, - tls: (process.env.SMTP_TLS || credentials.smtp.tls) === 'true', - starttls: (process.env.SMTP_STARTTLS || credentials.smtp.starttls) === 'true', - pgp: (process.env.SMTP_PGP || credentials.smtp.pgp) === 'true', - auth: { - user: process.env.SMTP_USER || credentials.smtp.user, - pass: process.env.SMTP_PASS || credentials.smtp.pass - }, - sender: { - name: process.env.SENDER_NAME || credentials.sender.name, - email: process.env.SENDER_EMAIL || credentials.sender.email - } - }); + email.init(config.email); userId = new UserId(mongo); publicKey = new PublicKey(openpgp, mongo, email, userId); hkp = new HKP(publicKey); rest = new REST(publicKey, userId); } -function readCredentials() { - try { - return require('../credentials.json'); - } catch(e) { - log.info('app', 'No credentials.json found ... using environment vars.'); - } -} - // // Start app ... connect to the database and start listening // diff --git a/src/dao/mongo.js b/src/dao/mongo.js index 2bea667..5ee6846 100644 --- a/src/dao/mongo.js +++ b/src/dao/mongo.js @@ -26,12 +26,12 @@ class Mongo { /** * Create an instance of the MongoDB client. - * @param {String} uri The mongodb uri - * @param {String} user The databse user - * @param {String} password The database user's password + * @param {String} uri The mongodb uri + * @param {String} user The databse user + * @param {String} pass The database user's password */ constructor(options) { - this._uri = 'mongodb://' + options.user + ':' + options.password + '@' + options.uri; + this._uri = 'mongodb://' + options.user + ':' + options.pass + '@' + options.uri; } /** diff --git a/src/email/email.js b/src/email/email.js index 43a58b1..2767da9 100644 --- a/src/email/email.js +++ b/src/email/email.js @@ -49,10 +49,10 @@ class Email { host: options.host, port: options.port || 465, auth: options.auth, - secure: (options.tls !== undefined) ? options.tls : true, - requireTLS: (options.starttls !== undefined) ? options.starttls : true, + secure: (options.tls !== undefined) ? util.isTrue(options.tls) : true, + requireTLS: (options.starttls !== undefined) ? util.isTrue(options.starttls) : true, }); - if (options.pgp) { + if (util.isTrue(options.pgp)) { this._transport.use('stream', this._openpgpEncrypt()); } this._sender = options.sender; diff --git a/src/service/util.js b/src/service/util.js index 4514685..e56b022 100644 --- a/src/service/util.js +++ b/src/service/util.js @@ -28,6 +28,19 @@ exports.isString = function(data) { return typeof data === 'string' || String.prototype.isPrototypeOf(data); }; +/** + * Cast string to a boolean value + * @param {} data The input to be checked + * @return {boolean} If data is true + */ +exports.isTrue = function(data) { + if (this.isString(data)) { + return data === 'true'; + } else { + return !!data; + } +}; + /** * Checks for a valid key id which is between 8 and 40 hex chars. * @param {string} data The key id diff --git a/test/integration/app-test.js b/test/integration/app-test.js index 3e67089..f26b0d1 100644 --- a/test/integration/app-test.js +++ b/test/integration/app-test.js @@ -5,14 +5,11 @@ require('co-mocha')(require('mocha')); // monkey patch mocha for generators const request = require('supertest'); const Mongo = require('../../src/dao/mongo'); const nodemailer = require('nodemailer'); -const log = require('npmlog'); const config = require('config'); const fs = require('fs'); const expect = require('chai').expect; const sinon = require('sinon'); -log.level = config.log.level; - describe('Koa App (HTTP Server) Integration Tests', function() { this.timeout(20000); @@ -26,17 +23,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() { before(function *() { publicKeyArmored = fs.readFileSync(__dirname + '/../key1.asc', 'utf8'); - let credentials; - try { - credentials = require('../../credentials.json'); - } catch(e) { - log.info('app-test', 'No credentials.json found ... using environment vars.'); - } - mongo = new Mongo({ - uri: process.env.MONGO_URI || credentials.mongo.uri, - user: process.env.MONGO_USER || credentials.mongo.user, - password: process.env.MONGO_PASS || credentials.mongo.pass - }); + mongo = new Mongo(config.mongo); yield mongo.connect(); sendEmailStub = sinon.stub().returns(Promise.resolve({ response:'250' })); diff --git a/test/integration/email-test.js b/test/integration/email-test.js index 32cb76c..25757c0 100644 --- a/test/integration/email-test.js +++ b/test/integration/email-test.js @@ -3,49 +3,27 @@ require('co-mocha')(require('mocha')); // monkey patch mocha for generators const expect = require('chai').expect; -const log = require('npmlog'); const config = require('config'); const Email = require('../../src/email/email'); const nodemailer = require('nodemailer'); const openpgpEncrypt = require('nodemailer-openpgp').openpgpEncrypt; const tpl = require('../../src/email/templates.json'); -log.level = config.log.level; - describe('Email Integration Tests', function() { this.timeout(20000); - let email, credentials, userId, origin, publicKeyArmored; + let email, userId, origin, publicKeyArmored; const recipient = { name:'Test User', email:'safewithme.testuser@gmail.com' }; before(function() { - try { - credentials = require('../../credentials.json'); - } catch(e) { - log.info('email-test', 'No credentials.json found ... using environment vars.'); - } publicKeyArmored = require('fs').readFileSync(__dirname + '/../key1.asc', 'utf8'); origin = { protocol: 'http', host: 'localhost:' + config.server.port }; email = new Email(nodemailer, openpgpEncrypt); - email.init({ - host: process.env.SMTP_HOST || credentials.smtp.host, - port: process.env.SMTP_PORT || credentials.smtp.port, - tls: (process.env.SMTP_TLS || credentials.smtp.tls) === 'true', - starttls: (process.env.SMTP_STARTTLS || credentials.smtp.starttls) === 'true', - pgp: (process.env.SMTP_PGP || credentials.smtp.pgp) === 'true', - auth: { - user: process.env.SMTP_USER || credentials.smtp.user, - pass: process.env.SMTP_PASS || credentials.smtp.pass - }, - sender: { - name: process.env.SENDER_NAME || credentials.sender.name, - email: process.env.SENDER_EMAIL || credentials.sender.email - } - }); + email.init(config.email); }); beforeEach(() => { diff --git a/test/integration/mongo-test.js b/test/integration/mongo-test.js index cf375ec..4ebafce 100644 --- a/test/integration/mongo-test.js +++ b/test/integration/mongo-test.js @@ -2,7 +2,7 @@ require('co-mocha')(require('mocha')); // monkey patch mocha for generators -const log = require('npmlog'); +const config = require('config'); const Mongo = require('../../src/dao/mongo'); const expect = require('chai').expect; @@ -13,17 +13,7 @@ describe('Mongo Integration Tests', function() { let mongo; before(function *() { - let credentials; - try { - credentials = require('../../credentials.json'); - } catch(e) { - log.info('mongo-test', 'No credentials.json found ... using environment vars.'); - } - mongo = new Mongo({ - uri: process.env.MONGO_URI || credentials.mongo.uri, - user: process.env.MONGO_USER || credentials.mongo.user, - password: process.env.MONGO_PASS || credentials.mongo.pass - }); + mongo = new Mongo(config.mongo); yield mongo.connect(); }); diff --git a/test/integration/public-key-test.js b/test/integration/public-key-test.js index e20e44d..abc1978 100644 --- a/test/integration/public-key-test.js +++ b/test/integration/public-key-test.js @@ -2,7 +2,6 @@ require('co-mocha')(require('mocha')); // monkey patch mocha for generators -const log = require('npmlog'); const config = require('config'); const openpgp = require('openpgp'); const nodemailer = require('nodemailer'); @@ -13,8 +12,6 @@ const PublicKey = require('../../src/service/public-key'); const expect = require('chai').expect; const sinon = require('sinon'); -log.level = config.log.level; - describe('Public Key Integration Tests', function() { this.timeout(20000); @@ -28,17 +25,7 @@ describe('Public Key Integration Tests', function() { before(function *() { publicKeyArmored = require('fs').readFileSync(__dirname + '/../key1.asc', 'utf8'); - let credentials; - try { - credentials = require('../../credentials.json'); - } catch(e) { - log.info('mongo-test', 'No credentials.json found ... using environment vars.'); - } - mongo = new Mongo({ - uri: process.env.MONGO_URI || credentials.mongo.uri, - user: process.env.MONGO_USER || credentials.mongo.user, - password: process.env.MONGO_PASS || credentials.mongo.pass - }); + mongo = new Mongo(config.mongo); yield mongo.connect(); }); diff --git a/test/integration/user-id-test.js b/test/integration/user-id-test.js index 6934ecf..aca6415 100644 --- a/test/integration/user-id-test.js +++ b/test/integration/user-id-test.js @@ -2,7 +2,7 @@ require('co-mocha')(require('mocha')); // monkey patch mocha for generators -const log = require('npmlog'); +const config = require('config'); const UserId = require('../../src/service/user-id'); const Mongo = require('../../src/dao/mongo'); const expect = require('chai').expect; @@ -15,17 +15,7 @@ describe('User ID Integration Tests', function() { let mongo, userId, uid1, uid2; before(function *() { - let credentials; - try { - credentials = require('../../credentials.json'); - } catch(e) { - log.info('user-id-test', 'No credentials.json found ... using environment vars.'); - } - mongo = new Mongo({ - uri: process.env.MONGO_URI || credentials.mongo.uri, - user: process.env.MONGO_USER || credentials.mongo.user, - password: process.env.MONGO_PASS || credentials.mongo.pass - }); + mongo = new Mongo(config.mongo); yield mongo.connect(); userId = new UserId(mongo); }); diff --git a/test/unit/util-test.js b/test/unit/util-test.js index 903a48b..39b3065 100644 --- a/test/unit/util-test.js +++ b/test/unit/util-test.js @@ -22,6 +22,30 @@ describe('Util Unit Tests', () => { }); }); + describe('isTrue', () => { + it('should be true for "true"', () => { + expect(util.isTrue('true')).to.be.true; + }); + it('should be true for true', () => { + expect(util.isTrue(true)).to.be.true; + }); + it('should be false for "false"', () => { + expect(util.isTrue('false')).to.be.false; + }); + it('should be false for false', () => { + expect(util.isTrue(false)).to.be.false; + }); + it('should be true for a random string', () => { + expect(util.isTrue('asdf')).to.be.false; + }); + it('should be true for undefined', () => { + expect(util.isTrue(undefined)).to.be.false; + }); + it('should be true for null', () => { + expect(util.isTrue(null)).to.be.false; + }); + }); + describe('validateKeyId', () => { it('should be true for 40 byte hex', () => { expect(util.validateKeyId('0123456789ABCDEF0123456789ABCDEF01234567')).to.be.true;