summaryrefslogtreecommitdiff
path: root/app/models/preloaders/user_max_access_level_in_groups_preloader.rb
blob: 8df986b47a24c91354db1cf83774c58d8046f900 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# frozen_string_literal: true

module Preloaders
  # This class preloads the max access level (role) for the user within the given groups and
  # stores the values in requests store.
  class UserMaxAccessLevelInGroupsPreloader
    def initialize(groups, user)
      @groups = groups
      @user = user
    end

    def execute
      if ::Feature.enabled?(:use_traversal_ids)
        preload_with_traversal_ids
      else
        preload_direct_memberships
      end
    end

    private

    def preload_direct_memberships
      group_memberships = GroupMember.active_without_invites_and_requests
                                     .where(user: @user, source_id: @groups)
                                     .group(:source_id)
                                     .maximum(:access_level)

      @groups.each do |group|
        access_level = group_memberships[group.id]
        group.merge_value_to_request_store(User, @user.id, access_level) if access_level.present?
      end
    end

    def preload_with_traversal_ids
      max_access_levels = GroupMember.active_without_invites_and_requests
                                     .where(user: @user)
                                     .joins("INNER JOIN (#{traversal_join_sql}) as hierarchy ON members.source_id = hierarchy.traversal_id")
                                     .group('hierarchy.id')
                                     .maximum(:access_level)

      @groups.each do |group|
        max_access_level = max_access_levels[group.id] || Gitlab::Access::NO_ACCESS
        group.merge_value_to_request_store(User, @user.id, max_access_level)
      end
    end

    def traversal_join_sql
      Namespace.select('id, unnest(traversal_ids) as traversal_id').where(id: @groups.map(&:id)).to_sql
    end
  end
end