mirror of
https://github.com/discourse/discourse.git
synced 2025-03-06 11:19:51 +00:00
FIX: Disable 'Create Topic' button if tag is staff-only. (#6984)
* FIX: Disable 'Create Topic' button if tag is staff-only. * FIX: Staff-only tags should always return 404.
This commit is contained in:
parent
191e31dccf
commit
e6c2faf186
@ -74,9 +74,25 @@ export default Ember.Controller.extend(BulkTopicSelection, {
|
|||||||
return listDraft ? "topic.open_draft" : "topic.create";
|
return listDraft ? "topic.open_draft" : "topic.create";
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("canCreateTopic", "category", "canCreateTopicOnCategory")
|
@computed(
|
||||||
createTopicDisabled(canCreateTopic, category, canCreateTopicOnCategory) {
|
"canCreateTopic",
|
||||||
return !canCreateTopic || (category && !canCreateTopicOnCategory);
|
"category",
|
||||||
|
"canCreateTopicOnCategory",
|
||||||
|
"tag",
|
||||||
|
"canCreateTopicOnTag"
|
||||||
|
)
|
||||||
|
createTopicDisabled(
|
||||||
|
canCreateTopic,
|
||||||
|
category,
|
||||||
|
canCreateTopicOnCategory,
|
||||||
|
tag,
|
||||||
|
canCreateTopicOnTag
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
!canCreateTopic ||
|
||||||
|
(category && !canCreateTopicOnCategory) ||
|
||||||
|
(tag && !canCreateTopicOnTag)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
queryParams: [
|
queryParams: [
|
||||||
|
@ -111,14 +111,18 @@ export default Discourse.Route.extend({
|
|||||||
).then(list => {
|
).then(list => {
|
||||||
if (list.topic_list.tags && list.topic_list.tags.length === 1) {
|
if (list.topic_list.tags && list.topic_list.tags.length === 1) {
|
||||||
// Update name of tag (case might be different)
|
// Update name of tag (case might be different)
|
||||||
tag.set("id", list.topic_list.tags[0].name);
|
tag.setProperties({
|
||||||
|
id: list.topic_list.tags[0].name,
|
||||||
|
staff: list.topic_list.tags[0].staff
|
||||||
|
});
|
||||||
}
|
}
|
||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
list,
|
list,
|
||||||
canCreateTopic: list.get("can_create_topic"),
|
canCreateTopic: list.get("can_create_topic"),
|
||||||
loading: false,
|
loading: false,
|
||||||
canCreateTopicOnCategory:
|
canCreateTopicOnCategory:
|
||||||
this.get("category.permission") === PermissionType.FULL
|
this.get("category.permission") === PermissionType.FULL,
|
||||||
|
canCreateTopicOnTag: !tag.get("staff") || this.get("currentUser.staff")
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -98,6 +98,8 @@ class TagsController < ::ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
raise Discourse::NotFound if DiscourseTagging.hidden_tag_names(guardian).include?(params[:tag_id])
|
||||||
|
|
||||||
show_latest
|
show_latest
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ class TagGroup < ActiveRecord::Base
|
|||||||
before_create :init_permissions
|
before_create :init_permissions
|
||||||
before_save :apply_permissions
|
before_save :apply_permissions
|
||||||
|
|
||||||
|
after_commit { DiscourseTagging.clear_cache! }
|
||||||
|
|
||||||
attr_accessor :permissions
|
attr_accessor :permissions
|
||||||
|
|
||||||
def tag_names=(tag_names_arg)
|
def tag_names=(tag_names_arg)
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
class TagSerializer < ApplicationSerializer
|
class TagSerializer < ApplicationSerializer
|
||||||
attributes :id, :name, :topic_count
|
attributes :id, :name, :topic_count, :staff
|
||||||
|
|
||||||
|
def staff
|
||||||
|
DiscourseTagging.staff_tag_names.include?(name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,6 +2,7 @@ module DiscourseTagging
|
|||||||
|
|
||||||
TAGS_FIELD_NAME = "tags"
|
TAGS_FIELD_NAME = "tags"
|
||||||
TAGS_FILTER_REGEXP = /[\/\?#\[\]@!\$&'\(\)\*\+,;=\.%\\`^\s|\{\}"<>]+/ # /?#[]@!$&'()*+,;=.%\`^|{}"<>
|
TAGS_FILTER_REGEXP = /[\/\?#\[\]@!\$&'\(\)\*\+,;=\.%\\`^\s|\{\}"<>]+/ # /?#[]@!$&'()*+,;=.%\`^|{}"<>
|
||||||
|
TAGS_STAFF_CACHE_KEY = "staff_tag_names"
|
||||||
|
|
||||||
def self.tag_topic_by_names(topic, guardian, tag_names_arg, append: false)
|
def self.tag_topic_by_names(topic, guardian, tag_names_arg, append: false)
|
||||||
if guardian.can_tag?(topic)
|
if guardian.can_tag?(topic)
|
||||||
@ -194,11 +195,22 @@ module DiscourseTagging
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.staff_tag_names
|
def self.staff_tag_names
|
||||||
Tag.joins(tag_groups: :tag_group_permissions)
|
tag_names = Discourse.cache.read(TAGS_STAFF_CACHE_KEY, tag_names)
|
||||||
.where('tag_group_permissions.group_id = ? AND tag_group_permissions.permission_type = ?',
|
|
||||||
Group::AUTO_GROUPS[:everyone],
|
if !tag_names
|
||||||
TagGroupPermission.permission_types[:readonly]
|
tag_names = Tag.joins(tag_groups: :tag_group_permissions)
|
||||||
).pluck(:name)
|
.where('tag_group_permissions.group_id = ? AND tag_group_permissions.permission_type = ?',
|
||||||
|
Group::AUTO_GROUPS[:everyone],
|
||||||
|
TagGroupPermission.permission_types[:readonly]
|
||||||
|
).pluck(:name)
|
||||||
|
Discourse.cache.write(TAGS_STAFF_CACHE_KEY, tag_names, expires_in: 1.hour)
|
||||||
|
end
|
||||||
|
|
||||||
|
tag_names
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.clear_cache!
|
||||||
|
Discourse.cache.delete(TAGS_STAFF_CACHE_KEY)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.clean_tag(tag)
|
def self.clean_tag(tag)
|
||||||
|
@ -216,4 +216,29 @@ describe DiscourseTagging do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "staff_tag_names" do
|
||||||
|
let(:tag) { Fabricate(:tag) }
|
||||||
|
|
||||||
|
let(:staff_tag) { Fabricate(:tag) }
|
||||||
|
let(:other_staff_tag) { Fabricate(:tag) }
|
||||||
|
|
||||||
|
let!(:staff_tag_group) {
|
||||||
|
Fabricate(
|
||||||
|
:tag_group,
|
||||||
|
permissions: { "staff" => 1, "everyone" => 3 },
|
||||||
|
tag_names: [staff_tag.name]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
it "returns all staff tags" do
|
||||||
|
expect(DiscourseTagging.staff_tag_names).to contain_exactly(staff_tag.name)
|
||||||
|
|
||||||
|
staff_tag_group.update(tag_names: [staff_tag.name, other_staff_tag.name])
|
||||||
|
expect(DiscourseTagging.staff_tag_names).to contain_exactly(staff_tag.name, other_staff_tag.name)
|
||||||
|
|
||||||
|
staff_tag_group.update(tag_names: [other_staff_tag.name])
|
||||||
|
expect(DiscourseTagging.staff_tag_names).to contain_exactly(other_staff_tag.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -64,6 +64,18 @@ describe TagsController do
|
|||||||
get "/tags/%2ftest%2f"
|
get "/tags/%2ftest%2f"
|
||||||
expect(response.status).to eq(404)
|
expect(response.status).to eq(404)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "does not show staff-only tags" do
|
||||||
|
tag_group = Fabricate(:tag_group, permissions: { "staff" => 1 }, tag_names: ["test"])
|
||||||
|
|
||||||
|
get "/tags/test"
|
||||||
|
expect(response.status).to eq(404)
|
||||||
|
|
||||||
|
sign_in(Fabricate(:admin))
|
||||||
|
|
||||||
|
get "/tags/test"
|
||||||
|
expect(response.status).to eq(200)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#check_hashtag' do
|
describe '#check_hashtag' do
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { acceptance } from "helpers/qunit-helpers";
|
import { replaceCurrentUser, acceptance } from "helpers/qunit-helpers";
|
||||||
acceptance("Tags", { loggedIn: true });
|
acceptance("Tags", { loggedIn: true });
|
||||||
|
|
||||||
QUnit.test("list the tags", async assert => {
|
QUnit.test("list the tags", async assert => {
|
||||||
@ -92,3 +92,83 @@ QUnit.test("list the tags in groups", async assert => {
|
|||||||
"always uses lowercase URLs for mixed case tags"
|
"always uses lowercase URLs for mixed case tags"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("new topic button is not available for staff-only tags", async assert => {
|
||||||
|
/* global server */
|
||||||
|
server.get("/tags/regular-tag/notifications", () => [
|
||||||
|
200,
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
{ tag_notification: { id: "regular-tag", notification_level: 1 } }
|
||||||
|
]);
|
||||||
|
|
||||||
|
server.get("/tags/regular-tag/l/latest.json", () => [
|
||||||
|
200,
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
{
|
||||||
|
users: [],
|
||||||
|
primary_groups: [],
|
||||||
|
topic_list: {
|
||||||
|
can_create_topic: true,
|
||||||
|
draft: null,
|
||||||
|
draft_key: "new_topic",
|
||||||
|
draft_sequence: 1,
|
||||||
|
per_page: 30,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "regular-tag",
|
||||||
|
topic_count: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
topics: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
server.get("/tags/staff-only-tag/notifications", () => [
|
||||||
|
200,
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
{ tag_notification: { id: "staff-only-tag", notification_level: 1 } }
|
||||||
|
]);
|
||||||
|
|
||||||
|
server.get("/tags/staff-only-tag/l/latest.json", () => [
|
||||||
|
200,
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
{
|
||||||
|
users: [],
|
||||||
|
primary_groups: [],
|
||||||
|
topic_list: {
|
||||||
|
can_create_topic: true,
|
||||||
|
draft: null,
|
||||||
|
draft_key: "new_topic",
|
||||||
|
draft_sequence: 1,
|
||||||
|
per_page: 30,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "staff-only-tag",
|
||||||
|
topic_count: 1,
|
||||||
|
staff: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
topics: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
replaceCurrentUser({ staff: false });
|
||||||
|
|
||||||
|
await visit("/tags/regular-tag");
|
||||||
|
assert.ok(find("#create-topic:disabled").length === 0);
|
||||||
|
|
||||||
|
await visit("/tags/staff-only-tag");
|
||||||
|
assert.ok(find("#create-topic:disabled").length === 1);
|
||||||
|
|
||||||
|
replaceCurrentUser({ staff: true });
|
||||||
|
|
||||||
|
await visit("/tags/regular-tag");
|
||||||
|
assert.ok(find("#create-topic:disabled").length === 0);
|
||||||
|
|
||||||
|
await visit("/tags/staff-only-tag");
|
||||||
|
assert.ok(find("#create-topic:disabled").length === 0);
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user