From a60d8b86a9e1f731819e20d2c815b84f1479a6e2 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Tue, 14 Jun 2016 12:10:53 +0200 Subject: [PATCH] Cleanup REST api and use 'op' query param for verbs --- README.md | 14 +++-------- src/app.js | 16 +----------- src/email/templates.json | 8 +++--- src/route/rest.js | 29 ++++++++++++--------- src/static/demo.html | 3 ++- test/integration/app-test.js | 49 ++++++++++++------------------------ 6 files changed, 43 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 9eb937e..af7f93a 100644 --- a/README.md +++ b/README.md @@ -131,27 +131,19 @@ POST /api/v1/key ### Verify uploaded key ``` -GET /api/v1/verify?keyId=b8e4105cc9dedc77&nonce=6a314915c09368224b11df0feedbc53c +GET /api/v1/key?op=verify&keyId=b8e4105cc9dedc77&nonce=6a314915c09368224b11df0feedbc53c ``` ### Request key removal -#### Via delete request - ``` -DELETE /api/v1/key?keyId=b8e4105cc9dedc77 OR ?email=user@example.com -``` - -#### Via link - -``` -GET /api/v1/removeKey?keyId=b8e4105cc9dedc77 OR ?email=user@example.com +GET /api/v1/key?op=remove&keyId=b8e4105cc9dedc77 OR ?email=user@example.com ``` ### Verify key removal ``` -GET /api/v1/verifyRemove?keyId=b8e4105cc9dedc77&nonce=6a314915c09368224b11df0feedbc53c +GET /api/v1/key?op=verifyRemove&keyId=b8e4105cc9dedc77&nonce=6a314915c09368224b11df0feedbc53c ``` diff --git a/src/app.js b/src/app.js index ba304f8..5353ede 100644 --- a/src/app.js +++ b/src/app.js @@ -49,21 +49,7 @@ router.post('/api/v1/key', function *() { yield rest.create(this); }); router.get('/api/v1/key', function *() { - yield rest.read(this); -}); -router.del('/api/v1/key', function *() { - yield rest.remove(this); -}); - -// links for verification, removal and sharing -router.get('/api/v1/verify', function *() { - yield rest.verify(this); -}); -router.get('/api/v1/removeKey', function *() { - yield rest.remove(this); -}); -router.get('/api/v1/verifyRemove', function *() { - yield rest.verifyRemove(this); + yield rest.query(this); }); // Redirect all http traffic to https diff --git a/src/email/templates.json b/src/email/templates.json index a04f26b..533a707 100644 --- a/src/email/templates.json +++ b/src/email/templates.json @@ -1,12 +1,12 @@ { "verifyKey": { "subject": "Verify Your Key", - "text": "Hello {{name}},\n\nplease click here to verify your key:\n\n{{baseUrl}}/api/v1/verify?keyId={{keyId}}&nonce={{nonce}}", - "html": "

Hello {{name}},

please click here to verify your key.

" + "text": "Hello {{name}},\n\nplease click here to verify your key:\n\n{{baseUrl}}/api/v1/key?op=verify&keyId={{keyId}}&nonce={{nonce}}", + "html": "

Hello {{name}},

please click here to verify your key.

" }, "verifyRemove": { "subject": "Verify Key Removal", - "text": "Hello {{name}},\n\nplease click here to verify the removal of your key:\n\n{{baseUrl}}/api/v1/verifyRemove?keyId={{keyId}}&nonce={{nonce}}", - "html": "

Hello {{name}},

please click here to verify the removal of your key.

" + "text": "Hello {{name}},\n\nplease click here to verify the removal of your key:\n\n{{baseUrl}}/api/v1/key?op=verifyRemove&keyId={{keyId}}&nonce={{nonce}}", + "html": "

Hello {{name}},

please click here to verify the removal of your key.

" } } \ No newline at end of file diff --git a/src/route/rest.js b/src/route/rest.js index c6171f9..18adcf6 100644 --- a/src/route/rest.js +++ b/src/route/rest.js @@ -50,6 +50,23 @@ class REST { ctx.status = 201; } + /** + * Public key query via http GET + * @param {Object} ctx The koa request/response context + */ + *query(ctx) { + let op = ctx.query.op; + if (this[op]) { + return yield this[op](ctx); // delegate operation + } + // do READ if no 'op' provided + let q = { keyId:ctx.query.keyId, fingerprint:ctx.query.fingerprint, email:ctx.query.email }; + if (!util.isKeyId(q.keyId) && !util.isFingerPrint(q.fingerprint) && !util.isEmail(q.email)) { + ctx.throw(400, 'Invalid request!'); + } + ctx.body = yield this._publicKey.get(q); + } + /** * Verify a public key's user id via http GET * @param {Object} ctx The koa request/response context @@ -66,18 +83,6 @@ class REST { ctx.set('Content-Type', 'text/html; charset=utf-8'); } - /** - * Public key fetch via http GET - * @param {Object} ctx The koa request/response context - */ - *read(ctx) { - let q = { keyId:ctx.query.keyId, fingerprint:ctx.query.fingerprint, email:ctx.query.email }; - if (!util.isKeyId(q.keyId) && !util.isFingerPrint(q.fingerprint) && !util.isEmail(q.email)) { - ctx.throw(400, 'Invalid request!'); - } - ctx.body = yield this._publicKey.get(q); - } - /** * Request public key removal via http DELETE * @param {Object} ctx The koa request/response context diff --git a/src/static/demo.html b/src/static/demo.html index bcc2646..cda176e 100644 --- a/src/static/demo.html +++ b/src/static/demo.html @@ -53,7 +53,8 @@

OpenPGP key removal

-
+ +
diff --git a/test/integration/app-test.js b/test/integration/app-test.js index 743387a..e511c74 100644 --- a/test/integration/app-test.js +++ b/test/integration/app-test.js @@ -97,7 +97,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() { }); }); - describe('GET /api/v1/verify', () => { + describe('GET /api/v1/key?op=verify', () => { beforeEach(done => { request(app.listen()) .post('/api/v1/key') @@ -108,21 +108,21 @@ describe('Koa App (HTTP Server) Integration Tests', function() { it('should return 200 for valid params', done => { request(app.listen()) - .get('/api/v1/verify?keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) + .get('/api/v1/key?op=verify&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) .expect(200) .end(done); }); it('should return 400 for missing keyid and', done => { request(app.listen()) - .get('/api/v1/verify?nonce=' + emailParams.nonce) + .get('/api/v1/key?op=verify&nonce=' + emailParams.nonce) .expect(400) .end(done); }); it('should return 400 for missing nonce', done => { request(app.listen()) - .get('/api/v1/verify?keyId=' + emailParams.keyId) + .get('/api/v1/key?op=verify&keyId=' + emailParams.keyId) .expect(400) .end(done); }); @@ -148,7 +148,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() { describe('Verified', () => { beforeEach(done => { request(app.listen()) - .get('/api/v1/verify?keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) + .get('/api/v1/key?op=verify&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) .expect(200) .end(done); }); @@ -190,7 +190,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() { }); }); - describe('DELETE /api/v1/key', () => { + describe('GET /api/v1/key?op=remove', () => { beforeEach(done => { request(app.listen()) .post('/api/v1/key') @@ -201,51 +201,34 @@ describe('Koa App (HTTP Server) Integration Tests', function() { it('should return 202 for key id', done => { request(app.listen()) - .del('/api/v1/key?keyId=' + emailParams.keyId) + .get('/api/v1/key?op=remove&keyId=' + emailParams.keyId) .expect(202) .end(done); }); it('should return 202 for email address', done => { request(app.listen()) - .del('/api/v1/key?email=' + primaryEmail) + .get('/api/v1/key?op=remove&email=' + primaryEmail) .expect(202) .end(done); }); it('should return 400 for invalid params', done => { request(app.listen()) - .del('/api/v1/key') + .get('/api/v1/key?op=remove') .expect(400) .end(done); }); it('should return 404 for unknown email address', done => { request(app.listen()) - .del('/api/v1/key?email=a@foo.com') + .get('/api/v1/key?op=remove&email=a@foo.com') .expect(404) .end(done); }); }); - describe('GET /api/v1/removeKey', () => { - beforeEach(done => { - request(app.listen()) - .post('/api/v1/key') - .send({ publicKeyArmored, primaryEmail }) - .expect(201) - .end(done); - }); - - it('should return 202 for key id', done => { - request(app.listen()) - .get('/api/v1/removeKey?keyId=' + emailParams.keyId) - .expect(202) - .end(done); - }); - }); - - describe('GET /api/v1/verifyRemove', () => { + describe('GET /api/v1/key?op=verifyRemove', () => { beforeEach(done => { request(app.listen()) .post('/api/v1/key') @@ -253,7 +236,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() { .expect(201) .end(function() { request(app.listen()) - .del('/api/v1/key?keyId=' + emailParams.keyId) + .get('/api/v1/key?op=remove&keyId=' + emailParams.keyId) .expect(202) .end(done); }); @@ -261,21 +244,21 @@ describe('Koa App (HTTP Server) Integration Tests', function() { it('should return 200 for key id', done => { request(app.listen()) - .get('/api/v1/verifyRemove?keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) + .get('/api/v1/key?op=verifyRemove&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) .expect(200) .end(done); }); it('should return 400 for invalid params', done => { request(app.listen()) - .get('/api/v1/verifyRemove') + .get('/api/v1/key?op=verifyRemove') .expect(400) .end(done); }); it('should return 404 for unknown key id', done => { request(app.listen()) - .get('/api/v1/verifyRemove?keyId=0123456789ABCDEF&nonce=' + emailParams.nonce) + .get('/api/v1/key?op=verifyRemove&keyId=0123456789ABCDEF&nonce=' + emailParams.nonce) .expect(404) .end(done); }); @@ -325,7 +308,7 @@ describe('Koa App (HTTP Server) Integration Tests', function() { describe('Verified', () => { beforeEach(done => { request(app.listen()) - .get('/api/v1/verify?keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) + .get('/api/v1/key?op=verify&keyId=' + emailParams.keyId + '&nonce=' + emailParams.nonce) .expect(200) .end(done); });