FIX: List parent/child tags correctly for categories restricted to tag groups (#23708)

Co-authored-by: Sérgio Saquetim <saquetim@discourse.org>
This commit is contained in:
Mark VanLandingham 2023-10-10 12:30:24 -05:00 committed by GitHub
parent f29c476521
commit 4c584f6e03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 4 deletions

View File

@ -379,13 +379,13 @@ module DiscourseTagging
CATEGORY_RESTRICTIONS_SQL ||= <<~SQL
category_restrictions AS (
SELECT t.id as tag_id, ct.id as ct_id, ct.category_id as category_id
SELECT t.id as tag_id, ct.id as ct_id, ct.category_id as category_id, NULL AS category_tag_group_id
FROM tags t
INNER JOIN category_tags ct ON t.id = ct.tag_id /*and_name_like*/
UNION
SELECT t.id as tag_id, ctg.id as ctg_id, ctg.category_id as category_id
SELECT t.id as tag_id, ctg.id as ctg_id, ctg.category_id as category_id, ctg.tag_group_id AS category_tag_group_id
FROM tags t
INNER JOIN tag_group_memberships tgm ON tgm.tag_id = t.id /*and_name_like*/
INNER JOIN category_tag_groups ctg ON tgm.tag_group_id = ctg.tag_group_id
@ -458,7 +458,7 @@ module DiscourseTagging
FROM tags t
INNER JOIN tag_group_restrictions tgr ON tgr.tag_id = t.id
#{outer_join ? "LEFT OUTER" : "INNER"}
JOIN category_restrictions cr ON t.id = cr.tag_id
JOIN category_restrictions cr ON t.id = cr.tag_id AND (tgr.tag_group_id = cr.category_tag_group_id OR cr.category_tag_group_id IS NULL)
/*where*/
/*order_by*/
/*limit*/
@ -572,7 +572,7 @@ module DiscourseTagging
WHERE tg.one_per_topic
SQL
if !one_tag_per_group_ids.empty?
if one_tag_per_group_ids.present?
builder.where(
"t.id NOT IN (SELECT DISTINCT tag_id FROM tag_group_restrictions WHERE tag_group_id IN (?)) OR id IN (:selected_tag_ids)",
one_tag_per_group_ids,

View File

@ -1482,6 +1482,52 @@ RSpec.describe DiscourseTagging do
end
end
describe "Tag in multiple tag groups" do
fab!(:parent) { Fabricate(:tag) }
fab!(:child) { Fabricate(:tag) }
fab!(:no_show_tag) { Fabricate(:tag) }
fab!(:no_show_tag_group) do
Fabricate(:tag_group, permissions: { "everyone" => 1 }, tag_names: [no_show_tag.name])
end
fab!(:child_tag_group) do
Fabricate(
:tag_group,
permissions: {
"everyone" => 1,
},
tag_names: [child.name, no_show_tag.name],
parent_tag_id: parent.id,
)
end
fab!(:parent_tag_group) do
Fabricate(:tag_group, permissions: { "everyone" => 1 }, tag_names: [parent.name])
end
fab!(:category) do
Fabricate(:category, allowed_tag_groups: [parent_tag_group.name, child_tag_group.name])
end
# this test is to make sure that the parent tag is the only one returned when the child tag is also in a tag group
# allowed in the category
it "Will only return the parent tag" do
tags =
DiscourseTagging.filter_allowed_tags(
Guardian.new(user),
selected_tags: nil,
for_input: true,
category: category,
term: "",
).map(&:name)
expect(tags).to include(parent.name)
expect(tags).not_to include(child.name)
expect(tags).not_to include(no_show_tag.name)
end
end
describe "staff_tag_names" do
fab!(:tag) { Fabricate(:tag) }