103 lines
2.4 KiB
Ruby
103 lines
2.4 KiB
Ruby
module DeclarativePolicy
|
|
# The DSL evaluation context inside rule { ... } blocks.
|
|
# Responsible for creating and combining Rule objects.
|
|
#
|
|
# See Base.rule
|
|
class RuleDsl
|
|
def initialize(context_class)
|
|
@context_class = context_class
|
|
end
|
|
|
|
def can?(ability)
|
|
Rule::Ability.new(ability)
|
|
end
|
|
|
|
def all?(*rules)
|
|
Rule::And.make(rules)
|
|
end
|
|
|
|
def any?(*rules)
|
|
Rule::Or.make(rules)
|
|
end
|
|
|
|
def none?(*rules)
|
|
~Rule::Or.new(rules)
|
|
end
|
|
|
|
def cond(condition)
|
|
Rule::Condition.new(condition)
|
|
end
|
|
|
|
def delegate(delegate_name, condition)
|
|
Rule::DelegatedCondition.new(delegate_name, condition)
|
|
end
|
|
|
|
def method_missing(m, *a, &b)
|
|
return super unless a.size == 0 && !block_given?
|
|
|
|
if @context_class.delegations.key?(m)
|
|
DelegateDsl.new(self, m)
|
|
else
|
|
cond(m.to_sym)
|
|
end
|
|
end
|
|
end
|
|
|
|
# Used when the name of a delegate is mentioned in
|
|
# the rule DSL.
|
|
class DelegateDsl
|
|
def initialize(rule_dsl, delegate_name)
|
|
@rule_dsl = rule_dsl
|
|
@delegate_name = delegate_name
|
|
end
|
|
|
|
def method_missing(m, *a, &b)
|
|
return super unless a.size == 0 && !block_given?
|
|
|
|
@rule_dsl.delegate(@delegate_name, m)
|
|
end
|
|
end
|
|
|
|
# The return value of a rule { ... } declaration.
|
|
# Can call back to register rules with the containing
|
|
# Policy class (context_class here). See Base.rule
|
|
#
|
|
# Note that the #policy method just performs an #instance_eval,
|
|
# which is useful for multiple #enable or #prevent callse.
|
|
#
|
|
# Also provides a #method_missing proxy to the context
|
|
# class's class methods, so that helper methods can be
|
|
# defined and used in a #policy { ... } block.
|
|
class PolicyDsl
|
|
def initialize(context_class, rule)
|
|
@context_class = context_class
|
|
@rule = rule
|
|
end
|
|
|
|
def policy(&b)
|
|
instance_eval(&b)
|
|
end
|
|
|
|
def enable(*abilities)
|
|
@context_class.enable_when(abilities, @rule)
|
|
end
|
|
|
|
def prevent(*abilities)
|
|
@context_class.prevent_when(abilities, @rule)
|
|
end
|
|
|
|
def prevent_all
|
|
@context_class.prevent_all_when(@rule)
|
|
end
|
|
|
|
def method_missing(m, *a, &b)
|
|
return super unless @context_class.respond_to?(m)
|
|
|
|
@context_class.__send__(m, *a, &b) # rubocop:disable GitlabSecurity/PublicSend
|
|
end
|
|
|
|
def respond_to_missing?(m)
|
|
@context_class.respond_to?(m) || super
|
|
end
|
|
end
|
|
end
|