DEV: return user status on the user search route (#17716)

This commit is contained in:
Andrei Prigorshnev 2022-08-09 14:54:33 +04:00 committed by GitHub
parent 7f9c2c0bfb
commit 3755bad03c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 142 additions and 7 deletions

View File

@ -1193,11 +1193,7 @@ class UsersController < ApplicationController
options[:category_id] = category_id if category_id options[:category_id] = category_id if category_id
results = UserSearch.new(term, options).search results = UserSearch.new(term, options).search
to_render = serialize_found_users(results)
user_fields = [:username, :upload_avatar_template]
user_fields << :name if SiteSetting.enable_names?
to_render = { users: results.as_json(only: user_fields, methods: [:avatar_template]) }
# blank term is only handy for in-topic search of users after @ # blank term is only handy for in-topic search of users after @
# we do not want group results ever if term is blank # we do not want group results ever if term is blank
@ -1969,4 +1965,12 @@ class UsersController < ApplicationController
error: message error: message
} }
end end
def serialize_found_users(users)
each_serializer = SiteSetting.enable_user_status? ?
FoundUserWithStatusSerializer :
FoundUserSerializer
{ users: ActiveModel::ArraySerializer.new(users, each_serializer: each_serializer).as_json }
end
end end

View File

@ -1619,7 +1619,7 @@ class User < ActiveRecord::Base
publish_user_status(nil) publish_user_status(nil)
end end
def set_status!(description, emoji, ends_at) def set_status!(description, emoji, ends_at = nil)
status = { status = {
description: description, description: description,
emoji: emoji, emoji: emoji,

View File

@ -179,10 +179,16 @@ class UserSearch
ids = search_ids ids = search_ids
return User.where("0=1") if ids.empty? return User.where("0=1") if ids.empty?
User.joins("JOIN (SELECT unnest uid, row_number() OVER () AS rn results = User.joins("JOIN (SELECT unnest uid, row_number() OVER () AS rn
FROM unnest('{#{ids.join(",")}}'::int[]) FROM unnest('{#{ids.join(",")}}'::int[])
) x on uid = users.id") ) x on uid = users.id")
.order("rn") .order("rn")
if SiteSetting.enable_user_status
results = results.includes(:user_status)
end
results
end end
end end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class FoundUserSerializer < ApplicationSerializer
attributes :username, :name, :avatar_template
def include_name?
SiteSetting.enable_names?
end
end

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
class FoundUserWithStatusSerializer < FoundUserSerializer
attributes :status
def include_status?
SiteSetting.enable_user_status && object.has_status?
end
def status
UserStatusSerializer.new(object.user_status, root: false)
end
end

View File

@ -4536,6 +4536,42 @@ RSpec.describe UsersController do
expect(json["users"].size).to eq(limit) expect(json["users"].size).to eq(limit)
end end
end end
it "returns avatar_template" do
get "/u/search/users.json", params: { term: user.username }
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["users"][0]).to have_key("avatar_template")
expect(json["users"][0]["avatar_template"]).to eq("/letter_avatar_proxy/v4/letter/j/f475e1/{size}.png")
end
describe "#status" do
it "returns user status if enabled in site settings" do
SiteSetting.enable_user_status = true
emoji = "tooth"
description = "off to dentist"
user.set_status!(description, emoji)
get "/u/search/users.json", params: { term: user.name }
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["users"][0]).to have_key("status")
expect(json["users"][0]["status"]["description"]).to eq(description)
expect(json["users"][0]["status"]["emoji"]).to eq(emoji)
end
it "doesn't return user status if disabled in site settings" do
SiteSetting.enable_user_status = false
user.set_status!("off to dentist", "tooth")
get "/u/search/users.json", params: { term: user.name }
expect(response.status).to eq(200)
json = response.parsed_body
expect(json["users"][0]).not_to have_key("status")
end
end
end end
describe '#email_login' do describe '#email_login' do

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
RSpec.describe FoundUserSerializer do
fab!(:user) { Fabricate(:user) }
let(:serializer) { described_class.new(user, root: false) }
describe '#name' do
it "returns name if enabled in site settings" do
SiteSetting.enable_names = true
json = serializer.as_json
expect(json.keys).to include :name
expect(json[:name]).to eq(user.name)
end
it "doesn't return name if disabled in site settings" do
SiteSetting.enable_names = false
json = serializer.as_json
expect(json.keys).not_to include :name
end
end
end

View File

@ -0,0 +1,46 @@
# frozen_string_literal: true
RSpec.describe FoundUserWithStatusSerializer do
fab!(:user_status) { Fabricate(:user_status) }
fab!(:user) { Fabricate(:user, user_status: user_status) }
let(:serializer) { described_class.new(user, root: false) }
describe "#status" do
it "adds user status when enabled" do
SiteSetting.enable_user_status = true
json = serializer.as_json
expect(json[:status]).to_not be_nil do |status|
expect(status.description).to eq(user_status.description)
expect(status.emoji).to eq(user_status.emoji)
end
end
it "doesn't add user status when disabled" do
SiteSetting.enable_user_status = false
json = serializer.as_json
expect(json.keys).not_to include :status
end
it "doesn't add expired user status" do
SiteSetting.enable_user_status = true
user.user_status.ends_at = 1.minutes.ago
serializer = described_class.new(user, scope: Guardian.new(user), root: false)
json = serializer.as_json
expect(json.keys).not_to include :status
end
it "doesn't return status if user doesn't have it" do
SiteSetting.enable_user_status = true
user.clear_status!
user.reload
json = serializer.as_json
expect(json.keys).not_to include :status
end
end
end