diff --git a/lib/topic_query.rb b/lib/topic_query.rb index a2275b89e5f..a6cbacf3f49 100644 --- a/lib/topic_query.rb +++ b/lib/topic_query.rb @@ -481,6 +481,23 @@ class TopicQuery result end + def apply_shared_drafts(result, category_id, options) + viewing_shared = category_id && category_id == SiteSetting.shared_drafts_category.to_i + + if guardian.can_create_shared_draft? + result = result.includes(:shared_draft).references(:shared_draft) + + if options[:destination_category_id] + destination_category_id = get_category_id(options[:destination_category_id]) + return result.where("shared_drafts.category_id" => destination_category_id) + end + + return result.where("shared_drafts.id IS NULL") unless viewing_shared + end + + result + end + def apply_ordering(result, options) sort_column = SORTABLE_MAPPING[options[:order]] || 'default' sort_dir = (options[:ascending] == "true") ? "ASC" : "DESC" @@ -606,16 +623,7 @@ class TopicQuery result = apply_ordering(result, options) result = result.listable_topics.includes(:category) - - # Avoid N+1 for shared drafts - if category_id && category_id == SiteSetting.shared_drafts_category.to_i - result = result.includes(:shared_draft) - end - - if options[:destination_category_id] - destination_category_id = get_category_id(options[:destination_category_id]) - result = result.includes(:shared_draft).where("shared_drafts.category_id" => destination_category_id) - end + result = apply_shared_drafts(result, category_id, options) if options[:exclude_category_ids] && options[:exclude_category_ids].is_a?(Array) && options[:exclude_category_ids].size > 0 result = result.where("categories.id NOT IN (?)", options[:exclude_category_ids]).references(:categories) diff --git a/spec/components/topic_query_spec.rb b/spec/components/topic_query_spec.rb index 989348f4c54..fcce4812528 100644 --- a/spec/components/topic_query_spec.rb +++ b/spec/components/topic_query_spec.rb @@ -981,4 +981,39 @@ describe TopicQuery do expect(topics).to eq([]) end end + + context "shared drafts" do + let(:category) { Fabricate(:category) } + let(:shared_drafts_category) { Fabricate(:category) } + let!(:topic) { Fabricate(:topic, category: shared_drafts_category) } + let!(:shared_draft) { Fabricate(:shared_draft, topic: topic, category: category) } + let(:admin) { Fabricate(:admin) } + let(:user) { Fabricate(:user) } + let(:group) { Fabricate(:group) } + + before do + shared_drafts_category.set_permissions(group => :full) + shared_drafts_category.save + SiteSetting.shared_drafts_category = shared_drafts_category.id + end + + context "destination_category_id" do + it "doesn't allow regular users to query destination_category_id" do + list = TopicQuery.new(user, destination_category_id: category.id).list_latest + expect(list.topics).not_to include(topic) + end + + it "allows staff users to query destination_category_id" do + list = TopicQuery.new(admin, destination_category_id: category.id).list_latest + expect(list.topics).to include(topic) + end + end + + context "latest" do + it "doesn't include shared topics unless filtering by category" do + list = TopicQuery.new(moderator).list_latest + expect(list.topics).not_to include(topic) + end + end + end end