From 203d3c7ee961763df004e161e6b61cb2b87a19e7 Mon Sep 17 00:00:00 2001
From: Wyatt Johnson
Date: Mon, 25 Sep 2017 16:12:40 -0600
Subject: [PATCH] bug fixes
---
app.js | 18 +++--------
routes/api/account/index.js | 17 +++++------
services/email/email-confirm.html.ejs | 2 +-
services/email/email-confirm.txt.ejs | 2 +-
services/email/password-reset.html.ejs | 2 +-
services/email/password-reset.txt.ejs | 2 +-
services/locals.js | 20 ++++++++++++
services/mailer.js | 4 +++
services/users.js | 6 +++-
views/admin/password-reset.ejs | 42 ++++++++++++++++++++------
10 files changed, 77 insertions(+), 38 deletions(-)
create mode 100644 services/locals.js
diff --git a/app.js b/app.js
index 9da2041fc..2989ae00a 100644
--- a/app.js
+++ b/app.js
@@ -6,13 +6,9 @@ const merge = require('lodash/merge');
const helmet = require('helmet');
const compression = require('compression');
const cookieParser = require('cookie-parser');
-const {
- BASE_URL,
- BASE_PATH,
- MOUNT_PATH,
- STATIC_URL,
- HELMET_CONFIGURATION,
-} = require('./url');
+const {HELMET_CONFIGURATION} = require('./config');
+const {MOUNT_PATH} = require('./url');
+const {applyLocals} = require('./services/locals');
const routes = require('./routes');
const debug = require('debug')('talk:app');
@@ -57,12 +53,8 @@ app.set('view engine', 'ejs');
// ROUTES
//==============================================================================
-// Apply the BASE_PATH, BASE_URL, and MOUNT_PATH on the app.locals, which will
-// make them available on the templates and the routers.
-app.locals.BASE_URL = BASE_URL;
-app.locals.BASE_PATH = BASE_PATH;
-app.locals.MOUNT_PATH = MOUNT_PATH;
-app.locals.STATIC_URL = STATIC_URL;
+// Add the locals to the app renderer.
+applyLocals(app.locals);
debug(`mounting routes on the ${MOUNT_PATH} path`);
diff --git a/routes/api/account/index.js b/routes/api/account/index.js
index 85558d33c..c35f709cb 100644
--- a/routes/api/account/index.js
+++ b/routes/api/account/index.js
@@ -4,9 +4,6 @@ const UsersService = require('../../../services/users');
const mailer = require('../../../services/mailer');
const authorization = require('../../../middleware/authorization');
const errors = require('../../../errors');
-const {
- ROOT_URL
-} = require('../../../config');
//==============================================================================
// ROUTES
@@ -55,7 +52,6 @@ router.post('/password/reset', async (req, res, next) => {
template: 'password-reset',
locals: {
token,
- rootURL: ROOT_URL
},
subject: 'Password Reset',
to: email
@@ -74,22 +70,23 @@ router.post('/password/reset', async (req, res, next) => {
* 2) the new password {String}
*/
router.put('/password/reset', async (req, res, next) => {
-
- const {
- token,
- password
- } = req.body;
+ const {check} = req.query;
+ const {token, password} = req.body;
if (!token) {
return next(errors.ErrMissingToken);
}
- if (!password || password.length < 8) {
+ if (check !== 'true' && (!password || password.length < 8)) {
return next(errors.ErrPasswordTooShort);
}
try {
let [user, loc] = await UsersService.verifyPasswordResetToken(token);
+ if (check === 'true') {
+ res.status(204).end();
+ return;
+ }
// Change the users' password.
await UsersService.changePassword(user.id, password);
diff --git a/services/email/email-confirm.html.ejs b/services/email/email-confirm.html.ejs
index 08a505521..8a1bd05f7 100644
--- a/services/email/email-confirm.html.ejs
+++ b/services/email/email-confirm.html.ejs
@@ -1,3 +1,3 @@
<%= t('email.confirm.has_been_requested') %> <%= email %>.
-<%= t('email.confirm.to_confirm') %> Confirm Email
+<%= t('email.confirm.to_confirm') %> Confirm Email
<%= t('email.confirm.if_you_did_not') %>
diff --git a/services/email/email-confirm.txt.ejs b/services/email/email-confirm.txt.ejs
index 6d3cb219c..d327220a7 100644
--- a/services/email/email-confirm.txt.ejs
+++ b/services/email/email-confirm.txt.ejs
@@ -4,6 +4,6 @@
<%= t('email.confirm.to_confirm') %>
- <%= rootURL %>/confirm/endpoint#<%= token %>
+ <%= BASE_URL %>confirm/endpoint#<%= token %>
<%= t('email.confirm.if_you_did_not') %>
diff --git a/services/email/password-reset.html.ejs b/services/email/password-reset.html.ejs
index 258f0d079..c0ec4ea46 100644
--- a/services/email/password-reset.html.ejs
+++ b/services/email/password-reset.html.ejs
@@ -1,2 +1,2 @@
<%= t('email.password_reset.we_received_a_request') %>
-<%= t('email.password_reset.if_you_did') %> <%= t('email.password_reset.please_click') %>.
+<%= t('email.password_reset.if_you_did') %> <%= t('email.password_reset.please_click') %>.
diff --git a/services/email/password-reset.txt.ejs b/services/email/password-reset.txt.ejs
index a8387925d..e8db4bab2 100644
--- a/services/email/password-reset.txt.ejs
+++ b/services/email/password-reset.txt.ejs
@@ -1,3 +1,3 @@
<%= t('email.password_reset.we_received_a_request') %>. <%= t('email.password_reset.if_you_did') %> <%= t('email.password_reset.please_click') %>:
-<%= rootURL %>/admin/password-reset#<%= token %>
+<%= BASE_URL %>admin/password-reset#<%= token %>
diff --git a/services/locals.js b/services/locals.js
new file mode 100644
index 000000000..9a6a6bec8
--- /dev/null
+++ b/services/locals.js
@@ -0,0 +1,20 @@
+const {
+ BASE_URL,
+ BASE_PATH,
+ MOUNT_PATH,
+ STATIC_URL,
+} = require('../url');
+
+const applyLocals = (locals) => {
+
+ // Apply the BASE_PATH, BASE_URL, and MOUNT_PATH on the app.locals, which will
+ // make them available on the templates and the routers.
+ locals.BASE_URL = BASE_URL;
+ locals.BASE_PATH = BASE_PATH;
+ locals.MOUNT_PATH = MOUNT_PATH;
+ locals.STATIC_URL = STATIC_URL;
+};
+
+module.exports = {
+ applyLocals,
+};
diff --git a/services/mailer.js b/services/mailer.js
index 68252bea3..8d650726d 100644
--- a/services/mailer.js
+++ b/services/mailer.js
@@ -4,6 +4,7 @@ const kue = require('./kue');
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
+const {applyLocals} = require('./locals');
const i18n = require('./i18n');
@@ -92,6 +93,9 @@ const mailer = module.exports = {
// Prefix the subject with `[Talk]`.
subject = `[Talk] ${subject}`;
+ applyLocals(locals);
+
+ // Attach the templating function.
locals['t'] = i18n.t;
return Promise.all([
diff --git a/services/users.js b/services/users.js
index faea67d75..1dc9bceb6 100644
--- a/services/users.js
+++ b/services/users.js
@@ -610,12 +610,16 @@ module.exports = class UsersService {
* @param {String} token the JSON Web Token to verify
*/
static async verifyPasswordResetToken(token) {
- const {userId, loc} = await UsersService.verifyToken(token, {
+ const {userId, loc, version} = await UsersService.verifyToken(token, {
subject: PASSWORD_RESET_JWT_SUBJECT
});
const user = await UsersService.findById(userId);
+ if (version !== user.__v) {
+ throw new Error('password reset token has expired');
+ }
+
return [user, loc];
}
diff --git a/views/admin/password-reset.ejs b/views/admin/password-reset.ejs
index f02e5b6f8..6725409d1 100644
--- a/views/admin/password-reset.ejs
+++ b/views/admin/password-reset.ejs
@@ -15,11 +15,13 @@
background: #fff;
}
- #root form {
+ .container {
max-width: 300px;
- border: 1px solid lightgrey;
- box-shadow: 0px 10px 24px 2px rgba(0,0,0,0.2);
margin: 50px auto;
+ }
+
+ #root form {
+ display: none;
padding: 15px;
}
@@ -81,7 +83,8 @@