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
 |