FIX: Serialize visible allowed_tag_groups to all users (#42654)

Previously, 361869df7c stopped serializing `allowed_tag_groups` for
users who cannot edit the category. This went further than hiding
restricted names: it also removed the names of tag groups that are
visible to everyone — the same names any user (including anonymous) can
already enumerate through `/tag_groups/filter/search` — which broke
per-category tag-group UIs for everyone except editors.

This change serializes `allowed_tag_groups` on the full category record
for all users, filtered through `TagGroup.visible(guardian)` — the same
visibility filter the public search endpoint applies — so restricted
group names remain hidden from non-editors. Editors keep the unfiltered
list, which the category edit UI round-trips.

Note for reviewers: the one piece of information this exposes that was
not previously readable by non-editors is the mapping of visible tag
groups to a specific category (the group names themselves are already
public via the search endpoint, and the composer's tag chooser already
returns a required group's name to any user who can post). Reported by a
site running a per-category tag-group filter UI, where the field's
removal made the filters render for staff only.
This commit is contained in:
Gabriel Grubba
2026-08-17 18:47:10 -03:00
committed by GitHub
parent fa61f4c7a3
commit bba80124b4
2 changed files with 22 additions and 6 deletions
+4 -2
View File
@@ -194,10 +194,12 @@ class CategorySerializer < SiteCategorySerializer
end
def include_allowed_tag_groups?
can_edit_tags?
SiteSetting.tagging_enabled
end
def allowed_tag_groups
object.tag_groups.map(&:name)
return object.tag_groups.map(&:name) if can_edit_tags?
TagGroup.visible(scope || Guardian.new).where(id: object.tag_groups.map(&:id)).pluck(:name)
end
end
+18 -4
View File
@@ -398,14 +398,25 @@ RSpec.describe CategorySerializer do
subject(:json) { described_class.new(category, scope: scope, root: false).as_json }
fab!(:attached_tag_group) { Fabricate(:tag_group, name: "category-allowed-group") }
fab!(:restricted_tag_group) do
Fabricate(:tag_group, name: "category-restricted-group", permissions: { "staff" => 1 })
end
before { category.tag_groups << attached_tag_group }
before { category.tag_groups << [attached_tag_group, restricted_tag_group] }
context "for a non-editor" do
let(:scope) { user.guardian }
it "is not included" do
expect(json).not_to have_key(:allowed_tag_groups)
it "includes only the names of tag groups visible to the user" do
expect(json[:allowed_tag_groups]).to contain_exactly(attached_tag_group.name)
end
end
context "for an anonymous user" do
let(:scope) { Guardian.new }
it "includes only the names of publicly visible tag groups" do
expect(json[:allowed_tag_groups]).to contain_exactly(attached_tag_group.name)
end
end
@@ -413,7 +424,10 @@ RSpec.describe CategorySerializer do
let(:scope) { admin.guardian }
it "is included with all tag-group names" do
expect(json[:allowed_tag_groups]).to contain_exactly(attached_tag_group.name)
expect(json[:allowed_tag_groups]).to contain_exactly(
attached_tag_group.name,
restricted_tag_group.name,
)
end
end