diff options
author | Bob Van Landuyt <bob@vanlanduyt.co> | 2017-12-11 17:21:06 +0300 |
---|---|---|
committer | Bob Van Landuyt <bob@vanlanduyt.co> | 2018-02-22 19:11:36 +0300 |
commit | 148816cd67a314f17e79c107270cc708501bdd39 (patch) | |
tree | eba07d109322392bb5862b715adc066a0ebbdf95 /lib/gitlab/cross_project_access.rb | |
parent | b5306075c21f5546d1447052558da6227629c15e (diff) |
Port `read_cross_project` ability from EE
Diffstat (limited to 'lib/gitlab/cross_project_access.rb')
-rw-r--r-- | lib/gitlab/cross_project_access.rb | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/gitlab/cross_project_access.rb b/lib/gitlab/cross_project_access.rb new file mode 100644 index 00000000000..6eaed51b64c --- /dev/null +++ b/lib/gitlab/cross_project_access.rb @@ -0,0 +1,67 @@ +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 |