diff --git a/lib/mailer.js b/lib/mailer.js index 30ff5aef..763ed6ed 100644 --- a/lib/mailer.js +++ b/lib/mailer.js @@ -12,7 +12,6 @@ let templates = new Map(); module.exports.transport = false; - module.exports.update = () => { createMailer(() => false); }; diff --git a/public/css/narrow.css b/public/css/narrow.css index fd8cb28d..6b9414cd 100644 --- a/public/css/narrow.css +++ b/public/css/narrow.css @@ -21,7 +21,6 @@ body { border-bottom: 1px solid #e5e5e5; } - /* Make the masthead heading the same height as the navigation */ .header h3 { @@ -94,3 +93,7 @@ body { border-bottom: 0; } } + +.gpg-text { + font-family: monospace; +} diff --git a/routes/subscription.js b/routes/subscription.js index b48831db..22d1be9c 100644 --- a/routes/subscription.js +++ b/routes/subscription.js @@ -12,6 +12,7 @@ let lists = require('../lib/models/lists'); let fields = require('../lib/models/fields'); let subscriptions = require('../lib/models/subscriptions'); let settings = require('../lib/models/settings'); +let openpgp = require('openpgp'); router.get('/subscribe/:cid', (req, res, next) => { subscriptions.subscribe(req.params.cid, req.ip, (err, subscription) => { @@ -34,7 +35,7 @@ router.get('/subscribe/:cid', (req, res, next) => { return next(err); } - settings.list(['defaultHomepage', 'serviceUrl'], (err, configItems) => { + settings.list(['defaultHomepage', 'serviceUrl', 'pgpPrivateKey'], (err, configItems) => { if (err) { return next(err); } @@ -43,7 +44,8 @@ router.get('/subscribe/:cid', (req, res, next) => { title: list.name, layout: 'subscription/layout', 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.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)); } - settings.list(['defaultHomepage', 'defaultFrom', 'defaultAddress', 'serviceUrl'], (err, configItems) => { + fields.list(list.id, (err, fieldList) => { if (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({ - 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 => { + settings.list(['defaultHomepage', 'defaultFrom', 'defaultAddress', 'serviceUrl'], (err, configItems) => { 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; - 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; diff --git a/views/subscription/manage.hbs b/views/subscription/manage.hbs index 996af8ed..dc578bef 100644 --- a/views/subscription/manage.hbs +++ b/views/subscription/manage.hbs @@ -1,5 +1,12 @@

Update your preferences

+{{#if hasPubkey}} +
+ + +
+{{/if}} +
@@ -42,7 +49,7 @@ {{#if typeGpg}} - Insert your GPG public key here to encrypt messages sent to your address + (optional) Insert your GPG public key here to encrypt messages sent to your address {{/if}} {{#if typeDateUs}} @@ -104,6 +111,11 @@ {{/each}}
+
+ {{#if hasPubkey}} + + {{/if}} +
or Unsubscribe
diff --git a/views/subscription/subscribe.hbs b/views/subscription/subscribe.hbs index b8129989..d943b86f 100644 --- a/views/subscription/subscribe.hbs +++ b/views/subscription/subscribe.hbs @@ -1,3 +1,10 @@ +{{#if hasPubkey}} +
+ + +
+{{/if}} +
@@ -39,7 +46,7 @@ {{#if typeGpg}} - Insert your GPG public key here to encrypt messages sent to your address + (optional) Insert your GPG public key here to encrypt messages sent to your address {{/if}} {{#if typeDateUs}} @@ -101,6 +108,11 @@ {{/each}}
+
+ {{#if hasPubkey}} + + {{/if}} +