2016-06-01 10:28:37 +00:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
require('co-mocha')(require('mocha')); // monkey patch mocha for generators
|
|
|
|
|
2016-06-01 13:20:49 +00:00
|
|
|
const config = require('config');
|
2016-06-01 10:28:37 +00:00
|
|
|
const nodemailer = require('nodemailer');
|
|
|
|
const Email = require('../../src/email/email');
|
|
|
|
const Mongo = require('../../src/dao/mongo');
|
2016-06-09 15:07:51 +00:00
|
|
|
const PGP = require('../../src/service/pgp');
|
2016-06-01 10:28:37 +00:00
|
|
|
const PublicKey = require('../../src/service/public-key');
|
|
|
|
const expect = require('chai').expect;
|
|
|
|
const sinon = require('sinon');
|
|
|
|
|
|
|
|
describe('Public Key Integration Tests', function() {
|
|
|
|
this.timeout(20000);
|
|
|
|
|
2016-06-09 15:07:51 +00:00
|
|
|
let publicKey, email, mongo, pgp,
|
2016-06-14 11:13:34 +00:00
|
|
|
sendEmailStub, publicKeyArmored, publicKeyArmored2, mailsSent;
|
2016-06-01 10:28:37 +00:00
|
|
|
|
2016-06-09 15:07:51 +00:00
|
|
|
const DB_TYPE = 'publickey';
|
|
|
|
const primaryEmail = 'test1@example.com';
|
2016-06-14 11:13:34 +00:00
|
|
|
const primaryEmail2 = 'test2@example.com';
|
2016-06-01 10:28:37 +00:00
|
|
|
const origin = { host:'localhost', protocol:'http' };
|
|
|
|
|
|
|
|
before(function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
publicKeyArmored = require('fs').readFileSync(__dirname + '/../key3.asc', 'utf8');
|
2016-06-14 11:13:34 +00:00
|
|
|
publicKeyArmored2 = require('fs').readFileSync(__dirname + '/../key4.asc', 'utf8');
|
2016-06-08 12:01:30 +00:00
|
|
|
mongo = new Mongo();
|
|
|
|
yield mongo.init(config.mongo);
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield mongo.clear(DB_TYPE);
|
2016-06-14 11:13:34 +00:00
|
|
|
mailsSent = [];
|
2016-06-01 10:28:37 +00:00
|
|
|
sendEmailStub = sinon.stub().returns(Promise.resolve({ response:'250' }));
|
|
|
|
sendEmailStub.withArgs(sinon.match(recipient => {
|
2016-06-14 11:13:34 +00:00
|
|
|
mailsSent[mailsSent.length] = {to:recipient.to.address};
|
|
|
|
return true;
|
2016-06-01 10:28:37 +00:00
|
|
|
}), sinon.match(params => {
|
2016-06-14 11:13:34 +00:00
|
|
|
mailsSent[mailsSent.length - 1].params = params;
|
|
|
|
expect(params.nonce).to.exist;
|
|
|
|
expect(params.keyId).to.exist;
|
|
|
|
return true;
|
2016-06-01 10:28:37 +00:00
|
|
|
}));
|
|
|
|
sinon.stub(nodemailer, 'createTransport').returns({
|
|
|
|
templateSender: () => { return sendEmailStub; }
|
|
|
|
});
|
|
|
|
email = new Email(nodemailer);
|
|
|
|
email.init({
|
|
|
|
host: 'localhost',
|
|
|
|
auth: { user:'user', pass:'pass' },
|
|
|
|
sender: { name:'Foo Bar', email:'foo@bar.com' }
|
|
|
|
});
|
2016-06-09 15:07:51 +00:00
|
|
|
pgp = new PGP();
|
|
|
|
publicKey = new PublicKey(pgp, mongo, email);
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
afterEach(() => {
|
|
|
|
nodemailer.createTransport.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
after(function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield mongo.clear(DB_TYPE);
|
2016-06-01 10:28:37 +00:00
|
|
|
yield mongo.disconnect();
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('put', () => {
|
2016-06-01 13:20:49 +00:00
|
|
|
it('should persist key and send verification email with primaryEmail', function *() {
|
2016-06-01 10:28:37 +00:00
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
expect(mailsSent.length).to.equal(1);
|
|
|
|
expect(mailsSent[0].to).to.equal(primaryEmail);
|
|
|
|
expect(mailsSent[0].params.keyId).to.exist;
|
|
|
|
expect(mailsSent[0].params.nonce).to.exist;
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
2016-06-01 13:20:49 +00:00
|
|
|
it('should persist key and send verification email without primaryEmail', function *() {
|
|
|
|
yield publicKey.put({ publicKeyArmored, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
expect(mailsSent.length).to.equal(4);
|
2016-06-01 13:20:49 +00:00
|
|
|
});
|
2016-06-01 10:28:37 +00:00
|
|
|
|
|
|
|
it('should work twice if not yet verified', function *() {
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
expect(mailsSent.length).to.equal(1);
|
2016-06-01 10:28:37 +00:00
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
expect(mailsSent.length).to.equal(2);
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw 304 if key already exists', function *() {
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
yield publicKey.verify(mailsSent[0].params);
|
2016-06-01 10:28:37 +00:00
|
|
|
try {
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
|
|
|
expect(false).to.be.true;
|
|
|
|
} catch(e) {
|
|
|
|
expect(e.status).to.equal(304);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-09 15:07:51 +00:00
|
|
|
describe('verify', () => {
|
|
|
|
it('should update the document', function *() {
|
2016-06-14 11:13:34 +00:00
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
|
|
|
let emailParams = mailsSent[0].params;
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.verify(emailParams);
|
|
|
|
let gotten = yield mongo.get({ keyId:emailParams.keyId }, DB_TYPE);
|
|
|
|
expect(gotten.userIds[0].verified).to.be.true;
|
|
|
|
expect(gotten.userIds[0].nonce).to.be.null;
|
|
|
|
expect(gotten.userIds[1].verified).to.be.false;
|
|
|
|
expect(gotten.userIds[1].nonce).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should not find the document', function *() {
|
2016-06-14 11:13:34 +00:00
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
|
|
|
let emailParams = mailsSent[0].params;
|
2016-06-09 15:07:51 +00:00
|
|
|
try {
|
|
|
|
yield publicKey.verify({ keyId:emailParams.keyId, nonce:'fake_nonce' });
|
|
|
|
expect(true).to.be.false;
|
|
|
|
} catch(e) {
|
|
|
|
expect(e.status).to.equal(404);
|
|
|
|
}
|
|
|
|
let gotten = yield mongo.get({ keyId:emailParams.keyId }, DB_TYPE);
|
|
|
|
expect(gotten.userIds[0].verified).to.be.false;
|
|
|
|
expect(gotten.userIds[0].nonce).to.equal(emailParams.nonce);
|
|
|
|
expect(gotten.userIds[1].verified).to.be.false;
|
|
|
|
expect(gotten.userIds[1].nonce).to.exist;
|
|
|
|
});
|
2016-06-14 11:13:34 +00:00
|
|
|
|
|
|
|
it('should not verify a second key for already verified user id of another key', function *() {
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail:primaryEmail2, origin });
|
|
|
|
expect(mailsSent.length).to.equal(1);
|
|
|
|
yield publicKey.put({ publicKeyArmored:publicKeyArmored2, primaryEmail:primaryEmail2, origin });
|
|
|
|
expect(mailsSent.length).to.equal(2);
|
|
|
|
yield publicKey.verify(mailsSent[1].params);
|
|
|
|
|
|
|
|
try {
|
|
|
|
yield publicKey.verify(mailsSent[0].params);
|
|
|
|
expect(true).to.be.false;
|
|
|
|
} catch(e) {
|
|
|
|
expect(e.status).to.equal(304);
|
|
|
|
}
|
|
|
|
let gotten = yield mongo.get({ keyId:mailsSent[0].params.keyId }, DB_TYPE);
|
|
|
|
expect(gotten.userIds[1].email).to.equal(primaryEmail2);
|
|
|
|
expect(gotten.userIds[1].verified).to.be.false;
|
|
|
|
expect(gotten.userIds[1].nonce).to.equal(mailsSent[0].params.nonce);
|
|
|
|
});
|
2016-06-09 15:07:51 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
describe('getVerified', () => {
|
|
|
|
let key;
|
|
|
|
|
|
|
|
describe('should find a verified key', () => {
|
|
|
|
beforeEach(function *() {
|
|
|
|
key = pgp.parseKey(publicKeyArmored);
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
yield publicKey.verify(mailsSent[0].params);
|
2016-06-09 15:07:51 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('by fingerprint', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ fingerprint:key.fingerprint });
|
|
|
|
expect(verified).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by all userIds', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ userIds:key.userIds });
|
|
|
|
expect(verified).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by verified userId', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ userIds:[key.userIds[0]] });
|
|
|
|
expect(verified).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by unverified userId', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ userIds:[key.userIds[1]] });
|
|
|
|
expect(verified).to.not.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by keyId', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ keyId:key.keyId });
|
|
|
|
expect(verified).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by all params', function *() {
|
|
|
|
let verified = yield publicKey.getVerified(key);
|
|
|
|
expect(verified).to.exist;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('should not find an unverified key', () => {
|
|
|
|
beforeEach(function *() {
|
|
|
|
key = pgp.parseKey(publicKeyArmored);
|
|
|
|
key.userIds[0].verified = false;
|
|
|
|
yield mongo.create(key, DB_TYPE);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by fingerprint', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ fingerprint:key.fingerprint });
|
|
|
|
expect(verified).to.not.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by userIds', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ userIds:key.userIds });
|
|
|
|
expect(verified).to.not.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by keyId', function *() {
|
|
|
|
let verified = yield publicKey.getVerified({ keyId:key.keyId });
|
|
|
|
expect(verified).to.not.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('by all params', function *() {
|
|
|
|
let verified = yield publicKey.getVerified(key);
|
|
|
|
expect(verified).to.not.exist;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2016-06-01 10:28:37 +00:00
|
|
|
describe('get', () => {
|
2016-06-14 11:13:34 +00:00
|
|
|
let emailParams;
|
|
|
|
|
2016-06-01 10:28:37 +00:00
|
|
|
beforeEach(function *() {
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
emailParams = mailsSent[0].params;
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should return verified key by key id', function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.verify(emailParams);
|
|
|
|
let key = yield publicKey.get({ keyId:emailParams.keyId });
|
|
|
|
expect(key.publicKeyArmored).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return verified key by key id (uppercase)', function *() {
|
|
|
|
yield publicKey.verify(emailParams);
|
|
|
|
let key = yield publicKey.get({ keyId:emailParams.keyId.toUpperCase() });
|
|
|
|
expect(key.publicKeyArmored).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return verified key by fingerprint', function *() {
|
|
|
|
yield publicKey.verify(emailParams);
|
|
|
|
let fingerprint = pgp.parseKey(publicKeyArmored).fingerprint;
|
|
|
|
let key = yield publicKey.get({ fingerprint });
|
|
|
|
expect(key.publicKeyArmored).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return verified key by fingerprint (uppercase)', function *() {
|
|
|
|
yield publicKey.verify(emailParams);
|
|
|
|
let fingerprint = pgp.parseKey(publicKeyArmored).fingerprint.toUpperCase();
|
|
|
|
let key = yield publicKey.get({ fingerprint });
|
|
|
|
expect(key.publicKeyArmored).to.exist;
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should return verified key by email address', function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.verify(emailParams);
|
2016-06-01 10:28:37 +00:00
|
|
|
let key = yield publicKey.get({ email:primaryEmail });
|
2016-06-09 15:07:51 +00:00
|
|
|
expect(key.publicKeyArmored).to.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should return verified key by email address (uppercase)', function *() {
|
|
|
|
yield publicKey.verify(emailParams);
|
|
|
|
let key = yield publicKey.get({ email:primaryEmail.toUpperCase() });
|
|
|
|
expect(key.publicKeyArmored).to.exist;
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw 404 for unverified key', function *() {
|
|
|
|
try {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.get({ keyId:emailParams.keyId });
|
2016-06-01 10:28:37 +00:00
|
|
|
expect(false).to.be.true;
|
|
|
|
} catch(e) {
|
|
|
|
expect(e.status).to.equal(404);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('requestRemove', () => {
|
2016-06-09 15:07:51 +00:00
|
|
|
let keyId;
|
2016-06-01 10:28:37 +00:00
|
|
|
|
|
|
|
beforeEach(function *() {
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
keyId = mailsSent[0].params.keyId;
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should work for verified key', function *() {
|
2016-06-14 11:13:34 +00:00
|
|
|
yield publicKey.verify(mailsSent[0].params);
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.requestRemove({ keyId, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
expect(mailsSent.length).to.equal(5);
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should work for unverified key', function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.requestRemove({ keyId, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
expect(mailsSent.length).to.equal(5);
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should work by email address', function *() {
|
|
|
|
yield publicKey.requestRemove({ email:primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
expect(mailsSent.length).to.equal(2);
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw 404 for no key', function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield mongo.remove({ keyId }, DB_TYPE);
|
2016-06-01 10:28:37 +00:00
|
|
|
try {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.requestRemove({ keyId, origin });
|
2016-06-01 10:28:37 +00:00
|
|
|
expect(false).to.be.true;
|
|
|
|
} catch(e) {
|
|
|
|
expect(e.status).to.equal(404);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('verifyRemove', () => {
|
2016-06-09 15:07:51 +00:00
|
|
|
let keyId;
|
2016-06-01 10:28:37 +00:00
|
|
|
|
|
|
|
beforeEach(function *() {
|
|
|
|
yield publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
2016-06-14 11:13:34 +00:00
|
|
|
keyId = mailsSent[0].params.keyId;
|
2016-06-09 15:07:51 +00:00
|
|
|
yield publicKey.requestRemove({ keyId, origin });
|
2016-06-01 10:28:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
it('should remove key', function *() {
|
2016-06-14 11:13:34 +00:00
|
|
|
yield publicKey.verifyRemove(mailsSent[1].params);
|
2016-06-09 15:07:51 +00:00
|
|
|
let key = yield mongo.get({ keyId }, DB_TYPE);
|
2016-06-01 10:28:37 +00:00
|
|
|
expect(key).to.not.exist;
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw 404 for no key', function *() {
|
2016-06-09 15:07:51 +00:00
|
|
|
yield mongo.remove({ keyId }, DB_TYPE);
|
2016-06-01 10:28:37 +00:00
|
|
|
try {
|
2016-06-14 11:13:34 +00:00
|
|
|
yield publicKey.verifyRemove(mailsSent[1].params);
|
2016-06-01 10:28:37 +00:00
|
|
|
expect(false).to.be.true;
|
|
|
|
} catch(e) {
|
|
|
|
expect(e.status).to.equal(404);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
});
|