Skip to content

Commit 0df7548

Browse files
author
Martin Krulis
committed
Updating registration and login error messages.
1 parent baf28df commit 0df7548

File tree

7 files changed

+90
-32
lines changed

7 files changed

+90
-32
lines changed

src/components/forms/RegistrationCAS/RegistrationCAS.js

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,49 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
3-
import { FormattedMessage, FormattedHTMLMessage } from 'react-intl';
3+
import { FormattedMessage, FormattedHTMLMessage, intlShape, injectIntl } from 'react-intl';
44
import { Alert, FormControl, ControlLabel, Well } from 'react-bootstrap';
55

66
import Box from '../../widgets/Box';
77
import AuthenticationButtonContainer from '../../../containers/CAS/AuthenticationButtonContainer';
88
import { safeGet } from '../../../helpers/common';
99
import { getConfigVar } from '../../../helpers/config';
10+
import { getErrorMessage } from '../../../locales/apiErrorMessages';
1011

1112
const casHelpdeskUrl = getConfigVar('CAS_HELPDESK_URL');
1213

1314
class RegistrationCAS extends Component {
14-
state = { instanceId: null, failed: false };
15+
state = { instanceId: null, lastError: null };
1516

1617
changeInstance = ev => {
1718
this.setState({ instanceId: ev.target.value });
1819
};
1920

2021
ticketObtainedHandler = (ticket, clientUrl) => {
21-
const { instances, onSubmit } = this.props;
22-
this.setState({ failed: false });
22+
const {
23+
instances,
24+
onSubmit,
25+
intl: { formatMessage },
26+
} = this.props;
27+
this.setState({ lastError: null });
2328
onSubmit({
2429
instanceId: this.state.instanceId || safeGet(instances, [0, 'id']),
2530
serviceId: 'cas-uk',
2631
clientUrl,
2732
ticket,
28-
});
33+
}).catch(err =>
34+
err.json().then(body => this.setState({ lastError: getErrorMessage(formatMessage)(body && body.error) }))
35+
);
2936
};
3037

3138
failedHandler = () => {
32-
this.setState({ failed: true });
39+
this.setState({
40+
lastError: (
41+
<FormattedMessage
42+
id="app.externalRegistrationForm.uiFailure"
43+
defaultMessage="Unexpected UI failure. Communication between frontend and external registrator has been disrupted."
44+
/>
45+
),
46+
});
3347
};
3448

3549
render() {
@@ -40,26 +54,21 @@ class RegistrationCAS extends Component {
4054
footer={
4155
<div className="text-center">
4256
<AuthenticationButtonContainer
43-
retry={this.state.failed}
57+
retry={this.state.lastError !== null}
4458
onTicketObtained={this.ticketObtainedHandler}
4559
onFailed={this.failedHandler}
4660
/>
4761
</div>
4862
}>
4963
<div>
50-
{this.state.failed && (
64+
{this.state.lastError !== null && (
5165
<Alert bsStyle="danger">
52-
<p>
53-
<FormattedMessage
54-
id="app.externalRegistrationForm.failed"
55-
defaultMessage="Registration failed. Please check the notification message for more details."
56-
/>
57-
</p>
66+
<p>{this.state.lastError}</p>
5867
{casHelpdeskUrl && casHelpdeskUrl.startsWith('mailto:') && (
5968
<p>
6069
<FormattedHTMLMessage
6170
id="app.externalRegistrationForm.failedHelpdeskMail"
62-
defaultMessage=" If the problems prevail, please, contact the <a href='{casHelpdeskUrl}'>technical support</a>."
71+
defaultMessage=" If the problem prevails, please, contact the <a href='{casHelpdeskUrl}'>technical support</a>."
6372
values={{ casHelpdeskUrl }}
6473
/>
6574
</p>
@@ -68,7 +77,7 @@ class RegistrationCAS extends Component {
6877
<p>
6978
<FormattedHTMLMessage
7079
id="app.externalRegistrationForm.failedHelpdeskPage"
71-
defaultMessage=" If the problems prevail, please, visit the <a href='{casHelpdeskUrl}'>help page</a>."
80+
defaultMessage=" If the problem prevails, please, visit the <a href='{casHelpdeskUrl}'>help page</a>."
7281
values={{ casHelpdeskUrl }}
7382
/>
7483
</p>
@@ -102,6 +111,7 @@ class RegistrationCAS extends Component {
102111
RegistrationCAS.propTypes = {
103112
instances: PropTypes.array.isRequired,
104113
onSubmit: PropTypes.func.isRequired,
114+
intl: intlShape,
105115
};
106116

107-
export default RegistrationCAS;
117+
export default injectIntl(RegistrationCAS);

src/containers/CAS/LoginBox.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ export default connect(
4545
login: (ticket, clientUrl, popupWindow = null) => {
4646
const login = externalLogin(loginServices.external.CAS_UK_TICKET);
4747
const promise = dispatch(login({ ticket, clientUrl }, popupWindow));
48-
return afterLogin ? promise.then(afterLogin) : promise;
48+
return (afterLogin ? promise.then(afterLogin) : promise).catch(_ => {
49+
/* intentionally ignoring the error */
50+
});
4951
},
5052
})
5153
)(LoginBox);

src/locales/apiErrorMessages.js

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,37 @@
11
import React from 'react';
2-
import { FormattedMessage } from 'react-intl';
2+
import { FormattedMessage, defineMessages } from 'react-intl';
33

4-
const apiErrorCodes = {
5-
'400-101': <FormattedMessage id="app.apiErrorCodes.400-101" defaultMessage="The credentials are not valid." />,
6-
'403-001': <FormattedMessage id="app.apiErrorCodes.403-001" defaultMessage="The user account does not exist." />,
7-
'403-002': <FormattedMessage id="app.apiErrorCodes.403-002" defaultMessage="The user account has been disabled." />,
8-
};
4+
const apiErrorCodes = defineMessages({
5+
'400-001': {
6+
id: 'app.apiErrorCodes.400-001',
7+
defaultMessage:
8+
'The user has multiple e-mail addresses and multiple matching accounts already exist. Accounts cannot be associated due to ambiguity.',
9+
},
10+
'400-101': { id: 'app.apiErrorCodes.400-101', defaultMessage: 'The credentials are not valid.' },
11+
'400-106': { id: 'app.apiErrorCodes.400-106', defaultMessage: 'The user is already registered.' },
12+
'403-001': { id: 'app.apiErrorCodes.403-001', defaultMessage: 'The user account does not exist.' },
13+
'403-002': { id: 'app.apiErrorCodes.403-002', defaultMessage: 'The user account has been disabled.' },
14+
'409_100': {
15+
id: 'app.apiErrorCodes.409_100',
16+
defaultMessage:
17+
'The user data received from the CAS contain no affiliation attributes that would match current registration policies.',
18+
},
19+
'409_101': {
20+
id: 'app.apiErrorCodes.409_101',
21+
defaultMessage: 'The user attributes received from the CAS do not contain an email address, which is required.',
22+
},
23+
'409_102': {
24+
id: 'app.apiErrorCodes.409_102',
25+
defaultMessage: 'The user attributes received from the CAS are incomplete.',
26+
},
27+
'500-000': { id: 'app.apiErrorCodes.500-000', defaultMessage: 'Unexpected internal error.' },
28+
});
929

10-
export const getErrorMessage = error => {
30+
export const getErrorMessage = formatMessage => error => {
1131
const code = error && error.code;
32+
const parameters = (error && error.parameters) || {};
1233
if (code && apiErrorCodes[code]) {
13-
return apiErrorCodes[code];
34+
return formatMessage(apiErrorCodes[code], parameters);
1435
} else {
1536
return (
1637
(error && error.message) || (

src/locales/cs.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@
3030
"app.addUserContainer.emptyQuery": "Žádné výsledky. Zadejte vyhledávací dotaz...",
3131
"app.allowUserButton.confirmAllow": "Uživatel mohl být zablokován z dobrého důvodu. Opravdu si přejete povolit účet?",
3232
"app.allowUserButton.confirmDisallow": "Pokud zakážete tento uživatelský účet, uživatel nebude moci provést žádnou operaci ani vidět žádná data. Opravdu si přejete účet zakázat?",
33+
"app.apiErrorCodes.400-001": "Uživatel má více registrovaných e-malových adres, které odpovídají více než jednomu existujícímu účtu. Asociace účtů není možná z důvodu nejednoznačnosti.",
3334
"app.apiErrorCodes.400-101": "Nesprávné přihlašovací údaje.",
35+
"app.apiErrorCodes.400-106": "Uživatel je již registrován.",
3436
"app.apiErrorCodes.403-001": "Uživatelský účet neexistuje.",
3537
"app.apiErrorCodes.403-002": "Uživatelský účet byl zablokován.",
38+
"app.apiErrorCodes.409_100": "Uživatelská data získaná z CASu neobsahují údaje o vztahu k instituci, které by odpovídaly povoleným registračním pravidlům.",
39+
"app.apiErrorCodes.409_101": "Uživatelská data získaná z CASu neobsahují e-mailovou adresu, což je vyžadováno.",
40+
"app.apiErrorCodes.409_102": "Uživatelská data získaná z CASu jsou neúplná.",
41+
"app.apiErrorCodes.500-000": "Neočekávaná vnitřní chyba.",
3642
"app.apiErrorCodes.unknown": "Neznámá chyba API.",
3743
"app.archive.archivedGroups": "Všechny skupiny včetně archivních",
3844
"app.archive.description": "Seznam archivních skupin.",
@@ -699,6 +705,7 @@
699705
"app.externalRegistrationForm.instance": "Instance:",
700706
"app.externalRegistrationForm.password": "Heslo:",
701707
"app.externalRegistrationForm.title": "Vytvořit ReCodEx účet s použitím CAS",
708+
"app.externalRegistrationForm.uiFailure": "Neočekávaná chyba v uživatelském rozhraní. Komunikace mezi frontendem a externím registrátorem byla přerušena.",
702709
"app.externalRegistrationForm.username": "Uživatelské jméno CAS (UKČO):",
703710
"app.externalRegistrationForm.validation.emptyPassword": "Heslo nemůže být prázdné.",
704711
"app.externalRegistrationForm.validation.emptyUsername": "Uživatelské jméno nemůže být prázdné.",

src/locales/en.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@
3030
"app.addUserContainer.emptyQuery": "No results. Enter a search query...",
3131
"app.allowUserButton.confirmAllow": "The user may have been disabled for a reason. Do you really wish to enable the account?",
3232
"app.allowUserButton.confirmDisallow": "If you disable the account, the user will not be able to perform any operation nor access any data. Do you wish to disable it?",
33+
"app.apiErrorCodes.400-001": "The user has multiple e-mail addresses and multiple matching accounts already exist. Accounts cannot be associated due to ambiguity.",
3334
"app.apiErrorCodes.400-101": "The credentials are not valid.",
35+
"app.apiErrorCodes.400-106": "The user is already registered.",
3436
"app.apiErrorCodes.403-001": "The user account does not exist.",
3537
"app.apiErrorCodes.403-002": "The user account has been disabled.",
38+
"app.apiErrorCodes.409_100": "The user data received from the CAS contain no affiliation attributes that would match current registration policies.",
39+
"app.apiErrorCodes.409_101": "The user attributes received from the CAS do not contain an email address, which is required.",
40+
"app.apiErrorCodes.409_102": "The user attributes received from the CAS are incomplete.",
41+
"app.apiErrorCodes.500-000": "Unexpected internal error.",
3642
"app.apiErrorCodes.unknown": "Unknown API error.",
3743
"app.archive.archivedGroups": "All Groups Including Archived",
3844
"app.archive.description": "List of archived groups.",
@@ -693,12 +699,13 @@
693699
"app.externalLinkPreview.showAsMarkdown": "Show as markdown",
694700
"app.externalLinkPreview.title": "Preview",
695701
"app.externalRegistrationForm.failed": "Registration failed. Please check the notification message for more details.",
696-
"app.externalRegistrationForm.failedHelpdeskMail": "If the problems prevail, please, contact the <a href='{casHelpdeskUrl}'>technical support</a>.",
697-
"app.externalRegistrationForm.failedHelpdeskPage": "If the problems prevail, please, visit the <a href='{casHelpdeskUrl}'>help page</a>.",
702+
"app.externalRegistrationForm.failedHelpdeskMail": "If the problem prevails, please, contact the <a href='{casHelpdeskUrl}'>technical support</a>.",
703+
"app.externalRegistrationForm.failedHelpdeskPage": "If the problem prevails, please, visit the <a href='{casHelpdeskUrl}'>help page</a>.",
698704
"app.externalRegistrationForm.gdprConfirm": "I agree that my personal data will be processed by ReCodEx in accordance with GDPR policy.",
699705
"app.externalRegistrationForm.instance": "Instance:",
700706
"app.externalRegistrationForm.password": "Password:",
701707
"app.externalRegistrationForm.title": "Create ReCodEx account using CAS",
708+
"app.externalRegistrationForm.uiFailure": "Unexpected UI failure. Communication between frontend and external registrator has been disrupted.",
702709
"app.externalRegistrationForm.username": "CAS login (UKČO):",
703710
"app.externalRegistrationForm.validation.emptyPassword": "Password cannot be empty.",
704711
"app.externalRegistrationForm.validation.emptyUsername": "Username cannot be empty.",

src/locales/whitelist_en.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@
3030
"app.addUserContainer.emptyQuery",
3131
"app.allowUserButton.confirmAllow",
3232
"app.allowUserButton.confirmDisallow",
33+
"app.apiErrorCodes.400-001",
3334
"app.apiErrorCodes.400-101",
35+
"app.apiErrorCodes.400-106",
3436
"app.apiErrorCodes.403-001",
3537
"app.apiErrorCodes.403-002",
38+
"app.apiErrorCodes.409_100",
39+
"app.apiErrorCodes.409_101",
40+
"app.apiErrorCodes.409_102",
41+
"app.apiErrorCodes.500-000",
3642
"app.apiErrorCodes.unknown",
3743
"app.archive.archivedGroups",
3844
"app.archive.description",
@@ -699,6 +705,7 @@
699705
"app.externalRegistrationForm.instance",
700706
"app.externalRegistrationForm.password",
701707
"app.externalRegistrationForm.title",
708+
"app.externalRegistrationForm.uiFailure",
702709
"app.externalRegistrationForm.username",
703710
"app.externalRegistrationForm.validation.emptyPassword",
704711
"app.externalRegistrationForm.validation.emptyUsername",

src/pages/Login/Login.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
33
import ImmutablePropTypes from 'react-immutable-proptypes';
4-
import { FormattedMessage } from 'react-intl';
4+
import { FormattedMessage, intlShape, injectIntl } from 'react-intl';
55
import { connect } from 'react-redux';
66
import { Link } from 'react-router-dom';
77
import { reset, SubmissionError } from 'redux-form';
@@ -70,13 +70,16 @@ class Login extends Component {
7070
* Log the user in (by given credentials) and then perform the redirect.
7171
*/
7272
loginAndRedirect = credentials => {
73-
const { login } = this.props;
73+
const {
74+
login,
75+
intl: { formatMessage },
76+
} = this.props;
7477
return login(credentials)
7578
.then(this.redirectAfterLogin)
7679
.catch(e =>
7780
// Translate fetch response error into form error message...
7881
e.json().then(body => {
79-
throw new SubmissionError({ _error: getErrorMessage(body && body.error) });
82+
throw new SubmissionError({ _error: getErrorMessage(formatMessage)(body && body.error) });
8083
})
8184
);
8285
};
@@ -178,6 +181,7 @@ Login.propTypes = {
178181
loggedInUser: ImmutablePropTypes.map,
179182
reset: PropTypes.func.isRequired,
180183
links: PropTypes.object.isRequired,
184+
intl: intlShape,
181185
};
182186

183187
export default withLinks(
@@ -193,5 +197,5 @@ export default withLinks(
193197
dispatch(reset('login'));
194198
},
195199
})
196-
)(Login)
200+
)(injectIntl(Login))
197201
);

0 commit comments

Comments
 (0)