mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 00:49:03 +00:00
Display server errors on the Reset Password Form (#1154)
This commit is contained in:
parent
3120acf8f3
commit
482ff32be6
6 changed files with 70 additions and 42 deletions
|
|
@ -595,9 +595,12 @@ describe('Kolide - API client', () => {
|
|||
});
|
||||
|
||||
it('return errors correctly for unsuccessful requests', (done) => {
|
||||
const error = 'Resource not found';
|
||||
const errorResponse = {
|
||||
message: 'Resource not found',
|
||||
errors: [{ name: 'base', reason: 'Resource not found' }],
|
||||
};
|
||||
const passwordResetToken = 'invalid-password-reset-token';
|
||||
const request = invalidResetPasswordRequest(newPassword, passwordResetToken, error);
|
||||
const request = invalidResetPasswordRequest(newPassword, passwordResetToken, errorResponse);
|
||||
const formData = {
|
||||
new_password: newPassword,
|
||||
password_reset_token: passwordResetToken,
|
||||
|
|
@ -605,10 +608,7 @@ describe('Kolide - API client', () => {
|
|||
|
||||
Kolide.resetPassword(formData)
|
||||
.then(done)
|
||||
.catch((errorResponse) => {
|
||||
const { response } = errorResponse;
|
||||
|
||||
expect(response).toEqual({ error });
|
||||
.catch(() => {
|
||||
expect(request.isDone()).toEqual(true);
|
||||
done();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { noop } from 'lodash';
|
||||
import { noop, size } from 'lodash';
|
||||
import { push } from 'react-router-redux';
|
||||
|
||||
import debounce from '../../utilities/debounce';
|
||||
import { resetPassword } from '../../redux/nodes/components/ResetPasswordPage/actions';
|
||||
import ResetPasswordForm from '../../components/forms/ResetPasswordForm';
|
||||
import StackedWhiteBoxes from '../../components/StackedWhiteBoxes';
|
||||
import { performRequiredPasswordReset } from '../../redux/nodes/auth/actions';
|
||||
import userInterface from '../../interfaces/user';
|
||||
import debounce from 'utilities/debounce';
|
||||
import { clearResetPasswordErrors, resetPassword } from 'redux/nodes/components/ResetPasswordPage/actions';
|
||||
import ResetPasswordForm from 'components/forms/ResetPasswordForm';
|
||||
import StackedWhiteBoxes from 'components/StackedWhiteBoxes';
|
||||
import { performRequiredPasswordReset } from 'redux/nodes/auth/actions';
|
||||
import userInterface from 'interfaces/user';
|
||||
|
||||
export class ResetPasswordPage extends Component {
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func,
|
||||
errors: PropTypes.shape({
|
||||
base: PropTypes.string,
|
||||
new_password: PropTypes.string,
|
||||
}),
|
||||
token: PropTypes.string,
|
||||
user: userInterface,
|
||||
};
|
||||
|
|
@ -31,6 +35,16 @@ export class ResetPasswordPage extends Component {
|
|||
return false;
|
||||
}
|
||||
|
||||
onResetErrors = () => {
|
||||
const { dispatch, errors } = this.props;
|
||||
|
||||
if (size(errors)) {
|
||||
dispatch(clearResetPasswordErrors);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
onSubmit = debounce((formData) => {
|
||||
const { dispatch, token, user } = this.props;
|
||||
|
||||
|
|
@ -46,7 +60,8 @@ export class ResetPasswordPage extends Component {
|
|||
return dispatch(resetPassword(resetPasswordData))
|
||||
.then(() => {
|
||||
return dispatch(push('/login'));
|
||||
});
|
||||
})
|
||||
.catch(() => false);
|
||||
})
|
||||
|
||||
handleLeave = (location) => {
|
||||
|
|
@ -61,11 +76,13 @@ export class ResetPasswordPage extends Component {
|
|||
const passwordUpdateParams = { password };
|
||||
|
||||
return dispatch(performRequiredPasswordReset(passwordUpdateParams))
|
||||
.then(() => { return dispatch(push('/')); });
|
||||
.then(() => { return dispatch(push('/')); })
|
||||
.catch(() => false);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { handleLeave, onSubmit } = this;
|
||||
const { handleLeave, onResetErrors, onSubmit } = this;
|
||||
const { errors } = this.props;
|
||||
|
||||
return (
|
||||
<StackedWhiteBoxes
|
||||
|
|
@ -73,7 +90,11 @@ export class ResetPasswordPage extends Component {
|
|||
leadText="Create a new password using at least one letter, one numeral and seven characters."
|
||||
onLeave={handleLeave}
|
||||
>
|
||||
<ResetPasswordForm handleSubmit={onSubmit} />
|
||||
<ResetPasswordForm
|
||||
handleSubmit={onSubmit}
|
||||
onChangeFunc={onResetErrors}
|
||||
serverErrors={errors}
|
||||
/>
|
||||
</StackedWhiteBoxes>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import Kolide from '../../../../kolide';
|
||||
import { formatErrorResponse } from 'redux/nodes/entities/base/helpers';
|
||||
import Kolide from 'kolide';
|
||||
|
||||
export const CLEAR_RESET_PASSWORD_ERRORS = 'CLEAR_RESET_PASSWORD_ERRORS';
|
||||
export const RESET_PASSWORD_ERROR = 'RESET_PASSWORD_ERROR';
|
||||
|
|
@ -6,11 +7,11 @@ export const RESET_PASSWORD_REQUEST = 'RESET_PASSWORD_REQUEST';
|
|||
export const RESET_PASSWORD_SUCCESS = 'RESET_PASSWORD_SUCCESS';
|
||||
|
||||
export const clearResetPasswordErrors = { type: CLEAR_RESET_PASSWORD_ERRORS };
|
||||
export const resetPasswordError = (error) => {
|
||||
export const resetPasswordError = (errors) => {
|
||||
return {
|
||||
type: RESET_PASSWORD_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
errors,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -27,9 +28,10 @@ export const resetPassword = (formData) => {
|
|||
return dispatch(resetPasswordSuccess);
|
||||
})
|
||||
.catch((response) => {
|
||||
const { error } = response;
|
||||
const errorsObject = formatErrorResponse(response);
|
||||
|
||||
dispatch(resetPasswordError(errorsObject));
|
||||
|
||||
dispatch(resetPasswordError(error));
|
||||
throw response;
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {
|
|||
} from './actions';
|
||||
|
||||
export const initialState = {
|
||||
error: null,
|
||||
errors: {},
|
||||
loading: false,
|
||||
};
|
||||
|
||||
|
|
@ -15,12 +15,12 @@ export default (state = initialState, { type, payload }) => {
|
|||
case CLEAR_RESET_PASSWORD_ERRORS:
|
||||
return {
|
||||
...state,
|
||||
error: null,
|
||||
errors: {},
|
||||
};
|
||||
case RESET_PASSWORD_ERROR:
|
||||
return {
|
||||
...state,
|
||||
error: payload.error,
|
||||
errors: payload.errors,
|
||||
loading: false,
|
||||
};
|
||||
case RESET_PASSWORD_REQUEST:
|
||||
|
|
@ -31,7 +31,7 @@ export default (state = initialState, { type, payload }) => {
|
|||
case RESET_PASSWORD_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
error: null,
|
||||
errors: {},
|
||||
loading: false,
|
||||
};
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ describe('ResetPasswordPage - reducer', () => {
|
|||
it('changes the loading state to true', () => {
|
||||
const errorState = {
|
||||
...initialState,
|
||||
error: 'Something went wrong',
|
||||
errors: { base: 'Something went wrong' },
|
||||
};
|
||||
|
||||
expect(reducer(errorState, clearResetPasswordErrors)).toEqual({
|
||||
...errorState,
|
||||
error: null,
|
||||
errors: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -45,23 +45,23 @@ describe('ResetPasswordPage - reducer', () => {
|
|||
it('changes the loading state to false and errors to null', () => {
|
||||
const loadingStateWithError = {
|
||||
loading: true,
|
||||
error: 'Something went wrong',
|
||||
errors: { base: 'Something went wrong' },
|
||||
};
|
||||
|
||||
expect(reducer(loadingStateWithError, resetPasswordSuccess)).toEqual({
|
||||
loading: false,
|
||||
error: null,
|
||||
errors: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetPasswordError', () => {
|
||||
it('changes the loading state to false and sets the error state', () => {
|
||||
const error = 'There was an error with your request';
|
||||
const errors = { base: 'There was an error with your request' };
|
||||
|
||||
expect(reducer(initialState, resetPasswordError(error))).toEqual({
|
||||
expect(reducer(initialState, resetPasswordError(errors))).toEqual({
|
||||
...initialState,
|
||||
error,
|
||||
errors,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
|
|
@ -98,18 +98,23 @@ describe('ResetPasswordPage - reducer', () => {
|
|||
new_password: newPassword,
|
||||
password_reset_token: token,
|
||||
};
|
||||
const error = 'Something went wrong';
|
||||
const invalidRequest = invalidResetPasswordRequest(newPassword, token, error);
|
||||
const errors = [{ name: 'base', reason: 'Something went wrong' }];
|
||||
const errorResponse = {
|
||||
status: 422,
|
||||
message: 'Something went wrong',
|
||||
errors,
|
||||
};
|
||||
const invalidRequest = invalidResetPasswordRequest(newPassword, token, errorResponse);
|
||||
const store = reduxMockStore();
|
||||
|
||||
store.dispatch(resetPassword(formData))
|
||||
.then(done)
|
||||
.catch((errorResponse) => {
|
||||
.catch(() => {
|
||||
const actions = store.getActions();
|
||||
const { response } = errorResponse;
|
||||
|
||||
expect(response).toEqual({ error });
|
||||
expect(actions).toInclude(resetPasswordError(error));
|
||||
expect(actions).toInclude(resetPasswordError({
|
||||
base: 'Something went wrong',
|
||||
http_status: 422,
|
||||
}));
|
||||
expect(invalidRequest.isDone()).toEqual(true);
|
||||
done();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -347,13 +347,13 @@ export const validRevokeInviteRequest = (bearerToken, invite) => {
|
|||
.reply(200, {});
|
||||
};
|
||||
|
||||
export const invalidResetPasswordRequest = (password, token, error) => {
|
||||
export const invalidResetPasswordRequest = (password, token, errorResponse) => {
|
||||
return nock('http://localhost:8080')
|
||||
.post('/api/v1/kolide/reset_password', JSON.stringify({
|
||||
new_password: password,
|
||||
password_reset_token: token,
|
||||
}))
|
||||
.reply(422, { error });
|
||||
.reply(422, errorResponse);
|
||||
};
|
||||
|
||||
export const validRunQueryRequest = (bearerToken, data) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue