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

ancestors_resolver.rb « work_items « resolvers « graphql « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 33adbfc9c865d260bcb8129e2bf69a17be493539 (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
# 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