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

group_projects_finder.rb « finders « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 00b700a101ec63cd1f73bf09abf8f22df2781fae (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
# frozen_string_literal: true

# GroupProjectsFinder
#
# Used to filter Projects  by set of params
#
# Arguments:
#   current_user - which user use
#   project_ids_relation: int[] - project ids to use
#   group
#   options:
#     only_owned: boolean
#     only_shared: boolean
#     limit: integer
#     include_subgroups: boolean
#     include_ancestor_groups: boolean
#   params:
#     sort: string
#     visibility_level: int
#     tags: string[]
#     personal: boolean
#     search: string
#     non_archived: boolean
#     with_issues_enabled: boolean
#     with_merge_requests_enabled: boolean
#     min_access_level: int
#
class GroupProjectsFinder < ProjectsFinder
  DEFAULT_PROJECTS_LIMIT = 100

  attr_reader :group, :options

  def initialize(group:, params: {}, options: {}, current_user: nil, project_ids_relation: nil)
    super(
      params: params,
      current_user: current_user,
      project_ids_relation: project_ids_relation
    )
    @group = group
    @options = options
  end

  def execute
    collection = super
    limit(collection)
  end

  private

  def filter_projects(collection)
    projects = super
    by_feature_availability(projects)
  end

  def limit(collection)
    limit = options[:limit]

    limit.present? ? collection.with_limit(limit) : collection
  end

  def init_collection
    projects =
      if only_shared?
        [shared_projects]
      elsif only_owned?
        [owned_projects]
      else
        [owned_projects, shared_projects]
      end

    projects.map! do |project_relation|
      filter_by_visibility(project_relation)
    end

    union(projects)
  end

  def by_feature_availability(projects)
    projects = projects.with_issues_available_for_user(current_user) if params[:with_issues_enabled].present?
    projects = projects.with_merge_requests_available_for_user(current_user) if params[:with_merge_requests_enabled].present?
    projects
  end

  def filter_by_visibility(relation)
    if current_user
      if min_access_level?
        relation.visible_to_user_and_access_level(current_user, params[:min_access_level])
      else
        relation.public_or_visible_to_user(current_user)
      end
    else
      relation.public_only
    end
  end

  def union(items)
    if items.one?
      items.first
    else
      find_union(items, Project)
    end
  end

  def only_owned?
    options.fetch(:only_owned, false)
  end

  def only_shared?
    options.fetch(:only_shared, false)
  end

  # subgroups are supported only for owned projects not for shared
  def include_subgroups?
    options.fetch(:include_subgroups, false)
  end

  # ancestor groups are supported only for owned projects not for shared
  def include_ancestor_groups?
    options.fetch(:include_ancestor_groups, false)
  end

  def owned_projects
    return group.projects unless include_subgroups? || include_ancestor_groups?

    union_relations = []
    union_relations << Project.for_group_and_its_subgroups(group) if include_subgroups?
    union_relations << Project.for_group_and_its_ancestor_groups(group) if include_ancestor_groups?

    Project.from_union(union_relations)
  end

  def shared_projects
    group.shared_projects
  end
end

GroupProjectsFinder.prepend_mod_with('GroupProjectsFinder')