diff --git a/app/models/post.rb b/app/models/post.rb index bdbf598682b..ad2b98e2f45 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -59,6 +59,18 @@ class Post < ActiveRecord::Base SHORT_POST_CHARS = 1200 + scope :private_posts_for_user, ->(user) { + where("posts.topic_id IN (SELECT topic_id + FROM topic_allowed_users + WHERE user_id = :user_id + UNION ALL + SELECT tg.topic_id + FROM topic_allowed_groups tg + JOIN group_users gu ON gu.user_id = :user_id AND + gu.group_id = tg.group_id)", + user_id: user.id) + } + scope :by_newest, -> { order('created_at desc, id desc') } scope :by_post_number, -> { order('post_number ASC') } scope :with_user, -> { includes(:user) } diff --git a/lib/search.rb b/lib/search.rb index 81c924df44b..6b0f4581483 100644 --- a/lib/search.rb +++ b/lib/search.rb @@ -610,7 +610,7 @@ class Search posts = posts.where("topics.archetype = ?", Archetype.private_message) unless @guardian.is_admin? - posts = posts.where("topics.id IN (SELECT topic_id FROM topic_allowed_users WHERE user_id = ?)", @guardian.user.id) + posts = posts.private_posts_for_user(@guardian.user) end else posts = posts.where("topics.archetype <> ?", Archetype.private_message) @@ -654,15 +654,7 @@ class Search if @search_context.is_a?(User) if opts[:private_messages] - posts = posts.where("topics.id IN (SELECT topic_id - FROM topic_allowed_users - WHERE user_id = :user_id - UNION ALL - SELECT tg.topic_id - FROM topic_allowed_groups tg - JOIN group_users gu ON gu.user_id = :user_id AND - gu.group_id = tg.group_id)", - user_id: @search_context.id) + posts = posts.private_posts_for_user(@search_context) else posts = posts.where("posts.user_id = #{@search_context.id}") end diff --git a/spec/components/search_spec.rb b/spec/components/search_spec.rb index 386af7b1671..056491b81b0 100644 --- a/spec/components/search_spec.rb +++ b/spec/components/search_spec.rb @@ -159,50 +159,64 @@ describe Search do it 'searches correctly' do - expect do - Search.execute('mars', type_filter: 'private_messages') - end.to raise_error(Discourse::InvalidAccess) + expect do + Search.execute('mars', type_filter: 'private_messages') + end.to raise_error(Discourse::InvalidAccess) - TopicAllowedUser.create!(user_id: reply.user_id, topic_id: topic.id) - TopicAllowedUser.create!(user_id: post.user_id, topic_id: topic.id) + TopicAllowedUser.create!(user_id: reply.user_id, topic_id: topic.id) + TopicAllowedUser.create!(user_id: post.user_id, topic_id: topic.id) - results = Search.execute('mars', - type_filter: 'private_messages', - guardian: Guardian.new(reply.user)) + results = Search.execute('mars', + type_filter: 'private_messages', + guardian: Guardian.new(reply.user)) - expect(results.posts.length).to eq(1) + expect(results.posts.length).to eq(1) - results = Search.execute('mars', - search_context: topic, - guardian: Guardian.new(reply.user)) + results = Search.execute('mars', + search_context: topic, + guardian: Guardian.new(reply.user)) - expect(results.posts.length).to eq(1) + expect(results.posts.length).to eq(1) - # does not leak out - results = Search.execute('mars', - type_filter: 'private_messages', - guardian: Guardian.new(Fabricate(:user))) + # does not leak out + results = Search.execute('mars', + type_filter: 'private_messages', + guardian: Guardian.new(Fabricate(:user))) - expect(results.posts.length).to eq(0) + expect(results.posts.length).to eq(0) - Fabricate(:topic, category_id: nil, archetype: 'private_message') - Fabricate(:post, topic: topic, raw: 'another secret pm from mars, testing') + Fabricate(:topic, category_id: nil, archetype: 'private_message') + Fabricate(:post, topic: topic, raw: 'another secret pm from mars, testing') - # admin can search everything with correct context - results = Search.execute('mars', - type_filter: 'private_messages', - search_context: post.user, - guardian: Guardian.new(Fabricate(:admin))) + # admin can search everything with correct context + results = Search.execute('mars', + type_filter: 'private_messages', + search_context: post.user, + guardian: Guardian.new(Fabricate(:admin))) - expect(results.posts.length).to eq(1) + expect(results.posts.length).to eq(1) - results = Search.execute('mars in:private', - search_context: post.user, - guardian: Guardian.new(post.user)) + results = Search.execute('mars in:private', + search_context: post.user, + guardian: Guardian.new(post.user)) - expect(results.posts.length).to eq(1) + expect(results.posts.length).to eq(1) + + # can search group PMs as well as non admin + # + user = Fabricate(:user) + group = Fabricate.build(:group) + group.add(user) + group.save! + + TopicAllowedGroup.create!(group_id: group.id, topic_id: topic.id) + + results = Search.execute('mars in:private', + guardian: Guardian.new(user)) + + expect(results.posts.length).to eq(1) end