diff --git a/client/constants.js b/client/constants.js
index 77b3ff51..e9d79ac1 100644
--- a/client/constants.js
+++ b/client/constants.js
@@ -94,6 +94,7 @@ export const DETECT_INFINITE_LOOPS = 'DETECT_INFINITE_LOOPS';
export const RESET_INFINITE_LOOPS = 'RESET_INFINITE_LOOPS';
export const RESET_PASSWORD_INITIATE = 'RESET_PASSWORD_INITIATE';
+export const RESET_PASSWORD_RESET = 'RESET_PASSWORD_RESET';
// eventually, handle errors more specifically and better
export const ERROR = 'ERROR';
diff --git a/client/modules/IDE/components/ResetPasswordForm.js b/client/modules/IDE/components/ResetPasswordForm.js
index d4c7d81a..3efe16b3 100644
--- a/client/modules/IDE/components/ResetPasswordForm.js
+++ b/client/modules/IDE/components/ResetPasswordForm.js
@@ -13,12 +13,12 @@ function ResetPasswordForm(props) {
{...email}
/>
-
+
Reset Your Password
-
Login
- or
-
Sign up
+
+ Your password reset email should arrive shortly. If you don't see it, check
+ in your spam folder as sometimes it can end up there.
+
+
+ Login
+ or
+ Sign up
+
Cancel
);
}
}
+ResetPasswordView.propTypes = {
+ resetPasswordReset: PropTypes.func.isRequired,
+ user: PropTypes.shape({
+ passwordResetInitialized: PropTypes.bool
+ }).isRequired,
+};
+
function mapStateToProps(state) {
return {
user: state.user
@@ -37,13 +59,13 @@ function mapDispatchToProps(dispatch) {
function validate(formProps) {
const errors = {};
if (!formProps.email) {
- errors.email = 'Please enter an email'
+ errors.email = 'Please enter an email';
}
return errors;
}
export default reduxForm({
form: 'reset-password',
- fields: 'email',
+ fields: ['email'],
validate
}, mapStateToProps, mapDispatchToProps)(ResetPasswordView);
diff --git a/client/modules/User/actions.js b/client/modules/User/actions.js
index 2ab47918..b6422d78 100644
--- a/client/modules/User/actions.js
+++ b/client/modules/User/actions.js
@@ -105,15 +105,23 @@ export function logoutUser() {
};
}
-export function initiatePasswordReset(formValues) {
+export function initiateResetPassword(formValues) {
return (dispatch) => {
- axios.post(`${ROOT_URL}/reset-password`, formValues, { withCredentials: true})
- .then(response => {
+ axios.post(`${ROOT_URL}/reset-password`, formValues, { withCredentials: true })
+ .then(() => {
dispatch({
type: ActionTypes.RESET_PASSWORD_INITIATE
});
})
- .catch(response => dispatch({ActionTypes.ERROR}));
- }
+ .catch(response => dispatch({
+ type: ActionTypes.ERROR,
+ message: response.data
+ }));
+ };
}
+export function resetPasswordReset() {
+ return {
+ type: ActionTypes.RESET_PASSWORD_RESET
+ };
+}
diff --git a/client/modules/User/reducers.js b/client/modules/User/reducers.js
index c2f3f8ab..01b6a6fe 100644
--- a/client/modules/User/reducers.js
+++ b/client/modules/User/reducers.js
@@ -13,6 +13,8 @@ const user = (state = { authenticated: false }, action) => {
return {
authenticated: false
};
+ case ActionTypes.RESET_PASSWORD_INITIATE:
+ return Object.assign(state, {}, { resetPasswordInitiate: true });
default:
return state;
}
diff --git a/client/styles/components/_reset-password.scss b/client/styles/components/_reset-password.scss
index 5bd6d662..ad63f76f 100644
--- a/client/styles/components/_reset-password.scss
+++ b/client/styles/components/_reset-password.scss
@@ -6,4 +6,21 @@
justify-content: center;
padding: #{20 / $base-font-size}rem;
align-items: center;
-}
\ No newline at end of file
+}
+
+.reset-password-form__email-input {
+ width: #{300 / $base-font-size}rem;
+}
+
+.reset-password-form__field {
+ margin: #{20 / $base-font-size}rem 0;
+}
+
+.reset-password__submitted {
+ width: #{300 / $base-font-size}rem;
+ display: none;
+ .reset-password--submitted {
+ display: block;
+
+ }
+}
diff --git a/server/controllers/user.controller.js b/server/controllers/user.controller.js
index b3b93c69..d453d37c 100644
--- a/server/controllers/user.controller.js
+++ b/server/controllers/user.controller.js
@@ -1,4 +1,6 @@
import User from '../models/user';
+import crypto from 'crypto';
+import async from 'async';
export function createUser(req, res, next) {
const user = new User({
@@ -74,11 +76,31 @@ export function updatePreferences(req, res) {
}
export function resetPasswordInitiate(req, res) {
- User.findOne({ email: req.body.email }, (err, user) => {
- if (!user) {
- return res.json({message: 'If the email is registered with the editor, an email has been sent.'});
+ async.waterfall([
+ (done) => {
+ crypto.randomBytes(20, function(err, buf) {
+ var token = buf.toString('hex');
+ done(err, token);
+ });
+ },
+ (token, done) => {
+ User.findOne({ email: req.body.email }, (err, user) => {
+ if (!user) {
+ return res.json({success: true, message: 'If the email is registered with the editor, an email has been sent.'});
+ }
+ user.resetPasswordToken = token;
+ user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
+
+ user.save(function(err) {
+ done(err, token, user);
+ });
+ });
}
- user.resetPasswordToken = token;
- user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
+ ], (err) => {
+ if (err) {
+ console.log(err);
+ return res.json({success: false});
+ }
+ return res.json({success: true, message: 'If the email is registered with the editor, an email has been sent.'});
});
}