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 RESET_INFINITE_LOOPS = 'RESET_INFINITE_LOOPS';
|
||||
|
||||
export const RESET_PASSWORD_INITIATE = 'RESET_PASSWORD_INITIATE';
|
||||
|
||||
// eventually, handle errors more specifically and better
|
||||
export const ERROR = 'ERROR';
|
||||
|
|
|
@ -18,9 +18,14 @@ class LoginView extends React.Component {
|
|||
<LoginForm {...this.props} />
|
||||
{/* <h2 className="login__divider">Or</h2>
|
||||
<GithubButton buttonText="Login with Github" /> */}
|
||||
<Link className="form__signup-button" to="/signup">Signup</Link>
|
||||
Or
|
||||
<Link className="form__reset-password-button" to="/reset-password">Reset your password</Link>
|
||||
<p className="form__navigation-options">
|
||||
Don't have an account?
|
||||
<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>
|
||||
</div>
|
||||
);
|
||||
|
@ -42,7 +47,7 @@ function mapDispatchToProps() {
|
|||
function validate(formProps) {
|
||||
const errors = {};
|
||||
if (!formProps.email) {
|
||||
errors.email = 'Please enter a email';
|
||||
errors.email = 'Please enter an email';
|
||||
}
|
||||
if (!formProps.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 { 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 {
|
||||
componentDidMount() {
|
||||
this.refs.forgotPassword.focus();
|
||||
this.refs.resetPassword.focus();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="forgot-password" ref="forgotPassword" tabIndex="0">
|
||||
<h1>Forgot Password</h1>
|
||||
<div className="reset-password" ref="resetPassword" tabIndex="0">
|
||||
<h1>Reset Your Password</h1>
|
||||
<ResetPasswordForm {...this.props} />
|
||||
<Link className="form__login-button" to="/login">Login</Link>
|
||||
or
|
||||
<Link className="form__signup-button" to="/signup">Sign up</Link>
|
||||
|
@ -17,4 +22,28 @@ class ResetPasswordView extends React.Component {
|
|||
</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 {
|
||||
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/signup';
|
||||
@import 'components/login';
|
||||
@import 'components/reset-password';
|
||||
@import 'components/sketch-list';
|
||||
@import 'components/sidebar';
|
||||
@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('/reset-password').post(UserController.resetPasswordInitiate);
|
||||
|
||||
export default router;
|
||||
|
|
Loading…
Reference in a new issue