diff --git a/app/assets/javascripts/discourse/templates/components/tag-list.hbs b/app/assets/javascripts/discourse/templates/components/tag-list.hbs
index 5d4deec2c2d..cd09db7bc35 100644
--- a/app/assets/javascripts/discourse/templates/components/tag-list.hbs
+++ b/app/assets/javascripts/discourse/templates/components/tag-list.hbs
@@ -10,7 +10,7 @@
{{#each sortedTags as |tag|}}
{{#if tag.count}}
- {{discourse-tag tag.id isPrivateMessage=isPrivateMessage}} x {{tag.count}}
+ {{discourse-tag tag.id isPrivateMessage=isPrivateMessage tagsForUser=tagsForUser}} x {{tag.count}}
{{else}}
{{discourse-tag tag.id}}
{{/if}}
diff --git a/app/assets/javascripts/discourse/templates/components/topic-list.hbs b/app/assets/javascripts/discourse/templates/components/topic-list.hbs
index b0d2ae5b115..dcb3f4c307b 100644
--- a/app/assets/javascripts/discourse/templates/components/topic-list.hbs
+++ b/app/assets/javascripts/discourse/templates/components/topic-list.hbs
@@ -40,7 +40,8 @@
expandGloballyPinned=expandGloballyPinned
expandAllPinned=expandAllPinned
lastVisitedTopic=lastVisitedTopic
- selected=selected}}
+ selected=selected
+ tagsForUser=tagsForUser}}
{{raw "list/visited-line" lastVisitedTopic=lastVisitedTopic topic=topic}}
{{/each}}
diff --git a/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs b/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs
index 020e32ecf4b..942e3f8d820 100644
--- a/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs
+++ b/app/assets/javascripts/discourse/templates/list/topic-list-item.raw.hbs
@@ -18,7 +18,7 @@
{{/if}}
- {{discourse-tags topic mode="list"}}
+ {{discourse-tags topic mode="list" tagsForUser=tagsForUser}}
{{#if expandPinned}}
{{raw "list/topic-excerpt" topic=topic}}
{{/if}}
diff --git a/app/assets/javascripts/discourse/templates/user-private-messages-tags.hbs b/app/assets/javascripts/discourse/templates/user-private-messages-tags.hbs
index 0682a895765..2310f0be8df 100644
--- a/app/assets/javascripts/discourse/templates/user-private-messages-tags.hbs
+++ b/app/assets/javascripts/discourse/templates/user-private-messages-tags.hbs
@@ -13,5 +13,5 @@
{{#if model}}
- {{tag-list tags=model sortProperties=sortProperties titleKey="tagging.all_tags" isPrivateMessage=true}}
+ {{tag-list tags=model sortProperties=sortProperties titleKey="tagging.all_tags" isPrivateMessage=true tagsForUser=tagsForUser}}
{{/if}}
diff --git a/app/assets/javascripts/discourse/templates/user-topics-list.hbs b/app/assets/javascripts/discourse/templates/user-topics-list.hbs
index 0749c7c837c..933e3dfe168 100644
--- a/app/assets/javascripts/discourse/templates/user-topics-list.hbs
+++ b/app/assets/javascripts/discourse/templates/user-topics-list.hbs
@@ -7,7 +7,8 @@
selected=selected
hasIncoming=hasIncoming
incomingCount=incomingCount
- showInserted="showInserted"}}
+ showInserted="showInserted"
+ tagsForUser=tagsForUser}}
{{conditional-loading-spinner condition=model.loadingMore}}
{{/load-more}}
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index 6cf3b813ffb..3a6d5f0d674 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -193,7 +193,10 @@ class TagsController < ::ApplicationController
def personal_messages
guardian.ensure_can_tag_pms!
- pm_tags = Tag.pm_tags(guardian: guardian)
+ allowed_user = fetch_user_from_params
+ raise Discourse::NotFound if allowed_user.blank?
+ raise Discourse::NotFound if current_user.id != allowed_user.id && !@guardian.is_admin?
+ pm_tags = Tag.pm_tags(guardian: guardian, allowed_user: allowed_user)
render json: { tags: pm_tags }
end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index c7c67f2625b..f110e677ce6 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -59,17 +59,27 @@ class Tag < ActiveRecord::Base
tag_names_with_counts.map { |row| row['tag_name'] }
end
- def self.pm_tags(limit_arg: nil, guardian: nil)
- return [] unless (guardian || Guardian.new).can_tag_pms?
+ def self.pm_tags(limit_arg: nil, guardian: nil, allowed_user: nil)
+ return [] if allowed_user.blank? || !(guardian || Guardian.new).can_tag_pms?
limit = limit_arg || SiteSetting.max_tags_in_filter_list
+ user_id = allowed_user.id
tag_names_with_counts = Tag.exec_sql <<~SQL
- SELECT tags.name, COUNT(topics.id) AS topic_count
+ SELECT tags.name,
+ COUNT(topics.id) AS topic_count
FROM tags
INNER JOIN topic_tags ON tags.id = topic_tags.tag_id
INNER JOIN topics ON topics.id = topic_tags.topic_id
AND topics.deleted_at IS NULL
AND topics.archetype = 'private_message'
+ WHERE topic_tags.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)
GROUP BY tags.name
LIMIT #{limit}
SQL
diff --git a/config/routes.rb b/config/routes.rb
index f1dfc801bb6..23b2bebef95 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -739,7 +739,7 @@ Discourse::Application.routes.draw do
get '/filter/list' => 'tags#index'
get '/filter/search' => 'tags#search'
get '/check' => 'tags#check_hashtag'
- get '/personal_messages' => 'tags#personal_messages'
+ get '/personal_messages/:username' => 'tags#personal_messages'
constraints(tag_id: /[^\/]+?/, format: /json|rss/) do
get '/:tag_id.rss' => 'tags#tag_feed'
get '/:tag_id' => 'tags#show', as: 'tag_show'
diff --git a/spec/models/tag_spec.rb b/spec/models/tag_spec.rb
index d642d96f70f..23602878b26 100644
--- a/spec/models/tag_spec.rb
+++ b/spec/models/tag_spec.rb
@@ -97,23 +97,31 @@ describe Tag do
end
describe '#pm_tags' do
+ let(:regular_user) { Fabricate(:trust_level_4) }
+ let(:admin) { Fabricate(:admin) }
+ let(:personal_message) do
+ Fabricate(:private_message_topic, user: regular_user, topic_allowed_users: [
+ Fabricate.build(:topic_allowed_user, user: regular_user),
+ Fabricate.build(:topic_allowed_user, user: admin)
+ ])
+ end
+
before do
- personal_message = Fabricate(:private_message_topic)
2.times { |i| Fabricate(:tag, topics: [personal_message], name: "tag-#{i}") }
end
it "returns nothing if user is not a staff" do
- expect(described_class.pm_tags.sort).to be_empty
+ expect(described_class.pm_tags(guardian: Guardian.new(regular_user))).to be_empty
end
it "returns nothing if allow_staff_to_tag_pms setting is disabled" do
SiteSetting.allow_staff_to_tag_pms = false
- expect(described_class.pm_tags(guardian: Guardian.new(Fabricate(:admin))).sort).to be_empty
+ expect(described_class.pm_tags(guardian: Guardian.new(admin)).sort).to be_empty
end
it "returns all pm tags if user is a staff and pm tagging is enabled" do
SiteSetting.allow_staff_to_tag_pms = true
- tags = described_class.pm_tags(guardian: Guardian.new(Fabricate(:admin)))
+ tags = described_class.pm_tags(guardian: Guardian.new(admin), allowed_user: regular_user)
expect(tags.length).to eq(2)
expect(tags[0][:id]).to eq("tag-0")
expect(tags[1][:text]).to eq("tag-1")
diff --git a/spec/requests/tags_controller_spec.rb b/spec/requests/tags_controller_spec.rb
index 58928384cf5..f77f8ee312c 100644
--- a/spec/requests/tags_controller_spec.rb
+++ b/spec/requests/tags_controller_spec.rb
@@ -55,28 +55,67 @@ describe TagsController do
end
describe '#personal_messages' do
+ let(:regular_user) { Fabricate(:trust_level_4) }
+ let(:moderator) { Fabricate(:moderator) }
+ let(:admin) { Fabricate(:admin) }
+ let(:personal_message) do
+ Fabricate(:private_message_topic, user: regular_user, topic_allowed_users: [
+ Fabricate.build(:topic_allowed_user, user: regular_user),
+ Fabricate.build(:topic_allowed_user, user: moderator),
+ Fabricate.build(:topic_allowed_user, user: admin)
+ ])
+ end
+
before do
SiteSetting.allow_staff_to_tag_pms = true
- personal_message = Fabricate(:private_message_topic)
Fabricate(:tag, topics: [personal_message], name: 'test')
end
- context "as a normal user" do
- it "should return the right response" do
- get "/tags/personal_messages.json"
+ context "as a regular user" do
+ it "can't see pm tags" do
+ get "/tags/personal_messages/#{regular_user.username}.json"
expect(response).not_to be_success
end
end
+ context "as an moderator" do
+ before do
+ sign_in(moderator)
+ end
+
+ it "can't see pm tags for regular user" do
+ get "/tags/personal_messages/#{regular_user.username}.json"
+
+ expect(response).not_to be_success
+ end
+
+ it "can see their own pm tags" do
+ get "/tags/personal_messages/#{moderator.username}.json"
+
+ expect(response).to be_success
+
+ tag = JSON.parse(response.body)['tags']
+ expect(tag[0]["id"]).to eq('test')
+ end
+ end
+
context "as an admin" do
before do
- admin = Fabricate(:admin)
sign_in(admin)
end
- it "should return the right response" do
- get "/tags/personal_messages.json"
+ it "can see pm tags for regular user" do
+ get "/tags/personal_messages/#{regular_user.username}.json"
+
+ expect(response).to be_success
+
+ tag = JSON.parse(response.body)['tags']
+ expect(tag[0]["id"]).to eq('test')
+ end
+
+ it "can see their own pm tags" do
+ get "/tags/personal_messages/#{admin.username}.json"
expect(response).to be_success