Read about our upcoming Code of Conduct on this issue

projects_finder.rb 4.19 KB
Newer Older
1
2
# frozen_string_literal: true

3
4
5
6
7
8
9
10
11
# ProjectsFinder
#
# Used to filter Projects  by set of params
#
# Arguments:
#   current_user - which user use
#   project_ids_relation: int[] - project ids to use
#   params:
#     trending: boolean
Toon Claes's avatar
Toon Claes committed
12
#     owned: boolean
13
14
15
16
17
18
19
20
#     non_public: boolean
#     starred: boolean
#     sort: string
#     visibility_level: int
#     tags: string[]
#     personal: boolean
#     search: string
#     non_archived: boolean
21
#     archived: 'only' or boolean
22
#     min_access_level: integer
23
#
Douwe Maan's avatar
Douwe Maan committed
24
class ProjectsFinder < UnionFinder
25
26
  include CustomAttributesFilter

27
28
  attr_accessor :params
  attr_reader :current_user, :project_ids_relation
29

30
31
32
33
34
35
36
  def initialize(params: {}, current_user: nil, project_ids_relation: nil)
    @params = params
    @current_user = current_user
    @project_ids_relation = project_ids_relation
  end

  def execute
vanadium23's avatar
vanadium23 committed
37
38
39
    user = params.delete(:user)
    collection =
      if user
40
        PersonalProjectsFinder.new(user, finder_params).execute(current_user) # rubocop: disable CodeReuse/Finder
vanadium23's avatar
vanadium23 committed
41
42
43
44
      else
        init_collection
      end

45
    collection = filter_projects(collection)
46
    sort(collection)
47
48
49
50
  end

  private

51
  def init_collection
52
53
54
55
56
57
    if current_user
      collection_with_user
    else
      collection_without_user
    end
  end
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
58

59
60
61
62
63
64
  # EE would override this to add more filters
  def filter_projects(collection)
    collection = by_ids(collection)
    collection = by_personal(collection)
    collection = by_starred(collection)
    collection = by_trending(collection)
65
    collection = by_visibility_level(collection)
66
67
68
69
70
71
72
73
    collection = by_tags(collection)
    collection = by_search(collection)
    collection = by_archived(collection)
    collection = by_custom_attributes(collection)
    collection = by_deleted_status(collection)
    collection
  end

74
75
76
  def collection_with_user
    if owned_projects?
      current_user.owned_projects
77
    elsif min_access_level?
78
      current_user.authorized_projects(params[:min_access_level])
Toon Claes's avatar
Toon Claes committed
79
    else
80
81
82
      if private_only?
        current_user.authorized_projects
      else
83
        Project.public_or_visible_to_user(current_user)
84
      end
Toon Claes's avatar
Toon Claes committed
85
    end
86
87
88
89
  end

  # Builds a collection for an anonymous user.
  def collection_without_user
90
    if private_only? || owned_projects? || min_access_level?
91
92
93
94
95
96
97
98
99
      Project.none
    else
      Project.public_to_user
    end
  end

  def owned_projects?
    params[:owned].present?
  end
100

101
102
  def private_only?
    params[:non_public].present?
103
  end
104

105
106
107
108
  def min_access_level?
    params[:min_access_level].present?
  end

109
  # rubocop: disable CodeReuse/ActiveRecord
110
  def by_ids(items)
111
    project_ids_relation ? items.where(id: project_ids_relation) : items
112
  end
113
  # rubocop: enable CodeReuse/ActiveRecord
114
115
116
117
118
119
120
121
122

  def union(items)
    find_union(items, Project).with_route
  end

  def by_personal(items)
    (params[:personal].present? && current_user) ? items.personal(current_user) : items
  end

123
124
125
126
  def by_starred(items)
    (params[:starred].present? && current_user) ? items.starred_by(current_user) : items
  end

127
128
129
130
  def by_trending(items)
    params[:trending].present? ? items.trending : items
  end

131
  # rubocop: disable CodeReuse/ActiveRecord
132
  def by_visibility_level(items)
133
134
    params[:visibility_level].present? ? items.where(visibility_level: params[:visibility_level]) : items
  end
135
  # rubocop: enable CodeReuse/ActiveRecord
136
137
138
139
140
141
142
143
144
145

  def by_tags(items)
    params[:tag].present? ? items.tagged_with(params[:tag]) : items
  end

  def by_search(items)
    params[:search] ||= params[:name]
    params[:search].present? ? items.search(params[:search]) : items
  end

146
147
148
149
  def by_deleted_status(items)
    params[:without_deleted].present? ? items.without_deleted : items
  end

150
  def sort(items)
151
    params[:sort].present? ? items.sort_by_attribute(params[:sort]) : items.order_id_desc
152
153
154
  end

  def by_archived(projects)
155
156
    if params[:non_archived]
      projects.non_archived
157
    elsif params.key?(:archived)
158
159
160
161
162
163
164
165
166
167
      if params[:archived] == 'only'
        projects.archived
      elsif Gitlab::Utils.to_boolean(params[:archived])
        projects
      else
        projects.non_archived
      end
    else
      projects
    end
168
  end
169
170
171
172
173
174

  def finder_params
    return {} unless min_access_level?

    { min_access_level: params[:min_access_level] }
  end
175
end