summaryrefslogtreecommitdiff
path: root/lib/gitlab/cross_project_access.rb
blob: 4ddc7e02d1b1225c15452e96a4036456a5ac9ac8 (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
# frozen_string_literal: true

module Gitlab
  class CrossProjectAccess
    class << self
      delegate :add_check, :find_check, :checks,
               to: :instance
    end

    def self.instance
      @instance ||= new
    end

    attr_reader :checks

    def initialize
      @checks = {}
    end

    def add_check(
          klass,
          actions: {},
          positive_condition: nil,
          negative_condition: nil,
          skip: false)

      new_check = CheckInfo.new(actions,
                                positive_condition,
                                negative_condition,
                                skip
                               )

      @checks[klass] ||= Gitlab::CrossProjectAccess::CheckCollection.new
      @checks[klass].add_check(new_check)
      recalculate_checks_for_class(klass)

      @checks[klass]
    end

    def find_check(object)
      @cached_checks ||= Hash.new do |cache, new_class|
        parent_classes = @checks.keys.select { |existing_class| new_class <= existing_class }
        closest_class = closest_parent(parent_classes, new_class)
        cache[new_class] = @checks[closest_class]
      end

      @cached_checks[object.class]
    end

    private

    def recalculate_checks_for_class(klass)
      new_collection = @checks[klass]

      @checks.each do |existing_class, existing_check_collection|
        if existing_class < klass
          existing_check_collection.add_collection(new_collection)
        elsif klass < existing_class
          new_collection.add_collection(existing_check_collection)
        end
      end
    end

    def closest_parent(classes, subject)
      relevant_ancestors = subject.ancestors & classes
      relevant_ancestors.first
    end
  end
end