mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
Merge pull request #5682 from techAPJ/allowed-tags-page
FIX: show only allowed tags on PM tags page and display correct count
This commit is contained in:
commit
f053e4cf37
@ -1,5 +1,6 @@
|
|||||||
export default Ember.Controller.extend({
|
export default Ember.Controller.extend({
|
||||||
sortProperties: ['count:desc', 'id'],
|
sortProperties: ['count:desc', 'id'],
|
||||||
|
tagsForUser: null,
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
sortByCount() {
|
sortByCount() {
|
||||||
|
@ -9,6 +9,7 @@ export default Ember.Controller.extend({
|
|||||||
newIncoming: [],
|
newIncoming: [],
|
||||||
incomingCount: 0,
|
incomingCount: 0,
|
||||||
channel: null,
|
channel: null,
|
||||||
|
tagsForUser: null,
|
||||||
|
|
||||||
_showFooter: function() {
|
_showFooter: function() {
|
||||||
this.set("application.showFooter", !this.get("model.canLoadMore"));
|
this.set("application.showFooter", !this.get("model.canLoadMore"));
|
||||||
|
@ -5,8 +5,12 @@ export default function renderTag(tag, params) {
|
|||||||
const tagName = params.tagName || "a";
|
const tagName = params.tagName || "a";
|
||||||
let path;
|
let path;
|
||||||
if (tagName === "a" && !params.noHref) {
|
if (tagName === "a" && !params.noHref) {
|
||||||
const current_user = Discourse.User.current();
|
if (params.isPrivateMessage && Discourse.User.current()) {
|
||||||
path = params.isPrivateMessage ? `/u/${current_user.username}/messages/tags/${tag}` : `/tags/${tag}`;
|
const username = params.tagsForUser ? params.tagsForUser : Discourse.User.current().username;
|
||||||
|
path = `/u/${username}/messages/tags/${tag}`;
|
||||||
|
} else {
|
||||||
|
path = `/tags/${tag}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const href = path ? ` href='${Discourse.getURL(path)}' ` : "";
|
const href = path ? ` href='${Discourse.getURL(path)}' ` : "";
|
||||||
|
|
||||||
|
@ -20,11 +20,17 @@ export function addTagsHtmlCallback(callback, options) {
|
|||||||
export default function(topic, params){
|
export default function(topic, params){
|
||||||
let tags = topic.tags;
|
let tags = topic.tags;
|
||||||
let buffer = "";
|
let buffer = "";
|
||||||
|
let tagsForUser = null;
|
||||||
const isPrivateMessage = topic.get('isPrivateMessage');
|
const isPrivateMessage = topic.get('isPrivateMessage');
|
||||||
|
|
||||||
if (params && params.mode === "list") {
|
if (params) {
|
||||||
|
if (params.mode === "list") {
|
||||||
tags = topic.get("visibleListTags");
|
tags = topic.get("visibleListTags");
|
||||||
}
|
}
|
||||||
|
if (params.tagsForUser) {
|
||||||
|
tagsForUser = params.tagsForUser;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let customHtml = null;
|
let customHtml = null;
|
||||||
if (callbacks) {
|
if (callbacks) {
|
||||||
@ -44,7 +50,7 @@ export default function(topic, params){
|
|||||||
buffer = "<div class='discourse-tags'>";
|
buffer = "<div class='discourse-tags'>";
|
||||||
if (tags) {
|
if (tags) {
|
||||||
for(let i=0; i<tags.length; i++){
|
for(let i=0; i<tags.length; i++){
|
||||||
buffer += renderTag(tags[i], { isPrivateMessage }) + ' ';
|
buffer += renderTag(tags[i], { isPrivateMessage, tagsForUser }) + ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ export default (viewName, path, channel) => {
|
|||||||
hideCategory: true,
|
hideCategory: true,
|
||||||
showPosters: true,
|
showPosters: true,
|
||||||
canBulkSelect: true,
|
canBulkSelect: true,
|
||||||
|
tagsForUser: this.modelFor("user").get("username_lower"),
|
||||||
selected: []
|
selected: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ import { popupAjaxError } from 'discourse/lib/ajax-error';
|
|||||||
|
|
||||||
export default Discourse.Route.extend({
|
export default Discourse.Route.extend({
|
||||||
model() {
|
model() {
|
||||||
return ajax('/tags/personal_messages').then(result => {
|
const username = this.modelFor("user").get("username_lower");
|
||||||
|
return ajax(`/tags/personal_messages/${username}`).then(result => {
|
||||||
return result.tags.map(tag => Ember.Object.create(tag));
|
return result.tags.map(tag => Ember.Object.create(tag));
|
||||||
}).catch(popupAjaxError);
|
}).catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
@ -15,7 +16,8 @@ export default Discourse.Route.extend({
|
|||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
this.controllerFor('user-private-messages-tags').setProperties({
|
this.controllerFor('user-private-messages-tags').setProperties({
|
||||||
model,
|
model,
|
||||||
sortProperties: this.siteSettings.tags_sort_alphabetically ? ['id'] : ['count:desc', 'id']
|
sortProperties: this.siteSettings.tags_sort_alphabetically ? ['id'] : ['count:desc', 'id'],
|
||||||
|
tagsForUser: this.modelFor("user").get("username_lower")
|
||||||
});
|
});
|
||||||
this.controllerFor('user-private-messages').setProperties({
|
this.controllerFor('user-private-messages').setProperties({
|
||||||
showToggleBulkSelect: false,
|
showToggleBulkSelect: false,
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
bulkSelectEnabled=bulkSelectEnabled
|
bulkSelectEnabled=bulkSelectEnabled
|
||||||
canBulkSelect=canBulkSelect
|
canBulkSelect=canBulkSelect
|
||||||
selected=selected
|
selected=selected
|
||||||
skipHeader=skipHeader}}
|
skipHeader=skipHeader
|
||||||
|
tagsForUser=tagsForUser}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#unless loadingMore}}
|
{{#unless loadingMore}}
|
||||||
<div class='alert alert-info'>
|
<div class='alert alert-info'>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
{{#each sortedTags as |tag|}}
|
{{#each sortedTags as |tag|}}
|
||||||
<div class='tag-box'>
|
<div class='tag-box'>
|
||||||
{{#if tag.count}}
|
{{#if tag.count}}
|
||||||
{{discourse-tag tag.id isPrivateMessage=isPrivateMessage}} <span class='tag-count'>x {{tag.count}}</span>
|
{{discourse-tag tag.id isPrivateMessage=isPrivateMessage tagsForUser=tagsForUser}} <span class='tag-count'>x {{tag.count}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{discourse-tag tag.id}}
|
{{discourse-tag tag.id}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -40,7 +40,8 @@
|
|||||||
expandGloballyPinned=expandGloballyPinned
|
expandGloballyPinned=expandGloballyPinned
|
||||||
expandAllPinned=expandAllPinned
|
expandAllPinned=expandAllPinned
|
||||||
lastVisitedTopic=lastVisitedTopic
|
lastVisitedTopic=lastVisitedTopic
|
||||||
selected=selected}}
|
selected=selected
|
||||||
|
tagsForUser=tagsForUser}}
|
||||||
{{raw "list/visited-line" lastVisitedTopic=lastVisitedTopic topic=topic}}
|
{{raw "list/visited-line" lastVisitedTopic=lastVisitedTopic topic=topic}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{{discourse-tags topic mode="list"}}
|
{{discourse-tags topic mode="list" tagsForUser=tagsForUser}}
|
||||||
{{#if expandPinned}}
|
{{#if expandPinned}}
|
||||||
{{raw "list/topic-excerpt" topic=topic}}
|
{{raw "list/topic-excerpt" topic=topic}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -13,5 +13,5 @@
|
|||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
{{#if model}}
|
{{#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}}
|
{{/if}}
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
selected=selected
|
selected=selected
|
||||||
hasIncoming=hasIncoming
|
hasIncoming=hasIncoming
|
||||||
incomingCount=incomingCount
|
incomingCount=incomingCount
|
||||||
showInserted="showInserted"}}
|
showInserted="showInserted"
|
||||||
|
tagsForUser=tagsForUser}}
|
||||||
|
|
||||||
{{conditional-loading-spinner condition=model.loadingMore}}
|
{{conditional-loading-spinner condition=model.loadingMore}}
|
||||||
{{/load-more}}
|
{{/load-more}}
|
||||||
|
@ -193,7 +193,10 @@ class TagsController < ::ApplicationController
|
|||||||
|
|
||||||
def personal_messages
|
def personal_messages
|
||||||
guardian.ensure_can_tag_pms!
|
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 }
|
render json: { tags: pm_tags }
|
||||||
end
|
end
|
||||||
|
@ -59,17 +59,27 @@ class Tag < ActiveRecord::Base
|
|||||||
tag_names_with_counts.map { |row| row['tag_name'] }
|
tag_names_with_counts.map { |row| row['tag_name'] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.pm_tags(limit_arg: nil, guardian: nil)
|
def self.pm_tags(limit_arg: nil, guardian: nil, allowed_user: nil)
|
||||||
return [] unless (guardian || Guardian.new).can_tag_pms?
|
return [] if allowed_user.blank? || !(guardian || Guardian.new).can_tag_pms?
|
||||||
limit = limit_arg || SiteSetting.max_tags_in_filter_list
|
limit = limit_arg || SiteSetting.max_tags_in_filter_list
|
||||||
|
user_id = allowed_user.id
|
||||||
|
|
||||||
tag_names_with_counts = Tag.exec_sql <<~SQL
|
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
|
FROM tags
|
||||||
INNER JOIN topic_tags ON tags.id = topic_tags.tag_id
|
INNER JOIN topic_tags ON tags.id = topic_tags.tag_id
|
||||||
INNER JOIN topics ON topics.id = topic_tags.topic_id
|
INNER JOIN topics ON topics.id = topic_tags.topic_id
|
||||||
AND topics.deleted_at IS NULL
|
AND topics.deleted_at IS NULL
|
||||||
AND topics.archetype = 'private_message'
|
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
|
GROUP BY tags.name
|
||||||
LIMIT #{limit}
|
LIMIT #{limit}
|
||||||
SQL
|
SQL
|
||||||
|
@ -739,7 +739,7 @@ Discourse::Application.routes.draw do
|
|||||||
get '/filter/list' => 'tags#index'
|
get '/filter/list' => 'tags#index'
|
||||||
get '/filter/search' => 'tags#search'
|
get '/filter/search' => 'tags#search'
|
||||||
get '/check' => 'tags#check_hashtag'
|
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
|
constraints(tag_id: /[^\/]+?/, format: /json|rss/) do
|
||||||
get '/:tag_id.rss' => 'tags#tag_feed'
|
get '/:tag_id.rss' => 'tags#tag_feed'
|
||||||
get '/:tag_id' => 'tags#show', as: 'tag_show'
|
get '/:tag_id' => 'tags#show', as: 'tag_show'
|
||||||
|
@ -97,23 +97,31 @@ describe Tag do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#pm_tags' do
|
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
|
before do
|
||||||
personal_message = Fabricate(:private_message_topic)
|
|
||||||
2.times { |i| Fabricate(:tag, topics: [personal_message], name: "tag-#{i}") }
|
2.times { |i| Fabricate(:tag, topics: [personal_message], name: "tag-#{i}") }
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns nothing if user is not a staff" do
|
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
|
end
|
||||||
|
|
||||||
it "returns nothing if allow_staff_to_tag_pms setting is disabled" do
|
it "returns nothing if allow_staff_to_tag_pms setting is disabled" do
|
||||||
SiteSetting.allow_staff_to_tag_pms = false
|
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
|
end
|
||||||
|
|
||||||
it "returns all pm tags if user is a staff and pm tagging is enabled" do
|
it "returns all pm tags if user is a staff and pm tagging is enabled" do
|
||||||
SiteSetting.allow_staff_to_tag_pms = true
|
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.length).to eq(2)
|
||||||
expect(tags[0][:id]).to eq("tag-0")
|
expect(tags[0][:id]).to eq("tag-0")
|
||||||
expect(tags[1][:text]).to eq("tag-1")
|
expect(tags[1][:text]).to eq("tag-1")
|
||||||
|
@ -55,28 +55,67 @@ describe TagsController do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#personal_messages' do
|
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
|
before do
|
||||||
SiteSetting.allow_staff_to_tag_pms = true
|
SiteSetting.allow_staff_to_tag_pms = true
|
||||||
personal_message = Fabricate(:private_message_topic)
|
|
||||||
Fabricate(:tag, topics: [personal_message], name: 'test')
|
Fabricate(:tag, topics: [personal_message], name: 'test')
|
||||||
end
|
end
|
||||||
|
|
||||||
context "as a normal user" do
|
context "as a regular user" do
|
||||||
it "should return the right response" do
|
it "can't see pm tags" do
|
||||||
get "/tags/personal_messages.json"
|
get "/tags/personal_messages/#{regular_user.username}.json"
|
||||||
|
|
||||||
expect(response).not_to be_success
|
expect(response).not_to be_success
|
||||||
end
|
end
|
||||||
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
|
context "as an admin" do
|
||||||
before do
|
before do
|
||||||
admin = Fabricate(:admin)
|
|
||||||
sign_in(admin)
|
sign_in(admin)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return the right response" do
|
it "can see pm tags for regular user" do
|
||||||
get "/tags/personal_messages.json"
|
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
|
expect(response).to be_success
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user