70 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			70 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# 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
 |