diff --git a/locales/de.json b/locales/de.json new file mode 100644 index 0000000..08e32d8 --- /dev/null +++ b/locales/de.json @@ -0,0 +1,8 @@ +{ + "key_not_found": "Schlüssel nicht gefunden", + "verify_key_subject": "Bestätigen Sie Ihre E-Mail-Adresse", + "verify_key_text": "Hallo {0},\n\nbitte bestätigen Sie Ihre E-Mail-Adresse {1}.\nKlicken Sie hierzu auf den folgenden Link:\n\n{2}\n\nNach der Bestätigung Ihrer E-Mail-Adresse ist ihr öffentlicher Schlüssel in unserem Schlüssel Verzeichnis verfügbar.\n\nWeitere Informationen finden Sie unter {3}.\n\nIhr Mailvelope Team", + "verify_success": "
Ihr öffentlicher OpenPGP Schlüssel ist ab jetzt unter folgendem Link verfügbar: {1}
", + "verify_removal_subject": "Entfernen Ihres Schlüssels bestätigen", + "verify_removal_text": "Hallo {0},\n\nbitte bestätigen Sie das Entfernen Ihrer E-Mail-Adresse {1} von unserem Key Server ({2}).\nKlicken Sie hierzu auf den folgenden Link:\n\n{3}\n\nIhr Mailvelope Team" +} diff --git a/locales/en.json b/locales/en.json new file mode 100644 index 0000000..a78102d --- /dev/null +++ b/locales/en.json @@ -0,0 +1,8 @@ +{ + "key_not_found": "Key not found", + "verify_key_subject": "Verify your email address", + "verify_key_text": "Hello {0},\n\nplease verify your email address {1} by clicking on the following link:\n\n{2}\n\nAfter verification of your email address your public key is available in our key directory.\n\nYou can find more info at {3}.\n\nGreetings from the Mailvelope Team", + "verify_success": "Your public OpenPGP key is now available at the following link: {1}
", + "verify_removal_subject": "Verify key removal", + "verify_removal_text": "Hello {0},\n\nplease verify removal of your email address {1} from our key server ({2}) by clicking on the following link:\n\n{3}\n\nGreetings from the Mailvelope Team" +} diff --git a/package-lock.json b/package-lock.json index c2eb2ac..0aa0266 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1017,6 +1017,14 @@ "statuses": ">= 1.4.0 < 2" } }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -1074,6 +1082,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, "inquirer": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.3.1.tgz", @@ -1314,6 +1327,32 @@ "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=" }, + "koa-locales": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/koa-locales/-/koa-locales-1.11.0.tgz", + "integrity": "sha512-VYrV3CCvpwqItjkqPQVB0O212CoVEJqARndN/u/CO2F8Dbhtnj+pjDaqpG1uZLQl8l/jhlpp6O1uWlvLWRqr3Q==", + "requires": { + "debug": "^2.6.0", + "humanize-ms": "^1.2.0", + "ini": "^1.3.4", + "object-assign": "^4.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, "koa-router": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-7.4.0.tgz", diff --git a/package.json b/package.json index 9c241f9..7304c5b 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "co-body": "6.0.0", "config": "3.1.0", "koa": "2.7.0", + "koa-locales": "1.11.0", "koa-router": "7.4.0", "koa-static": "5.0.0", "mongodb": "3.2.6", diff --git a/src/app/index.js b/src/app/index.js index a4a7e5d..9fe3b1b 100644 --- a/src/app/index.js +++ b/src/app/index.js @@ -18,18 +18,20 @@ 'use strict'; const Koa = require('koa'); -const config = require('config'); const serve = require('koa-static'); const router = require('koa-router')(); +const locales = require('koa-locales'); +const config = require('config'); const middleware = require('./middleware'); const Mongo = require('../dao/mongo'); const Email = require('../email/email'); -const PGP = require('../service/pgp'); -const PublicKey = require('../service/public-key'); const HKP = require('../route/hkp'); const REST = require('../route/rest'); +const PGP = require('../service/pgp'); +const PublicKey = require('../service/public-key'); const app = new Koa(); +locales(app); let hkp; let rest; diff --git a/src/email/email.js b/src/email/email.js index 9ce90fc..8b8d4d7 100644 --- a/src/email/email.js +++ b/src/email/email.js @@ -58,10 +58,9 @@ class Email { */ async send({template, userId, keyId, origin, publicKeyArmored}) { const compiled = template({ - name: userId.name, - baseUrl: util.url(origin), - keyId, - nonce: userId.nonce + ...userId, + origin, + keyId }); if (this._usePGPEncryption && publicKeyArmored) { compiled.text = await this._pgpEncrypt(compiled.text, publicKeyArmored); diff --git a/src/email/templates.js b/src/email/templates.js index edea073..0accfa0 100644 --- a/src/email/templates.js +++ b/src/email/templates.js @@ -1,11 +1,21 @@ 'use strict'; -exports.verifyKey = ({name, baseUrl, keyId, nonce}) => ({ - subject: 'Verify Your Key', - text: `Hello ${name},\n\nplease click here to verify your email address:\n\n${baseUrl}/api/v1/key?op=verify&keyId=${keyId}&nonce=${nonce}`, -}); +const util = require('../service/util'); -exports.verifyRemove = ({name, baseUrl, keyId, nonce}) => ({ - subject: 'Verify Key Removal', - text: `Hello ${name},\n\nplease click here to verify the removal of your email address:\n\n${baseUrl}/api/v1/key?op=verifyRemove&keyId=${keyId}&nonce=${nonce}`, -}); +function verifyKey(ctx, {name, email, nonce, origin, keyId}) { + const link = `${util.url(origin)}/api/v1/key?op=verify&keyId=${keyId}&nonce=${nonce}`; + return { + subject: ctx.__('verify_key_subject'), + text: ctx.__('verify_key_text', [name, email, link, origin.host]) + }; +} + +function verifyRemove(ctx, {name, email, nonce, origin, keyId}) { + const link = `${util.url(origin)}/api/v1/key?op=verifyRemove&keyId=${keyId}&nonce=${nonce}`; + return { + subject: ctx.__('verify_removal_subject'), + text: ctx.__('verify_removal_text', [name, email, origin.host, link]) + }; +} + +module.exports = {verifyKey, verifyRemove}; diff --git a/src/route/hkp.js b/src/route/hkp.js index be26616..060cb5c 100644 --- a/src/route/hkp.js +++ b/src/route/hkp.js @@ -43,7 +43,7 @@ class HKP { ctx.throw(400, 'Invalid request!'); } const origin = util.origin(ctx); - await this._publicKey.put({publicKeyArmored, origin}); + await this._publicKey.put({publicKeyArmored, origin}, ctx); ctx.body = 'Upload successful. Check your inbox to verify your email address.'; ctx.status = 201; } @@ -54,7 +54,7 @@ class HKP { */ async lookup(ctx) { const params = this.parseQueryString(ctx); - const key = await this._publicKey.get(params); + const key = await this._publicKey.get(params, ctx); this.setGetHeaders(ctx, params); this.setGetBody(ctx, params, key); } diff --git a/src/route/rest.js b/src/route/rest.js index 3d95a25..84fb75a 100644 --- a/src/route/rest.js +++ b/src/route/rest.js @@ -43,7 +43,7 @@ class REST { ctx.throw(400, 'Invalid request!'); } const origin = util.origin(ctx); - await this._publicKey.put({emails, publicKeyArmored, origin}); + await this._publicKey.put({emails, publicKeyArmored, origin}, ctx); ctx.body = 'Upload successful. Check your inbox to verify your email address.'; ctx.status = 201; } @@ -62,7 +62,7 @@ class REST { if (!util.isKeyId(q.keyId) && !util.isFingerPrint(q.fingerprint) && !util.isEmail(q.email)) { ctx.throw(400, 'Invalid request!'); } - ctx.body = await this._publicKey.get(q); + ctx.body = await this._publicKey.get(q, ctx); } /** @@ -74,10 +74,10 @@ class REST { if (!util.isKeyId(q.keyId) || !util.isString(q.nonce)) { ctx.throw(400, 'Invalid request!'); } - await this._publicKey.verify(q); + const {email} = await this._publicKey.verify(q); // create link for sharing - const link = util.url(util.origin(ctx), `/pks/lookup?op=get&search=0x${q.keyId.toUpperCase()}`); - ctx.body = `Email address successfully verified!
Link to share your key: ${link}
`; + const link = util.url(util.origin(ctx), `/pks/lookup?op=get&search=${email}`); + ctx.body = ctx.__('verify_success', [email, link]); ctx.set('Content-Type', 'text/html; charset=utf-8'); } @@ -90,7 +90,7 @@ class REST { if (!util.isKeyId(q.keyId) && !util.isEmail(q.email)) { ctx.throw(400, 'Invalid request!'); } - await this._publicKey.requestRemove(q); + await this._publicKey.requestRemove(q, ctx); ctx.body = 'Check your inbox to verify the removal of your email address.'; ctx.status = 202; } diff --git a/src/service/public-key.js b/src/service/public-key.js index 5cc3878..8e9c69a 100644 --- a/src/service/public-key.js +++ b/src/service/public-key.js @@ -66,9 +66,10 @@ class PublicKey { * @param {Array} emails (optional) The emails to upload/update * @param {String} publicKeyArmored The ascii armored pgp key block * @param {Object} origin Required for links to the keyserver e.g. { protocol:'https', host:'openpgpkeys@example.com' } + * @param {Object} ctx Context * @return {Promise} */ - async put({emails = [], publicKeyArmored, origin}) { + async put({emails = [], publicKeyArmored, origin}, ctx) { emails = emails.map(util.normalizeEmail); // lazily purge old/unverified keys on every key upload await this._purgeOldUnverified(); @@ -100,7 +101,7 @@ class PublicKey { key.publicKeyArmored = null; } // send mails to verify user ids - await this._sendVerifyEmail(key, origin); + await this._sendVerifyEmail(key, origin, ctx); // store key in database await this._persistKey(key); } @@ -162,14 +163,15 @@ class PublicKey { * If a primary email address is provided only one email will be sent. * @param {Array} userIds user id documents containg the verification nonces * @param {Object} origin the server's origin (required for email links) + * @param {Object} ctx Context * @return {Promise} */ - async _sendVerifyEmail({userIds, keyId}, origin) { + async _sendVerifyEmail({userIds, keyId}, origin, ctx) { for (const userId of userIds) { if (userId.notify && userId.notify === true) { // generate nonce for verification userId.nonce = util.random(); - await this._email.send({template: tpl.verifyKey, userId, keyId, origin, publicKeyArmored: userId.publicKeyArmored}); + await this._email.send({template: tpl.verifyKey.bind(null, ctx), userId, keyId, origin, publicKeyArmored: userId.publicKeyArmored}); } } } @@ -200,7 +202,7 @@ class PublicKey { * Verify a user id by proving knowledge of the nonce. * @param {string} keyId Correspronding public key id * @param {string} nonce The verification nonce proving email address ownership - * @return {Promise} + * @return {Promise} The email that has been verified */ async verify({keyId, nonce}) { // look for verification nonce in database @@ -210,7 +212,7 @@ class PublicKey { util.throw(404, 'User ID not found'); } await this._removeKeysWithSameEmail(key, nonce); - let {publicKeyArmored} = key.userIds.find(userId => userId.nonce === nonce); + let {publicKeyArmored, email} = key.userIds.find(userId => userId.nonce === nonce); // update armored key if (key.publicKeyArmored) { publicKeyArmored = await this._pgp.updateKey(key.publicKeyArmored, publicKeyArmored); @@ -222,6 +224,7 @@ class PublicKey { 'userIds.$.nonce': null, 'userIds.$.publicKeyArmored': null }, DB_TYPE); + return {email}; } /** @@ -283,14 +286,15 @@ class PublicKey { * @param {string} fingerprint (optional) The public key fingerprint * @param {string} keyId (optional) The public key id * @param {String} email (optional) The user's email address + * @param {Object} ctx Context * @return {Object} The public key document */ - async get({fingerprint, keyId, email}) { + async get({fingerprint, keyId, email}, ctx) { // look for verified key const userIds = email ? [{email}] : undefined; const key = await this.getVerified({keyId, fingerprint, userIds}); if (!key) { - util.throw(404, 'Key not found'); + util.throw(404, ctx.__('key_not_found')); } // clean json return value (_id, nonce) delete key._id; @@ -310,9 +314,10 @@ class PublicKey { * @param {String} keyId (optional) The public key id * @param {String} email (optional) The user's email address * @param {Object} origin Required for links to the keyserver e.g. { protocol:'https', host:'openpgpkeys@example.com' } + * @param {Object} ctx Context * @return {Promise} */ - async requestRemove({keyId, email, origin}) { + async requestRemove({keyId, email, origin}, ctx) { // flag user ids for removal const key = await this._flagForRemove(keyId, email); if (!key) { @@ -321,7 +326,7 @@ class PublicKey { // send verification mails keyId = key.keyId; // get keyId in case request was by email for (const userId of key.userIds) { - await this._email.send({template: tpl.verifyRemove, userId, keyId, origin}); + await this._email.send({template: tpl.verifyRemove.bind(null, ctx), userId, keyId, origin}); } } diff --git a/test/integration/app-test.js b/test/integration/app-test.js index 6509c0c..a1680b3 100644 --- a/test/integration/app-test.js +++ b/test/integration/app-test.js @@ -34,8 +34,9 @@ describe('Koa App (HTTP Server) Integration Tests', function() { emailParams = params; return Boolean(params.nonce); }); - sandbox.spy(templates, 'verifyKey').withArgs(paramMatcher); - sandbox.spy(templates, 'verifyRemove').withArgs(paramMatcher); + const ctxMatcher = sinon.match(ctx => Boolean(ctx)); + sandbox.spy(templates, 'verifyKey').withArgs(ctxMatcher, paramMatcher); + sandbox.spy(templates, 'verifyRemove').withArgs(ctxMatcher, paramMatcher); sendEmailStub = sandbox.stub().returns(Promise.resolve({response: '250'})); sendEmailStub.withArgs(sinon.match(sendOptions => sendOptions.to.address === primaryEmail)); diff --git a/test/integration/email-test.js b/test/integration/email-test.js index b897dda..44f4c39 100644 --- a/test/integration/email-test.js +++ b/test/integration/email-test.js @@ -15,6 +15,8 @@ describe('Email Integration Tests', function() { const recipient = {name: 'Test User', email: 'safewithme.testuser@gmail.com'}; + const ctx = {__: key => key}; + before(() => { publicKeyArmored = require('fs').readFileSync(`${__dirname}/../fixtures/key1.asc`, 'utf8'); origin = { @@ -52,22 +54,22 @@ describe('Email Integration Tests', function() { describe('send verifyKey template', () => { it('should send plaintext email', async () => { delete userId.publicKeyArmored; - await email.send({template: tpl.verifyKey, userId, keyId, origin}); + await email.send({template: tpl.verifyKey.bind(null, ctx), userId, keyId, origin}); }); it('should send pgp encrypted email', async () => { - await email.send({template: tpl.verifyKey, userId, keyId, origin}); + await email.send({template: tpl.verifyKey.bind(null, ctx), userId, keyId, origin}); }); }); describe('send verifyRemove template', () => { it('should send plaintext email', async () => { delete userId.publicKeyArmored; - await email.send({template: tpl.verifyRemove, userId, keyId, origin}); + await email.send({template: tpl.verifyRemove.bind(null, ctx), userId, keyId, origin}); }); it('should send pgp encrypted email', async () => { - await email.send({template: tpl.verifyRemove, userId, keyId, origin}); + await email.send({template: tpl.verifyRemove.bind(null, ctx), userId, keyId, origin}); }); }); }); diff --git a/test/integration/public-key-test.js b/test/integration/public-key-test.js index f34492f..3daff1b 100644 --- a/test/integration/public-key-test.js +++ b/test/integration/public-key-test.js @@ -21,6 +21,7 @@ describe('Public Key Integration Tests', function() { let publicKeyArmored; let publicKeyArmored2; let mailsSent; + const ctx = {__: key => key}; const DB_TYPE = 'publickey'; const primaryEmail = 'test1@example.com'; @@ -44,8 +45,9 @@ describe('Public Key Integration Tests', function() { expect(params.keyId).to.exist; return true; }); - sandbox.spy(templates, 'verifyKey').withArgs(paramMatcher); - sandbox.spy(templates, 'verifyRemove').withArgs(paramMatcher); + const ctxMatcher = sinon.match(context => Boolean(context)); + sandbox.spy(templates, 'verifyKey').withArgs(ctxMatcher, paramMatcher); + sandbox.spy(templates, 'verifyRemove').withArgs(ctxMatcher, paramMatcher); sendEmailStub = sinon.stub().returns(Promise.resolve({response: '250'})); sendEmailStub.withArgs(sinon.match(sendOptions => { @@ -77,22 +79,22 @@ describe('Public Key Integration Tests', function() { describe('put', () => { it('should persist key and send verification email', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); expect(mailsSent.length).to.equal(4); }); it('should work twice if not yet verified', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); expect(mailsSent.length).to.equal(4); - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); expect(mailsSent.length).to.equal(8); }); it.skip('should throw 304 if key already exists', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); await publicKey.verify(mailsSent[0].params); try { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); expect(false).to.be.true; } catch (e) { expect(e.status).to.equal(304); @@ -100,9 +102,9 @@ describe('Public Key Integration Tests', function() { }); it('should work for a key with an existing/verified email address to allow key update without an extra delete step in between', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); await publicKey.verify(mailsSent[1].params); - await publicKey.put({emails: [], publicKeyArmored: publicKeyArmored2, origin}); + await publicKey.put({emails: [], publicKeyArmored: publicKeyArmored2, origin}, ctx); expect(mailsSent.length).to.equal(5); }); }); @@ -150,7 +152,7 @@ describe('Public Key Integration Tests', function() { describe('verify', () => { it('should update the document', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); const emailParams = mailsSent[0].params; await publicKey.verify(emailParams); const gotten = await mongo.get({keyId: emailParams.keyId}, DB_TYPE); @@ -161,7 +163,7 @@ describe('Public Key Integration Tests', function() { }); it('should not find the document', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); const emailParams = mailsSent[0].params; try { await publicKey.verify({keyId: emailParams.keyId, nonce: 'fake_nonce'}); @@ -177,11 +179,11 @@ describe('Public Key Integration Tests', function() { }); it('should verify a second key for an already verified user id and delete the old key', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); await publicKey.verify(mailsSent[1].params); let firstKey = await publicKey.getVerified({keyId: mailsSent[1].params.keyId}); expect(firstKey).to.exist; - await publicKey.put({emails: [], publicKeyArmored: publicKeyArmored2, origin}); + await publicKey.put({emails: [], publicKeyArmored: publicKeyArmored2, origin}, ctx); await publicKey.verify(mailsSent[4].params); firstKey = await publicKey.getVerified({keyId: mailsSent[1].params.keyId}); expect(firstKey).to.not.exist; @@ -190,8 +192,8 @@ describe('Public Key Integration Tests', function() { }); it('should delete other keys with the same user id when verifying', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); - await publicKey.put({emails: [], publicKeyArmored: publicKeyArmored2, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); + await publicKey.put({emails: [], publicKeyArmored: publicKeyArmored2, origin}, ctx); expect(mailsSent[1].to).to.equal(mailsSent[4].to); await publicKey.verify(mailsSent[1].params); const firstKey = await publicKey.getVerified({keyId: mailsSent[1].params.keyId}); @@ -201,7 +203,7 @@ describe('Public Key Integration Tests', function() { }); it('should be able to verify multiple user ids', async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); expect(mailsSent.length).to.equal(4); await publicKey.verify(mailsSent[0].params); await publicKey.verify(mailsSent[1].params); @@ -221,7 +223,7 @@ describe('Public Key Integration Tests', function() { describe('should find a verified key', () => { beforeEach(async () => { key = await pgp.parseKey(publicKeyArmored); - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); await publicKey.verify(mailsSent[0].params); }); @@ -289,51 +291,51 @@ describe('Public Key Integration Tests', function() { let emailParams; beforeEach(async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); emailParams = mailsSent[0].params; }); it('should return verified key by key id', async () => { await publicKey.verify(emailParams); - const key = await publicKey.get({keyId: emailParams.keyId}); + const key = await publicKey.get({keyId: emailParams.keyId}, ctx); expect(key.publicKeyArmored).to.exist; }); it('should return verified key by key id (uppercase)', async () => { await publicKey.verify(emailParams); - const key = await publicKey.get({keyId: emailParams.keyId.toUpperCase()}); + const key = await publicKey.get({keyId: emailParams.keyId.toUpperCase()}, ctx); expect(key.publicKeyArmored).to.exist; }); it('should return verified key by fingerprint', async () => { await publicKey.verify(emailParams); const fingerprint = (await pgp.parseKey(publicKeyArmored)).fingerprint; - const key = await publicKey.get({fingerprint}); + const key = await publicKey.get({fingerprint}, ctx); expect(key.publicKeyArmored).to.exist; }); it('should return verified key by fingerprint (uppercase)', async () => { await publicKey.verify(emailParams); const fingerprint = (await pgp.parseKey(publicKeyArmored)).fingerprint.toUpperCase(); - const key = await publicKey.get({fingerprint}); + const key = await publicKey.get({fingerprint}, ctx); expect(key.publicKeyArmored).to.exist; }); it('should return verified key by email address', async () => { await publicKey.verify(emailParams); - const key = await publicKey.get({email: primaryEmail}); + const key = await publicKey.get({email: primaryEmail}, ctx); expect(key.publicKeyArmored).to.exist; }); it('should return verified key by email address (uppercase)', async () => { await publicKey.verify(emailParams); - const key = await publicKey.get({email: primaryEmail.toUpperCase()}); + const key = await publicKey.get({email: primaryEmail.toUpperCase()}, ctx); expect(key.publicKeyArmored).to.exist; }); it('should throw 404 for unverified key', async () => { try { - await publicKey.get({keyId: emailParams.keyId}); + await publicKey.get({keyId: emailParams.keyId}, ctx); expect(false).to.be.true; } catch (e) { expect(e.status).to.equal(404); @@ -345,30 +347,30 @@ describe('Public Key Integration Tests', function() { let keyId; beforeEach(async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); keyId = mailsSent[0].params.keyId; }); it('should work for verified key', async () => { await publicKey.verify(mailsSent[0].params); - await publicKey.requestRemove({keyId, origin}); + await publicKey.requestRemove({keyId, origin}, ctx); expect(mailsSent.length).to.equal(8); }); it('should work for unverified key', async () => { - await publicKey.requestRemove({keyId, origin}); + await publicKey.requestRemove({keyId, origin}, ctx); expect(mailsSent.length).to.equal(8); }); it('should work by email address', async () => { - await publicKey.requestRemove({email: primaryEmail, origin}); + await publicKey.requestRemove({email: primaryEmail, origin}, ctx); expect(mailsSent.length).to.equal(5); }); it('should throw 404 for no key', async () => { await mongo.remove({keyId}, DB_TYPE); try { - await publicKey.requestRemove({keyId, origin}); + await publicKey.requestRemove({keyId, origin}, ctx); expect(false).to.be.true; } catch (e) { expect(e.status).to.equal(404); @@ -380,7 +382,7 @@ describe('Public Key Integration Tests', function() { let keyId; beforeEach(async () => { - await publicKey.put({emails: [], publicKeyArmored, origin}); + await publicKey.put({emails: [], publicKeyArmored, origin}, ctx); keyId = mailsSent[0].params.keyId; }); @@ -389,7 +391,7 @@ describe('Public Key Integration Tests', function() { }); it('should remove unverified user ID', async () => { - await publicKey.requestRemove({keyId, origin}); + await publicKey.requestRemove({keyId, origin}, ctx); const key = await mongo.get({keyId}, DB_TYPE); expect(key.userIds[0].verified).to.be.false; expect(key.userIds[0].email).to.equal(primaryEmail); @@ -405,7 +407,7 @@ describe('Public Key Integration Tests', function() { expect(key.userIds[0].email).to.equal(primaryEmail); const keyFromArmored = await pgp.parseKey(key.publicKeyArmored); expect(keyFromArmored.userIds.find(userId => userId.email === primaryEmail)).not.to.be.undefined; - await publicKey.requestRemove({keyId, origin}); + await publicKey.requestRemove({keyId, origin}, ctx); await publicKey.verifyRemove(mailsSent[4].params); const modifiedKey = await mongo.get({keyId}, DB_TYPE); expect(modifiedKey.userIds[0].email).to.not.equal(primaryEmail); @@ -421,7 +423,7 @@ describe('Public Key Integration Tests', function() { const emails = [key.userIds[0].email, key.userIds[1].email]; const keyFromArmored = await pgp.parseKey(key.publicKeyArmored); expect(keyFromArmored.userIds.filter(userId => emails.includes(userId.email)).length).to.equal(2); - await publicKey.requestRemove({keyId, origin}); + await publicKey.requestRemove({keyId, origin}, ctx); await publicKey.verifyRemove(mailsSent[5].params); const modifiedKey = await mongo.get({keyId}, DB_TYPE); expect(modifiedKey.userIds[0].email).to.equal(emails[0]); @@ -432,7 +434,7 @@ describe('Public Key Integration Tests', function() { }); it('should remove key', async () => { - await publicKey.requestRemove({keyId, origin}); + await publicKey.requestRemove({keyId, origin}, ctx); await publicKey.verifyRemove(mailsSent[4].params); await publicKey.verifyRemove(mailsSent[5].params); await publicKey.verifyRemove(mailsSent[6].params);