Skip to content

Commit 3d58297

Browse files
authored
1680: Improve error when exporting through an account_link (#2756)
* 1680: Improve error when exporting through an account_link * 1680: add sanitation of error-message from codeharbor * 1680: add generic error message to avoid showing sensitive information to the user
1 parent 94b5be6 commit 3d58297

File tree

4 files changed

+57
-7
lines changed

4 files changed

+57
-7
lines changed

app/services/exercise_service/push_external.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,22 @@ def execute
1717
request.headers['Authorization'] = "Bearer #{@codeharbor_link.api_key}"
1818
request.body = body
1919
end
20+
return nil if response.success?
21+
return I18n.t('exercises.export_codeharbor.not_authorized') if response.status == 401
2022

21-
response.success? ? nil : response.body
23+
handle_error(message: response.body)
24+
rescue Faraday::ServerError => e
25+
handle_error(error: e, message: I18n.t('exercises.export_codeharbor.server_error'))
2226
rescue StandardError => e
23-
e.message
27+
handle_error(error: e, message: I18n.t('exercises.export_codeharbor.generic_error'))
2428
end
2529
end
30+
31+
private
32+
33+
def handle_error(message:, error: nil)
34+
Sentry.capture_exception(error) if error.present?
35+
ERB::Util.html_escape(message)
36+
end
2637
end
2738
end

config/locales/de/exercise.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ de:
101101
dialogtitle: Zu CodeHarbor exportieren
102102
error: Es ist ein Fehler bei der Kommunikation mit CodeHarbor aufgetreten.
103103
export_failed: 'Export ist fehlgeschlagen.<br>ID: %{id}<br>Title: %{title}<br><br>Error: %{error}'
104+
generic_error: Ein unbekannter Fehler ist beim exportieren der Aufgabe aufgetreten.
104105
label: Zu CodeHarbor exportieren
106+
not_authorized: Die Autorisierung mit CodeHarbor konnte nicht hergestellt werden. Ist der API-Schlüssel korrekt?
107+
server_error: Verbindung zu CodeHarbor fehlgeschlagen. Gegenseite nicht erreichbar.
105108
successfully_exported: 'Aufgabe wurde erfolgreich exportiert.<br>ID: %{id}<br>Title: %{title}'
106109
external_users:
107110
statistics:

config/locales/en/exercise.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ en:
101101
dialogtitle: Export to CodeHarbor
102102
error: An error occurred while contacting CodeHarbor
103103
export_failed: 'Export has failed.<br>ID: %{id}<br>Title: %{title}<br><br>Error: %{error}'
104+
generic_error: An unknown error has occurred while exporting the exercise.
104105
label: Export to CodeHarbor
106+
not_authorized: Authorization with could not be established with CodeHarbor. Is the API Key correct?
107+
server_error: Connection to CodeHarbor failed. Remote host unreachable.
105108
successfully_exported: 'Exercise has been successfully exported.<br>ID: %{id}<br>Title: %{title}'
106109
external_users:
107110
statistics:

spec/services/exercise_service/push_external_spec.rb

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@
2626
let(:status) { 200 }
2727
let(:response) { '' }
2828

29-
before { stub_request(:post, codeharbor_link.push_url).to_return(status:, body: response) }
29+
before do
30+
# Un-memoize the connection to force a reconnection for each example
31+
described_class.instance_variable_set(:@connection, nil)
32+
stub_request(:post, codeharbor_link.push_url).to_return(status:, body: response)
33+
end
3034

3135
it 'calls the correct url' do
3236
expect(push_external).to have_requested(:post, codeharbor_link.push_url)
@@ -49,16 +53,45 @@
4953

5054
context 'when response status is 500' do
5155
let(:status) { 500 }
52-
let(:response) { 'an error occured' }
56+
let(:response) { 'an error occurred' }
57+
58+
it { is_expected.to eql response }
59+
60+
context 'when response contains problematic characters' do
61+
let(:response) { 'an <error> occurred' }
62+
63+
it { is_expected.to eql 'an &lt;error&gt; occurred' }
64+
end
65+
66+
context 'when faraday throws an error' do
67+
let(:connection) { instance_double(Faraday::Connection) }
68+
let(:error) { Faraday::ServerError }
69+
70+
before do
71+
allow(Faraday).to receive(:new).and_return(connection)
72+
allow(connection).to receive(:post).and_raise(error)
73+
end
74+
75+
it { is_expected.to eql I18n.t('exercises.export_codeharbor.server_error') }
76+
77+
context 'when another error occurs' do
78+
let(:error) { 'another error' }
79+
80+
it { is_expected.to eql I18n.t('exercises.export_codeharbor.generic_error') }
81+
end
82+
end
83+
end
84+
85+
context 'when response status is 401' do
86+
let(:status) { 401 }
87+
let(:response) { I18n.t('exercises.export_codeharbor.not_authorized') }
5388

54-
it { is_expected.to be response }
89+
it { is_expected.to eql response }
5590
end
5691
end
5792

5893
context 'when an error occurs' do
5994
before do
60-
# Un-memoize the connection to force a reconnection
61-
described_class.instance_variable_set(:@connection, nil)
6295
allow(Faraday).to receive(:new).and_raise(StandardError)
6396
end
6497

0 commit comments

Comments
 (0)