diff options
Diffstat (limited to 'app/finders/group_members_finder.rb')
-rw-r--r-- | app/finders/group_members_finder.rb | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/app/finders/group_members_finder.rb b/app/finders/group_members_finder.rb index 05645dacab9..1025e0ebc9b 100644 --- a/app/finders/group_members_finder.rb +++ b/app/finders/group_members_finder.rb @@ -30,7 +30,11 @@ class GroupMembersFinder < UnionFinder def execute(include_relations: DEFAULT_RELATIONS) groups = groups_by_relations(include_relations) - members = all_group_members(groups).distinct_on_user_with_max_access_level + shared_from_groups = if include_relations&.include?(:shared_from_groups) + Group.shared_into_ancestors(group).public_or_visible_to_user(user) + end + + members = all_group_members(groups, shared_from_groups).distinct_on_user_with_max_access_level filter_members(members) end @@ -47,9 +51,8 @@ class GroupMembersFinder < UnionFinder related_groups << Group.by_id(group.id) if include_relations&.include?(:direct) related_groups << group.ancestors if include_relations&.include?(:inherited) related_groups << group.descendants if include_relations&.include?(:descendants) - related_groups << Group.shared_into_ancestors(group).public_or_visible_to_user(user) if include_relations&.include?(:shared_from_groups) - find_union(related_groups, Group) + related_groups end def filter_members(members) @@ -78,12 +81,49 @@ class GroupMembersFinder < UnionFinder group.members end - def all_group_members(groups) - members_of_groups(groups).non_minimal_access + def all_group_members(groups, shared_from_groups) + members_of_groups(groups, shared_from_groups).non_minimal_access + end + + def members_of_groups(groups, shared_from_groups) + if Feature.disabled?(:members_with_shared_group_access, @group.root_ancestor) + groups << shared_from_groups unless shared_from_groups.nil? + return GroupMember.non_request.of_groups(find_union(groups, Group)) + end + + members = GroupMember.non_request.of_groups(find_union(groups, Group)) + return members if shared_from_groups.nil? + + shared_members = GroupMember.non_request.of_groups(shared_from_groups) + select_attributes = GroupMember.attribute_names + members_shared_with_group_access = members_shared_with_group_access(shared_members, select_attributes) + + # `members` and `members_shared_with_group_access` should have even select values + find_union([members.select(select_attributes), members_shared_with_group_access], GroupMember) + end + + def members_shared_with_group_access(shared_members, select_attributes) + group_group_link_table = GroupGroupLink.arel_table + group_member_table = GroupMember.arel_table + + member_columns = select_attributes.map do |column_name| + if column_name == 'access_level' + args = [group_group_link_table[:group_access], group_member_table[:access_level]] + smallest_value_arel(args, 'access_level') + else + group_member_table[column_name] + end + end + + # rubocop:disable CodeReuse/ActiveRecord + shared_members + .joins("LEFT OUTER JOIN group_group_links ON members.source_id = group_group_links.shared_with_group_id") + .select(member_columns) + # rubocop:enable CodeReuse/ActiveRecord end - def members_of_groups(groups) - GroupMember.non_request.of_groups(groups) + def smallest_value_arel(args, column_alias) + Arel::Nodes::As.new(Arel::Nodes::NamedFunction.new('LEAST', args), Arel::Nodes::SqlLiteral.new(column_alias)) end def check_relation_arguments!(include_relations) |