summaryrefslogtreecommitdiff
path: root/app/finders/projects/groups_finder.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/finders/projects/groups_finder.rb')
-rw-r--r--app/finders/projects/groups_finder.rb68
1 files changed, 68 insertions, 0 deletions
diff --git a/app/finders/projects/groups_finder.rb b/app/finders/projects/groups_finder.rb
new file mode 100644
index 00000000000..d0c42ad5611
--- /dev/null
+++ b/app/finders/projects/groups_finder.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+# Used to filter ancestor and shared project's Groups by a set of params
+#
+# Arguments:
+# project
+# current_user - which user is requesting groups
+# params:
+# with_shared: boolean (optional)
+# shared_min_access_level: integer (optional)
+# skip_groups: array of integers (optional)
+#
+module Projects
+ class GroupsFinder < UnionFinder
+ def initialize(project:, current_user: nil, params: {})
+ @project = project
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ return Group.none unless authorized?
+
+ items = all_groups.map do |item|
+ item = exclude_group_ids(item)
+ item
+ end
+
+ find_union(items, Group).with_route.order_id_desc
+ end
+
+ private
+
+ attr_reader :project, :current_user, :params
+
+ def authorized?
+ Ability.allowed?(current_user, :read_project, project)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def all_groups
+ groups = []
+ groups << project.group.self_and_ancestors if project.group
+
+ if params[:with_shared]
+ shared_groups = project.invited_groups
+
+ if params[:shared_min_access_level]
+ shared_groups = shared_groups.where(
+ 'project_group_links.group_access >= ?', params[:shared_min_access_level]
+ )
+ end
+
+ groups << shared_groups
+ end
+
+ groups << Group.none if groups.compact.empty?
+ groups
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def exclude_group_ids(groups)
+ return groups unless params[:skip_groups]
+
+ groups.id_not_in(params[:skip_groups])
+ end
+ end
+end