users: fix find_by_name, name_to_id to strip whitespace.

Fix find_by_name and name_to_id to use normalize_name properly, so that
they ignore leading/trailing whitespace. This fixes various search forms
failing to return results when the username field contains trailing
whitespace (inserted by autocomplete).
This commit is contained in:
evazion
2019-08-18 03:50:43 -05:00
parent 82fbb19e0f
commit 7871dced00
2 changed files with 29 additions and 13 deletions

View File

@@ -128,29 +128,23 @@ class User < ApplicationRecord
end
end
module NameMethods
extend ActiveSupport::Concern
module ClassMethods
concerning :NameMethods do
class_methods do
def name_to_id(name)
Cache.get("uni:#{Cache.hash(name)}", 4.hours) do
val = select_value_sql("SELECT id FROM users WHERE lower(name) = ?", name.mb_chars.downcase.tr(" ", "_").to_s)
if val.present?
val.to_i
else
nil
end
find_by_name(name).try(:id)
end
end
def id_to_name(user_id)
Cache.get("uin:#{user_id}", 4.hours) do
select_value_sql("SELECT name FROM users WHERE id = ?", user_id) || Danbooru.config.default_guest_name
find_by_id(user_id).try(:name) || Danbooru.config.default_guest_name
end
end
# XXX downcasing is the wrong way to do case-insensitive comparison for unicode (should use casefolding).
def find_by_name(name)
where("lower(name) = ?", name.mb_chars.downcase.tr(" ", "_")).first
where("lower(name) = ?", normalize_name(name)).first
end
def normalize_name(name)
@@ -813,7 +807,6 @@ class User < ApplicationRecord
end
include BanMethods
include NameMethods
include PasswordMethods
include AuthenticationMethods
include LevelMethods

View File

@@ -164,6 +164,29 @@ class UserTest < ActiveSupport::TestCase
end
end
context "searching for users by name" do
setup do
@miku = create(:user, name: "hatsune_miku")
end
should "be case-insensitive" do
assert_equal("hatsune_miku", User.normalize_name("Hatsune_Miku"))
assert_equal(@miku.id, User.find_by_name("Hatsune_Miku").id)
assert_equal(@miku.id, User.name_to_id("Hatsune_Miku"))
end
should "handle whitespace" do
assert_equal("hatsune_miku", User.normalize_name(" hatsune miku "))
assert_equal(@miku.id, User.find_by_name(" hatsune miku ").id)
assert_equal(@miku.id, User.name_to_id(" hatsune miku "))
end
should "return nil for nonexistent names" do
assert_nil(User.find_by_name("does_not_exist"))
assert_nil(User.name_to_id("does_not_exist"))
end
end
context "ip address" do
setup do
@user = FactoryBot.create(:user)