73 lines
2.1 KiB
Ruby
73 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
|