diff --git a/public/language/en-GB/user.json b/public/language/en-GB/user.json index 31df96fb8c..6fd7f11675 100644 --- a/public/language/en-GB/user.json +++ b/public/language/en-GB/user.json @@ -223,5 +223,6 @@ "emailUpdate.optional": "This field is optional. You are not obligated to provide your email address, but without a validated email you will not be able to recover your account or login with your email.", "emailUpdate.required": "This field is required.", "emailUpdate.change-instructions": "A confirmation email will be sent to the entered email address with a unique link. Accessing that link will confirm your ownership of the email address and it will become active on your account. At any time, you are able to update your email on file from within your account page.", - "emailUpdate.password-challenge": "Please enter your password in order to verify account ownership." + "emailUpdate.password-challenge": "Please enter your password in order to verify account ownership.", + "emailUpdate.pending": "Your email address has not yet been confirmed, but an email has been sent out requesting confirmation. If you wish to invalidate that request and send a new confirmation request, please fill in the form below." } diff --git a/src/middleware/user.js b/src/middleware/user.js index fb3e5ed84f..57c1db8296 100644 --- a/src/middleware/user.js +++ b/src/middleware/user.js @@ -6,6 +6,7 @@ const nconf = require('nconf'); const path = require('path'); const util = require('util'); +const meta = require('../meta'); const user = require('../user'); const privileges = require('../privileges'); const plugins = require('../plugins'); @@ -231,12 +232,27 @@ module.exports = function (middleware) { }; middleware.registrationComplete = async function registrationComplete(req, res, next) { - // If the user's session contains registration data, redirect the user to complete registration + /** + * Redirect the user to complete registration if: + * * user's session contains registration data + * * email is required and they have no confirmed email (pending doesn't count, but admins are OK) + */ + const path = req.path.startsWith('/api/') ? req.path.replace('/api', '') : req.path; + if (!req.session.hasOwnProperty('registration')) { + if (req.uid && !path.endsWith('/edit/email')) { + const [confirmed, isAdmin] = await Promise.all([ + user.getUserField(req.uid, 'email:confirmed'), + user.isAdministrator(req.uid), + ]); + if (meta.config.requireEmailAddress && !confirmed && !isAdmin) { + controllers.helpers.redirect(res, '/me/edit/email'); + } + } + return setImmediate(next); } - const path = req.path.startsWith('/api/') ? req.path.replace('/api', '') : req.path; const { allowed } = await plugins.hooks.fire('filter:middleware.registrationComplete', { allowed: ['/register/complete'], }); diff --git a/src/user/interstitials.js b/src/user/interstitials.js index 9a0e96f6db..b87877b53e 100644 --- a/src/user/interstitials.js +++ b/src/user/interstitials.js @@ -28,9 +28,10 @@ Interstitials.email = async (data) => { return data; } - const [isAdminOrGlobalMod, hasPassword] = await Promise.all([ + const [isAdminOrGlobalMod, hasPassword, hasPending] = await Promise.all([ user.isAdminOrGlobalMod(data.req.uid), user.hasPassword(data.userData.uid), + user.email.isValidationPending(data.userData.uid), ]); let email; @@ -44,6 +45,7 @@ Interstitials.email = async (data) => { email, requireEmailAddress: meta.config.requireEmailAddress, issuePasswordChallenge: !!data.userData.uid && hasPassword, + hasPending, }, callback: async (userData, formData) => { // Validate and send email confirmation diff --git a/src/views/partials/email_update.tpl b/src/views/partials/email_update.tpl index ccadc6226b..788c49942f 100644 --- a/src/views/partials/email_update.tpl +++ b/src/views/partials/email_update.tpl @@ -1,4 +1,9 @@
[[user:emailUpdate.pending]]
+[[user:emailUpdate.intro]]
{{{ if requireEmailAddress }}}[[user:emailUpdate.required]]