From 7871dced00c4f70a13b1678880807b6decdc7133 Mon Sep 17 00:00:00 2001 From: evazion Date: Sun, 18 Aug 2019 03:50:43 -0500 Subject: [PATCH] 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). --- app/models/user.rb | 19 ++++++------------- test/unit/user_test.rb | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index 954d602ac..10bb2b92f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -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 diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index c8fd9170f..4233d3d45 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -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)