Feature:Backend Username Search Endpoint for Mention Completion (#11479)

* Feature:Backend Username Search Endpoint for Mention Completion

* ensure user is authenticated to use usernames endpoint

* update spec with authaa
This commit is contained in:
Molly Struve 2020-11-18 17:43:59 -05:00 committed by GitHub
parent 89e0ea79bb
commit fd8f83dc7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 1 deletions

View file

@ -1,5 +1,5 @@
class SearchController < ApplicationController
before_action :authenticate_user!, only: %i[tags chat_channels reactions]
before_action :authenticate_user!, only: %i[tags chat_channels reactions usernames]
before_action :format_integer_params
before_action :sanitize_params, only: %i[listings reactions feed_content]
@ -82,6 +82,14 @@ class SearchController < ApplicationController
render json: { result: user_search }
end
def usernames
usernames = Search::User.search_usernames(params[:username])
render json: { result: usernames }
rescue Search::Errors::Transport::BadRequest
render json: { result: [] }
end
def feed_content
feed_docs = if params[:class_name].blank?
# If we are in the main feed and not filtering by type return

View file

@ -7,8 +7,27 @@ module Search
DEFAULT_PER_PAGE = 20
class << self
def search_usernames(username)
results = search(body: username_query(username))
results.dig("hits", "hits").map do |doc|
doc.dig("_source", "username")
end
end
private
def username_query(username)
{
query: {
query_string: {
query: "username:#{username}*",
analyze_wildcard: true,
allow_leading_wildcard: false
}
}
}
end
def prepare_doc(hit)
source = hit["_source"]
{

View file

@ -310,6 +310,7 @@ Rails.application.routes.draw do
get "/search/chat_channels" => "search#chat_channels"
get "/search/listings" => "search#listings"
get "/search/users" => "search#users"
get "/search/usernames" => "search#usernames"
get "/search/feed_content" => "search#feed_content"
get "/search/reactions" => "search#reactions"
get "/chat_channel_memberships/find_by_chat_channel_id" => "chat_channel_memberships#find_by_chat_channel_id"

View file

@ -66,6 +66,20 @@ RSpec.describe "Search", type: :request, proper_status: true do
end
end
describe "GET /search/usernames" do
let(:authorized_user) { create(:user) }
let(:names) { ["username"] }
it "returns json" do
sign_in authorized_user
allow(Search::User).to receive(:search_usernames).and_return(
names,
)
get "/search/usernames"
expect(response.parsed_body).to eq("result" => names)
end
end
describe "GET /search/feed_content" do
let(:mock_documents) { [{ "title" => "article1" }] }

View file

@ -57,4 +57,34 @@ RSpec.describe Search::User, type: :service do
end
end
end
describe "::search_usernames", elasticsearch: "User" do
let(:user1) { create(:user, username: "star_wars_is_the_best") }
let(:user2) { create(:user, username: "star_trek_is_the_best") }
before do
index_documents([user1, user2])
end
it "searches with username" do
usernames = described_class.search_usernames(user1.username)
expect(usernames.count).to eq(1)
expect(usernames).to match([user1.username])
end
it "analyzes wildcards" do
user3 = create(:user, username: "does_not_start_with_a_star")
index_documents([user3])
usernames = described_class.search_usernames("star*")
expect(usernames).to match(
[user1.username, user2.username],
)
expect(usernames).not_to include(user3.username)
end
it "does not allow leading wildcards" do
expect { described_class.search_usernames("*star") }.to raise_error(Search::Errors::Transport::BadRequest)
end
end
end