fix(auth): Add verification route for email

This commit is contained in:
Mrugesh Mohapatra
2018-05-25 23:14:09 +05:30
parent 23eb3713c9
commit 59f700b110
8 changed files with 131 additions and 13 deletions

View File

@ -132,9 +132,9 @@ class EmailSettings extends PureComponent {
<FullWidthRow> <FullWidthRow>
<HelpBlock> <HelpBlock>
<Alert bsStyle='info'> <Alert bsStyle='info'>
A change of email address has not been verified. Your email has not been verified.
To use your new email, you must verify it first using the link To use your email, you must
we sent you. <a href='/update-email'> verify it here first</a>.
</Alert> </Alert>
</HelpBlock> </HelpBlock>
</FullWidthRow> </FullWidthRow>

View File

@ -38,10 +38,34 @@ module.exports = function enableAuthentication(app) {
ifUserRedirect, ifUserRedirect,
(req, res) => res.redirect(301, '/auth/auth0')); (req, res) => res.redirect(301, '/auth/auth0'));
router.get(
'/update-email',
ifNoUserRedirectHome,
(req, res) => res.render('account/update-email', {
title: 'Update your email'
})
);
router.get('/signout', (req, res) => { router.get('/signout', (req, res) => {
req.logout(); req.logout();
req.session.destroy( (err) => {
if (err) {
throw wrapHandledError(
new Error('could not destroy session'),
{
type: 'info',
message: 'Oops, something is not right.',
redirectTo: '/'
}
);
}
res.clearCookie('jwt_access_token');
res.clearCookie('access_token');
res.clearCookie('userId');
res.clearCookie('_csrf');
res.redirect('/'); res.redirect('/');
}); });
});
router.get( router.get(
'/deprecated-signin', '/deprecated-signin',

View File

@ -5,12 +5,12 @@ import { curry } from 'lodash';
import { import {
ifNoUser401, ifNoUser401,
ifNoUserRedirectTo, ifNoUserRedirectTo,
ifNotVerifiedRedirectToSettings ifNotVerifiedRedirectToUpdateEmail
} from '../utils/middleware'; } from '../utils/middleware';
const debug = debugFactory('fcc:boot:user'); const debug = debugFactory('fcc:boot:user');
const sendNonUserToMap = ifNoUserRedirectTo('/map'); const sendNonUserToHome = ifNoUserRedirectTo('/');
const sendNonUserToMapWithMessage = curry(ifNoUserRedirectTo, 2)('/map'); const sendNonUserToHomeWithMessage = curry(ifNoUserRedirectTo, 2)('/');
module.exports = function(app) { module.exports = function(app) {
const router = app.loopback.Router(); const router = app.loopback.Router();
@ -24,7 +24,7 @@ module.exports = function(app) {
); );
api.get( api.get(
'/account', '/account',
sendNonUserToMap, sendNonUserToHome,
getAccount getAccount
); );
api.post( api.post(
@ -34,15 +34,15 @@ module.exports = function(app) {
); );
api.get( api.get(
'/account/unlink/:social', '/account/unlink/:social',
sendNonUserToMap, sendNonUserToHome,
getUnlinkSocial getUnlinkSocial
); );
// Ensure these are the last routes! // Ensure these are the last routes!
router.get( router.get(
'/user/:username/report-user/', '/user/:username/report-user/',
sendNonUserToMapWithMessage('You must be signed in to report a user'), sendNonUserToHomeWithMessage('You must be signed in to report a user'),
ifNotVerifiedRedirectToSettings, ifNotVerifiedRedirectToUpdateEmail,
getReportUserProfile getReportUserProfile
); );
@ -119,6 +119,10 @@ module.exports = function(app) {
if (err) { return next(err); } if (err) { return next(err); }
req.logout(); req.logout();
req.flash('success', 'You have successfully deleted your account.'); req.flash('success', 'You have successfully deleted your account.');
res.clearCookie('jwt_access_token');
res.clearCookie('access_token');
res.clearCookie('userId');
res.clearCookie('_csrf');
return res.status(200).end(); return res.status(200).end();
}); });
} }

View File

@ -58,6 +58,7 @@
"./middlewares/jade-helpers": {}, "./middlewares/jade-helpers": {},
"./middlewares/flash-cheaters": {}, "./middlewares/flash-cheaters": {},
"./middlewares/passport-login": {}, "./middlewares/passport-login": {},
"./middlewares/email-not-verified-notice": {},
"./middlewares/privacy-terms-notice": {} "./middlewares/privacy-terms-notice": {}
}, },
"files": {}, "files": {},

View File

@ -0,0 +1,32 @@
import dedent from 'dedent';
const ALLOWED_METHODS = ['GET'];
const EXCLUDED_PATHS = [
'/api/flyers/findOne',
'/signout',
'/update-email'
];
export default function emailNotVerifiedNotice() {
return function(req, res, next) {
if (
ALLOWED_METHODS.indexOf(req.method) !== -1 &&
EXCLUDED_PATHS.indexOf(req.path) === -1
) {
const { user } = req;
if (user && (!user.email || user.email === '' || !user.emailVerified)) {
req.flash(
'danger',
dedent`
New privacy laws now require that we have an email address where we can reach
you. Please verify your email address below and click the link we send you to
confirm.
`
);
res.redirect('/update-email');
return next;
}
}
return next();
};
}

View File

@ -32,7 +32,7 @@ export function ifNoUser401(req, res, next) {
return res.status(401).end(); return res.status(401).end();
} }
export function ifNotVerifiedRedirectToSettings(req, res, next) { export function ifNotVerifiedRedirectToUpdateEmail(req, res, next) {
const { user } = req; const { user } = req;
if (!user) { if (!user) {
return next(); return next();

View File

@ -0,0 +1,57 @@
extends ../layout
block content
.container
.row.flashMessage.negative-30
.col-xs-12
#flash-board.alert.fade.in(style='display: none;')
button.close(type='button', data-dismiss='alert')
span.ion-close-circled#flash-close
#flash-content
h2.text-center Update your email address here:
form.form-horizontal.update-email(method='POST', action='/api/users/#{user.id}/update-email', name="updateEmailForm")
.row
.col-sm-6.col-sm-offset-3
input(type='hidden', name='_csrf', value=_csrf)
.form-group
input.input-lg.form-control(type='email', name='email', id='email', value=user.email || '', placeholder=user.email || 'Enter your new email', autofocus, required, autocomplete="off")
.form-group
button.btn.btn-lg.btn-primary.btn-block(type='submit')= !user.email || user.emailVerified ? 'Update my Email' : 'Verify Email'
a.btn.btn-lg.btn-block.btn-primary.btn-link-social(href='/signout')
| Sign out
script.
$(document).ready(function() {
$('form').submit(function(event){
event.preventDefault();
$('#flash-board').hide();
var $form = $(event.target);
$.ajax({
type : 'POST',
url : $form.attr('action'),
data : $form.serialize(),
dataType : 'json',
encode : true,
xhrFields : { withCredentials: true }
})
.fail(error => {
if (error.responseText){
var data = JSON.parse(error.responseText);
if(data.message)
$('#flash-content').html(data.message);
$('#flash-board')
.removeClass('alert-success')
.addClass('alert-info')
.fadeIn();
}
})
.done(data =>{
if(data && data.message){
$('#flash-content').html(data.message);
$('#flash-board')
.removeClass('alert-info')
.addClass('alert-success')
.fadeIn();
}
});
});
});

View File

@ -14,7 +14,7 @@ nav.navbar.navbar-default.navbar-static-top.nav-height
a(href='https://forum.freecodecamp.org', target='_blank' rel='noopener') Forum a(href='https://forum.freecodecamp.org', target='_blank' rel='noopener') Forum
if !user if !user
li li
a(href='/signin') Start Coding a(href='/signin') Sign in
else else
li li
a(href='/settings') Settings a(href='/settings') Settings