diff --git a/lib/topics_filter.rb b/lib/topics_filter.rb index e83d9bf210f..8b6044a0eea 100644 --- a/lib/topics_filter.rb +++ b/lib/topics_filter.rb @@ -51,6 +51,8 @@ class TopicsFilter if @guardian.can_see_deleted_topics?(category) @scope = @scope.unscope(where: :deleted_at).where("topics.deleted_at IS NOT NULL") end + when "public" + @scope = @scope.joins(:category).where("NOT categories.read_restricted") end @scope diff --git a/spec/lib/topics_filter_spec.rb b/spec/lib/topics_filter_spec.rb index 820481ae3a4..e837c49c249 100644 --- a/spec/lib/topics_filter_spec.rb +++ b/spec/lib/topics_filter_spec.rb @@ -2,6 +2,7 @@ RSpec.describe TopicsFilter do fab!(:admin) { Fabricate(:admin) } + fab!(:group) { Fabricate(:group) } describe "#filter_from_query_string" do describe "when filtering with multiple filters" do @@ -87,6 +88,22 @@ RSpec.describe TopicsFilter do .pluck(:id), ).to contain_exactly(topic.id) end + + it "should only return topics that are not in any read-restricted category when query string is `status:public`" do + private_category = Fabricate(:private_category, group: group) + topic_in_private_category = Fabricate(:topic, category: private_category) + + expect( + TopicsFilter.new(guardian: Guardian.new).filter_from_query_string("").pluck(:id), + ).to include(topic_in_private_category.id) + + expect( + TopicsFilter + .new(guardian: Guardian.new) + .filter_from_query_string("status:public") + .pluck(:id), + ).not_to include(topic_in_private_category.id) + end end describe "when filtering by tags" do diff --git a/spec/requests/list_controller_spec.rb b/spec/requests/list_controller_spec.rb index 00c5546baec..413567dc3b4 100644 --- a/spec/requests/list_controller_spec.rb +++ b/spec/requests/list_controller_spec.rb @@ -1179,5 +1179,25 @@ RSpec.describe ListController do expect(parsed["topic_list"]["topics"].first["id"]).to eq(topic_with_tag.id) end end + + describe "when filtering by status" do + fab!(:group) { Fabricate(:group) } + fab!(:private_category) { Fabricate(:private_category, group: group) } + fab!(:topic_in_private_category) { Fabricate(:topic, category: private_category) } + + it "does not return topics from read restricted categories when `q` query param is `status:public`" do + group.add(user) + + sign_in(user) + + get "/filter.json?q=status:public" + + expect(response.status).to eq(200) + + expect( + response.parsed_body["topic_list"]["topics"].map { |topic| topic["id"] }, + ).to contain_exactly(topic.id, topic_with_tag.id, topic2_with_tag.id) + end + end end end