diff options
author | Harrison Healey <harrisonmhealey@gmail.com> | 2017-09-05 17:40:35 -0400 |
---|---|---|
committer | Joram Wilander <jwawilander@gmail.com> | 2017-09-05 17:40:35 -0400 |
commit | e30e4cfe3d787e2528419b0d17973eb0fc162d56 (patch) | |
tree | 8b6e989dccfe7308786167c0767f4699f28841ae | |
parent | 6ca443a2556e5d4bade9a9ef7d6d877bf1d6fc45 (diff) | |
download | chat-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.go | 4 | ||||
-rw-r--r-- | api4/user.go | 2 | ||||
-rw-r--r-- | i18n/en.json | 12 | ||||
-rw-r--r-- | utils/api.go | 12 | ||||
-rw-r--r-- | webapp/actions/global_actions.jsx | 16 | ||||
-rw-r--r-- | webapp/components/error_page.jsx | 163 | ||||
-rwxr-xr-x | webapp/i18n/en.json | 11 | ||||
-rw-r--r-- | webapp/routes/route_root.jsx | 2 | ||||
-rw-r--r-- | webapp/routes/route_utils.jsx | 7 | ||||
-rw-r--r-- | webapp/utils/constants.jsx | 5 |
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 = { |