diff --git a/client/coral-admin/src/containers/Configure/CommentSettings.js b/client/coral-admin/src/containers/Configure/CommentSettings.js index 0ccb5f820..1051bb0ba 100644 --- a/client/coral-admin/src/containers/Configure/CommentSettings.js +++ b/client/coral-admin/src/containers/Configure/CommentSettings.js @@ -32,6 +32,10 @@ const updateModeration = (updateSettings, mod) => () => { updateSettings({moderation}); }; +const updateEmailConfirmation = (updateSettings, verify) => () => { + updateSettings({requireEmailConfirmation: !verify}); +}; + const updateInfoBoxEnable = (updateSettings, infoBox) => () => { const infoBoxEnable = !infoBox; updateSettings({infoBoxEnable}); @@ -67,106 +71,123 @@ const CommentSettings = ({fetchingSettings, title, updateSettings, settingsError return Loading settings...; } + // just putting this here for shorthand below + const on = styles.enabledSetting; + const off = styles.disabledSetting; + return (

{title}

- -
- -
-
+ +
+ +
+
{lang.t('configure.enable-pre-moderation')}

{lang.t('configure.enable-pre-moderation-text')}

-
- -
- -
-
-
{lang.t('configure.comment-count-header')}
-

- {lang.t('configure.comment-count-text-pre')} - - {lang.t('configure.comment-count-text-post')} - { - errors.charCount && - -
- - {lang.t('configure.comment-count-error')} -
- } -

-
-
- -
- -
-
- {lang.t('configure.include-comment-stream')} -

- {lang.t('configure.include-comment-stream-desc')} -

-
-
- -
+ + +
+ +
+
+
{lang.t('configure.require-email-verification')}
+

+ {lang.t('configure.require-email-verification-text')} +

+
+
+ +
+ +
+
+
{lang.t('configure.comment-count-header')}
+

+ {lang.t('configure.comment-count-text-pre')} + + {lang.t('configure.comment-count-text-post')} + { + errors.charCount && + +
+ + {lang.t('configure.comment-count-error')} +
+ } +

+
+
+ +
+ +
+
+ {lang.t('configure.include-comment-stream')} +

+ {lang.t('configure.include-comment-stream-desc')} +

+
+
+
- - -
- {lang.t('configure.closed-comments-desc')} -
- -
+
+
+ +
+ {lang.t('configure.closed-comments-desc')} +
+
- - -
- {lang.t('configure.close-after')} -
- -
- - - - - -
+
+
+ +
+ {lang.t('configure.close-after')} +
+ +
+ + + + +
- +
+
); }; diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json index 3718732fe..76749ffd7 100644 --- a/client/coral-admin/src/translations.json +++ b/client/coral-admin/src/translations.json @@ -43,6 +43,8 @@ "configure": { "enable-pre-moderation": "Enable pre-moderation", "enable-pre-moderation-text": "Moderators must approve any comment before it is published.", + "require-email-verification": "Require Email Confirmation", + "require-email-verification-text": "New Users must verify their email before commenting", "include-comment-stream": "Include Comment Stream Description for Readers.", "include-comment-stream-desc": "Write a message to be added to the top of your comment stream. Pose a topic, include community guidelines, etc.", "include-text": "Include your text here.", @@ -129,6 +131,8 @@ "configure": { "enable-pre-moderation": "Habilitar pre-moderación", "enable-pre-moderation-text": "Los moderadores deben aprobar cada comentario antes de que sea publicado.", + "require-email-verification": "Necesita confirmación de correo", + "require-email-verification-text": "Nuevos usuarios deben verificar sus correos antes de comentar", "include-comment-stream": "Incluir la Descripción a un Hilo de Comentario para los y las Lectoras.", "include-comment-stream-desc": "Escribir un mensaje que será agregado a la parte de arriba del tu hilo de comentarios. Por ejemplo, un tema, guias de comunidad, etc.", "include-text": "Incluir tu texto aqui.", diff --git a/routes/admin/index.js b/routes/admin/index.js index 2a37e8f0f..a3699143e 100644 --- a/routes/admin/index.js +++ b/routes/admin/index.js @@ -1,6 +1,11 @@ const express = require('express'); const router = express.Router(); +// Get /email-confirmation expects a signed JWT in the hash +router.get('/confirm-email', (req, res) => { + res.render('admin/confirm-email'); +}); + // Get /password-reset expects a signed token (JWT) in the hash. // Links to this endpoint are generated by /views/password-reset-email.ejs. router.get('/password-reset', (req, res) => { diff --git a/routes/api/account/index.js b/routes/api/account/index.js index 57647a89d..44749a488 100644 --- a/routes/api/account/index.js +++ b/routes/api/account/index.js @@ -28,8 +28,8 @@ router.post('/email/confirm', (req, res, next) => { UsersService .verifyEmailConfirmation(token) - .then(() => { - res.status(204).end(); + .then(([, referer]) => { + res.json({redirectUri: referer}); }) .catch((err) => { next(err); diff --git a/routes/api/users/index.js b/routes/api/users/index.js index 3ea3f3213..d42c5039b 100644 --- a/routes/api/users/index.js +++ b/routes/api/users/index.js @@ -69,8 +69,8 @@ router.post('/:user_id/status', authorization.needed('ADMIN'), (req, res, next) * @param {String} userID the id for the user to send the email to * @param {String} email the email for the user to send the email to */ -const SendEmailConfirmation = (app, userID, email) => UsersService - .createEmailConfirmToken(userID, email) +const SendEmailConfirmation = (app, userID, email, referer) => UsersService + .createEmailConfirmToken(userID, email, referer) .then((token) => { return mailer.sendSimple({ app, // needed to render the templates. @@ -103,7 +103,7 @@ router.post('/', (req, res, next) => { if (requireEmailConfirmation) { - SendEmailConfirmation(req.app, user.id, email) + SendEmailConfirmation(req.app, user.id, email, req.header('Referer')) .then(() => { // Then send back the user. diff --git a/services/users.js b/services/users.js index 0bf22e9e0..1a2c384d6 100644 --- a/services/users.js +++ b/services/users.js @@ -531,7 +531,7 @@ module.exports = class UsersService { * @param {String} email The email that we are needing to get confirmed. * @return {Promise} */ - static createEmailConfirmToken(userID, email) { + static createEmailConfirmToken(userID, email, referer) { if (!email || typeof email !== 'string') { return Promise.reject('email is required when creating a JWT for resetting passord'); } @@ -555,6 +555,7 @@ module.exports = class UsersService { const payload = { email, + referer, userID }; @@ -579,9 +580,9 @@ module.exports = class UsersService { .verifyToken(token, { subject: EMAIL_CONFIRM_JWT_SUBJECT }) - .then(({userID, email}) => { + .then(({userID, email, referer}) => { - return UserModel + const userUpdate = UserModel .update({ id: userID, profiles: { @@ -595,7 +596,10 @@ module.exports = class UsersService { 'profiles.$.metadata.confirmed_at': new Date() } }); + + return Promise.all([userUpdate, referer]); }); + } }; diff --git a/views/admin/confirm-email.ejs b/views/admin/confirm-email.ejs new file mode 100644 index 000000000..7d0475325 --- /dev/null +++ b/views/admin/confirm-email.ejs @@ -0,0 +1,92 @@ + + + + + + Confirm Email + + + + + + +
+
+
+

Confirm Email Address

+
+
+ Click the button below to confirm your new user account. +
+ +
+ +
+ + + + + diff --git a/views/email/email-confirm.ejs b/views/email/email-confirm.ejs index da1b0e815..2644c2225 100644 --- a/views/email/email-confirm.ejs +++ b/views/email/email-confirm.ejs @@ -1,3 +1,3 @@

A email confirmation has been requested for the following account: <%= email %>.

-

To confirm the account, please visit the following link: http://example.com/email/confirm/endpoint#<%= token %>

+

To confirm the account, please visit the following link: http://example.com/email/confirm/endpoint#<%= token %>

If you did not request this, you can safely ignore this email.

diff --git a/views/email/email-confirm.txt.ejs b/views/email/email-confirm.txt.ejs index 764991d8d..4c7d7d312 100644 --- a/views/email/email-confirm.txt.ejs +++ b/views/email/email-confirm.txt.ejs @@ -4,6 +4,6 @@ A email confirmation has been requested for the following account: To confirm the account, please visit the following link: - http://example.com/email/confirm/endpoint#<%= token %> + <%= rootURL %>/confirm/endpoint#<%= token %> If you did not request this, you can safely ignore this email.