From 526d2dc582d0dabbf6f9c1d143b9a960cae7bd4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Saquetim?= <1108771+megothss@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:00:33 -0300 Subject: [PATCH] FEATURE: Allow searching users using a list of usernames (#23902) --- app/controllers/users_controller.rb | 19 ++++++++++++++--- spec/requests/users_controller_spec.rb | 29 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 1392384f66a..4fa518e6f35 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1203,7 +1203,10 @@ class UsersController < ApplicationController SEARCH_USERS_LIMIT = 50 def search_users + # the search can specify the parameter term or usernames, term will perform the classic user search algorithm while + # usernames will perform an exact search on the usernames passed as parameter term = params[:term].to_s.strip + usernames = params[:usernames]&.split(",")&.map { |username| username.downcase.strip } topic_id = params[:topic_id].to_i if params[:topic_id].present? category_id = params[:category_id].to_i if params[:category_id].present? @@ -1232,13 +1235,18 @@ class UsersController < ApplicationController options[:topic_id] = topic_id if topic_id options[:category_id] = category_id if category_id - results = UserSearch.new(term, options).search + results = + if usernames.blank? + UserSearch.new(term, options).search + else + User.where(username_lower: usernames).limit(limit) + end to_render = serialize_found_users(results) # blank term is only handy for in-topic search of users after @ # we do not want group results ever if term is blank groups = - if term.present? && current_user + if (term.present? || usernames.present?) && current_user if params[:include_groups] == "true" Group.visible_groups(current_user) elsif params[:include_mentionable_groups] == "true" @@ -1260,7 +1268,12 @@ class UsersController < ApplicationController # register_modifier(:groups_for_users_search) will be evaluated without needing the # param. groups = DiscoursePluginRegistry.apply_modifier(:groups_for_users_search, groups) - groups = Group.search_groups(term, groups: groups, sort: :auto) + groups = + if usernames.blank? + Group.search_groups(term, groups: groups, sort: :auto) + else + groups.where(name: usernames).limit(limit) + end to_render[:groups] = groups.map { |m| { name: m.name, full_name: m.full_name } } end diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb index 868fde5826d..37182039147 100644 --- a/spec/requests/users_controller_spec.rb +++ b/spec/requests/users_controller_spec.rb @@ -4901,6 +4901,35 @@ RSpec.describe UsersController do expect(json["users"].map { |u| u["username"] }).to include(user.username) end + context "when searching usernames" do + it "searches when provided a list of usernames" do + users = Fabricate.times(3, :user) + + get "/u/search/users.json", params: { usernames: users.map(&:username).join(",") } + expect(response.status).to eq(200) + json = response.parsed_body + expect(json["users"].map { |u| u["username"] }).to match_array(users.map(&:username)) + end + + it "searches groups if include_groups = true" do + users = Fabricate.times(3, :user) + group = Fabricate(:group) + + sign_in(user) + + get "/u/search/users.json", + params: { + usernames: [group.name, users.first.username].join(","), + include_groups: true, + } + expect(response.status).to eq(200) + json = response.parsed_body + + expect(json["users"].map { |u| u["username"] }).to contain_exactly(users.first.username) + expect(json["groups"].map { |u| u["name"] }).to contain_exactly(group.name) + end + end + it "searches when provided the topic only" do get "/u/search/users.json", params: { topic_id: topic.id } expect(response.status).to eq(200)