988dc80585
We dropped MySQL support and a lot of mysql specific code has been removed in https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29608. This comes in from the other direction and removes any `if postgresql?` branches.
74 lines
2.3 KiB
Ruby
74 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class MembersFinder
|
|
attr_reader :project, :current_user, :group
|
|
|
|
def initialize(project, current_user)
|
|
@project = project
|
|
@current_user = current_user
|
|
@group = project.group
|
|
end
|
|
|
|
def execute(include_descendants: false, include_invited_groups_members: false)
|
|
project_members = project.project_members
|
|
project_members = project_members.non_invite unless can?(current_user, :admin_project, project)
|
|
|
|
union_members = group_union_members(include_descendants, include_invited_groups_members)
|
|
|
|
if union_members.any?
|
|
distinct_union_of_members(union_members << project_members)
|
|
else
|
|
project_members
|
|
end
|
|
end
|
|
|
|
def can?(*args)
|
|
Ability.allowed?(*args)
|
|
end
|
|
|
|
private
|
|
|
|
def group_union_members(include_descendants, include_invited_groups_members)
|
|
[].tap do |members|
|
|
members << direct_group_members(include_descendants) if group
|
|
members << project_invited_groups_members if include_invited_groups_members
|
|
end
|
|
end
|
|
|
|
def direct_group_members(include_descendants)
|
|
GroupMembersFinder.new(group).execute(include_descendants: include_descendants).non_invite # rubocop: disable CodeReuse/Finder
|
|
end
|
|
|
|
def project_invited_groups_members
|
|
invited_groups_ids_including_ancestors = Gitlab::ObjectHierarchy
|
|
.new(project.invited_groups)
|
|
.base_and_ancestors
|
|
.public_or_visible_to_user(current_user)
|
|
.select(:id)
|
|
|
|
GroupMember.with_source_id(invited_groups_ids_including_ancestors)
|
|
end
|
|
|
|
def distinct_union_of_members(union_members)
|
|
union = Gitlab::SQL::Union.new(union_members, remove_duplicates: false) # rubocop: disable Gitlab/Union
|
|
sql = distinct_on(union)
|
|
|
|
Member.includes(:user).from([Arel.sql("(#{sql}) AS #{Member.table_name}")]) # rubocop: disable CodeReuse/ActiveRecord
|
|
end
|
|
|
|
def distinct_on(union)
|
|
# We're interested in a list of members without duplicates by user_id.
|
|
# We prefer project members over group members, project members should go first.
|
|
<<~SQL
|
|
SELECT DISTINCT ON (user_id, invite_email) member_union.*
|
|
FROM (#{union.to_sql}) AS member_union
|
|
ORDER BY user_id,
|
|
invite_email,
|
|
CASE
|
|
WHEN type = 'ProjectMember' THEN 1
|
|
WHEN type = 'GroupMember' THEN 2
|
|
ELSE 3
|
|
END
|
|
SQL
|
|
end
|
|
end
|