From 3bcd1f1438bf55ee55e1c0eb5745ceea8da40cad Mon Sep 17 00:00:00 2001 From: Julian Lam Date: Fri, 23 Jul 2021 17:22:19 -0400 Subject: [PATCH] fix: email validation flow, so that it actually works, fixed event logging bug, new email verification template --- public/language/en-GB/email.json | 4 +++- src/socket.io/admin/email.js | 9 +++++++++ src/user/create.js | 2 ++ src/user/email.js | 15 ++++++++------- src/user/index.js | 8 +++++++- src/user/profile.js | 2 -- .../emails/{verify_email.tpl => verify-email.tpl} | 11 +++++++++-- 7 files changed, 38 insertions(+), 13 deletions(-) rename src/views/emails/{verify_email.tpl => verify-email.tpl} (86%) diff --git a/public/language/en-GB/email.json b/public/language/en-GB/email.json index 78d6c5c007..8d27730066 100644 --- a/public/language/en-GB/email.json +++ b/public/language/en-GB/email.json @@ -9,7 +9,9 @@ "greeting_with_name": "Hello %1", "email.verify-your-email.subject": "Please verify your email", - "email.verify.text1": "Your email address has changed!", + "email.verify.text1": "You've requested that we change or confirm your email address", + "email.verify.text2": "For security purposes, we only change or confirm the email address on file once its ownership has been confirmed via email. If you did not request this, no action is required on your part.", + "email.verify.text3": "Once you confirm this email address, we will replace your current email address with this one (%1).", "welcome.text1": "Thank you for registering with %1!", "welcome.text2": "To fully activate your account, we need to verify that you own the email address you registered with.", diff --git a/src/socket.io/admin/email.js b/src/socket.io/admin/email.js index 49a1bbbd83..c85b44778c 100644 --- a/src/socket.io/admin/email.js +++ b/src/socket.io/admin/email.js @@ -1,5 +1,6 @@ 'use strict'; +const meta = require('../../meta'); const userDigest = require('../../user/digest'); const userEmail = require('../../user/email'); const notifications = require('../../notifications'); @@ -13,6 +14,7 @@ Email.test = async function (socket, data) { ...(data.payload || {}), subject: '[[email:test-email.subject]]', }; + let template; switch (data.template) { case 'digest': @@ -31,9 +33,16 @@ Email.test = async function (socket, data) { await emailer.send(data.template, socket.uid, payload); break; + case 'verify-email': + template = 'verify-email'; + // falls through + case 'welcome': await userEmail.sendValidationEmail(socket.uid, { force: 1, + email: 'test@example.org', + template: template || 'welcome', + subject: !template ? `[[email:welcome-to, ${meta.config.title || meta.config.browserTitle || 'NodeBB'}]]` : undefined, }); break; diff --git a/src/user/create.js b/src/user/create.js index 90121be672..869db6b162 100644 --- a/src/user/create.js +++ b/src/user/create.js @@ -114,6 +114,8 @@ module.exports = function (User) { if (userData.email && userData.uid > 1) { User.email.sendValidationEmail(userData.uid, { email: userData.email, + template: 'welcome', + subject: `[[email:welcome-to, ${meta.config.title || meta.config.browserTitle || 'NodeBB'}]]`, }).catch(err => winston.error(`[user.create] Validation email failed to send\n[emailer.send] ${err.stack}`)); } if (userNameChanged) { diff --git a/src/user/email.js b/src/user/email.js index e7c03584b5..c7779dbc53 100644 --- a/src/user/email.js +++ b/src/user/email.js @@ -99,13 +99,14 @@ UserEmail.sendValidationEmail = async function (uid, options) { }); const data = { - username: username, - confirm_link: confirm_link, - confirm_code: confirm_code, + uid, + username, + confirm_link, + confirm_code, + email: options.email, - subject: options.subject || `[[email:welcome-to, ${meta.config.title || meta.config.browserTitle || 'NodeBB'}]]`, - template: options.template || 'welcome', - uid: uid, + subject: options.subject || '[[email:email.verify-your-email.subject]]', + template: options.template || 'verify-email', }; if (plugins.hooks.hasListeners('action:user.verify')) { @@ -134,8 +135,8 @@ UserEmail.confirmByCode = async function (code) { } } + await user.setUserField(confirmObj.uid, 'email', confirmObj.email); await Promise.all([ - user.setUserField('email', confirmObj.email), UserEmail.confirmByUid(confirmObj.uid), db.delete(`confirm:${code}`), ]); diff --git a/src/user/index.js b/src/user/index.js index a36de7bf38..b6698e95a0 100644 --- a/src/user/index.js +++ b/src/user/index.js @@ -262,8 +262,14 @@ User.addInterstitials = function (callback) { const [isAdminOrGlobalMod, canEdit] = await Promise.all([ User.isAdminOrGlobalMod(data.req.uid), privileges.users.canEdit(data.req.uid, userData.uid), + ]); - if (isAdminOrGlobalMod || canEdit) { + + // Admins editing will auto-confirm, unless editing their own email + if (isAdminOrGlobalMod && userData.uid !== data.req.uid) { + await User.setUserField(userData.uid, 'email', formData.email); + await User.email.confirmByUid(userData.uid); + } else if (canEdit) { await User.email.sendValidationEmail(userData.uid, { email: formData.email, force: true, diff --git a/src/user/profile.js b/src/user/profile.js index 822bb5c0af..2748690b81 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -246,8 +246,6 @@ module.exports = function (User) { if (newEmail) { await User.email.sendValidationEmail(uid, { email: newEmail, - subject: '[[email:email.verify-your-email.subject]]', - template: 'verify_email', force: 1, }).catch(err => winston.error(`[user.create] Validation email failed to send\n[emailer.send] ${err.stack}`)); } diff --git a/src/views/emails/verify_email.tpl b/src/views/emails/verify-email.tpl similarity index 86% rename from src/views/emails/verify_email.tpl rename to src/views/emails/verify-email.tpl index c5ec237065..cd9309209c 100644 --- a/src/views/emails/verify_email.tpl +++ b/src/views/emails/verify-email.tpl @@ -9,7 +9,7 @@ @@ -20,7 +20,14 @@ + + +
-

[[email:greeting_no_name]]

+

[[email:greeting_with_name, {username}]]

- [[email:welcome.text2]] + [[email:email.verify.text2]] +

+
+

+ [[email:email.verify.text3, {email}]]