users: fix find_by_name for names with special characters.

`User.find_by_name` used `where_ilike` to do a case-insensitve name
search, but it didn't escape `*` or `\` characters first, so it didn't
handle names containing these characters properly.
This commit is contained in:
evazion
2019-09-23 00:03:11 -05:00
parent dcc2c793f9
commit 09972477cd
3 changed files with 15 additions and 1 deletions

View File

@@ -25,6 +25,10 @@ class ApplicationRecord < ActiveRecord::Base
where.not("#{qualified_column_for(attr)} ILIKE ? ESCAPE E'\\\\'", value.mb_chars.to_escaped_for_sql_like)
end
def where_iequals(attr, value)
where_ilike(attr, value.gsub(/\\/, '\\\\').gsub(/\*/, '\*'))
end
# https://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-POSIX-REGEXP
# "(?e)" means force use of ERE syntax; see sections 9.7.3.1 and 9.7.3.4.
def where_regex(attr, value)

View File

@@ -142,7 +142,7 @@ class User < ApplicationRecord
# XXX downcasing is the wrong way to do case-insensitive comparison for unicode (should use casefolding).
def find_by_name(name)
where_ilike(:name, normalize_name(name)).first
where_iequals(:name, normalize_name(name)).first
end
def normalize_name(name)

View File

@@ -175,6 +175,16 @@ class UserTest < ActiveSupport::TestCase
assert_nil(User.find_by_name("does_not_exist"))
assert_nil(User.name_to_id("does_not_exist"))
end
should "work for names containing asterisks or backlashes" do
@user1 = create(:user, name: "user*1")
@user2 = create(:user, name: "user*2")
@user3 = create(:user, name: "user\*3")
assert_equal(@user1.id, User.find_by_name("user*1").id)
assert_equal(@user2.id, User.find_by_name("user*2").id)
assert_equal(@user3.id, User.find_by_name("user\*3").id)
end
end
context "ip address" do