FIX: assigned filter group visibility (#35726)

The assigned filter should take into account the visibility of the
group.

This PR fixes that and also adds testing to the `assigned:` filter

relates to: https://github.com/discourse/discourse/pull/35712
This commit is contained in:
Gabriel Grubba
2025-11-11 11:35:44 -03:00
committed by GitHub
parent 071c280303
commit ab435cceab
2 changed files with 89 additions and 5 deletions
+15 -5
View File
@@ -333,7 +333,12 @@ after_initialize do
)
end
group_id = Group.where(name: name.downcase).pick(:id)
group_id =
Group
.visible_groups(topic_query.guardian.user)
.members_visible_groups(topic_query.guardian.user)
.where(name: name.downcase)
.pick(:id)
if group_id
next(
@@ -917,17 +922,23 @@ after_initialize do
found_names ||= []
user_ids ||= []
# a bit edge casey cause we have username_lower for users but not for groups
# we share a namespace though so in practice this is ok
remaining_names = names - found_names
group_ids = []
group_ids.concat(Group.where(name: remaining_names).pluck(:id)) if remaining_names.present?
if remaining_names.present?
group_ids.concat(
Group
.visible_groups(guardian.user)
.members_visible_groups(guardian.user)
.where(name: remaining_names)
.pluck(:id),
)
end
next scope.none if user_ids.empty? && group_ids.empty?
assignment_query = Assignment.none # needed cause we are adding .or later
if user_ids.present?
assignment_query =
assignment_query.or(
@@ -975,7 +986,6 @@ after_initialize do
register_search_advanced_filter(/assigned:(.+)$/) do |posts, match|
next if !@guardian.can_assign? || match.blank?
if user_id = User.find_by_username(match)&.id
posts.where(<<~SQL, user_id)
topics.id IN (SELECT a.topic_id FROM assignments a WHERE a.assigned_to_id = ? AND a.assigned_to_type = 'User' AND a.active)
@@ -42,6 +42,80 @@ RSpec.describe DiscourseAssign do
end
end
describe "discourse-assign TopicsFilter filtering" do
fab!(:group)
fab!(:user)
fab!(:post_assignment) { Fabricate(:post_assignment, assigned_to: user) }
fab!(:topic_assignment) { Fabricate(:topic_assignment, assigned_to: group) }
before do
SiteSetting.assign_allowed_on_groups = "#{group.id}"
group.add(user)
end
describe "with assigned:username" do
it "returns topics assigned to the specified user" do
filtered_topic_ids =
TopicsFilter
.new(guardian: Guardian.new(user))
.filter_from_query_string("assigned:#{user.username}")
.pluck(:id)
expect(filtered_topic_ids).to contain_exactly(post_assignment.topic.id)
end
end
describe "with assigned:group" do
it "returns topics assigned to the specified group" do
filtered_topic_ids =
TopicsFilter
.new(guardian: Guardian.new(user))
.filter_from_query_string("assigned:#{group.name}")
.pluck(:id)
expect(filtered_topic_ids).to contain_exactly(topic_assignment.topic.id)
end
describe "when querying private groups" do
fab!(:private_group) do
Fabricate(:group, visibility_level: Group.visibility_levels[:owners])
end
fab!(:private_topic_assignment) { Fabricate(:topic_assignment, assigned_to: private_group) }
it "does not return topics from private groups the user is not a member of" do
filtered_topic_ids =
TopicsFilter
.new(guardian: Guardian.new(user))
.filter_from_query_string("assigned:#{private_group.name}")
.pluck(:id)
expect(filtered_topic_ids).to be_empty
end
it "does not return topics from private groups the user is a member of but lacks access to" do
private_group.add(user)
filtered_topic_ids =
TopicsFilter
.new(guardian: Guardian.new(user))
.filter_from_query_string("assigned:#{private_group.name}")
.pluck(:id)
expect(filtered_topic_ids).to be_empty
end
it "returns topics from private groups the user has access to" do
private_group.add_owner(user)
filtered_topic_ids =
TopicsFilter
.new(guardian: Guardian.new(user))
.filter_from_query_string("assigned:#{private_group.name}")
.pluck(:id)
expect(filtered_topic_ids).to contain_exactly(private_topic_assignment.topic.id)
end
end
end
end
describe "Events" do
describe "on 'user_removed_from_group'" do
let(:group) { Fabricate(:group) }