Commit 4a4c9839 authored by Tom Quirk's avatar Tom Quirk Committed by Nikola Milojevic

Add links to Jira-related error messages

Add frontend support for error messages that contain links.
This is achieved by v-safe-html.

This commit also adds links to relevent error messages defined in Rails.

Changelog: changed
parent c9d4a405
...@@ -67,9 +67,19 @@ module Jira ...@@ -67,9 +67,19 @@ module Jira
ServiceResponse.error(message: error_message(e)) ServiceResponse.error(message: error_message(e))
end end
def auth_docs_link_start
auth_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira', anchor: 'authentication-in-jira')
'<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: auth_docs_link_url }
end
def config_docs_link_start
config_docs_link_url = Rails.application.routes.url_helpers.help_page_path('integration/jira/configure')
'<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: config_docs_link_url }
end
def error_message(error) def error_message(error)
reportable_error_message(error) || reportable_error_message(error) ||
s_('JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again.') s_('JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again.').html_safe % { docs_link_start: config_docs_link_start, docs_link_end: '</a>'.html_safe }
end end
# Returns a user-facing error message if possible, otherwise `nil`. # Returns a user-facing error message if possible, otherwise `nil`.
...@@ -93,11 +103,11 @@ module Jira ...@@ -93,11 +103,11 @@ module Jira
def reportable_jira_ruby_error_message(error) def reportable_jira_ruby_error_message(error)
case error.message case error.message
when 'Unauthorized' when 'Unauthorized'
s_('JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again.') s_('JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again.').html_safe % { docs_link_start: auth_docs_link_start, docs_link_end: '</a>'.html_safe }
when 'Forbidden' when 'Forbidden'
s_('JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again.') s_('JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again.').html_safe % { docs_link_start: auth_docs_link_start, docs_link_end: '</a>'.html_safe }
when 'Bad Request' when 'Bad Request'
s_('JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again.') s_('JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again.').html_safe % { docs_link_start: config_docs_link_start, docs_link_end: '</a>'.html_safe }
when /errorMessages/ when /errorMessages/
jira_ruby_json_error_message(error.message) jira_ruby_json_error_message(error.message)
end end
...@@ -111,7 +121,7 @@ module Jira ...@@ -111,7 +121,7 @@ module Jira
messages = Rails::Html::FullSanitizer.new.sanitize(messages).presence messages = Rails::Html::FullSanitizer.new.sanitize(messages).presence
return unless messages return unless messages
s_('JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again.') % { messages: messages } s_('JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again.').html_safe % { messages: messages, docs_link_start: config_docs_link_start, docs_link_end: '</a>'.html_safe }
rescue JSON::ParserError rescue JSON::ParserError
end end
end end
......
...@@ -156,7 +156,6 @@ export default { ...@@ -156,7 +156,6 @@ export default {
}, },
]; ];
}, },
getFilteredSearchValue() { getFilteredSearchValue() {
const { labels, search } = this.filterParams || {}; const { labels, search } = this.filterParams || {};
const filteredSearchValue = []; const filteredSearchValue = [];
...@@ -228,12 +227,13 @@ export default { ...@@ -228,12 +227,13 @@ export default {
this.filterParams = filterParams; this.filterParams = filterParams;
}, },
}, },
alertSafeHtmlConfig: { ALLOW_TAGS: ['a'] },
}; };
</script> </script>
<template> <template>
<gl-alert v-if="errorMessage" class="gl-mt-3" variant="danger" :dismissible="false"> <gl-alert v-if="errorMessage" class="gl-mt-3" variant="danger" :dismissible="false">
{{ errorMessage }} <span v-safe-html:[$options.alertSafeHtmlConfig]="errorMessage"></span>
</gl-alert> </gl-alert>
<issuable-list <issuable-list
v-else v-else
......
...@@ -319,9 +319,11 @@ describe('ExternalIssuesListRoot', () => { ...@@ -319,9 +319,11 @@ describe('ExternalIssuesListRoot', () => {
describe('when request fails', () => { describe('when request fails', () => {
it.each` it.each`
APIErrors | expectedRenderedErrorMessage APIErrors | expectedRenderedErrorMessage
${['API error']} | ${'API error'} ${['API error']} | ${'API error'}
${undefined} | ${i18n.errorFetchingIssues} ${['API <a href="gitlab.com">error</a>']} | ${'API error'}
${['API <script src="hax0r.xyz">error</script>']} | ${'API'}
${undefined} | ${i18n.errorFetchingIssues}
`( `(
'displays error alert with "$expectedRenderedErrorMessage" when API responds with "$APIErrors"', 'displays error alert with "$expectedRenderedErrorMessage" when API responds with "$APIErrors"',
async ({ APIErrors, expectedRenderedErrorMessage }) => { async ({ APIErrors, expectedRenderedErrorMessage }) => {
......
...@@ -19493,19 +19493,19 @@ msgstr "" ...@@ -19493,19 +19493,19 @@ msgstr ""
msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again." msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. Try your request again."
msgstr "" msgstr ""
msgid "JiraRequest|An error occurred while requesting data from Jira. Check your Jira integration configuration and try again." msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr "" msgstr ""
msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your Jira integration configuration and try again." msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
msgstr "" msgstr ""
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again." msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr "" msgstr ""
msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your Jira integration credentials and try again." msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr "" msgstr ""
msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your Jira integration credentials and try again." msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
msgstr "" msgstr ""
msgid "JiraService| on branch %{branch_link}" msgid "JiraService| on branch %{branch_link}"
......
...@@ -90,7 +90,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do ...@@ -90,7 +90,7 @@ RSpec.describe Resolvers::Projects::JiraProjectsResolver do
end end
it 'raises failure error' do it 'raises failure error' do
expect { resolve_jira_projects }.to raise_error('An error occurred while requesting data from Jira: Some failure. Check your Jira integration configuration and try again.') expect { resolve_jira_projects }.to raise_error(/^An error occurred while requesting data from Jira: Some failure\..*/)
end end
end end
end end
......
...@@ -26,7 +26,7 @@ RSpec.shared_examples 'a service that handles Jira API errors' do ...@@ -26,7 +26,7 @@ RSpec.shared_examples 'a service that handles Jira API errors' do
expect(subject).to be_a(ServiceResponse) expect(subject).to be_a(ServiceResponse)
expect(subject).to be_error expect(subject).to be_error
expect(subject.message).to include(expected_message) expect(subject.message).to start_with(expected_message)
end end
end end
...@@ -39,7 +39,7 @@ RSpec.shared_examples 'a service that handles Jira API errors' do ...@@ -39,7 +39,7 @@ RSpec.shared_examples 'a service that handles Jira API errors' do
let(:error) { '{"errorMessages":' } let(:error) { '{"errorMessages":' }
it 'returns the default error message' do it 'returns the default error message' do
expect(subject.message).to eq('An error occurred while requesting data from Jira. Check your Jira integration configuration and try again.') expect(subject.message).to start_with('An error occurred while requesting data from Jira.')
end end
end end
...@@ -47,7 +47,7 @@ RSpec.shared_examples 'a service that handles Jira API errors' do ...@@ -47,7 +47,7 @@ RSpec.shared_examples 'a service that handles Jira API errors' do
let(:error) { '{"errorMessages":["<script>alert(true)</script>foo"]}' } let(:error) { '{"errorMessages":["<script>alert(true)</script>foo"]}' }
it 'sanitizes it' do it 'sanitizes it' do
expect(subject.message).to eq('An error occurred while requesting data from Jira: foo. Check your Jira integration configuration and try again.') expect(subject.message).to start_with('An error occurred while requesting data from Jira: foo')
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment