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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/graphql/resolvers/work_items/ancestors_resolver.rb')
-rw-r--r--app/graphql/resolvers/work_items/ancestors_resolver.rb58
1 files changed, 58 insertions, 0 deletions
diff --git a/app/graphql/resolvers/work_items/ancestors_resolver.rb b/app/graphql/resolvers/work_items/ancestors_resolver.rb
new file mode 100644
index 00000000000..33adbfc9c86
--- /dev/null
+++ b/app/graphql/resolvers/work_items/ancestors_resolver.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module WorkItems
+ class AncestorsResolver < BaseResolver
+ prepend ::WorkItems::LookAheadPreloads
+
+ type Types::WorkItemType.connection_type, null: true
+
+ def resolve_with_lookahead
+ ancestors = object.ancestors
+ return WorkItem.none unless ancestors
+
+ truncate_ancestors(apply_lookahead(ancestors)).reverse!
+ end
+
+ private
+
+ def truncate_ancestors(ancestors)
+ # Iterate from closest ancestor until root or first missing ancestor
+ authorized = authorized_ancestors(ancestors)
+
+ previous_ancestor = object.work_item
+ authorized.take_while do |ancestor|
+ is_direct_parent = previous_ancestor.work_item_parent.id == ancestor.id
+ previous_ancestor = ancestor
+
+ is_direct_parent
+ end
+ end
+
+ def authorized_ancestors(ancestors)
+ preload_resource_parents(ancestors)
+
+ DeclarativePolicy.user_scope do
+ ancestors.select { |ancestor| Ability.allowed?(current_user, :read_work_item, ancestor) }
+ end
+ end
+
+ def preload_resource_parents(work_items)
+ projects = work_items.filter_map(&:project)
+ namespaces = work_items.filter_map(&:namespace)
+ group_namespaces = namespaces.select { |n| n.type == ::Group.sti_name }
+
+ ::Preloaders::GroupPolicyPreloader.new(group_namespaces, current_user).execute if group_namespaces.any?
+ return unless projects.any?
+
+ ::Preloaders::UserMaxAccessLevelInProjectsPreloader.new(projects, current_user).execute
+ ::Preloaders::GroupPolicyPreloader.new(projects.filter_map(&:namespace), current_user).execute
+ ActiveRecord::Associations::Preloader.new(records: projects, associations: [:namespace]).call
+ end
+
+ def unconditional_includes
+ [:namespace, :work_item_parent, :work_item_type]
+ end
+ end
+ end
+end