summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarrison Healey <harrisonmhealey@gmail.com>2017-09-05 17:40:35 -0400
committerJoram Wilander <jwawilander@gmail.com>2017-09-05 17:40:35 -0400
commite30e4cfe3d787e2528419b0d17973eb0fc162d56 (patch)
tree8b6e989dccfe7308786167c0767f4699f28841ae
parent6ca443a2556e5d4bade9a9ef7d6d877bf1d6fc45 (diff)
downloadchat-e30e4cfe3d787e2528419b0d17973eb0fc162d56.tar.gz
chat-e30e4cfe3d787e2528419b0d17973eb0fc162d56.tar.bz2
chat-e30e4cfe3d787e2528419b0d17973eb0fc162d56.zip
PLT-7468 Moved more error pages to use predefined error types (#7378)
* PLT-7468 Moved more errors to use error types * PLT-7468 Moved 404 error page to use error types * Made helper function for rendering external links on error page
-rw-r--r--api4/oauth.go4
-rw-r--r--api4/user.go2
-rw-r--r--i18n/en.json12
-rw-r--r--utils/api.go12
-rw-r--r--webapp/actions/global_actions.jsx16
-rw-r--r--webapp/components/error_page.jsx163
-rwxr-xr-xwebapp/i18n/en.json11
-rw-r--r--webapp/routes/route_root.jsx2
-rw-r--r--webapp/routes/route_utils.jsx7
-rw-r--r--webapp/utils/constants.jsx5
10 files changed, 142 insertions, 92 deletions
diff --git a/api4/oauth.go b/api4/oauth.go
index c3586bbdf..ae5035fdc 100644
--- a/api4/oauth.go
+++ b/api4/oauth.go
@@ -392,9 +392,7 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
if len(code) == 0 {
- err := model.NewAppError("completeOAuth", "api.oauth.complete_oauth.missing_code.app_error", map[string]interface{}{"service": strings.Title(service)}, "URL: "+r.URL.String(), http.StatusBadRequest)
- err.Translate(c.T)
- http.Redirect(w, r, c.GetSiteURLHeader()+"/error?message="+err.Message, http.StatusTemporaryRedirect)
+ http.Redirect(w, r, c.GetSiteURLHeader()+"/error?type=oauth_missing_code&service="+strings.Title(service), http.StatusTemporaryRedirect)
return
}
diff --git a/api4/user.go b/api4/user.go
index 889fe56a3..805ec4241 100644
--- a/api4/user.go
+++ b/api4/user.go
@@ -244,7 +244,7 @@ func setProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
}
if err := r.ParseMultipartForm(*utils.Cfg.FileSettings.MaxFileSize); err != nil {
- c.Err = model.NewAppError("uploadProfileImage", "api.user.upload_profile_user.parse.app_error", nil, "", http.StatusInternalServerError)
+ c.Err = model.NewAppError("uploadProfileImage", "api.user.upload_profile_user.parse.app_error", nil, err.Error(), http.StatusInternalServerError)
return
}
diff --git a/i18n/en.json b/i18n/en.json
index eb7f5e1cc..afca44ef0 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1398,10 +1398,6 @@
"translation": "Missing one or more of response_type, client_id, or redirect_uri"
},
{
- "id": "api.oauth.complete_oauth.missing_code.app_error",
- "translation": "The service provider {{.service}} did not provide an authorization code in the redirect URL.\n\nFor [Google Apps](https://docs.mattermost.com/deployment/sso-google.html) make sure your administrator enabled the Google+ API.\n\nFor [Office 365](https://docs.mattermost.com/deployment/sso-office.html) make sure the administrator of your Microsoft organization has enabled the Mattermost app.\n\nFor [GitLab](https://docs.mattermost.com/deployment/sso-gitlab.html) please make sure you followed the setup instructions.\n\nIf you reviewed the above and are still having trouble with configuration, you may post in our [Troubleshooting forum](https://forum.mattermost.org/c/general/trouble-shoot) where we'll be happy to help with issues during setup."
- },
- {
"id": "api.oauth.delete.permissions.app_error",
"translation": "Invalid permissions to delete the OAuth2 App"
},
@@ -2232,14 +2228,6 @@
"translation": "Sent by "
},
{
- "id": "api.templates.error.link",
- "translation": "Go back to Mattermost"
- },
- {
- "id": "api.templates.error.title",
- "translation": "{{ .SiteName }} needs your help:"
- },
- {
"id": "api.templates.find_teams_body.found",
"translation": "Your request to find teams associated with your email found the following:"
},
diff --git a/utils/api.go b/utils/api.go
index d175e0c13..b206951e1 100644
--- a/utils/api.go
+++ b/utils/api.go
@@ -35,13 +35,8 @@ func GetOriginChecker(r *http.Request) OriginCheckerProc {
}
func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request) {
- T, _ := GetTranslationsAndLocale(w, r)
-
- title := T("api.templates.error.title", map[string]interface{}{"SiteName": ClientCfg["SiteName"]})
message := err.Message
details := err.DetailedError
- link := "/"
- linkMessage := T("api.templates.error.link")
status := http.StatusTemporaryRedirect
if err.StatusCode != http.StatusInternalServerError {
@@ -51,10 +46,7 @@ func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request)
http.Redirect(
w,
r,
- "/error?title="+url.QueryEscape(title)+
- "&message="+url.QueryEscape(message)+
- "&details="+url.QueryEscape(details)+
- "&link="+url.QueryEscape(link)+
- "&linkmessage="+url.QueryEscape(linkMessage),
+ "/error?message="+url.QueryEscape(message)+
+ "&details="+url.QueryEscape(details),
status)
}
diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx
index 025e56f7d..73a57e0b0 100644
--- a/webapp/actions/global_actions.jsx
+++ b/webapp/actions/global_actions.jsx
@@ -17,8 +17,7 @@ import {stopPeriodicStatusUpdates} from 'actions/status_actions.jsx';
import * as WebsocketActions from 'actions/websocket_actions.jsx';
import {trackEvent} from 'actions/diagnostics_actions.jsx';
-import Constants from 'utils/constants.jsx';
-const ActionTypes = Constants.ActionTypes;
+import {ActionTypes, Constants, ErrorPageTypes} from 'utils/constants.jsx';
import EventTypes from 'utils/event_types.jsx';
import WebSocketClient from 'client/web_websocket_client.jsx';
@@ -146,18 +145,7 @@ export function emitPostFocusEvent(postId, onSuccess) {
}
});
} else {
- let link = `${TeamStore.getCurrentTeamRelativeUrl()}/channels/`;
- const channel = ChannelStore.getCurrent();
- if (channel) {
- link += channel.name;
- } else {
- link += 'town-square';
- }
-
- const message = encodeURIComponent(Utils.localizeMessage('permalink.error.access', 'Permalink belongs to a deleted message or to a channel to which you do not have access.'));
- const title = encodeURIComponent(Utils.localizeMessage('permalink.error.title', 'Message Not Found'));
-
- browserHistory.push('/error?message=' + message + '&title=' + title + '&link=' + encodeURIComponent(link));
+ browserHistory.push('/error?type=' + ErrorPageTypes.PERMALINK_NOT_FOUND);
}
}
);
diff --git a/webapp/components/error_page.jsx b/webapp/components/error_page.jsx
index 14f6f2488..4e3e73188 100644
--- a/webapp/components/error_page.jsx
+++ b/webapp/components/error_page.jsx
@@ -8,7 +8,6 @@ import {FormattedMessage} from 'react-intl';
import {Link} from 'react-router/es6';
import {ErrorPageTypes} from 'utils/constants.jsx';
-import * as TextFormatting from 'utils/text_formatting.jsx';
import * as Utils from 'utils/utils.jsx';
export default class ErrorPage extends React.Component {
@@ -16,14 +15,6 @@ export default class ErrorPage extends React.Component {
location: PropTypes.object.isRequired
};
- constructor(props) {
- super(props);
-
- this.renderTitle = this.renderTitle.bind(this);
- this.renderMessage = this.renderMessage.bind(this);
- this.renderLink = this.renderLink.bind(this);
- }
-
componentDidMount() {
$('body').attr('class', 'sticky error');
}
@@ -32,18 +23,29 @@ export default class ErrorPage extends React.Component {
$('body').attr('class', '');
}
- linkFilter(link) {
- return link.startsWith('https://docs.mattermost.com') || link.startsWith('https://forum.mattermost.org');
- }
-
- renderTitle() {
- if (this.props.location.query.type === ErrorPageTypes.LOCAL_STORAGE) {
+ renderTitle = () => {
+ switch (this.props.location.query.type) {
+ case ErrorPageTypes.LOCAL_STORAGE:
return (
<FormattedMessage
id='error.local_storage.title'
defaultMessage='Cannot Load Mattermost'
/>
);
+ case ErrorPageTypes.PERMALINK_NOT_FOUND:
+ return (
+ <FormattedMessage
+ id='permalink.error.title'
+ defaultMessage='Message Not Found'
+ />
+ );
+ case ErrorPageTypes.PAGE_NOT_FOUND:
+ return (
+ <FormattedMessage
+ id='error.not_found.title'
+ defaultMessage='Message Not Found'
+ />
+ );
}
if (this.props.location.query.title) {
@@ -53,8 +55,9 @@ export default class ErrorPage extends React.Component {
return Utils.localizeMessage('error.generic.title', 'Error');
}
- renderMessage() {
- if (this.props.location.query.type === ErrorPageTypes.LOCAL_STORAGE) {
+ renderMessage = () => {
+ switch (this.props.location.query.type) {
+ case ErrorPageTypes.LOCAL_STORAGE:
return (
<div>
<FormattedMessage
@@ -83,45 +86,108 @@ export default class ErrorPage extends React.Component {
</ul>
</div>
);
+ case ErrorPageTypes.PERMALINK_NOT_FOUND:
+ return (
+ <p>
+ <FormattedMessage
+ id='permalink.error.access'
+ defaultMessage='Permalink belongs to a deleted message or to a channel to which you do not have access.'
+ />
+ </p>
+ );
+ case ErrorPageTypes.OAUTH_MISSING_CODE:
+ return (
+ <div>
+ <p>
+ <FormattedMessage
+ id='error.oauth_missing_code'
+ defaultMessage='The service provider {service} did not provide an authorization code in the redirect URL.'
+ values={{
+ service: this.props.location.query.service
+ }}
+ />
+ </p>
+ <p>
+ <FormattedMessage
+ id='error.oauth_missing_code.google'
+ defaultMessage='For {link} make sure your administrator enabled the Google+ API.'
+ values={{
+ link: this.renderLink('https://docs.mattermost.com/deployment/sso-google.html', 'error.oauth_missing_code.google.link', 'Google Apps')
+ }}
+ />
+ </p>
+ <p>
+ <FormattedMessage
+ id='error.oauth_missing_code.office365'
+ defaultMessage='For {link} make sure the administrator of your Microsoft organization has enabled the Mattermost app.'
+ values={{
+ link: this.renderLink('https://docs.mattermost.com/deployment/sso-office.html', 'error.oauth_missing_code.office365.link', 'Office 365')
+ }}
+ />
+ </p>
+ <p>
+ <FormattedMessage
+ id='error.oauth_missing_code.gitlab'
+ defaultMessage='For {link} please make sure you followed the setup instructions.'
+ values={{
+ link: this.renderLink('https://docs.mattermost.com/deployment/sso-gitlab.html', 'error.oauth_missing_code.gitlab.link', 'GitLab')
+ }}
+ />
+ </p>
+ <p>
+ <FormattedMessage
+ id='error.oauth_missing_code.forum'
+ defaultMessage="If you reviewed the above and are still having trouble with configuration, you may post in our {link} where we'll be happy to help with issues during setup."
+ values={{
+ link: this.renderLink('https://forum.mattermost.org/c/trouble-shoot', 'error.oauth_missing_code.forum.link', 'Troubleshooting forum')
+ }}
+ />
+ </p>
+ </div>
+ );
+ case ErrorPageTypes.PAGE_NOT_FOUND:
+ return (
+ <p>
+ <FormattedMessage
+ id='error.not_found.message'
+ defaultMessage='The page you were trying to reach does not exist'
+ />
+ </p>
+ );
}
- let message = this.props.location.query.message;
- if (!message) {
- message = Utils.localizeMessage('error.generic.message', 'An error has occoured.');
+ if (this.props.location.query.message) {
+ return <p>{this.props.location.query.message}</p>;
}
- return <div dangerouslySetInnerHTML={{__html: TextFormatting.formatText(message, {linkFilter: this.linkFilter})}}/>;
+ return (
+ <p>
+ <FormattedMessage
+ id='error.generic.message'
+ defaultMessage='An error has occurred.'
+ />
+ </p>
+ );
}
- renderLink() {
- let link = this.props.location.query.link;
- if (link) {
- link = link.trim();
- } else {
- link = '/';
- }
-
- if (!link.startsWith('/')) {
- // Only allow relative links
- link = '/';
- }
-
- let linkMessage = this.props.location.query.linkmessage;
- if (!linkMessage) {
- linkMessage = Utils.localizeMessage('error.generic.link_message', 'Back to Mattermost');
- }
-
+ renderLink = (url, id, defaultMessage) => {
return (
- <Link to={link}>
- {linkMessage}
- </Link>
+ <a
+ href={url}
+ rel='noopener noreferrer'
+ target='_blank'
+ >
+ <FormattedMessage
+ id={id}
+ defaultMessage={defaultMessage}
+ />
+ </a>
);
}
render() {
const title = this.renderTitle();
const message = this.renderMessage();
- const link = this.renderLink();
return (
<div className='container-fluid'>
@@ -129,9 +195,16 @@ export default class ErrorPage extends React.Component {
<div className='error__icon'>
<i className='fa fa-exclamation-triangle'/>
</div>
- <h2>{title}</h2>
+ <h2>
+ {title}
+ </h2>
{message}
- {link}
+ <Link to='/'>
+ <FormattedMessage
+ id='error.generic.link'
+ defaultMessage='Back to Mattermost'
+ />
+ </Link>
</div>
</div>
);
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index 4bb9542ef..754620969 100755
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -1440,6 +1440,8 @@
"emoji_picker.recent": "Recently Used",
"emoji_picker.search": "Search",
"emoji_picker.symbols": "Symbols",
+ "error.generic.link": "Back to Mattermost",
+ "error.generic.message": "An error has occurred.",
"error.local_storage.help1": "Enable cookies",
"error.local_storage.help2": "Turn off private browsing",
"error.local_storage.help3": "Use a supported browser (IE 11, Chrome 43+, Firefox 38+, Safari 9, Edge)",
@@ -1447,6 +1449,15 @@
"error.not_found.link_message": "Back to Mattermost",
"error.not_found.message": "The page you were trying to reach does not exist",
"error.not_found.title": "Page not found",
+ "error.oauth_missing_code": "The service provider {service} did not provide an authorization code in the redirect URL.",
+ "error.oauth_missing_code.forum": "If you reviewed the above and are still having trouble with configuration, you may post in our {link} where we'll be happy to help with issues during setup.",
+ "error.oauth_missing_code.forum.link": "Troubleshooting forum",
+ "error.oauth_missing_code.gitlab": "For {link} please make sure you followed the setup instructions.",
+ "error.oauth_missing_code.gitlab.link": "GitLab",
+ "error.oauth_missing_code.google": "For {link} make sure your administrator enabled the Google+ API.",
+ "error.oauth_missing_code.google.link": "Google Apps",
+ "error.oauth_missing_code.office365": "For {link} make sure the administrator of your Microsoft organization has enabled the Mattermost app.",
+ "error.oauth_missing_code.office365.link": "Office 365",
"error_bar.expired": "Enterprise license is expired and some features may be disabled. <a href='{link}' target='_blank'>Please renew</a>.",
"error_bar.expiring": "Enterprise license expires on {date}. <a href='{link}' target='_blank'>Please renew</a>.",
"error_bar.past_grace": "Enterprise license is expired and some features may be disabled. Please contact your System Administrator for details.",
diff --git a/webapp/routes/route_root.jsx b/webapp/routes/route_root.jsx
index f633049ce..8a1f440be 100644
--- a/webapp/routes/route_root.jsx
+++ b/webapp/routes/route_root.jsx
@@ -120,7 +120,7 @@ export default {
{
path: 'error',
getComponents: (location, callback) => {
- System.import('components/error_page.jsx').then(RouteUtils.importComponentSuccess(callback));
+ System.import('components/error_page').then(RouteUtils.importComponentSuccess(callback));
}
},
{
diff --git a/webapp/routes/route_utils.jsx b/webapp/routes/route_utils.jsx
index c5d889017..17fdc291d 100644
--- a/webapp/routes/route_utils.jsx
+++ b/webapp/routes/route_utils.jsx
@@ -1,8 +1,8 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import * as Utils from 'utils/utils.jsx';
import UserStore from 'stores/user_store.jsx';
+import {ErrorPageTypes} from 'utils/constants.jsx';
export function importComponentSuccess(callback) {
return (comp) => callback(null, comp.default);
@@ -13,10 +13,7 @@ export function createGetChildComponentsFunction(arrayOfComponents) {
}
export const notFoundParams = {
- title: Utils.localizeMessage('error.not_found.title', 'Page not found'),
- message: Utils.localizeMessage('error.not_found.message', 'The page you were trying to reach does not exist'),
- link: '/',
- linkmessage: Utils.localizeMessage('error.not_found.link_message', 'Back to Mattermost')
+ type: ErrorPageTypes.PAGE_NOT_FOUND
};
const mfaPaths = [
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 858ea6bbf..0741299fd 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -303,7 +303,10 @@ export const StatTypes = keyMirror({
});
export const ErrorPageTypes = {
- LOCAL_STORAGE: 'local_storage'
+ LOCAL_STORAGE: 'local_storage',
+ OAUTH_MISSING_CODE: 'oauth_missing_code',
+ PAGE_NOT_FOUND: 'page_not_found',
+ PERMALINK_NOT_FOUND: 'permalink_not_found'
};
export const JobTypes = {