debian-mirror-gitlab/spec/support/ability_check.rb
2023-05-27 22:25:52 +05:30

74 lines
2.1 KiB
Ruby

# 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