Skip to content

Commit

Permalink
Fixes #1761: feedback for password changing
Browse files Browse the repository at this point in the history
  • Loading branch information
mbarto committed May 12, 2017
1 parent 5b0b8c3 commit fe65215
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 6 deletions.
14 changes: 13 additions & 1 deletion web/client/components/security/forms/PasswordReset.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ const PasswordReset = React.createClass({

// I18N
newPasswordText: React.PropTypes.node,
passwordCheckText: React.PropTypes.node
passwordCheckText: React.PropTypes.node,
changed: React.PropTypes.bool,
error: React.PropTypes.object
},
contextTypes: {
messages: React.PropTypes.object
Expand Down Expand Up @@ -69,6 +71,15 @@ const PasswordReset = React.createClass({
}
return null;
},
renderStatus() {
if (this.props.changed) {
return <Alert bsStyle="success"><Message msgId="user.passwordChanged"/></Alert>;
}
if (this.props.error) {
return <Alert bsStyle="danger"><Message msgId="user.passwordError"/></Alert>;
}
return null;
},
render() {
return (<form ref="loginForm" onSubmit={this.handleSubmit}>
<FormGroup validationState={this.getPwStyle()}>
Expand All @@ -91,6 +102,7 @@ const PasswordReset = React.createClass({
placeholder={LocaleUtils.getMessageById(this.context.messages, "user.retypePwd")} />
</FormGroup>
{this.renderWarning()}
{this.renderStatus()}
</form>);
},
isValid(password, passwordcheck) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ describe("Test the password reset form component", () => {
expect(cmp).toExist();
});

it('alert for success', () => {
const cmp = ReactDOM.render(<PasswordReset changed={true}/>, document.getElementById("container"));
expect(cmp).toExist();
let alert = ReactDOM.findDOMNode(ReactTestUtils.scryRenderedDOMComponentsWithClass(cmp, "alert-success")[0]);
expect(alert).toExist();
});

it('alert for error', () => {
const cmp = ReactDOM.render(<PasswordReset error={{message: 'error'}}/>, document.getElementById("container"));
expect(cmp).toExist();
let alert = ReactDOM.findDOMNode(ReactTestUtils.scryRenderedDOMComponentsWithClass(cmp, "alert-danger")[0]);
expect(alert).toExist();
});

it('test component validity', () => {
const cmp = ReactDOM.render(<PasswordReset />, document.getElementById("container"));
expect(cmp).toExist();
Expand Down
5 changes: 4 additions & 1 deletion web/client/components/security/modals/PasswordResetModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ const PasswordResetModal = React.createClass({
closeGlyph: React.PropTypes.string,
style: React.PropTypes.object,
buttonSize: React.PropTypes.string,
includeCloseButton: React.PropTypes.bool
includeCloseButton: React.PropTypes.bool,
changed: React.PropTypes.bool,
error: React.PropTypes.object
},
getDefaultProps() {
return {
Expand Down Expand Up @@ -92,6 +94,7 @@ const PasswordResetModal = React.createClass({
},
getBody() {
return (<PasswordReset role="body" ref="passwordResetForm"
changed={this.props.changed}
onChange={(password, valid) => {
this.setState({passwordValid: valid, password});
}} />);
Expand Down
4 changes: 3 additions & 1 deletion web/client/plugins/login/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ const UserDetails = connect((state) => ({

const PasswordReset = connect((state) => ({
user: state.security && state.security.user,
show: state.controls.ResetPassword && state.controls.ResetPassword.enabled
show: state.controls.ResetPassword && state.controls.ResetPassword.enabled,
changed: state.security && state.security.passwordChanged && true || false,
error: state.security && state.security.passwordError
}), {
onPasswordChange: (user, pass) => { return geoStoreChangePassword(user, pass); },
onClose: setControlProperty.bind(null, "ResetPassword", "enabled", false, false)
Expand Down
18 changes: 17 additions & 1 deletion web/client/reducers/__tests__/security-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/
var expect = require('expect');
var security = require('../security');
var {LOGIN_SUCCESS, LOGIN_FAIL, RESET_ERROR, LOGOUT} = require('../../actions/security');
var {LOGIN_SUCCESS, LOGIN_FAIL, RESET_ERROR, LOGOUT, CHANGE_PASSWORD_SUCCESS, CHANGE_PASSWORD_FAIL} = require('../../actions/security');
var {USERMANAGER_UPDATE_USER} = require('../../actions/users');

describe('Test the security reducer', () => {
Expand Down Expand Up @@ -87,4 +87,20 @@ describe('Test the security reducer', () => {
expect(state).toExist();
expect(state.user.name).toBe("user");
});

it('change password success', () => {
let state = security({user: testUser.User}, {type: CHANGE_PASSWORD_SUCCESS, user: {
id: 6,
password: "newpassword"
}});
expect(state).toExist();
expect(state.user.password).toBe("newpassword");
expect(state.passwordChanged).toBe(true);
});

it('change password fail', () => {
let state = security({user: testUser.User}, {type: CHANGE_PASSWORD_FAIL, error: {message: 'error'}});
expect(state).toExist();
expect(state.passwordError).toExist();
});
});
20 changes: 18 additions & 2 deletions web/client/reducers/security.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
* LICENSE file in the root directory of this source tree.
*/

const { LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT, CHANGE_PASSWORD_SUCCESS, RESET_ERROR } = require('../actions/security');
const { LOGIN_SUCCESS, LOGIN_FAIL, LOGOUT, CHANGE_PASSWORD_SUCCESS, CHANGE_PASSWORD_FAIL, RESET_ERROR } = require('../actions/security');
const { SET_CONTROL_PROPERTY } = require('../actions/controls');
const { USERMANAGER_UPDATE_USER } = require('../actions/users');

const SecurityUtils = require('../utils/SecurityUtils');
Expand All @@ -23,6 +24,14 @@ function security(state = {user: null, errorCause: null}, action) {
});
}
return state;
case SET_CONTROL_PROPERTY:
if (action.control === 'ResetPassword' && action.property === 'enabled') {
return assign({}, state, {
passwordChanged: false,
passwordError: null
});
}
return state;
case LOGIN_SUCCESS:
const userAttributes = SecurityUtils.getUserAttributes(action.userDetails.User);
const userUuid = head(userAttributes.filter(attribute => attribute.name.toLowerCase() === 'uuid'));
Expand Down Expand Up @@ -50,7 +59,14 @@ function security(state = {user: null, errorCause: null}, action) {
case CHANGE_PASSWORD_SUCCESS:
return assign({}, state, {
user: assign({}, state.user, assign({}, action.user, {date: new Date().getUTCMilliseconds()})),
authHeader: action.authHeader
authHeader: action.authHeader,
passwordChanged: true,
passwordError: null
});
case CHANGE_PASSWORD_FAIL:
return assign({}, state, {
passwordError: action.error,
passwordChanged: false
});
default:
return state;
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.de-DE
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@
"passwordCheckFail": "Passwörter sind nicht identisch!",
"username": "Benutzername",
"password": "Passwort",
"passwordChanged": "Passwort geändert",
"passwordError": "Fehler beim Ändern des Passworts",
"signIn":"Anmelden",
"loginFail":"Anmeldung gescheitert",
"loginFailedStatusMessages": {
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.en-US
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@
"passwordCheckFail": "Passwords do not match!",
"username": "Username",
"password": "Password",
"passwordChanged": "Password changed",
"passwordError": "Error changing password",
"signIn":"Sign-in",
"loginFail":"Login Fail",
"loginFailedStatusMessages": {
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.fr-FR
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@
"passwordCheckFail": "Les deux mots de passe ne correspondent pas!",
"username": "Nom d'utilisateur",
"password": "Mot de passe",
"passwordChanged": "Mot de passe changé",
"passwordError": "Erreur de changement de mot de passe",
"signIn":"S'authentifier",
"loginFail":"Erreur d'authentification",
"loginFailedStatusMessages": {
Expand Down
2 changes: 2 additions & 0 deletions web/client/translations/data.it-IT
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,8 @@
"passwordCheckFail": "Le due password non corrispondono",
"username": "Username",
"password": "Password",
"passwordChanged": "La password è stata cambiata",
"passwordError": "Errore nel cambio della password",
"signIn":"Accedi",
"loginFail":"Login Fallito",
"loginFailedStatusMessages": {
Expand Down

0 comments on commit fe65215

Please sign in to comment.