Added PGP pubkey download button

This commit is contained in:
Andris Reinman 2016-04-16 14:09:23 -07:00
parent 4d56287583
commit 9c9af58eb5
5 changed files with 123 additions and 30 deletions

View file

@ -12,7 +12,6 @@ let templates = new Map();
module.exports.transport = false; module.exports.transport = false;
module.exports.update = () => { module.exports.update = () => {
createMailer(() => false); createMailer(() => false);
}; };

View file

@ -21,7 +21,6 @@ body {
border-bottom: 1px solid #e5e5e5; border-bottom: 1px solid #e5e5e5;
} }
/* Make the masthead heading the same height as the navigation */ /* Make the masthead heading the same height as the navigation */
.header h3 { .header h3 {
@ -94,3 +93,7 @@ body {
border-bottom: 0; border-bottom: 0;
} }
} }
.gpg-text {
font-family: monospace;
}

View file

@ -12,6 +12,7 @@ let lists = require('../lib/models/lists');
let fields = require('../lib/models/fields'); let fields = require('../lib/models/fields');
let subscriptions = require('../lib/models/subscriptions'); let subscriptions = require('../lib/models/subscriptions');
let settings = require('../lib/models/settings'); let settings = require('../lib/models/settings');
let openpgp = require('openpgp');
router.get('/subscribe/:cid', (req, res, next) => { router.get('/subscribe/:cid', (req, res, next) => {
subscriptions.subscribe(req.params.cid, req.ip, (err, subscription) => { subscriptions.subscribe(req.params.cid, req.ip, (err, subscription) => {
@ -34,7 +35,7 @@ router.get('/subscribe/:cid', (req, res, next) => {
return next(err); return next(err);
} }
settings.list(['defaultHomepage', 'serviceUrl'], (err, configItems) => { settings.list(['defaultHomepage', 'serviceUrl', 'pgpPrivateKey'], (err, configItems) => {
if (err) { if (err) {
return next(err); return next(err);
} }
@ -43,7 +44,8 @@ router.get('/subscribe/:cid', (req, res, next) => {
title: list.name, title: list.name,
layout: 'subscription/layout', layout: 'subscription/layout',
homepage: configItems.defaultHomepage || configItems.serviceUrl, homepage: configItems.defaultHomepage || configItems.serviceUrl,
preferences: '/subscription/' + list.cid + '/manage/' + subscription.cid preferences: '/subscription/' + list.cid + '/manage/' + subscription.cid,
hasPubkey: !!configItems.pgpPrivateKey
}); });
}); });
}); });
@ -77,7 +79,13 @@ router.get('/:cid', passport.csrfProtection, (req, res, next) => {
data.customFields = fields.getRow(fieldList, data); data.customFields = fields.getRow(fieldList, data);
data.useEditor = true; data.useEditor = true;
res.render('subscription/subscribe', data); settings.list(['pgpPrivateKey'], (err, configItems) => {
if (err) {
return next(err);
}
data.hasPubkey = !!configItems.pgpPrivateKey;
res.render('subscription/subscribe', data);
});
}); });
}); });
}); });
@ -192,35 +200,49 @@ router.post('/:cid/subscribe', passport.parseForm, passport.csrfProtection, (req
return res.redirect('/subscription/' + encodeURIComponent(req.params.cid) + '?' + tools.queryParams(req.body)); return res.redirect('/subscription/' + encodeURIComponent(req.params.cid) + '?' + tools.queryParams(req.body));
} }
settings.list(['defaultHomepage', 'defaultFrom', 'defaultAddress', 'serviceUrl'], (err, configItems) => { fields.list(list.id, (err, fieldList) => {
if (err) { if (err) {
return next(err); return next(err);
} }
res.redirect('/subscription/' + req.params.cid + '/confirm-notice'); let encryptionKeys = [];
fields.getRow(fieldList, data).forEach(field => {
if (field.type === 'gpg' && field.value) {
encryptionKeys.push(field.value.trim());
}
});
mailer.sendMail({ settings.list(['defaultHomepage', 'defaultFrom', 'defaultAddress', 'serviceUrl'], (err, configItems) => {
from: {
name: configItems.defaultFrom,
address: configItems.defaultAddress
},
to: {
name: [].concat(data.firstName || []).concat(data.lastName || []).join(' '),
address: email
},
subject: list.name + ': Please Confirm Subscription'
}, {
html: 'emails/confirm-html.hbs',
text: 'emails/confirm-text.hbs',
data: {
title: list.name,
contactAddress: configItems.defaultAddress,
confirmUrl: urllib.resolve(configItems.serviceUrl, '/subscription/subscribe/' + confirmCid)
}
}, err => {
if (err) { if (err) {
log.error('Subscription', err.stack); return next(err);
} }
res.redirect('/subscription/' + req.params.cid + '/confirm-notice');
mailer.sendMail({
from: {
name: configItems.defaultFrom,
address: configItems.defaultAddress
},
to: {
name: [].concat(data.firstName || []).concat(data.lastName || []).join(' '),
address: email
},
subject: list.name + ': Please Confirm Subscription',
encryptionKeys
}, {
html: 'emails/confirm-html.hbs',
text: 'emails/confirm-text.hbs',
data: {
title: list.name,
contactAddress: configItems.defaultAddress,
confirmUrl: urllib.resolve(configItems.serviceUrl, '/subscription/subscribe/' + confirmCid)
}
}, err => {
if (err) {
log.error('Subscription', err.stack);
}
});
}); });
}); });
}); });
@ -261,7 +283,14 @@ router.get('/:lcid/manage/:ucid', passport.csrfProtection, (req, res, next) => {
subscription.useEditor = true; subscription.useEditor = true;
res.render('subscription/manage', subscription); settings.list(['pgpPrivateKey'], (err, configItems) => {
if (err) {
return next(err);
}
subscription.hasPubkey = !!configItems.pgpPrivateKey;
res.render('subscription/manage', subscription);
});
}); });
}); });
}); });
@ -343,4 +372,42 @@ router.post('/:lcid/unsubscribe', passport.parseForm, passport.csrfProtection, (
}); });
}); });
router.post('/publickey', passport.parseForm, passport.csrfProtection, (req, res, next) => {
settings.list(['pgpPassphrase', 'pgpPrivateKey'], (err, configItems) => {
if (err) {
return next(err);
}
if (!configItems.pgpPrivateKey) {
err = new Error('Public key is not set');
err.status = 404;
return next(err);
}
let privKey;
try {
privKey = openpgp.key.readArmored(configItems.pgpPrivateKey).keys[0];
if (configItems.pgpPassphrase && !privKey.decrypt(configItems.pgpPassphrase)) {
privKey = false;
}
} catch (E) {
// just ignore if failed
}
if (!privKey) {
err = new Error('Public key is not set');
err.status = 404;
return next(err);
}
let pubkey = privKey.toPublic().armor();
res.writeHead(200, {
'Content-Type': 'application/octet-stream',
'Content-Disposition': 'attachment; filename=public.asc'
});
res.end(pubkey);
});
});
module.exports = router; module.exports = router;

View file

@ -1,5 +1,12 @@
<h2>Update your preferences</h2> <h2>Update your preferences</h2>
{{#if hasPubkey}}
<form method="post" id="download-pubkey" action="/subscription/publickey">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<input type="hidden" name="cid" value="{{cid}}">
</form>
{{/if}}
<form method="post" action="/subscription/{{lcid}}/manage"> <form method="post" action="/subscription/{{lcid}}/manage">
<input type="hidden" name="_csrf" value="{{csrfToken}}"> <input type="hidden" name="_csrf" value="{{csrfToken}}">
@ -42,7 +49,7 @@
{{#if typeGpg}} {{#if typeGpg}}
<textarea class="form-control gpg-text" rows="3" name="{{column}}">{{value}}</textarea> <textarea class="form-control gpg-text" rows="3" name="{{column}}">{{value}}</textarea>
<span class="help-block">Insert your GPG public key here to encrypt messages sent to your address</span> <span class="help-block">(optional) Insert your GPG public key here to encrypt messages sent to your address</span>
{{/if}} {{/if}}
{{#if typeDateUs}} {{#if typeDateUs}}
@ -104,6 +111,11 @@
{{/each}} {{/each}}
<div class="form-group"> <div class="form-group">
<div class="pull-right">
{{#if hasPubkey}}
<button type="submit" class="btn btn-default" form="download-pubkey"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Download our public GPG key</button>
{{/if}}
</div>
<button type="submit" class="btn btn-primary"><i class="glyphicon glyphicon-ok"></i> Update Profile</button> or <a href="/subscription/{{lcid}}/unsubscribe/{{cid}}">Unsubscribe</a> <button type="submit" class="btn btn-primary"><i class="glyphicon glyphicon-ok"></i> Update Profile</button> or <a href="/subscription/{{lcid}}/unsubscribe/{{cid}}">Unsubscribe</a>
</div> </div>
</form> </form>

View file

@ -1,3 +1,10 @@
{{#if hasPubkey}}
<form method="post" id="download-pubkey" action="/subscription/publickey">
<input type="hidden" name="_csrf" value="{{csrfToken}}">
<input type="hidden" name="cid" value="{{cid}}">
</form>
{{/if}}
<form method="post" action="/subscription/{{cid}}/subscribe"> <form method="post" action="/subscription/{{cid}}/subscribe">
<input type="hidden" name="_csrf" value="{{csrfToken}}"> <input type="hidden" name="_csrf" value="{{csrfToken}}">
@ -39,7 +46,7 @@
{{#if typeGpg}} {{#if typeGpg}}
<textarea class="form-control gpg-text" rows="3" name="{{column}}">{{value}}</textarea> <textarea class="form-control gpg-text" rows="3" name="{{column}}">{{value}}</textarea>
<span class="help-block">Insert your GPG public key here to encrypt messages sent to your address</span> <span class="help-block">(optional) Insert your GPG public key here to encrypt messages sent to your address</span>
{{/if}} {{/if}}
{{#if typeDateUs}} {{#if typeDateUs}}
@ -101,6 +108,11 @@
{{/each}} {{/each}}
<div class="form-group"> <div class="form-group">
<div class="pull-right">
{{#if hasPubkey}}
<button type="submit" class="btn btn-default" form="download-pubkey"><span class="glyphicon glyphicon-cloud-download" aria-hidden="true"></span> Download our public GPG key</button>
{{/if}}
</div>
<button type="submit" class="btn btn-primary">Subscribe to list</button> <button type="submit" class="btn btn-primary">Subscribe to list</button>
</div> </div>
</form> </form>