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 'lib/declarative_policy/rule.rb')
-rw-r--r--lib/declarative_policy/rule.rb312
1 files changed, 0 insertions, 312 deletions
diff --git a/lib/declarative_policy/rule.rb b/lib/declarative_policy/rule.rb
deleted file mode 100644
index 964d35cde9e..00000000000
--- a/lib/declarative_policy/rule.rb
+++ /dev/null
@@ -1,312 +0,0 @@
-# frozen_string_literal: true
-
-module DeclarativePolicy
- module Rule
- # A Rule is the object that results from the `rule` declaration,
- # usually built using the DSL in `RuleDsl`. It is a basic logical
- # combination of building blocks, and is capable of deciding,
- # given a context (instance of DeclarativePolicy::Base) whether it
- # passes or not. Note that this decision doesn't by itself know
- # how that affects the actual ability decision - for that, a
- # `Step` is used.
- class Base
- def self.make(*args)
- new(*args).simplify
- end
-
- # true or false whether this rule passes.
- # `context` is a policy - an instance of
- # DeclarativePolicy::Base.
- def pass?(context)
- raise 'abstract'
- end
-
- # same as #pass? except refuses to do any I/O,
- # returning nil if the result is not yet cached.
- # used for accurately scoring And/Or
- def cached_pass?(context)
- raise 'abstract'
- end
-
- # abstractly, how long would it take to compute
- # this rule? lower-scored rules are tried first.
- def score(context)
- raise 'abstract'
- end
-
- # unwrap double negatives and nested and/or
- def simplify
- self
- end
-
- # convenience combination methods
- def or(other)
- Or.make([self, other])
- end
-
- def and(other)
- And.make([self, other])
- end
-
- def negate
- Not.make(self)
- end
-
- alias_method :|, :or
- alias_method :&, :and
- alias_method :~@, :negate
-
- def inspect
- "#<Rule #{repr}>"
- end
- end
-
- # A rule that checks a condition. This is the
- # type of rule that results from a basic bareword
- # in the rule dsl (see RuleDsl#method_missing).
- class Condition < Base
- def initialize(name)
- @name = name
- end
-
- # we delegate scoring to the condition. See
- # ManifestCondition#score.
- def score(context)
- context.condition(@name).score
- end
-
- # Let the ManifestCondition from the context
- # decide whether we pass.
- def pass?(context)
- context.condition(@name).pass?
- end
-
- # returns nil unless it's already cached
- def cached_pass?(context)
- condition = context.condition(@name)
- return unless condition.cached?
-
- condition.pass?
- end
-
- def description(context)
- context.class.conditions[@name].description
- end
-
- def repr
- @name.to_s
- end
- end
-
- # A rule constructed from DelegateDsl - using a condition from a
- # delegated policy.
- class DelegatedCondition < Base
- # Internal use only - this is rescued each time it's raised.
- MissingDelegate = Class.new(StandardError)
-
- def initialize(delegate_name, name)
- @delegate_name = delegate_name
- @name = name
- end
-
- def delegated_context(context)
- policy = context.delegated_policies[@delegate_name]
- raise MissingDelegate if policy.nil?
-
- policy
- end
-
- def score(context)
- delegated_context(context).condition(@name).score
- rescue MissingDelegate
- 0
- end
-
- def cached_pass?(context)
- condition = delegated_context(context).condition(@name)
- return unless condition.cached?
-
- condition.pass?
- rescue MissingDelegate
- false
- end
-
- def pass?(context)
- delegated_context(context).condition(@name).pass?
- rescue MissingDelegate
- false
- end
-
- def repr
- "#{@delegate_name}.#{@name}"
- end
- end
-
- # A rule constructed from RuleDsl#can?. Computes a different ability
- # on the same subject.
- class Ability < Base
- attr_reader :ability
- def initialize(ability)
- @ability = ability
- end
-
- # We ask the ability's runner for a score
- def score(context)
- context.runner(@ability).score
- end
-
- def pass?(context)
- context.allowed?(@ability)
- end
-
- def cached_pass?(context)
- runner = context.runner(@ability)
- return unless runner.cached?
-
- runner.pass?
- end
-
- def description(context)
- "User can #{@ability.inspect}"
- end
-
- def repr
- "can?(#{@ability.inspect})"
- end
- end
-
- # Logical `and`, containing a list of rules. Only passes
- # if all of them do.
- class And < Base
- attr_reader :rules
- def initialize(rules)
- @rules = rules
- end
-
- def simplify
- simplified_rules = @rules.flat_map do |rule|
- simplified = rule.simplify
- case simplified
- when And then simplified.rules
- else [simplified]
- end
- end
-
- And.new(simplified_rules)
- end
-
- def score(context)
- return 0 unless cached_pass?(context).nil?
-
- # note that cached rules will have score 0 anyways.
- @rules.map { |r| r.score(context) }.inject(0, :+)
- end
-
- def pass?(context)
- # try to find a cached answer before
- # checking in order
- cached = cached_pass?(context)
- return cached unless cached.nil?
-
- @rules.all? { |r| r.pass?(context) }
- end
-
- def cached_pass?(context)
- @rules.each do |rule|
- pass = rule.cached_pass?(context)
-
- return pass if pass.nil? || pass == false
- end
-
- true
- end
-
- def repr
- "all?(#{rules.map(&:repr).join(', ')})"
- end
- end
-
- # Logical `or`. Mirrors And.
- class Or < Base
- attr_reader :rules
- def initialize(rules)
- @rules = rules
- end
-
- def pass?(context)
- cached = cached_pass?(context)
- return cached unless cached.nil?
-
- @rules.any? { |r| r.pass?(context) }
- end
-
- def simplify
- simplified_rules = @rules.flat_map do |rule|
- simplified = rule.simplify
- case simplified
- when Or then simplified.rules
- else [simplified]
- end
- end
-
- Or.new(simplified_rules)
- end
-
- def cached_pass?(context)
- @rules.each do |rule|
- pass = rule.cached_pass?(context)
-
- return pass if pass.nil? || pass == true
- end
-
- false
- end
-
- def score(context)
- return 0 unless cached_pass?(context).nil?
-
- @rules.map { |r| r.score(context) }.inject(0, :+)
- end
-
- def repr
- "any?(#{@rules.map(&:repr).join(', ')})"
- end
- end
-
- class Not < Base
- attr_reader :rule
- def initialize(rule)
- @rule = rule
- end
-
- def simplify
- case @rule
- when And then Or.new(@rule.rules.map(&:negate)).simplify
- when Or then And.new(@rule.rules.map(&:negate)).simplify
- when Not then @rule.rule.simplify
- else Not.new(@rule.simplify)
- end
- end
-
- def pass?(context)
- !@rule.pass?(context)
- end
-
- def cached_pass?(context)
- case @rule.cached_pass?(context)
- when nil then nil
- when true then false
- when false then true
- end
- end
-
- def score(context)
- @rule.score(context)
- end
-
- def repr
- "~#{@rule.repr}"
- end
- end
- end
-end