Feature #35073 » 0003-use-sanitize_sql_like-in-like-scopes.patch
| app/models/issue.rb | ||
|---|---|---|
| 102 | 102 |
scope :like, (lambda do |q| |
| 103 | 103 |
q = q.to_s |
| 104 | 104 |
if q.present? |
| 105 |
where("LOWER(#{table_name}.subject) LIKE LOWER(?)", "%#{q}%")
|
|
| 105 |
where("LOWER(#{table_name}.subject) LIKE LOWER(?)", "%#{sanitize_sql_like q}%")
|
|
| 106 | 106 |
end |
| 107 | 107 |
end) |
| 108 | 108 | |
| app/models/principal.rb | ||
|---|---|---|
| 71 | 71 |
if q.blank? |
| 72 | 72 |
where({})
|
| 73 | 73 |
else |
| 74 |
pattern = "%#{q}%"
|
|
| 74 |
pattern = "%#{sanitize_sql_like q}%"
|
|
| 75 | 75 |
sql = +"LOWER(#{table_name}.login) LIKE LOWER(:p)"
|
| 76 | 76 |
sql << " OR #{table_name}.id IN (SELECT user_id FROM #{EmailAddress.table_name} WHERE LOWER(address) LIKE LOWER(:p))"
|
| 77 | 77 |
params = {:p => pattern}
|
| 78 | 78 | |
| 79 |
tokens = q.split(/\s+/).reject(&:blank?).map {|token| "%#{token}%"}
|
|
| 79 |
tokens = q.split(/\s+/).reject(&:blank?).map {|token| "%#{sanitize_sql_like token}%"}
|
|
| 80 | 80 |
if tokens.present? |
| 81 | 81 |
sql << ' OR ('
|
| 82 | 82 |
sql << tokens.map.with_index do |token, index| |
| app/models/project.rb | ||
|---|---|---|
| 105 | 105 |
end) |
| 106 | 106 |
scope :like, (lambda do |arg| |
| 107 | 107 |
if arg.present? |
| 108 |
pattern = "%#{arg.to_s.strip}%"
|
|
| 108 |
pattern = "%#{sanitize_sql_like arg.to_s.strip}%"
|
|
| 109 | 109 |
where("LOWER(identifier) LIKE LOWER(:p) OR LOWER(name) LIKE LOWER(:p)", :p => pattern)
|
| 110 | 110 |
end |
| 111 | 111 |
end) |
| app/models/version.rb | ||
|---|---|---|
| 137 | 137 |
scope :named, lambda {|arg| where("LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip)}
|
| 138 | 138 |
scope :like, (lambda do |arg| |
| 139 | 139 |
if arg.present? |
| 140 |
pattern = "%#{arg.to_s.strip}%"
|
|
| 140 |
pattern = "%#{sanitize_sql_like arg.to_s.strip}%"
|
|
| 141 | 141 |
where([Redmine::Database.like("#{Version.table_name}.name", '?'), pattern])
|
| 142 | 142 |
end |
| 143 | 143 |
end) |
| test/unit/issue_test.rb | ||
|---|---|---|
| 3406 | 3406 | |
| 3407 | 3407 |
assert_equal [5], issue2.filter_projects_scope('').ids.sort
|
| 3408 | 3408 |
end |
| 3409 | ||
| 3410 |
def test_like_should_escape_query |
|
| 3411 |
issue = Issue.generate!(:subject => "asdf") |
|
| 3412 |
r = Issue.like('as_f')
|
|
| 3413 |
assert_not_include issue, r |
|
| 3414 |
r = Issue.like('as%f')
|
|
| 3415 |
assert_not_include issue, r |
|
| 3416 | ||
| 3417 |
issue = Issue.generate!(:subject => "as%f") |
|
| 3418 |
r = Issue.like('as%f')
|
|
| 3419 |
assert_include issue, r |
|
| 3420 | ||
| 3421 |
issue = Issue.generate!(:subject => "as_f") |
|
| 3422 |
r = Issue.like('as_f')
|
|
| 3423 |
assert_include issue, r |
|
| 3424 |
end |
|
| 3409 | 3425 |
end |
| test/unit/principal_test.rb | ||
|---|---|---|
| 147 | 147 |
assert_equal 1, results.count |
| 148 | 148 |
assert_equal user, results.first |
| 149 | 149 |
end |
| 150 | ||
| 151 |
def test_like_scope_should_escape_query |
|
| 152 |
user = User.generate!(:firstname => 'Leonardo', :lastname => 'da Vinci') |
|
| 153 |
r = Principal.like('Vi_ci')
|
|
| 154 |
assert_not_include user, r |
|
| 155 |
r = Principal.like('Vi%ci')
|
|
| 156 |
assert_not_include user, r |
|
| 157 | ||
| 158 |
user.update_column :lastname, 'da Vi%ci' |
|
| 159 |
r = Principal.like('vi%ci')
|
|
| 160 |
assert_include user, r |
|
| 161 | ||
| 162 |
user.update_column :lastname, 'da Vi_ci' |
|
| 163 |
r = Principal.like('vi_ci')
|
|
| 164 |
assert_include user, r |
|
| 165 |
end |
|
| 150 | 166 |
end |
| test/unit/project_test.rb | ||
|---|---|---|
| 1120 | 1120 |
assert_equal 'valuea', project.custom_field_value(cf1) |
| 1121 | 1121 |
assert_nil project.custom_field_value(cf2) |
| 1122 | 1122 |
end |
| 1123 | ||
| 1124 |
def test_like_scope_should_escape_query |
|
| 1125 |
project = Project.find 'ecookbook' |
|
| 1126 |
r = Project.like('eco_k')
|
|
| 1127 |
assert_not_include project, r |
|
| 1128 |
r = Project.like('eco%k')
|
|
| 1129 |
assert_not_include project, r |
|
| 1130 | ||
| 1131 |
project.update_column :name, 'Eco%kbook' |
|
| 1132 |
r = Project.like('eco%k')
|
|
| 1133 |
assert_include project, r |
|
| 1134 | ||
| 1135 |
project.update_column :name, 'Eco_kbook' |
|
| 1136 |
r = Project.like('eco_k')
|
|
| 1137 |
assert_include project, r |
|
| 1138 |
end |
|
| 1123 | 1139 |
end |
| test/unit/version_test.rb | ||
|---|---|---|
| 300 | 300 |
assert_includes Version.like('like scope'), version
|
| 301 | 301 |
end |
| 302 | 302 | |
| 303 |
def test_like_scope_should_escape_query |
|
| 304 |
version = Version.create!(:project => Project.find(1), :name => 'Version for like scope test') |
|
| 305 |
r = Version.like('Ver_ion')
|
|
| 306 |
assert_not_include version, r |
|
| 307 |
r = Version.like('Ver%ion')
|
|
| 308 |
assert_not_include version, r |
|
| 309 | ||
| 310 |
version.update_column :name, 'Ver%ion' |
|
| 311 |
r = Version.like('ver%i')
|
|
| 312 |
assert_include version, r |
|
| 313 | ||
| 314 |
version.update_column :name, 'Ver_ion' |
|
| 315 |
r = Version.like('ver_i')
|
|
| 316 |
assert_include version, r |
|
| 317 |
end |
|
| 318 | ||
| 303 | 319 |
def test_safe_attributes_should_include_only_custom_fields_visible_to_user |
| 304 | 320 |
cf1 = VersionCustomField.create!(:name => 'Visible field', |
| 305 | 321 |
:field_format => 'string', |