mirror of
https://github.com/discourse/discourse.git
synced 2026-08-06 13:08:40 +08:00
This PR removes searches by admins and moderators from the new dashboard’s Search section. This helps staff focus on what community members are searching for. Staff often search for personal or work-related topics. Including those searches adds noise and makes it harder to see what members need and what content may be missing. Key changes: * Exclude admin and moderator searches from totals, changes over time, trending searches, and content gaps. * On the Search Logs pages, rename the “Logged in only” filter to “Non-staff users” because the old filter still included admins and moderators. * Use the non-staff filter when someone clicks a trending search, so the details also leave out staff searches.
308 lines
10 KiB
Ruby
Vendored
308 lines
10 KiB
Ruby
Vendored
# frozen_string_literal: true
|
|
|
|
RSpec.describe SearchLog, type: :model do
|
|
after { SearchLog.clear_debounce_cache! }
|
|
|
|
describe ".log" do
|
|
context "with invalid arguments" do
|
|
it "no search type returns error" do
|
|
status, _ =
|
|
SearchLog.log(term: "bounty hunter", search_type: :missing, ip_address: "127.0.0.1")
|
|
|
|
expect(status).to eq(:error)
|
|
end
|
|
|
|
it "no IP returns error" do
|
|
status, _ = SearchLog.log(term: "bounty hunter", search_type: :header, ip_address: nil)
|
|
|
|
expect(status).to eq(:error)
|
|
end
|
|
|
|
it "truncates the `user_agent` attribute if it exceeds #{described_class::MAXIMUM_USER_AGENT_LENGTH} characters" do
|
|
user_agent = "a" * (described_class::MAXIMUM_USER_AGENT_LENGTH + 1)
|
|
|
|
status, _ =
|
|
SearchLog.log(
|
|
term: "bounty hunter",
|
|
search_type: :header,
|
|
user_agent:,
|
|
ip_address: "127.0.0.1",
|
|
)
|
|
|
|
expect(status).to eq(:created)
|
|
expect(SearchLog.last.user_agent).to eq("a" * described_class::MAXIMUM_USER_AGENT_LENGTH)
|
|
end
|
|
end
|
|
|
|
context "when anonymous" do
|
|
it "logs and updates the search" do
|
|
freeze_time
|
|
action, log_id =
|
|
SearchLog.log(
|
|
term: "jabba",
|
|
search_type: :header,
|
|
ip_address: "192.168.0.33",
|
|
user_agent: "Mozilla",
|
|
)
|
|
expect(action).to eq(:created)
|
|
log = SearchLog.find(log_id)
|
|
expect(log.term).to eq("jabba")
|
|
expect(log.search_type).to eq(SearchLog.search_types[:header])
|
|
expect(log.ip_address).to eq("192.168.0.33")
|
|
expect(log.user_agent).to eq("Mozilla")
|
|
|
|
action, updated_log_id =
|
|
SearchLog.log(term: "jabba the hut", search_type: :header, ip_address: "192.168.0.33")
|
|
expect(action).to eq(:updated)
|
|
expect(updated_log_id).to eq(log_id)
|
|
end
|
|
|
|
it "creates a new search with a different prefix" do
|
|
freeze_time
|
|
action, _ = SearchLog.log(term: "darth", search_type: :header, ip_address: "127.0.0.1")
|
|
expect(action).to eq(:created)
|
|
|
|
action, _ = SearchLog.log(term: "anakin", search_type: :header, ip_address: "127.0.0.1")
|
|
expect(action).to eq(:created)
|
|
end
|
|
|
|
it "creates a new search with a different ip" do
|
|
freeze_time
|
|
action, _ = SearchLog.log(term: "darth", search_type: :header, ip_address: "127.0.0.1")
|
|
expect(action).to eq(:created)
|
|
|
|
action, _ = SearchLog.log(term: "darth", search_type: :header, ip_address: "127.0.0.2")
|
|
expect(action).to eq(:created)
|
|
end
|
|
end
|
|
|
|
context "when logged in" do
|
|
fab!(:user)
|
|
let!(:plugin) { Plugin::Instance.new }
|
|
let!(:modifier) { :search_log_can_log }
|
|
let!(:deny_block) { Proc.new { false } }
|
|
let!(:allow_block) { Proc.new { true } }
|
|
|
|
it "logs and updates the search" do
|
|
freeze_time
|
|
action, log_id =
|
|
SearchLog.log(
|
|
term: "hello",
|
|
search_type: :full_page,
|
|
ip_address: "192.168.0.1",
|
|
user_agent: "Mozilla",
|
|
user_id: user.id,
|
|
)
|
|
expect(action).to eq(:created)
|
|
log = SearchLog.find(log_id)
|
|
expect(log.term).to eq("hello")
|
|
expect(log.search_type).to eq(SearchLog.search_types[:full_page])
|
|
expect(log.ip_address).to eq(nil)
|
|
expect(log.user_agent).to eq("Mozilla")
|
|
expect(log.user_id).to eq(user.id)
|
|
|
|
action, updated_log_id =
|
|
SearchLog.log(
|
|
term: "hello dolly",
|
|
search_type: :header,
|
|
ip_address: "192.168.0.33",
|
|
user_id: user.id,
|
|
)
|
|
expect(action).to eq(:updated)
|
|
expect(updated_log_id).to eq(log_id)
|
|
end
|
|
|
|
it "logs again if time has passed" do
|
|
freeze_time(10.minutes.ago)
|
|
|
|
action, _ =
|
|
SearchLog.log(
|
|
term: "hello",
|
|
search_type: :full_page,
|
|
ip_address: "192.168.0.1",
|
|
user_id: user.id,
|
|
)
|
|
expect(action).to eq(:created)
|
|
|
|
freeze_time(10.minutes.from_now)
|
|
Discourse.redis.del(SearchLog.redis_key(ip_address: "192.168.0.1", user_id: user.id))
|
|
|
|
action, _ =
|
|
SearchLog.log(
|
|
term: "hello",
|
|
search_type: :full_page,
|
|
ip_address: "192.168.0.1",
|
|
user_id: user.id,
|
|
)
|
|
|
|
expect(action).to eq(:created)
|
|
end
|
|
|
|
it "logs again with a different user" do
|
|
freeze_time
|
|
|
|
action, _ =
|
|
SearchLog.log(
|
|
term: "hello",
|
|
search_type: :full_page,
|
|
ip_address: "192.168.0.1",
|
|
user_id: user.id,
|
|
)
|
|
expect(action).to eq(:created)
|
|
|
|
action, _ =
|
|
SearchLog.log(
|
|
term: "hello dolly",
|
|
search_type: :full_page,
|
|
ip_address: "192.168.0.1",
|
|
user_id: Fabricate(:user).id,
|
|
)
|
|
expect(action).to eq(:created)
|
|
end
|
|
|
|
it "allows plugins to control logging" do
|
|
DiscoursePluginRegistry.register_modifier(plugin, modifier, &deny_block)
|
|
action, _ =
|
|
SearchLog.log(
|
|
term: "hello dolly",
|
|
search_type: :full_page,
|
|
ip_address: "192.168.0.1",
|
|
user_id: Fabricate(:user).id,
|
|
)
|
|
expect(action).to_not eq(:created)
|
|
|
|
DiscoursePluginRegistry.register_modifier(plugin, modifier, &allow_block)
|
|
action, _ =
|
|
SearchLog.log(
|
|
term: "hello dolly",
|
|
search_type: :full_page,
|
|
ip_address: "192.168.0.1",
|
|
user_id: Fabricate(:user).id,
|
|
)
|
|
expect(action).to eq(:created)
|
|
ensure
|
|
DiscoursePluginRegistry.unregister_modifier(plugin, modifier, &deny_block)
|
|
DiscoursePluginRegistry.unregister_modifier(plugin, modifier, &allow_block)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe ".term_details" do
|
|
it "should only use the date for the period" do
|
|
time = Time.utc(2019, 5, 23, 18, 15, 30)
|
|
freeze_time(time)
|
|
|
|
search_log = Fabricate(:search_log, created_at: time - 1.hour)
|
|
search_log2 = Fabricate(:search_log, created_at: time + 1.hour)
|
|
|
|
details = SearchLog.term_details(search_log.term, :daily)
|
|
|
|
expect(details[:data].first[:y]).to eq(2)
|
|
end
|
|
|
|
it "correctly returns term details" do
|
|
Fabricate(:search_log, term: "ruby")
|
|
Fabricate(:search_log, term: "ruBy", user: Fabricate(:user))
|
|
Fabricate(:search_log, term: "ruby core", ip_address: "127.0.0.3")
|
|
|
|
Fabricate(
|
|
:search_log,
|
|
term: "ruBy",
|
|
search_type: SearchLog.search_types[:full_page],
|
|
ip_address: "127.0.0.2",
|
|
)
|
|
|
|
term_details = SearchLog.term_details("ruby")
|
|
expect(term_details[:data][0][:y]).to eq(3)
|
|
|
|
term_header_details = SearchLog.term_details("ruby", :all, :header)
|
|
expect(term_header_details[:data][0][:y]).to eq(2)
|
|
|
|
SearchLog
|
|
.where("lower(term) = ?", "ruby")
|
|
.where(ip_address: "127.0.0.2")
|
|
.update_all(search_result_id: 24)
|
|
|
|
term_click_through_details = SearchLog.term_details("ruby", :all, :click_through_only)
|
|
expect(term_click_through_details[:period]).to eq("all")
|
|
expect(term_click_through_details[:data][0][:y]).to eq(1)
|
|
end
|
|
|
|
it "returns only non-staff users' searches with the non_staff_only search type" do
|
|
member = Fabricate(:user)
|
|
admin = Fabricate(:admin)
|
|
moderator = Fabricate(:moderator)
|
|
Fabricate(:search_log, term: "ruby", user: member)
|
|
Fabricate(:search_log, term: "ruby", user: admin)
|
|
Fabricate(:search_log, term: "ruby", user: moderator)
|
|
Fabricate(:search_log, term: "ruby", user: nil)
|
|
|
|
expect(
|
|
SearchLog.term_details("ruby", :weekly, :non_staff_only)[:data].sum { |point| point[:y] },
|
|
).to eq(1)
|
|
end
|
|
end
|
|
|
|
describe "trending" do
|
|
fab!(:user)
|
|
before do
|
|
SearchLog.log(term: "ruby", search_type: :header, ip_address: "127.0.0.1")
|
|
SearchLog.log(term: "php", search_type: :header, ip_address: "127.0.0.1")
|
|
SearchLog.log(term: "java", search_type: :header, ip_address: "127.0.0.1")
|
|
SearchLog.log(term: "ruby", search_type: :header, ip_address: "127.0.0.1", user_id: user.id)
|
|
SearchLog.log(term: "swift", search_type: :header, ip_address: "127.0.0.1")
|
|
SearchLog.log(term: "ruby", search_type: :header, ip_address: "127.0.0.2")
|
|
end
|
|
|
|
it "considers time period" do
|
|
expect(SearchLog.trending.to_a.count).to eq(4)
|
|
|
|
SearchLog.where(term: "swift").update_all(created_at: 1.year.ago)
|
|
expect(SearchLog.trending(:monthly).to_a.count).to eq(3)
|
|
end
|
|
|
|
it "correctly returns trending data" do
|
|
top_trending = SearchLog.trending.first
|
|
expect(top_trending.term).to eq("ruby")
|
|
expect(top_trending.searches).to eq(3)
|
|
expect(top_trending.click_through).to eq(0)
|
|
|
|
SearchLog.where(term: "ruby", ip_address: "127.0.0.1").update_all(search_result_id: 12)
|
|
SearchLog.where(term: "ruby", user_id: user.id).update_all(search_result_id: 12)
|
|
SearchLog.where(term: "ruby", ip_address: "127.0.0.2").update_all(search_result_id: 24)
|
|
top_trending = SearchLog.trending.first
|
|
expect(top_trending.click_through).to eq(3)
|
|
end
|
|
|
|
it "returns only non-staff users' searches with the non_staff_only search type" do
|
|
admin = Fabricate(:admin)
|
|
moderator = Fabricate(:moderator)
|
|
Fabricate(:search_log, term: "admin-search", user: admin)
|
|
Fabricate(:search_log, term: "moderator-search", user: moderator)
|
|
Fabricate(:search_log, term: "anonymous-search", user: nil)
|
|
|
|
results = SearchLog.trending(:all, :non_staff_only).to_a
|
|
|
|
expect(results.map { |trend| [trend.term, trend.searches] }).to eq([["ruby", 1]])
|
|
end
|
|
end
|
|
|
|
describe "clean_up" do
|
|
it "will remove old logs" do
|
|
SearchLog.log(term: "jawa", search_type: :header, ip_address: "127.0.0.1")
|
|
SearchLog.log(term: "jedi", search_type: :header, ip_address: "127.0.0.1")
|
|
SearchLog.log(term: "rey", search_type: :header, ip_address: "127.0.0.1")
|
|
SearchLog.log(term: "finn", search_type: :header, ip_address: "127.0.0.1")
|
|
|
|
SiteSetting.search_query_log_max_size = 5
|
|
SearchLog.clean_up
|
|
expect(SearchLog.count).to eq(4)
|
|
|
|
SiteSetting.search_query_log_max_size = 2
|
|
SearchLog.clean_up
|
|
expect(SearchLog.count).to eq(2)
|
|
expect(SearchLog.where(term: "rey").first).to be_present
|
|
expect(SearchLog.where(term: "finn").first).to be_present
|
|
end
|
|
end
|
|
end
|