Implement public-key requestRemove and verifyRemove
This commit is contained in:
parent
33d3ad737e
commit
0f4f6413d6
2
index.js
2
index.js
@ -29,7 +29,7 @@ log.level = config.log.level; // set log level depending on process.env.NODE_ENV
|
|||||||
//
|
//
|
||||||
|
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
for (var i = 0; i < numCPUs; i++) {
|
for (let i = 0; i < numCPUs; i++) {
|
||||||
cluster.fork();
|
cluster.fork();
|
||||||
}
|
}
|
||||||
cluster.on('fork', worker => log.info('cluster', 'Forked worker #%s [pid:%s]', worker.id, worker.process.pid));
|
cluster.on('fork', worker => log.info('cluster', 'Forked worker #%s [pid:%s]', worker.id, worker.process.pid));
|
||||||
|
@ -25,7 +25,7 @@ const router = require('koa-router')();
|
|||||||
const openpgp = require('openpgp');
|
const openpgp = require('openpgp');
|
||||||
const nodemailer = require('nodemailer');
|
const nodemailer = require('nodemailer');
|
||||||
const Mongo = require('./dao/mongo');
|
const Mongo = require('./dao/mongo');
|
||||||
const Email = require('./dao/email');
|
const Email = require('./email/email');
|
||||||
const UserId = require('./service/user-id');
|
const UserId = require('./service/user-id');
|
||||||
const PublicKey = require('./service/public-key');
|
const PublicKey = require('./service/public-key');
|
||||||
const HKP = require('./route/hkp');
|
const HKP = require('./route/hkp');
|
||||||
|
@ -40,11 +40,10 @@ class REST {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*create(ctx) {
|
*create(ctx) {
|
||||||
let body = yield parse.json(ctx, { limit: '1mb' });
|
let q = yield parse.json(ctx, { limit: '1mb' });
|
||||||
let primaryEmail = body.primaryEmail;
|
let publicKeyArmored = q.publicKeyArmored, primaryEmail = q.primaryEmail;
|
||||||
let publicKeyArmored = body.publicKeyArmored;
|
if (!util.validatePublicKey(publicKeyArmored) ||
|
||||||
if ((primaryEmail && !util.validateAddress(primaryEmail)) ||
|
(primaryEmail && !util.validateAddress(primaryEmail))) {
|
||||||
!util.validatePublicKey(publicKeyArmored)) {
|
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
let origin = util.getOrigin(ctx);
|
let origin = util.getOrigin(ctx);
|
||||||
@ -58,7 +57,7 @@ class REST {
|
|||||||
*/
|
*/
|
||||||
*verify(ctx) {
|
*verify(ctx) {
|
||||||
let q = { keyid:ctx.query.keyid, nonce:ctx.query.nonce };
|
let q = { keyid:ctx.query.keyid, nonce:ctx.query.nonce };
|
||||||
if (!util.validateKeyId(q.keyid) && !util.isString(q.nonce)) {
|
if (!util.validateKeyId(q.keyid) || !util.isString(q.nonce)) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
yield this._userId.verify(q);
|
yield this._userId.verify(q);
|
||||||
@ -88,14 +87,28 @@ class REST {
|
|||||||
ctx.body = (yield this._publicKey.get(q)).publicKeyArmored;
|
ctx.body = (yield this._publicKey.get(q)).publicKeyArmored;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request public key removal via http DELETE
|
||||||
|
* @param {Object} ctx The koa request/response context
|
||||||
|
*/
|
||||||
*remove(ctx) {
|
*remove(ctx) {
|
||||||
ctx.throw(501, 'Not implemented!');
|
let q = { keyid:ctx.query.keyid, email:ctx.query.email, origin:util.getOrigin(ctx) };
|
||||||
yield;
|
if (!util.validateKeyId(q.keyid) && !util.validateAddress(q.email)) {
|
||||||
|
ctx.throw(400, 'Invalid request!');
|
||||||
|
}
|
||||||
|
yield this._publicKey.requestRemove(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify public key removal via http GET
|
||||||
|
* @param {Object} ctx The koa request/response context
|
||||||
|
*/
|
||||||
*verifyRemove(ctx) {
|
*verifyRemove(ctx) {
|
||||||
ctx.throw(501, 'Not implemented!');
|
let q = { keyid:ctx.query.keyid, nonce:ctx.query.nonce };
|
||||||
yield;
|
if (!util.validateKeyId(q.keyid) || !util.isString(q.nonce)) {
|
||||||
|
ctx.throw(400, 'Invalid request!');
|
||||||
|
}
|
||||||
|
yield this._publicKey.verifyRemove(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
const log = require('npmlog');
|
const log = require('npmlog');
|
||||||
const util = require('./util');
|
const util = require('./util');
|
||||||
|
const tpl = require('../email/templates.json');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database documents have the format:
|
* Database documents have the format:
|
||||||
@ -76,7 +77,13 @@ class PublicKey {
|
|||||||
util.throw(500, 'Failed to persist key');
|
util.throw(500, 'Failed to persist key');
|
||||||
}
|
}
|
||||||
// send mails to verify user ids (send only one if primary email is provided)
|
// send mails to verify user ids (send only one if primary email is provided)
|
||||||
yield this._email.sendVerifyKey({ userIds, primaryEmail, origin });
|
let primaryUserId = userIds.find(uid => uid.email === primaryEmail);
|
||||||
|
if (primaryUserId) {
|
||||||
|
userIds = [primaryUserId];
|
||||||
|
}
|
||||||
|
for (let userId of userIds) {
|
||||||
|
yield this._email.send({ template:tpl.verifyKey, userId, origin });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,10 +109,6 @@ class PublicKey {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
verify() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a verified public key from the database. Either the key id or the
|
* Fetch a verified public key from the database. Either the key id or the
|
||||||
* email address muss be provided.
|
* email address muss be provided.
|
||||||
@ -125,12 +128,38 @@ class PublicKey {
|
|||||||
return yield this._mongo.get({ _id:verified.keyid }, DB_TYPE);
|
return yield this._mongo.get({ _id:verified.keyid }, DB_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
flagForRemove() {
|
/**
|
||||||
|
* Request removal of the public key by flagging all user ids and sending
|
||||||
|
* a verification email to the primary email address. Only one email
|
||||||
|
* needs to sent to a single user id to authenticate removal of all user ids
|
||||||
|
* that belong the a certain key id.
|
||||||
|
* @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' }
|
||||||
|
* @yield {undefined}
|
||||||
|
*/
|
||||||
|
*requestRemove(options) {
|
||||||
|
let keyid = options.keyid, email = options.email, origin = options.origin;
|
||||||
|
let userIds = yield this._userid.flagForRemove({ keyid, email }, DB_TYPE);
|
||||||
|
for (let userId of userIds) {
|
||||||
|
yield this._email.send({ template:tpl.verifyRemove, userId, origin });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
verifyRemove() {
|
/**
|
||||||
|
* Verify the removal of the user's key id by proving knowledge of the nonce.
|
||||||
|
* Also deletes all user id documents of that key id.
|
||||||
|
* @param {string} keyid public key id
|
||||||
|
* @param {string} nonce The verification nonce proving email address ownership
|
||||||
|
* @yield {undefined}
|
||||||
|
*/
|
||||||
|
*verifyRemove(options) {
|
||||||
|
let keyid = options.keyid, nonce = options.nonce;
|
||||||
|
let flagged = yield this._userId.getFlaggedForRemove({ keyid, nonce });
|
||||||
|
if (!flagged) {
|
||||||
|
util.throw(404, 'User id not found');
|
||||||
|
}
|
||||||
|
yield this.remove({ keyid });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,10 +168,11 @@ class PublicKey {
|
|||||||
* @yield {undefined}
|
* @yield {undefined}
|
||||||
*/
|
*/
|
||||||
*remove(options) {
|
*remove(options) {
|
||||||
|
let keyid = options.keyid;
|
||||||
// remove key document
|
// remove key document
|
||||||
yield this._mongo.remove({ _id:options.keyid }, DB_TYPE);
|
yield this._mongo.remove({ _id:keyid }, DB_TYPE);
|
||||||
// remove matching user id documents
|
// remove matching user id documents
|
||||||
yield this._userid.remove({ keyid:options.keyid });
|
yield this._userid.remove({ keyid });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user