diff --git a/app/models/topic.rb b/app/models/topic.rb index c2b7f738d88..f917f4fdeb2 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -634,14 +634,27 @@ class Topic < ActiveRecord::Base tsquery = Search.to_tsquery(term: tsquery, joiner: "|") + guardian = Guardian.new(user) + + excluded_category_ids_sql = Category.secured(guardian).where(search_priority: Searchable::PRIORITIES[:ignore]).select(:id).to_sql + + if user + excluded_category_ids_sql = <<~SQL + #{excluded_category_ids_sql} + UNION + #{CategoryUser.where(notification_level: CategoryUser.notification_levels[:muted], user: user).select(:category_id).to_sql} + SQL + end + candidates = Topic .visible .listable_topics - .secured(Guardian.new(user)) + .secured(guardian) .joins("JOIN topic_search_data s ON topics.id = s.topic_id") .joins("LEFT JOIN categories c ON topics.id = c.topic_id") .where("search_data @@ #{tsquery}") .where("c.topic_id IS NULL") + .where("topics.category_id NOT IN (#{excluded_category_ids_sql})") .order("ts_rank(search_data, #{tsquery}) DESC") .limit(SiteSetting.max_similar_results * 3) diff --git a/spec/models/topic_spec.rb b/spec/models/topic_spec.rb index 701c84b1227..0e1e784bd53 100644 --- a/spec/models/topic_spec.rb +++ b/spec/models/topic_spec.rb @@ -685,10 +685,28 @@ RSpec.describe Topic do expect(topics).to eq([]) end + it 'does not return topics from categories with search priority set to ignore' do + expect(Topic.similar_to("has evil trout made any topics?", "")).to eq([topic]) + + topic.category.update!(search_priority: Searchable::PRIORITIES[:ignore]) + + expect(Topic.similar_to("has evil trout made any topics?", "")).to eq([]) + end + + it 'does not return topics from categories which the user has muted' do + expect(Topic.similar_to("has evil trout made any topics?", "", user)).to eq([topic]) + + CategoryUser.create!(category: topic.category, user: user, notification_level: CategoryUser.notification_levels[:muted]) + + expect(Topic.similar_to("has evil trout made any topics?", "", user)).to eq([]) + end + context "with secure categories" do + fab!(:group) { Fabricate(:group) } + fab!(:private_category) { Fabricate(:private_category, group: group) } + before do - category.update!(read_restricted: true) - topic.update!(category: category) + topic.update!(category: private_category) end it "doesn't return topics from private categories" do @@ -696,7 +714,8 @@ RSpec.describe Topic do end it "should return the cat since the user can see it" do - Guardian.any_instance.expects(:secure_category_ids).returns([category.id]) + group.add(user) + expect(Topic.similar_to("has evil trout made any topics?", "i am wondering has evil trout made any topics?", user)).to include(topic) end end