Simplify configuration for different environments
This commit is contained in:
parent
2ab6333a15
commit
2acbffa2f2
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,4 @@
|
||||
.DS_Store
|
||||
credentials.json
|
||||
.vscode
|
||||
|
||||
# Logs
|
||||
|
@ -14,4 +14,4 @@ notifications:
|
||||
services:
|
||||
- mongodb
|
||||
env:
|
||||
- MONGO_URI=127.0.0.1:27017/test_db MONGO_USER=travis MONGO_PASS=test
|
||||
- NODE_ENV=integration MONGO_URI=127.0.0.1:27017/test_db MONGO_USER=travis MONGO_PASS=test
|
16
README.md
16
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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
|
||||
log: {
|
||||
level: "warn"
|
||||
level: 'warn'
|
||||
}
|
||||
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
|
||||
log: {
|
||||
level: "error"
|
||||
level: 'error'
|
||||
}
|
||||
|
||||
};
|
@ -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",
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
31
src/app.js
31
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
|
||||
//
|
||||
|
@ -28,10 +28,10 @@ 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} 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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' }));
|
||||
|
@ -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(() => {
|
||||
|
@ -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();
|
||||
});
|
||||
|
||||
|
@ -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();
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user