diff --git a/app/assets/javascripts/discourse/templates/components/tag-info.hbs b/app/assets/javascripts/discourse/templates/components/tag-info.hbs index f1d11d66658..d52cd0bcf4f 100644 --- a/app/assets/javascripts/discourse/templates/components/tag-info.hbs +++ b/app/assets/javascripts/discourse/templates/components/tag-info.hbs @@ -22,7 +22,11 @@ {{/each}} {{/if}} {{#if nothingToShow}} - {{i18n "tagging.default_info"}} + {{#if tagInfo.category_restricted}} + {{i18n "tagging.category_restricted"}} + {{else}} + {{i18n "tagging.default_info"}} + {{/if}} {{/if}} {{#if tagInfo.synonyms}} diff --git a/app/serializers/detailed_tag_serializer.rb b/app/serializers/detailed_tag_serializer.rb index 25b0c555c9e..79354be61fb 100644 --- a/app/serializers/detailed_tag_serializer.rb +++ b/app/serializers/detailed_tag_serializer.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class DetailedTagSerializer < TagSerializer - attributes :synonyms, :tag_group_names + attributes :synonyms, :tag_group_names, :category_restricted has_many :categories, serializer: BasicCategorySerializer @@ -10,12 +10,11 @@ class DetailedTagSerializer < TagSerializer end def categories - Category.secured(scope).where( - id: object.categories.pluck(:id) + - object.tag_groups.includes(:categories).map do |tg| - tg.categories.map(&:id) - end.flatten - ) + Category.secured(scope).where(id: category_ids) + end + + def category_restricted + !category_ids.empty? end def include_tag_group_names? @@ -25,4 +24,13 @@ class DetailedTagSerializer < TagSerializer def tag_group_names object.tag_groups.map(&:name) end + + private + + def category_ids + @_category_ids ||= object.categories.pluck(:id) + + object.tag_groups.includes(:categories).map do |tg| + tg.categories.map(&:id) + end.flatten + end end diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 133013bece9..3d18a0e0f2b 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -3100,6 +3100,7 @@ en: choose_for_topic: "optional tags" info: "Info" default_info: "This tag isn't restricted to any categories, and has no synonyms." + category_restricted: "This tag is restricted to categories you don't have permission to access." synonyms: "Synonyms" synonyms_description: "When the following tags are used, they will be replaced with %{base_tag_name}." tag_groups_info: diff --git a/spec/requests/tags_controller_spec.rb b/spec/requests/tags_controller_spec.rb index f750e03116d..85281946911 100644 --- a/spec/requests/tags_controller_spec.rb +++ b/spec/requests/tags_controller_spec.rb @@ -191,6 +191,7 @@ describe TagsController do expect(json.dig('tag_info', 'name')).to eq(tag.name) expect(json.dig('tag_info', 'synonyms')).to be_empty expect(json.dig('tag_info', 'category_ids')).to be_empty + expect(json.dig('tag_info', 'category_restricted')).to eq(false) end it "can handle a synonym" do @@ -199,6 +200,7 @@ describe TagsController do expect(json.dig('tag_info', 'name')).to eq(synonym.name) expect(json.dig('tag_info', 'synonyms')).to be_empty expect(json.dig('tag_info', 'category_ids')).to be_empty + expect(json.dig('tag_info', 'category_restricted')).to eq(false) end it "can return a tag's synonyms" do @@ -230,6 +232,7 @@ describe TagsController do get "/tag/#{tag.name}/info.json" expect(json.dig('tag_info', 'category_ids')).to contain_exactly(category.id, category2.id) expect(json['categories']).to be_present + expect(json.dig('tag_info', 'category_restricted')).to eq(true) end context 'tag belongs to a tag group' do @@ -246,6 +249,39 @@ describe TagsController do get "/tag/#{tag.name}/info.json" expect(json['tag_info'].has_key?('tag_group_names')).to eq(false) end + + context "restricted to a private category" do + let!(:private_category) do + Fabricate(:private_category, + group: Fabricate(:group), + tag_groups: [tag_group], + allow_global_tags: true + ) + end + + it "can return categories to users who can access them" do + sign_in(admin) + get "/tag/#{tag.name}/info.json" + expect(json.dig('tag_info', 'category_ids')).to contain_exactly(private_category.id) + expect(json['categories']).to be_present + expect(json.dig('tag_info', 'category_restricted')).to eq(true) + end + + it "can indicate category restriction to users who can't access them" do + sign_in(user) + get "/tag/#{tag.name}/info.json" + expect(json.dig('tag_info', 'category_ids')).to be_empty + expect(json['categories']).to be_blank + expect(json.dig('tag_info', 'category_restricted')).to eq(true) + end + + it "can indicate category restriction to anon" do + get "/tag/#{tag.name}/info.json" + expect(json.dig('tag_info', 'category_ids')).to be_empty + expect(json['categories']).to be_blank + expect(json.dig('tag_info', 'category_restricted')).to eq(true) + end + end end end