Welcome to mirror list, hosted at ThFree Co, Russian Federation.

groups_finder.rb « finders « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 61d7988500142768e0f0a037f63f16853ef4331c (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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# frozen_string_literal: true

# GroupsFinder
#
# Used to filter Groups by a set of params
#
# Arguments:
#   current_user - which user is requesting groups
#   params:
#     owned: boolean
#     parent: Group
#     all_available: boolean (defaults to true)
#     min_access_level: integer
#     search: string
#     exclude_group_ids: array of integers
#     include_parent_descendants: boolean (defaults to false) - includes descendant groups when
#                                 filtering by parent. The parent param must be present.
#     include_ancestors: boolean (defaults to true)
#
# Users with full private access can see all groups. The `owned` and `parent`
# params can be used to restrict the groups that are returned.
#
# Anonymous users will never return any `owned` groups. They will return all
# public groups instead, even if `all_available` is set to false.
class GroupsFinder < UnionFinder
  include CustomAttributesFilter

  def initialize(current_user = nil, params = {})
    @current_user = current_user
    @params = params
  end

  def execute
    items = all_groups.map do |item|
      item = by_parent(item)
      item = by_custom_attributes(item)
      item = exclude_group_ids(item)
      item = by_search(item)

      item
    end

    find_union(items, Group).with_route.order_id_desc
  end

  private

  attr_reader :current_user, :params

  def all_groups
    return [owned_groups] if params[:owned]
    return [groups_with_min_access_level] if min_access_level?
    return [Group.all] if current_user&.can_read_all_resources? && all_available?

    groups = []
    groups = get_groups_for_user if current_user

    groups << Group.unscoped.public_to_user(current_user) if include_public_groups?
    groups << Group.none if groups.empty?
    groups
  end

  def groups_for_ancestors
    current_user.authorized_groups
  end

  def groups_for_descendants
    current_user.groups
  end

  # rubocop: disable CodeReuse/ActiveRecord
  def groups_with_min_access_level
    groups = current_user
      .groups
      .where('members.access_level >= ?', params[:min_access_level])

    if Feature.enabled?(:use_traversal_ids_groups_finder, current_user)
      groups.self_and_descendants
    else
      Gitlab::ObjectHierarchy
        .new(groups)
        .base_and_descendants
    end
  end
  # rubocop: enable CodeReuse/ActiveRecord

  def exclude_group_ids(groups)
    return groups unless params[:exclude_group_ids]

    groups.id_not_in(params[:exclude_group_ids])
  end

  # rubocop: disable CodeReuse/ActiveRecord
  def by_parent(groups)
    return groups unless params[:parent]

    if include_parent_descendants?
      groups.id_in(params[:parent].descendants)
    else
      groups.where(parent: params[:parent])
    end
  end
  # rubocop: enable CodeReuse/ActiveRecord

  # rubocop: disable CodeReuse/ActiveRecord
  def by_search(groups)
    return groups unless params[:search].present?

    groups.search(params[:search], include_parents: params[:parent].blank?)
  end
  # rubocop: enable CodeReuse/ActiveRecord

  def owned_groups
    current_user&.owned_groups || Group.none
  end

  def include_public_groups?
    current_user.nil? || all_available?
  end

  def all_available?
    params.fetch(:all_available, true)
  end

  def include_parent_descendants?
    params.fetch(:include_parent_descendants, false)
  end

  def min_access_level?
    current_user && params[:min_access_level].present?
  end

  def include_ancestors?
    params.fetch(:include_ancestors, true)
  end

  def get_groups_for_user
    groups = []

    if Feature.enabled?(:use_traversal_ids_groups_finder, current_user)
      groups << if include_ancestors?
                  current_user.authorized_groups.self_and_ancestors
                else
                  current_user.authorized_groups
                end

      groups << current_user.groups.self_and_descendants
    elsif include_ancestors?
      groups << Gitlab::ObjectHierarchy.new(groups_for_ancestors, groups_for_descendants).all_objects
    else
      groups << current_user.authorized_groups
      groups << Gitlab::ObjectHierarchy.new(groups_for_descendants).base_and_descendants
    end

    groups
  end
end