diff options
Diffstat (limited to 'app/models/project_team.rb')
-rw-r--r-- | app/models/project_team.rb | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 9d312a53790..67faea1f9f3 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -132,22 +132,41 @@ class ProjectTeam Gitlab::Access.options_with_owner.key(max_member_access(user_id)) end - # This method assumes project and group members are eager loaded for optimal - # performance. - def max_member_access(user_id) - access = [] + # Determine the maximum access level for a group of users in bulk. + # + # Returns a Hash mapping user ID -> maxmum access level. + def max_member_access_for_user_ids(user_ids) + user_ids = user_ids.uniq + key = "max_member_access:#{project.id}" + RequestStore.store[key] ||= Hash.new + access = RequestStore.store[key] - access += project.members.where(user_id: user_id).has_access.pluck(:access_level) + # Lookup only the IDs we need + user_ids = user_ids - access.keys - if group - access += group.members.where(user_id: user_id).has_access.pluck(:access_level) - end + if user_ids.present? + user_ids.map { |id| access[id] = Gitlab::Access::NO_ACCESS } - if project.invited_groups.any? && project.allowed_to_share_with_group? - access << max_invited_level(user_id) + member_access = project.members.where(user_id: user_ids).has_access.pluck(:user_id, :access_level).to_h + merge_max!(access, member_access) + + if group + group_access = group.members.where(user_id: user_ids).has_access.pluck(:user_id, :access_level).to_h + merge_max!(access, group_access) + end + + if project.invited_groups.any? && project.allowed_to_share_with_group? + # Not optimized + invited_levels = user_ids.map { |id| [id, max_invited_level(id)] }.to_h + merge_max!(access, invited_levels) + end end - access.compact.max + access + end + + def max_member_access(user_id) + max_member_access_for_user_ids([user_id])[user_id] end private @@ -156,6 +175,7 @@ class ProjectTeam project.project_group_links.map do |group_link| invited_group = group_link.group access = invited_group.group_members.find_by(user_id: user_id).try(:access_field) + access = Gitlab::Access::NO_ACCESS unless access.present? # If group member has higher access level we should restrict it # to max allowed access level @@ -215,4 +235,8 @@ class ProjectTeam def group project.group end + + def merge_max!(first_hash, second_hash) + first_hash.merge!(second_hash) { |_key, old, new| old > new ? old : new } + end end |