mirror of
https://github.com/wassname/talk.git
synced 2026-07-06 05:17:19 +08:00
Merge pull request #435 from coralproject/reset-password-redirect
redirect to the parent url when resetting your password
This commit is contained in:
@@ -3,6 +3,7 @@ import translations from './../translations';
|
||||
const lang = new I18n(translations);
|
||||
import * as actions from '../constants/auth';
|
||||
import coralApi, {base} from '../helpers/response';
|
||||
import {pym} from 'coral-framework';
|
||||
|
||||
// Dialog Actions
|
||||
export const showSignInDialog = (offset = 0) => ({type: actions.SHOW_SIGNIN_DIALOG, offset});
|
||||
@@ -135,7 +136,8 @@ const forgotPassowordFailure = () => ({type: actions.FETCH_FORGOT_PASSWORD_FAILU
|
||||
|
||||
export const fetchForgotPassword = email => (dispatch) => {
|
||||
dispatch(forgotPassowordRequest(email));
|
||||
coralApi('/account/password/reset', {method: 'POST', body: {email}})
|
||||
const redirectUri = pym.parentUrl || location.href;
|
||||
coralApi('/account/password/reset', {method: 'POST', body: {email, loc: redirectUri}})
|
||||
.then(() => dispatch(forgotPassowordSuccess()))
|
||||
.catch(error => dispatch(forgotPassowordFailure(error)));
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ router.get('/password-reset', (req, res) => {
|
||||
|
||||
// TODO: store the redirect uri in the token or something fancy.
|
||||
// admins and regular users should probably be redirected to different places.
|
||||
res.render('admin/password-reset', {redirectUri: process.env.TALK_ROOT_URL});
|
||||
res.render('admin/password-reset');
|
||||
});
|
||||
|
||||
router.get('*', (req, res) => {
|
||||
|
||||
@@ -41,14 +41,14 @@ router.post('/email/verify', (req, res, next) => {
|
||||
* if it does, create a JWT and send an email
|
||||
*/
|
||||
router.post('/password/reset', (req, res, next) => {
|
||||
const {email} = req.body;
|
||||
const {email, loc} = req.body;
|
||||
|
||||
if (!email) {
|
||||
return next('you must submit an email when requesting a password.');
|
||||
}
|
||||
|
||||
UsersService
|
||||
.createPasswordResetToken(email)
|
||||
.createPasswordResetToken(email, loc)
|
||||
.then((token) => {
|
||||
|
||||
// Check to see if the token isn't defined.
|
||||
@@ -101,11 +101,11 @@ router.put('/password/reset', (req, res, next) => {
|
||||
|
||||
UsersService
|
||||
.verifyPasswordResetToken(token)
|
||||
.then((user) => {
|
||||
return UsersService.changePassword(user.id, password);
|
||||
.then(([user, loc]) => {
|
||||
return Promise.all([UsersService.changePassword(user.id, password), loc]);
|
||||
})
|
||||
.then(() => {
|
||||
res.status(204).end();
|
||||
.then(([ , loc]) => {
|
||||
res.json({redirect: loc});
|
||||
})
|
||||
.catch(() => {
|
||||
next(authorization.ErrNotAuthorized);
|
||||
|
||||
+23
-4
@@ -1,4 +1,5 @@
|
||||
const bcrypt = require('bcrypt');
|
||||
const url = require('url');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const Wordlist = require('./wordlist');
|
||||
const errors = require('../errors');
|
||||
@@ -13,6 +14,7 @@ const USER_ROLES = require('../models/user').USER_ROLES;
|
||||
const RECAPTCHA_WINDOW_SECONDS = 60 * 10; // 10 minutes.
|
||||
const RECAPTCHA_INCORRECT_TRIGGER = 5; // after 3 incorrect attempts, recaptcha will be required.
|
||||
|
||||
const SettingsService = require('./settings');
|
||||
const ActionsService = require('./actions');
|
||||
|
||||
// In the event that the TALK_SESSION_SECRET is missing but we are testing, then
|
||||
@@ -478,15 +480,18 @@ module.exports = class UsersService {
|
||||
* Creates a JWT from a user email. Only works for local accounts.
|
||||
* @param {String} email of the local user
|
||||
*/
|
||||
static createPasswordResetToken(email) {
|
||||
static createPasswordResetToken(email, loc) {
|
||||
if (!email || typeof email !== 'string') {
|
||||
return Promise.reject('email is required when creating a JWT for resetting passord');
|
||||
}
|
||||
|
||||
email = email.toLowerCase();
|
||||
|
||||
return UserModel.findOne({profiles: {$elemMatch: {id: email}}})
|
||||
.then((user) => {
|
||||
return Promise.all([
|
||||
UserModel.findOne({profiles: {$elemMatch: {id: email}}}),
|
||||
SettingsService.retrieve()
|
||||
])
|
||||
.then(([user, settings]) => {
|
||||
if (!user) {
|
||||
|
||||
// Since we don't want to reveal that the email does/doesn't exist
|
||||
@@ -495,9 +500,21 @@ module.exports = class UsersService {
|
||||
return;
|
||||
}
|
||||
|
||||
let redirectDomain;
|
||||
try {
|
||||
redirectDomain = url.parse(loc).hostname;
|
||||
} catch (e) {
|
||||
return Promise.reject('redirect location is invalid');
|
||||
}
|
||||
|
||||
if (settings.domains.whitelist.indexOf(redirectDomain) === -1) {
|
||||
return Promise.reject('redirect location is not on the list of acceptable domains');
|
||||
}
|
||||
|
||||
const payload = {
|
||||
jti: uuid.v4(),
|
||||
email,
|
||||
loc,
|
||||
userId: user.id,
|
||||
version: user.__v
|
||||
};
|
||||
@@ -542,7 +559,9 @@ module.exports = class UsersService {
|
||||
})
|
||||
|
||||
// TODO: add search by __v as well
|
||||
.then((decoded) => UsersService.findById(decoded.userId));
|
||||
.then((decoded) => {
|
||||
return Promise.all([UsersService.findById(decoded.userId), decoded.loc]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
},
|
||||
data: JSON.stringify({password: password, token: location.hash.replace('#', '')})
|
||||
}).then(function (success) {
|
||||
location.href = '<%= redirectUri %>';
|
||||
location.href = success.redirect;
|
||||
}).catch(function (error) {
|
||||
showError(error.responseText);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user