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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/support/ability_check.rb')
-rw-r--r--spec/support/ability_check.rb73
1 files changed, 73 insertions, 0 deletions
diff --git a/spec/support/ability_check.rb b/spec/support/ability_check.rb
new file mode 100644
index 00000000000..213944506bb
--- /dev/null
+++ b/spec/support/ability_check.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'gitlab/utils/strong_memoize'
+
+module Support
+ module AbilityCheck
+ def self.inject(mod)
+ mod.prepend AbilityExtension
+ end
+
+ module AbilityExtension
+ def before_check(policy, ability, user, subject, opts)
+ return super if Checker.ok?(policy, ability)
+
+ ActiveSupport::Deprecation.warn(<<~WARNING)
+ Ability #{ability.inspect} in #{policy.class} not found.
+ user=#{user.inspect}, subject=#{subject}, opts=#{opts.inspect}"
+
+ To exclude this check add this entry to #{Checker::TODO_YAML}:
+ #{policy.class}:
+ - #{ability}
+ WARNING
+ end
+ end
+
+ module Checker
+ include Gitlab::Utils::StrongMemoize
+ extend self
+
+ TODO_YAML = File.join(__dir__, 'ability_check_todo.yml')
+
+ def ok?(policy, ability)
+ ignored?(policy, ability) || ability_found?(policy, ability)
+ end
+
+ private
+
+ def ignored?(policy, ability)
+ todo_list[policy.class.name]&.include?(ability.to_s)
+ end
+
+ # Use Policy#has_ability? instead after it has been accepted and released.
+ # See https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/-/issues/25
+ def ability_found?(policy, ability)
+ # NilPolicy has no abilities. Ignore it.
+ return true if policy.is_a?(DeclarativePolicy::NilPolicy)
+
+ # Search in current policy first
+ return true if policy.class.ability_map.map.key?(ability)
+
+ # Search recursively in all delegations otherwise.
+ # This is potentially slow.
+ # Stolen from:
+ # https://gitlab.com/gitlab-org/ruby/gems/declarative-policy/-/blob/d691e/lib/declarative_policy/base.rb#L360-369
+ policy.class.delegations.any? do |_, block|
+ new_subject = policy.instance_eval(&block)
+ new_policy = policy.policy_for(new_subject)
+
+ ability_found?(new_policy, ability)
+ end
+ end
+
+ def todo_list
+ hash = YAML.load_file(TODO_YAML)
+ return {} unless hash.is_a?(Hash)
+
+ hash.transform_values(&:to_set)
+ end
+
+ strong_memoize_attr :todo_list
+ end
+ end
+end