class Permissify::DecisionContext
The typed input a permission/fact block evaluates against. It is explicit on purpose: it does not serialize the resource, inject magic keys, or hash object graphs. Facts read ‘actor`, `resource`, and `environment` directly, and compose other facts through `fact`, `all?`, `any?`, `none?`.
Attributes
action[R]
actor[R]
environment[R]
resource[R]
Public Class Methods
new(actor:, resource:, action:, resource_def:, environment:, fact_source:)
click to toggle source
# File lib/permissify/decision_context.rb, line 11 def initialize(actor:, resource:, action:, resource_def:, environment:, fact_source:) @actor = actor @resource = resource @action = action @resource_def = resource_def @environment = environment @fact_source = fact_source @cache = {} @checks = [] end
Public Instance Methods
all?(*names)
click to toggle source
# File lib/permissify/decision_context.rb, line 32 def all?(*names) = names.all? { |n| record(n) } def any?(*names) = names.any? { |n| record(n) } def none?(*names) = names.none? { |n| record(n) } # The ordered trace of composed checks, attached to the Decision. def checks = @checks private def record(name) result = fact(name) @checks << { name: name.to_sym, result: result } result end def compute(name) block = @resource_def.facts[name] if block block.call(self) ? true : false else value = @fact_source.fetch(name, self) raise MissingFact, name if value.equal?(FactSource::Missing) value ? true : false end end
any?(*names)
click to toggle source
# File lib/permissify/decision_context.rb, line 33 def any?(*names) = names.any? { |n| record(n) } def none?(*names) = names.none? { |n| record(n) } # The ordered trace of composed checks, attached to the Decision. def checks = @checks private def record(name) result = fact(name) @checks << { name: name.to_sym, result: result } result end def compute(name) block = @resource_def.facts[name] if block block.call(self) ? true : false else value = @fact_source.fetch(name, self) raise MissingFact, name if value.equal?(FactSource::Missing) value ? true : false end end end
checks(= @checks)
click to toggle source
The ordered trace of composed checks, attached to the Decision.
# File lib/permissify/decision_context.rb, line 37 def checks = @checks private def record(name) result = fact(name) @checks << { name: name.to_sym, result: result } result end def compute(name) block = @resource_def.facts[name] if block block.call(self) ? true : false else value = @fact_source.fetch(name, self) raise MissingFact, name if value.equal?(FactSource::Missing) value ? true : false end end end
compute(name)
click to toggle source
# File lib/permissify/decision_context.rb, line 47 def compute(name) block = @resource_def.facts[name] if block block.call(self) ? true : false else value = @fact_source.fetch(name, self) raise MissingFact, name if value.equal?(FactSource::Missing) value ? true : false end end
fact(name)
click to toggle source
Resolve a named fact to a boolean. Inline-registered facts win; otherwise the FactSource is consulted, and an unresolvable fact raises MissingFact (which the pipeline turns into a default-deny). Results are memoized per context.
# File lib/permissify/decision_context.rb, line 25 def fact(name) key = name.to_sym return @cache[key] if @cache.key?(key) @cache[key] = compute(key) end
none?(*names)
click to toggle source
# File lib/permissify/decision_context.rb, line 34 def none?(*names) = names.none? { |n| record(n) } # The ordered trace of composed checks, attached to the Decision. def checks = @checks private def record(name) result = fact(name) @checks << { name: name.to_sym, result: result } result end def compute(name) block = @resource_def.facts[name] if block block.call(self) ? true : false else value = @fact_source.fetch(name, self) raise MissingFact, name if value.equal?(FactSource::Missing) value ? true : false end end end end
record(name)
click to toggle source
# File lib/permissify/decision_context.rb, line 41 def record(name) result = fact(name) @checks << { name: name.to_sym, result: result } result end