diff --git a/lib/paper_trail/version_concern.rb b/lib/paper_trail/version_concern.rb index ef10c390..6337c0b7 100644 --- a/lib/paper_trail/version_concern.rb +++ b/lib/paper_trail/version_concern.rb @@ -110,23 +110,23 @@ module PaperTrail raise ArgumentError, 'expected to receive a Hash' unless args.is_a?(Hash) if columns_hash['object'].type == :jsonb - where_conditions = "object @> '#{args.to_json}'::jsonb" + where("object @> ?", args.to_json) elsif columns_hash['object'].type == :json - where_conditions = args.map do |field, value| - "object->>'#{field}' = '#{value}'" + predicates = [] + values = [] + args.each do |field, value| + predicates.push "object->>? = ?" + values.concat([field, value.to_s]) end - where_conditions = where_conditions.join(" AND ") + sql = predicates.join(" and ") + where(sql, *values) else arel_field = arel_table[:object] - - where_conditions = args.map do |field, value| + where_conditions = args.map { |field, value| PaperTrail.serializer.where_object_condition(arel_field, field, value) - end.reduce do |condition1, condition2| - condition1.and(condition2) - end + }.reduce { |a, e| a.and(e) } + where(where_conditions) end - - where(where_conditions) end def where_object_changes(args = {}) @@ -134,24 +134,25 @@ module PaperTrail if columns_hash['object_changes'].type == :jsonb args.each { |field, value| args[field] = [value] } - where_conditions = "object_changes @> '#{args.to_json}'::jsonb" + where("object_changes @> ?", args.to_json) elsif columns_hash['object'].type == :json - where_conditions = args.map do |field, value| - "((object_changes->>'#{field}' ILIKE '[#{value.to_json},%') " + - "OR (object_changes->>'#{field}' ILIKE '[%,#{value.to_json}]%'))" + predicates = [] + values = [] + args.each do |field, value| + predicates.push( + "((object_changes->>? ILIKE ?) OR (object_changes->>? ILIKE ?))" + ) + values.concat([field, "[#{value.to_json},%", field, "[%,#{value.to_json}]%"]) end - where_conditions = where_conditions.join(" AND ") + sql = predicates.join(" and ") + where(sql, *values) else arel_field = arel_table[:object_changes] - - where_conditions = args.map do |field, value| + where_conditions = args.map { |field, value| PaperTrail.serializer.where_object_changes_condition(arel_field, field, value) - end.reduce do |condition1, condition2| - condition1.and(condition2) - end + }.reduce { |a, e| a.and(e) } + where(where_conditions) end - - where(where_conditions) end def primary_key_is_int? diff --git a/spec/models/json_version_spec.rb b/spec/models/json_version_spec.rb index cffef51e..c13127d4 100644 --- a/spec/models/json_version_spec.rb +++ b/spec/models/json_version_spec.rb @@ -15,6 +15,16 @@ if JsonVersion.table_exists? describe '#where_object' do it { expect(JsonVersion).to respond_to(:where_object) } + it "escapes values" do + f = Fruit.create(:name => 'Bobby') + expect( + f. + versions. + where_object(:name => "Robert'; DROP TABLE Students;--"). + count + ).to eq(0) + end + context "invalid arguments" do it "should raise an error" do expect { JsonVersion.where_object(:foo) }.to raise_error(ArgumentError) @@ -44,6 +54,16 @@ if JsonVersion.table_exists? describe '#where_object_changes' do it { expect(JsonVersion).to respond_to(:where_object_changes) } + it "escapes values" do + f = Fruit.create(:name => 'Bobby') + expect( + f. + versions. + where_object_changes(:name => "Robert'; DROP TABLE Students;--"). + count + ).to eq(0) + end + context "invalid arguments" do it "should raise an error" do expect { JsonVersion.where_object_changes(:foo) }.to raise_error(ArgumentError)