Improve login errors.
--- a/client/src/components/Login.js Mon Jun 26 15:45:50 2017 +0200
+++ b/client/src/components/Login.js Mon Jun 26 16:43:22 2017 +0200
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
-import { Grid, Row, Col, Panel, FormGroup, ControlLabel, FormControl, Button, Alert } from 'react-bootstrap';
+import { Grid, Row, Col, Panel, FormGroup, ControlLabel, FormControl, Button, Alert, HelpBlock } from 'react-bootstrap';
import '../App.css';
import Navbar from './Navbar';
import * as authActions from '../actions/authActions';
@@ -20,10 +20,25 @@
this.props.history.push('/register');
}
- renderError() {
- return (
- <Alert bsStyle="danger">Bad credentials</Alert>
- )
+ renderErrorMessage(errorMessages, fieldname) {
+ if (errorMessages && errorMessages.has(fieldname)) {
+ return errorMessages.get(fieldname).map((message, key) =>
+ <HelpBlock key={ key }>{ message }</HelpBlock>
+ );
+ }
+ }
+
+ renderNonFieldErrors(errorMessages) {
+ if (errorMessages && errorMessages.has('non_field_errors')) {
+ const errors = errorMessages.get('non_field_errors');
+ return (
+ <Alert bsStyle="danger">
+ { errors.map((message, key) =>
+ <p key={ key }>{ message }</p>
+ ) }
+ </Alert>
+ )
+ }
}
render() {
@@ -32,6 +47,8 @@
<h4 className="text-uppercase text-center">Login</h4>
)
+ const errorMessages = this.props.login.get('errorMessages');
+
return (
<div>
<Navbar history={this.props.history} />
@@ -40,15 +57,17 @@
<Col md={6} mdOffset={3}>
<Panel header={ panelHeader } className="panel-login">
<form>
- <FormGroup>
+ <FormGroup validationState={ errorMessages && errorMessages.has('username') ? 'error' : null }>
<ControlLabel>Username</ControlLabel>
<FormControl componentClass="input" type="text" inputRef={ref => { this.username = ref; }} />
+ { this.renderErrorMessage(errorMessages, 'username') }
</FormGroup>
- <FormGroup>
+ <FormGroup validationState={ errorMessages && errorMessages.has('password') ? 'error' : null }>
<ControlLabel>Password</ControlLabel>
<FormControl componentClass="input" type="password" inputRef={ref => { this.password = ref; }} />
+ { this.renderErrorMessage(errorMessages, 'password') }
</FormGroup>
- { this.props.login.error && this.renderError() }
+ { this.renderNonFieldErrors(errorMessages) }
<Button block bsStyle="primary" onClick={this.login}>Login</Button>
</form>
</Panel>
@@ -65,7 +84,6 @@
function mapStateToProps(state, props) {
return {
- currentUser: state['currentUser'],
login: state['login']
};
}
--- a/client/src/components/Register.js Mon Jun 26 15:45:50 2017 +0200
+++ b/client/src/components/Register.js Mon Jun 26 16:43:22 2017 +0200
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
-import { Grid, Row, Col, Panel, FormGroup, ControlLabel, FormControl, Button, Alert, HelpBlock } from 'react-bootstrap';
+import { Grid, Row, Col, Panel, FormGroup, ControlLabel, FormControl, Button, HelpBlock } from 'react-bootstrap';
import '../App.css';
import Navbar from './Navbar';
import * as authActions from '../actions/authActions';
@@ -22,12 +22,6 @@
this.props.history.push('/login');
}
- renderError() {
- return (
- <Alert bsStyle="danger">Bad credentials</Alert>
- )
- }
-
renderErrorMessage(errorMessages, fieldname) {
if (errorMessages && errorMessages.has(fieldname)) {
return errorMessages.get(fieldname).map((message, key) =>
--- a/client/src/constants/actionTypes.js Mon Jun 26 15:45:50 2017 +0200
+++ b/client/src/constants/actionTypes.js Mon Jun 26 16:43:22 2017 +0200
@@ -10,14 +10,15 @@
export const AUTH_LOGIN_SUBMIT = 'AUTH_LOGIN_SUBMIT';
export const AUTH_LOGIN_REQUEST = 'AUTH_LOGIN_REQUEST';
-export const AUTH_LOGIN_SUCCESS = 'AUTH_LOGIN_SUCCESS';
export const AUTH_LOGIN_ERROR = 'AUTH_LOGIN_ERROR';
export const AUTH_REGISTER_SUBMIT = 'AUTH_REGISTER_SUBMIT';
export const AUTH_REGISTER_REQUEST = 'AUTH_REGISTER_REQUEST';
-export const AUTH_REGISTER_SUCCESS = 'AUTH_REGISTER_SUCCESS';
export const AUTH_REGISTER_ERROR = 'AUTH_REGISTER_ERROR';
+// Used both by login & register
+export const AUTH_LOGIN_SUCCESS = 'AUTH_LOGIN_SUCCESS';
+
export const AUTH_STORE_TOKEN_ASYNC = 'AUTH_STORE_TOKEN_ASYNC';
export const AUTH_STORE_TOKEN = 'AUTH_STORE_TOKEN';
export const AUTH_LOGOUT = 'AUTH_LOGOUT';
--- a/client/src/reducers/authReducer.js Mon Jun 26 15:45:50 2017 +0200
+++ b/client/src/reducers/authReducer.js Mon Jun 26 16:43:22 2017 +0200
@@ -8,7 +8,6 @@
case types.AUTH_LOGOUT:
return false;
case types.AUTH_LOGIN_SUCCESS:
- case types.AUTH_REGISTER_SUCCESS:
return true;
default:
return state;
@@ -21,7 +20,6 @@
case types.AUTH_LOGOUT:
return null;
case types.AUTH_LOGIN_SUCCESS:
- case types.AUTH_REGISTER_SUCCESS:
return new UserRecord(action.user);
case types.USER_UPDATE_SETTINGS:
return state.merge({
@@ -49,6 +47,7 @@
loading: false,
success: false,
error: false,
+ errorMessages: Immutable.Map({})
});
export const login = (state = loginState, action) => {
@@ -65,6 +64,7 @@
loading: false,
success: action.type === types.AUTH_LOGIN_SUCCESS,
error: action.type === types.AUTH_LOGIN_ERROR,
+ errorMessages: action.type === types.AUTH_LOGIN_ERROR ? Immutable.Map(action.error) : Immutable.Map({})
})
default:
return state
@@ -86,11 +86,11 @@
success: false,
error: false,
})
- case types.AUTH_REGISTER_SUCCESS:
+ case types.AUTH_LOGIN_SUCCESS:
case types.AUTH_REGISTER_ERROR:
return Immutable.Map({
loading: false,
- success: action.type === types.AUTH_REGISTER_SUCCESS,
+ success: action.type === types.AUTH_LOGIN_SUCCESS,
error: action.type === types.AUTH_REGISTER_ERROR,
errorMessages: action.type === types.AUTH_REGISTER_ERROR ? Immutable.Map(action.error) : Immutable.Map({})
})
--- a/client/src/sagas/authSaga.js Mon Jun 26 15:45:50 2017 +0200
+++ b/client/src/sagas/authSaga.js Mon Jun 26 16:43:22 2017 +0200
@@ -62,7 +62,7 @@
type: types.AUTH_STORE_TOKEN_ASYNC,
token: response.token,
}, {
- type: types.AUTH_REGISTER_SUCCESS,
+ type: types.AUTH_LOGIN_SUCCESS,
user: response.user,
token: response.token,
}];
--- a/client/src/store/configureStore.js Mon Jun 26 15:45:50 2017 +0200
+++ b/client/src/store/configureStore.js Mon Jun 26 16:43:22 2017 +0200
@@ -35,6 +35,7 @@
loading: false,
success: false,
error: false,
+ errorMessages: Immutable.Map({})
}),
register: Immutable.Map({
loading: false,