Cleanup url handling
This commit is contained in:
parent
405bb84ca6
commit
d5bd65b4bc
@ -2,6 +2,10 @@ module.exports = {
|
|||||||
|
|
||||||
log: {
|
log: {
|
||||||
level: 'error'
|
level: 'error'
|
||||||
}
|
},
|
||||||
|
|
||||||
|
server: {
|
||||||
|
upgradeHTTP: true
|
||||||
|
},
|
||||||
|
|
||||||
};
|
};
|
@ -22,6 +22,7 @@ const app = require('koa')();
|
|||||||
const log = require('npmlog');
|
const log = require('npmlog');
|
||||||
const config = require('config');
|
const config = require('config');
|
||||||
const router = require('koa-router')();
|
const router = require('koa-router')();
|
||||||
|
const util = require('./service/util');
|
||||||
const Mongo = require('./dao/mongo');
|
const Mongo = require('./dao/mongo');
|
||||||
const Email = require('./email/email');
|
const Email = require('./email/email');
|
||||||
const PGP = require('./service/pgp');
|
const PGP = require('./service/pgp');
|
||||||
@ -85,7 +86,7 @@ app.use(function *(next) {
|
|||||||
|
|
||||||
// Redirect all http traffic to https
|
// Redirect all http traffic to https
|
||||||
app.use(function *(next) {
|
app.use(function *(next) {
|
||||||
if (process.env.NODE_ENV === 'production' && !this.secure && this.get('X-Forwarded-Proto') === 'http') {
|
if (config.server.upgradeHTTP && util.checkHTTP(this)) {
|
||||||
this.redirect('https://' + this.hostname + this.url);
|
this.redirect('https://' + this.hostname + this.url);
|
||||||
} else {
|
} else {
|
||||||
yield next;
|
yield next;
|
||||||
|
@ -69,7 +69,7 @@ class Email {
|
|||||||
html: template.html,
|
html: template.html,
|
||||||
params: {
|
params: {
|
||||||
name: userId.name,
|
name: userId.name,
|
||||||
baseUrl: origin.protocol + '://' + origin.host,
|
baseUrl: util.url(origin),
|
||||||
keyId: encodeURIComponent(keyId),
|
keyId: encodeURIComponent(keyId),
|
||||||
nonce: encodeURIComponent(userId.nonce)
|
nonce: encodeURIComponent(userId.nonce)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ class HKP {
|
|||||||
if (!publicKeyArmored) {
|
if (!publicKeyArmored) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
let origin = util.getOrigin(ctx);
|
let origin = util.origin(ctx);
|
||||||
yield this._publicKey.put({ publicKeyArmored, origin });
|
yield this._publicKey.put({ publicKeyArmored, origin });
|
||||||
ctx.status = 201;
|
ctx.status = 201;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,34 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const util = require('../service/util');
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
let tls = this.secure || process.env.NODE_ENV === 'production' && this.get('X-Forwarded-Proto') === 'https';
|
let hkpLink = util.hkpUrl(this);
|
||||||
let hkp = (tls ? 'hkps://' : 'hkp://') + this.host;
|
let removeLink = util.url(util.origin(this), '/api/v1/removeKey?email=user@example.com');
|
||||||
let del = (tls ? 'https://' : 'http://') + this.host + '/api/v1/removeKey?email=user@example.com';
|
|
||||||
this.body =
|
this.body =
|
||||||
`
|
`
|
||||||
<h1>Welcome to the OpenPGP key server</h1>
|
<!DOCTYPE html>
|
||||||
<p>This server verifies email address as well as private key ownership by sending an encrypted verification email.</p>
|
<html>
|
||||||
<h2>Try it out</h2>
|
<head>
|
||||||
<ol>
|
<meta charset="utf-8">
|
||||||
<li>Configure this key server in your HKP compatible OpenPGP client using this url: <a href="${hkp}" target="_blank">${hkp}</a></li>
|
<title>OpenPGP key server</title>
|
||||||
<li>Now just upload a public key like you always do.</li>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||||
<li>Check your inbox and click on the verification link inside the encrypted message.</li>
|
</head>
|
||||||
<li>You can delete all your data from the server at any time using this link: <a href="${del}" target="_blank">${del}</a></li>
|
<body>
|
||||||
</ol>
|
<h1>Welcome to the OpenPGP key server</h1>
|
||||||
<h2>Documentation and code</h2>
|
<p>This server verifies email address as well as private key ownership by sending an encrypted verification email.</p>
|
||||||
<p>Please refer to <a href="https://github.com/mailvelope/keyserver" target="_blank">the documentation</a> to learn more about the api.</p>
|
<h2>Try it out</h2>
|
||||||
<p>License AGPL v3.0</p>
|
<ol>
|
||||||
|
<li>Configure this key server in your HKP compatible OpenPGP client using this url: <a href="${hkpLink}" target="_blank">${hkpLink}</a></li>
|
||||||
|
<li>Now just upload a public key like you always do.</li>
|
||||||
|
<li>Check your inbox and click on the verification link inside the encrypted message.</li>
|
||||||
|
<li>You can delete all your data from the server at any time using this link: <a href="${removeLink}" target="_blank">${removeLink}</a></li>
|
||||||
|
</ol>
|
||||||
|
<h2>Documentation and code</h2>
|
||||||
|
<p>Please refer to <a href="https://github.com/mailvelope/keyserver" target="_blank">the documentation</a> to learn more about the api.</p>
|
||||||
|
<p>License AGPL v3.0</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
this.set('Content-Type', 'text/html; charset=utf-8');
|
this.set('Content-Type', 'text/html; charset=utf-8');
|
||||||
|
@ -44,7 +44,7 @@ class REST {
|
|||||||
if (!publicKeyArmored || (primaryEmail && !util.isEmail(primaryEmail))) {
|
if (!publicKeyArmored || (primaryEmail && !util.isEmail(primaryEmail))) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
let origin = util.getOrigin(ctx);
|
let origin = util.origin(ctx);
|
||||||
yield this._publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
yield this._publicKey.put({ publicKeyArmored, primaryEmail, origin });
|
||||||
ctx.status = 201;
|
ctx.status = 201;
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ class REST {
|
|||||||
* @param {Object} ctx The koa request/response context
|
* @param {Object} ctx The koa request/response context
|
||||||
*/
|
*/
|
||||||
*remove(ctx) {
|
*remove(ctx) {
|
||||||
let q = { keyId:ctx.query.keyId, email:ctx.query.email, origin:util.getOrigin(ctx) };
|
let q = { keyId:ctx.query.keyId, email:ctx.query.email, origin:util.origin(ctx) };
|
||||||
if (!util.isKeyId(q.keyId) && !util.isEmail(q.email)) {
|
if (!util.isKeyId(q.keyId) && !util.isEmail(q.email)) {
|
||||||
ctx.throw(400, 'Invalid request!');
|
ctx.throw(400, 'Invalid request!');
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,25 @@ exports.random = function(bytes) {
|
|||||||
return crypto.randomBytes(bytes).toString('hex');
|
return crypto.randomBytes(bytes).toString('hex');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user is connecting over a plaintext http connection.
|
||||||
|
* This can be used as an indicator to upgrade their connection to https.
|
||||||
|
* @param {Object} ctx The koa request/repsonse context
|
||||||
|
* @return {boolean} If http is used
|
||||||
|
*/
|
||||||
|
exports.checkHTTP = function(ctx) {
|
||||||
|
return !ctx.secure && ctx.get('X-Forwarded-Proto') === 'http';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user is connecting over a https connection.
|
||||||
|
* @param {Object} ctx The koa request/repsonse context
|
||||||
|
* @return {boolean} If https is used
|
||||||
|
*/
|
||||||
|
exports.checkHTTPS = function(ctx) {
|
||||||
|
return ctx.secure || ctx.get('X-Forwarded-Proto') === 'https';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the server's own origin host and protocol. Required for sending
|
* Get the server's own origin host and protocol. Required for sending
|
||||||
* verification links via email. If the PORT environmane variable
|
* verification links via email. If the PORT environmane variable
|
||||||
@ -110,9 +129,29 @@ exports.random = function(bytes) {
|
|||||||
* @param {Object} ctx The koa request/repsonse context
|
* @param {Object} ctx The koa request/repsonse context
|
||||||
* @return {Object} The server origin
|
* @return {Object} The server origin
|
||||||
*/
|
*/
|
||||||
exports.getOrigin = function(ctx) {
|
exports.origin = function(ctx) {
|
||||||
return {
|
return {
|
||||||
protocol: process.env.PORT ? 'https' : ctx.protocol,
|
protocol: this.checkHTTPS(ctx) ? 'https' : ctx.protocol,
|
||||||
host: ctx.host
|
host: ctx.host
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to create urls pointing to this server
|
||||||
|
* @param {Object} origin The server's origin
|
||||||
|
* @param {string} resource (optional) The resource to point to
|
||||||
|
* @return {string} The complete url
|
||||||
|
*/
|
||||||
|
exports.url = function(origin, resource) {
|
||||||
|
return origin.protocol + '://' + origin.host + (resource || '');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to create a url for hkp clients to connect to this server via
|
||||||
|
* the hkp protocol.
|
||||||
|
* @param {Object} ctx The koa request/repsonse context
|
||||||
|
* @return {string} The complete url
|
||||||
|
*/
|
||||||
|
exports.hkpUrl = function(ctx) {
|
||||||
|
return (this.checkHTTPS(ctx) ? 'hkps://' : 'hkp://') + ctx.host;
|
||||||
|
};
|
@ -135,9 +135,21 @@ describe('Util Unit Tests', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getOrigin', () => {
|
describe('origin', () => {
|
||||||
it('should work', () => {
|
it('should work', () => {
|
||||||
expect(util.getOrigin({host:'h', protocol:'p'})).to.exist;
|
expect(util.origin({ secure:true, host:'h', protocol:'p' })).to.exist;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('url', () => {
|
||||||
|
it('should work with resource', () => {
|
||||||
|
let url = util.url({ host:'localhost', protocol:'http'}, '/foo');
|
||||||
|
expect(url).to.equal('http://localhost/foo');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work without resource', () => {
|
||||||
|
let url = util.url({ host:'localhost', protocol:'http'});
|
||||||
|
expect(url).to.equal('http://localhost');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user