more password reset stuff
This commit is contained in:
parent
1610b0168d
commit
ea6d30c430
10 changed files with 116 additions and 8 deletions
|
@ -93,5 +93,7 @@ export const END_SKETCH_REFRESH = 'END_SKETCH_REFRESH';
|
||||||
export const DETECT_INFINITE_LOOPS = 'DETECT_INFINITE_LOOPS';
|
export const DETECT_INFINITE_LOOPS = 'DETECT_INFINITE_LOOPS';
|
||||||
export const RESET_INFINITE_LOOPS = 'RESET_INFINITE_LOOPS';
|
export const RESET_INFINITE_LOOPS = 'RESET_INFINITE_LOOPS';
|
||||||
|
|
||||||
|
export const RESET_PASSWORD_INITIATE = 'RESET_PASSWORD_INITIATE';
|
||||||
|
|
||||||
// eventually, handle errors more specifically and better
|
// eventually, handle errors more specifically and better
|
||||||
export const ERROR = 'ERROR';
|
export const ERROR = 'ERROR';
|
||||||
|
|
|
@ -18,9 +18,14 @@ class LoginView extends React.Component {
|
||||||
<LoginForm {...this.props} />
|
<LoginForm {...this.props} />
|
||||||
{/* <h2 className="login__divider">Or</h2>
|
{/* <h2 className="login__divider">Or</h2>
|
||||||
<GithubButton buttonText="Login with Github" /> */}
|
<GithubButton buttonText="Login with Github" /> */}
|
||||||
<Link className="form__signup-button" to="/signup">Signup</Link>
|
<p className="form__navigation-options">
|
||||||
Or
|
Don't have an account?
|
||||||
<Link className="form__reset-password-button" to="/reset-password">Reset your password</Link>
|
<Link className="form__signup-button" to="/signup">Sign Up</Link>
|
||||||
|
</p>
|
||||||
|
<p className="form__navigation-options">
|
||||||
|
Forgot your password?
|
||||||
|
<Link className="form__reset-password-button" to="/reset-password">Reset your password</Link>
|
||||||
|
</p>
|
||||||
<Link className="form__cancel-button" to="/">Cancel</Link>
|
<Link className="form__cancel-button" to="/">Cancel</Link>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -42,7 +47,7 @@ function mapDispatchToProps() {
|
||||||
function validate(formProps) {
|
function validate(formProps) {
|
||||||
const errors = {};
|
const errors = {};
|
||||||
if (!formProps.email) {
|
if (!formProps.email) {
|
||||||
errors.email = 'Please enter a email';
|
errors.email = 'Please enter an email';
|
||||||
}
|
}
|
||||||
if (!formProps.password) {
|
if (!formProps.password) {
|
||||||
errors.password = 'Please enter a password';
|
errors.password = 'Please enter a password';
|
||||||
|
|
32
client/modules/IDE/components/ResetPasswordForm.js
Normal file
32
client/modules/IDE/components/ResetPasswordForm.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
|
||||||
|
function ResetPasswordForm(props) {
|
||||||
|
const { fields: { email }, handleSubmit, submitting, invalid, pristine } = props;
|
||||||
|
return (
|
||||||
|
<form className="reset-password-form" onSubmit={handleSubmit(props.initiateResetPassword.bind(this))}>
|
||||||
|
<p className="reset-password-form__field">
|
||||||
|
<input
|
||||||
|
className="reset-password-form__email-input"
|
||||||
|
aria-label="email"
|
||||||
|
type="text"
|
||||||
|
placeholder="Email used for registration"
|
||||||
|
{...email}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<input type="submit" disabled={submitting || invalid || pristine} value="Send email to reset password" aria-label="Send email to reset password" />
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetPassword.propTypes = {
|
||||||
|
fields: PropTypes.shape({
|
||||||
|
email: PropTypes.object.isRequired
|
||||||
|
}).isRequired,
|
||||||
|
handleSubmit: PropTypes.func.isRequired,
|
||||||
|
initiateResetPassword: PropTypes.func.isRequired,
|
||||||
|
submitting: PropTypes.bool,
|
||||||
|
invalid: PropTypes.bool,
|
||||||
|
pristine: PropTypes.bool
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResetPasswordForm;
|
|
@ -1,15 +1,20 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router';
|
import { Link } from 'react-router';
|
||||||
|
import * as UserActions from '../../User/actions';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { reduxForm } from 'redux-form';
|
||||||
|
import ResetPasswordForm from './ResetPasswordForm';
|
||||||
|
|
||||||
class ResetPasswordView extends React.Component {
|
class ResetPasswordView extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.refs.forgotPassword.focus();
|
this.refs.resetPassword.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="forgot-password" ref="forgotPassword" tabIndex="0">
|
<div className="reset-password" ref="resetPassword" tabIndex="0">
|
||||||
<h1>Forgot Password</h1>
|
<h1>Reset Your Password</h1>
|
||||||
|
<ResetPasswordForm {...this.props} />
|
||||||
<Link className="form__login-button" to="/login">Login</Link>
|
<Link className="form__login-button" to="/login">Login</Link>
|
||||||
or
|
or
|
||||||
<Link className="form__signup-button" to="/signup">Sign up</Link>
|
<Link className="form__signup-button" to="/signup">Sign up</Link>
|
||||||
|
@ -17,4 +22,28 @@ class ResetPasswordView extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
user: state.user
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps(dispatch) {
|
||||||
|
return bindActionCreators(UserActions, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate(formProps) {
|
||||||
|
const errors = {};
|
||||||
|
if (!formProps.email) {
|
||||||
|
errors.email = 'Please enter an email'
|
||||||
|
}
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default reduxForm({
|
||||||
|
form: 'reset-password',
|
||||||
|
fields: 'email',
|
||||||
|
validate
|
||||||
|
}, mapStateToProps, mapDispatchToProps)(ResetPasswordView);
|
||||||
|
|
|
@ -105,3 +105,15 @@ export function logoutUser() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function initiatePasswordReset(formValues) {
|
||||||
|
return (dispatch) => {
|
||||||
|
axios.post(`${ROOT_URL}/reset-password`, formValues, { withCredentials: true})
|
||||||
|
.then(response => {
|
||||||
|
dispatch({
|
||||||
|
type: ActionTypes.RESET_PASSWORD_INITIATE
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(response => dispatch({ActionTypes.ERROR}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,4 +8,10 @@
|
||||||
|
|
||||||
.form__cancel-button {
|
.form__cancel-button {
|
||||||
margin-top: #{10 / $base-font-size}rem;
|
margin-top: #{10 / $base-font-size}rem;
|
||||||
|
font-size: #{12 / $base-font-size}rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form__navigation-options {
|
||||||
|
margin-top: #{10 / $base-font-size}rem;
|
||||||
|
font-size: #{12 / $base-font-size}rem;
|
||||||
}
|
}
|
9
client/styles/components/_reset-password.scss
Normal file
9
client/styles/components/_reset-password.scss
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.reset-password {
|
||||||
|
@extend %modal;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
padding: #{20 / $base-font-size}rem;
|
||||||
|
align-items: center;
|
||||||
|
}
|
|
@ -20,6 +20,7 @@
|
||||||
@import 'components/preferences';
|
@import 'components/preferences';
|
||||||
@import 'components/signup';
|
@import 'components/signup';
|
||||||
@import 'components/login';
|
@import 'components/login';
|
||||||
|
@import 'components/reset-password';
|
||||||
@import 'components/sketch-list';
|
@import 'components/sketch-list';
|
||||||
@import 'components/sidebar';
|
@import 'components/sidebar';
|
||||||
@import 'components/modal';
|
@import 'components/modal';
|
||||||
|
|
|
@ -72,3 +72,13 @@ 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.'});
|
||||||
|
}
|
||||||
|
user.resetPasswordToken = token;
|
||||||
|
user.resetPasswordExpires = Date.now() + 3600000; // 1 hour
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -8,4 +8,6 @@ router.route('/signup/duplicate_check').get(UserController.duplicateUserCheck);
|
||||||
|
|
||||||
router.route('/preferences').put(UserController.updatePreferences);
|
router.route('/preferences').put(UserController.updatePreferences);
|
||||||
|
|
||||||
|
router.route('/reset-password').post(UserController.resetPasswordInitiate);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
Loading…
Reference in a new issue