Merge pull request #45 from mailvelope/dev/remove-primaryEmail-param

Dev/remove primary email param
This commit is contained in:
Tankred Hase 2017-08-24 14:13:26 +08:00 committed by GitHub
commit 2b969c0382
5 changed files with 36 additions and 71 deletions

View File

@ -124,13 +124,11 @@ POST /api/v1/key
```json
{
"publicKeyArmored": "-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----",
"primaryEmail": "user@example.com"
"publicKeyArmored": "-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----"
}
```
* **publicKeyArmored**: The ascii armored public PGP key to be uploaded
* **primaryEmail (optional)**: The ascii armored block is parsed to check for user ids, so this parameter is purely optional. Normally a verification email is sent to every user id found in the pgp key. To prevent this behaviour, user agents can specify the user's primary email address to send out only one email.
### Verify uploaded key (via link in email)

View File

@ -37,12 +37,12 @@ class REST {
* @param {Object} ctx The koa request/response context
*/
async create(ctx) {
const {publicKeyArmored, primaryEmail} = ctx.request.body;
if (!publicKeyArmored || (primaryEmail && !util.isEmail(primaryEmail))) {
const {publicKeyArmored} = ctx.request.body;
if (!publicKeyArmored) {
ctx.throw(400, 'Invalid request!');
}
const origin = util.origin(ctx);
await this._publicKey.put({publicKeyArmored, primaryEmail, origin});
await this._publicKey.put({publicKeyArmored, origin});
ctx.body = 'Upload successful. Check your inbox to verify your email address.';
ctx.status = 201;
}

View File

@ -36,6 +36,7 @@ const tpl = require('../email/templates.json');
* }
* ],
* created: Sat Oct 17 2015 12:17:03 GMT+0200 (CEST), // key creation time as JavaScript Date
* uploaded: Sat Oct 17 2015 12:17:03 GMT+0200 (CEST), // time of key upload as JavaScript Date
* algorithm: 'rsa_encrypt_sign', // primary key alogrithm
* keySize: 4096, // key length in bits
* publicKeyArmored: '-----BEGIN PGP PUBLIC KEY BLOCK----- ... -----END PGP PUBLIC KEY BLOCK-----'
@ -62,11 +63,10 @@ class PublicKey {
/**
* Persist a new public key
* @param {String} publicKeyArmored The ascii armored pgp key block
* @param {String} primaryEmail (optional) The key's primary email address
* @param {Object} origin Required for links to the keyserver e.g. { protocol:'https', host:'openpgpkeys@example.com' }
* @yield {undefined}
*/
async put({publicKeyArmored, primaryEmail, origin}) {
async put({publicKeyArmored, origin}) {
// lazily purge old/unverified keys on every key upload
await this._purgeOldUnverified();
// parse key block
@ -79,7 +79,7 @@ class PublicKey {
// store key in database
await this._persisKey(key);
// send mails to verify user ids (send only one if primary email is provided)
await this._sendVerifyEmail(key, primaryEmail, origin);
await this._sendVerifyEmail(key, origin);
}
/**
@ -121,17 +121,10 @@ class PublicKey {
* Send verification emails to the public keys user ids for verification.
* If a primary email address is provided only one email will be sent.
* @param {Array} userIds user id documents containg the verification nonces
* @param {string} primaryEmail the public key's primary email address
* @param {Object} origin the server's origin (required for email links)
* @yield {undefined}
*/
async _sendVerifyEmail({userIds, keyId, publicKeyArmored}, primaryEmail, origin) {
// check for primary email (send only one email)
const primaryUserId = userIds.find(uid => uid.email === primaryEmail);
if (primaryUserId) {
userIds = [primaryUserId];
}
// send emails
async _sendVerifyEmail({userIds, keyId, publicKeyArmored}, origin) {
for (const userId of userIds) {
userId.publicKeyArmored = publicKeyArmored; // set key for encryption
await this._email.send({template: tpl.verifyKey, userId, keyId, origin});

View File

@ -68,26 +68,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
.end(done);
});
it('should return 400 for an invalid primaryEmail', done => {
request(app.listen())
.post('/api/v1/key')
.send({publicKeyArmored, primaryEmail: 'foo'})
.expect(400)
.end(done);
});
it('should return 201 with primaryEmail', done => {
request(app.listen())
.post('/api/v1/key')
.send({publicKeyArmored, primaryEmail})
.expect(201)
.end(() => {
expect(emailParams).to.exist;
done();
});
});
it('should return 201 without primaryEmail', done => {
it('should return 201', done => {
request(app.listen())
.post('/api/v1/key')
.send({publicKeyArmored})
@ -103,7 +84,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
beforeEach(done => {
request(app.listen())
.post('/api/v1/key')
.send({publicKeyArmored, primaryEmail})
.send({publicKeyArmored})
.expect(201)
.end(done);
});
@ -134,7 +115,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
beforeEach(done => {
request(app.listen())
.post('/api/v1/key')
.send({publicKeyArmored, primaryEmail})
.send({publicKeyArmored})
.expect(201)
.end(done);
});
@ -196,7 +177,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
beforeEach(done => {
request(app.listen())
.post('/api/v1/key')
.send({publicKeyArmored, primaryEmail})
.send({publicKeyArmored})
.expect(201)
.end(done);
});
@ -234,7 +215,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() {
beforeEach(done => {
request(app.listen())
.post('/api/v1/key')
.send({publicKeyArmored, primaryEmail})
.send({publicKeyArmored})
.expect(201)
.end(() => {
request(app.listen())

View File

@ -73,30 +73,23 @@ describe('Public Key Integration Tests', function() {
});
describe('put', () => {
it('should persist key and send verification email with primaryEmail', async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
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;
});
it('should persist key and send verification email without primaryEmail', async () => {
it('should persist key and send verification email', async () => {
await publicKey.put({publicKeyArmored, origin});
expect(mailsSent.length).to.equal(4);
});
it('should work twice if not yet verified', async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
expect(mailsSent.length).to.equal(1);
await publicKey.put({publicKeyArmored, primaryEmail, origin});
expect(mailsSent.length).to.equal(2);
await publicKey.put({publicKeyArmored, origin});
expect(mailsSent.length).to.equal(4);
await publicKey.put({publicKeyArmored, origin});
expect(mailsSent.length).to.equal(8);
});
it('should throw 304 if key already exists', async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
await publicKey.verify(mailsSent[0].params);
try {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
expect(false).to.be.true;
} catch (e) {
expect(e.status).to.equal(304);
@ -147,7 +140,7 @@ describe('Public Key Integration Tests', function() {
describe('verify', () => {
it('should update the document', async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
const emailParams = mailsSent[0].params;
await publicKey.verify(emailParams);
const gotten = await mongo.get({keyId: emailParams.keyId}, DB_TYPE);
@ -158,7 +151,7 @@ describe('Public Key Integration Tests', function() {
});
it('should not find the document', async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
const emailParams = mailsSent[0].params;
try {
await publicKey.verify({keyId: emailParams.keyId, nonce: 'fake_nonce'});
@ -174,11 +167,11 @@ describe('Public Key Integration Tests', function() {
});
it('should not verify a second key for already verified user id of another key', async () => {
await publicKey.put({publicKeyArmored, primaryEmail: primaryEmail2, origin});
expect(mailsSent.length).to.equal(1);
await publicKey.put({publicKeyArmored: publicKeyArmored2, primaryEmail: primaryEmail2, origin});
expect(mailsSent.length).to.equal(2);
await publicKey.verify(mailsSent[1].params);
await publicKey.put({publicKeyArmored, origin});
expect(mailsSent.length).to.equal(4);
await publicKey.put({publicKeyArmored: publicKeyArmored2, origin});
expect(mailsSent.length).to.equal(5);
await publicKey.verify(mailsSent[4].params);
try {
await publicKey.verify(mailsSent[0].params);
@ -189,7 +182,7 @@ describe('Public Key Integration Tests', function() {
const gotten = await 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);
expect(gotten.userIds[1].nonce).to.equal(mailsSent[1].params.nonce);
});
it('should be able to verify multiple user ids', async () => {
@ -213,7 +206,7 @@ describe('Public Key Integration Tests', function() {
describe('should find a verified key', () => {
beforeEach(async () => {
key = pgp.parseKey(publicKeyArmored);
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
await publicKey.verify(mailsSent[0].params);
});
@ -281,7 +274,7 @@ describe('Public Key Integration Tests', function() {
let emailParams;
beforeEach(async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
emailParams = mailsSent[0].params;
});
@ -337,24 +330,24 @@ describe('Public Key Integration Tests', function() {
let keyId;
beforeEach(async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
keyId = mailsSent[0].params.keyId;
});
it('should work for verified key', async () => {
await publicKey.verify(mailsSent[0].params);
await publicKey.requestRemove({keyId, origin});
expect(mailsSent.length).to.equal(5);
expect(mailsSent.length).to.equal(8);
});
it('should work for unverified key', async () => {
await publicKey.requestRemove({keyId, origin});
expect(mailsSent.length).to.equal(5);
expect(mailsSent.length).to.equal(8);
});
it('should work by email address', async () => {
await publicKey.requestRemove({email: primaryEmail, origin});
expect(mailsSent.length).to.equal(2);
expect(mailsSent.length).to.equal(5);
});
it('should throw 404 for no key', async () => {
@ -372,13 +365,13 @@ describe('Public Key Integration Tests', function() {
let keyId;
beforeEach(async () => {
await publicKey.put({publicKeyArmored, primaryEmail, origin});
await publicKey.put({publicKeyArmored, origin});
keyId = mailsSent[0].params.keyId;
await publicKey.requestRemove({keyId, origin});
});
it('should remove key', async () => {
await publicKey.verifyRemove(mailsSent[1].params);
await publicKey.verifyRemove(mailsSent[4].params);
const key = await mongo.get({keyId}, DB_TYPE);
expect(key).to.not.exist;
});