Skip to content

Commit

Permalink
Fixing "PG::UntranslatableCharacter" error when storing some Pender d…
Browse files Browse the repository at this point in the history
…ata annotations

PostgreSQL doesn't support null characters in a JSON column, so these characters need to be removed before storing.

Fixes CV2-3582.
  • Loading branch information
caiosba authored Sep 16, 2023
1 parent 49cbc02 commit 1ff3a22
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 36 deletions.
1 change: 1 addition & 0 deletions app/models/annotations/dynamic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def create_field(name, value)
f.skip_check_ability = true
f.disable_es_callbacks = self.disable_es_callbacks || value.blank?
f.field_name = name
value.gsub!('\u0000', '') if value.is_a?(String) # Avoid PG::UntranslatableCharacter exception
f.value = value
f.annotation_id = self.id
f
Expand Down
73 changes: 37 additions & 36 deletions test/controllers/graphql_controller_3_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -343,42 +343,43 @@ def setup

test "should set smooch user slack channel url in background" do
Sidekiq::Testing.fake! do
u = create_user
t = create_team
create_team_user team: t, user: u, role: 'admin'
p = create_project team: t
author_id = random_string
set_fields = { smooch_user_data: { id: author_id }.to_json, smooch_user_app_id: 'fake', smooch_user_id: 'fake' }.to_json
d = create_dynamic_annotation annotated: p, annotation_type: 'smooch_user', set_fields: set_fields
Sidekiq::Worker.drain_all
assert_equal 0, Sidekiq::Worker.jobs.size
authenticate_with_token
url = random_url
query = 'mutation { updateDynamicAnnotationSmoochUser(input: { clientMutationId: "1", id: "' + d.graphql_id + '", set_fields: "{\"smooch_user_slack_channel_url\":\"' + url + '\"}" }) { project { dbid } } }'
post :create, params: { query: query }
assert_response :success
assert_equal url, d.reload.get_field_value('smooch_user_slack_channel_url')
# check that cache key exists
key = "SmoochUserSlackChannelUrl:Team:#{d.team_id}:#{author_id}"
assert_equal url, Rails.cache.read(key)
# test using a new mutation `smoochBotAddSlackChannelUrl`
Sidekiq::Worker.drain_all
assert_equal 0, Sidekiq::Worker.jobs.size
url2 = random_url
query = 'mutation { smoochBotAddSlackChannelUrl(input: { clientMutationId: "1", id: "' + d.id.to_s + '", set_fields: "{\"smooch_user_slack_channel_url\":\"' + url2 + '\"}" }) { annotation { dbid } } }'
post :create, params: { query: query }
assert_response :success
assert Sidekiq::Worker.jobs.size > 0
assert_equal url, d.reload.get_field_value('smooch_user_slack_channel_url')
# execute job and check that url was set
Sidekiq::Worker.drain_all
assert_equal url2, d.get_field_value('smooch_user_slack_channel_url')
# check that cache key exists
assert_equal url2, Rails.cache.read(key)
# call mutation with non existing id
query = 'mutation { smoochBotAddSlackChannelUrl(input: { clientMutationId: "1", id: "99999", set_fields: "{\"smooch_user_slack_channel_url\":\"' + url2 + '\"}" }) { annotation { dbid } } }'
post :create, params: { query: query }
assert_response :success
u = create_user
t = create_team
create_team_user team: t, user: u, role: 'admin'
p = create_project team: t
author_id = random_string
set_fields = { smooch_user_data: { id: author_id }.to_json, smooch_user_app_id: 'fake', smooch_user_id: 'fake' }.to_json
d = create_dynamic_annotation annotated: p, annotation_type: 'smooch_user', set_fields: set_fields
Sidekiq::Worker.drain_all
assert_equal 0, Sidekiq::Worker.jobs.size
authenticate_with_token
url = random_url
query = 'mutation { updateDynamicAnnotationSmoochUser(input: { clientMutationId: "1", id: "' + d.graphql_id + '", set_fields: "{\"smooch_user_slack_channel_url\":\"' + url + '\"}" }) { project { dbid } } }'
post :create, params: { query: query }
assert_response :success
Sidekiq::Worker.drain_all
assert_equal url, d.reload.get_field_value('smooch_user_slack_channel_url')
# check that cache key exists
key = "SmoochUserSlackChannelUrl:Team:#{d.team_id}:#{author_id}"
assert_equal url, Rails.cache.read(key)
# test using a new mutation `smoochBotAddSlackChannelUrl`
Sidekiq::Worker.drain_all
assert_equal 0, Sidekiq::Worker.jobs.size
url2 = random_url
query = 'mutation { smoochBotAddSlackChannelUrl(input: { clientMutationId: "1", id: "' + d.id.to_s + '", set_fields: "{\"smooch_user_slack_channel_url\":\"' + url2 + '\"}" }) { annotation { dbid } } }'
post :create, params: { query: query }
assert_response :success
assert Sidekiq::Worker.jobs.size > 0
assert_equal url, d.reload.get_field_value('smooch_user_slack_channel_url')
# execute job and check that url was set
Sidekiq::Worker.drain_all
assert_equal url2, d.get_field_value('smooch_user_slack_channel_url')
# check that cache key exists
assert_equal url2, Rails.cache.read(key)
# call mutation with non existing id
query = 'mutation { smoochBotAddSlackChannelUrl(input: { clientMutationId: "1", id: "99999", set_fields: "{\"smooch_user_slack_channel_url\":\"' + url2 + '\"}" }) { annotation { dbid } } }'
post :create, params: { query: query }
assert_response :success
end
end

Expand Down
10 changes: 10 additions & 0 deletions test/models/media_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -593,4 +593,14 @@ def setup
l = create_valid_media
assert_equal '', l.picture
end

test "should sanitize link data before storing" do
pender_url = CheckConfig.get('pender_url_private') + '/api/medias'
url = random_url
response = { type: 'media', data: { url: url, type: 'item', title: "Foo \u0000 bar" } }
WebMock.stub_request(:get, pender_url).with({ query: { url: url } }).to_return(body: response.to_json)
assert_difference 'Link.count' do
create_media url: url
end
end
end

0 comments on commit 1ff3a22

Please sign in to comment.