lib/conjur/policy/yaml/handler.rb in conjur-asset-policy-0.12.0 vs lib/conjur/policy/yaml/handler.rb in conjur-asset-policy-0.13.0

- old
+ new

@@ -10,21 +10,17 @@ # its particular context (sequence, mapping, etc). # # The handler can decide that the message is not allowed by not implementing the message. # class Base - attr_reader :parent + attr_reader :parent, :anchor - def initialize parent + def initialize parent, anchor @parent = parent + @anchor = anchor end - # Each handler should implement this method to return the result object (which may only be - # partially constructed). This method is used by the root handler to associate the handler - # result with an anchor (if applicable). - def result; raise "Not implemented"; end - # Handlers are organized in a stack. Each handler can find the root Handler by traversing up the stack. def handler parent.handler end @@ -43,17 +39,17 @@ raise "Unexpected alias #{anchor}" end # Start a new mapping with the specified tag. # If the handler wants to accept the message, it should return a new handler. - def start_mapping tag + def start_mapping tag, anchor raise "Unexpected mapping" end # Start a new sequence. # If the handler wants to accept the message, it should return a new handler. - def start_sequence + def start_sequence anchor raise "Unexpected sequence" end # End the current sequence. The handler should populate the sequence into the parent handler. def end_sequence @@ -64,13 +60,11 @@ def end_mapping raise "Unexpected end of mapping" end # Process a scalar value. It may be a map key, a map value, or a sequence value. - # The handler should return a result from this method, so that the root Handler can - # associate it with an anchor, if any. - def scalar value, tag, quoted + def scalar value, tag, quoted, anchor raise "Unexpected scalar" end protected @@ -101,11 +95,11 @@ # Handles the root document, which should be a sequence. class Root < Base attr_reader :result, :handler def initialize handler - super nil + super nil, nil @handler = handler @result = nil end @@ -117,14 +111,14 @@ end # The document root is expected to start with a sequence. # A Sequence handler is constructed with no implicit type. This # sub-handler handles the message. - def start_sequence - Sequence.new(self, nil).tap do |h| + def start_sequence anchor + Sequence.new(self, anchor, nil).tap do |h| h.push_handler - end.result + end end # Finish the sequence, and the document. def end_sequence pop_handler @@ -135,84 +129,87 @@ # +record_type+ default record type, inferred from the field name on the parent record. # +args+ the start_sequence arguments. class Sequence < Base attr_reader :record_type - def initialize parent, record_type - super parent + def initialize parent, anchor, record_type + super parent, anchor @record_type = record_type @list = [] end - def result; @list; end - # Adds a mapping to the sequence. def mapping value + handler.log { "#{handler.indent}Adding mapping #{value} to sequence" } @list.push value end # Adds a sequence to the sequence. def sequence value + handler.log { "#{handler.indent}Adding sequence #{value} to sequence" } @list.push value end # When the sequence receives an alias, the alias should be mapped to the previously stored # value and added to the result list. def alias anchor + handler.log { "#{handler.indent}Adding alias *#{anchor} to sequence, whose value is #{handler.anchor(anchor)}" } @list.push handler.anchor(anchor) end # When the sequence contains a mapping, a new record should be created corresponding to either: # # * The explicit stated type (tag) of the mapping # * The implicit field type of the sequence # # If neither of these is available, it's an error. - def start_mapping tag + def start_mapping tag, anchor if type = type_of(tag, record_type) - Mapping.new(self, type).tap do |h| + Mapping.new(self, anchor, type).tap do |h| h.push_handler - end.result + end else raise "No type given or inferred for sequence entry" end end # Process a sequence within a sequence. - def start_sequence - Sequence.new(self, record_type).tap do |h| + def start_sequence anchor + Sequence.new(self, anchor, record_type).tap do |h| h.push_handler - end.result + end end # When the sequence contains a scalar, the value should be appended to the result. - def scalar value, tag, quoted + def scalar value, tag, quoted, anchor scalar_value(value, tag, quoted, record_type).tap do |value| + handler.log { "#{handler.indent}Adding scalar *#{value} to sequence" } @list.push value + handler.anchor anchor, value if anchor end end def end_sequence parent.sequence @list + handler.anchor anchor, @list if anchor pop_handler end end # Handles a mapping, each of which will be parsed into a structured record. class Mapping < Base attr_reader :type - def initialize parent, type - super parent + def initialize parent, anchor, type + super parent, anchor @record = type.new end - def result; @record; end - def map_entry key, value + handler.log { "#{handler.indent}Setting map entry #{key} = #{value}" } if @record.respond_to?(:[]=) @record.send(:[]=, key, value) else begin @record.send("#{key}=", value) @@ -223,80 +220,80 @@ end # Begins a mapping with the anchor value as the key. def alias anchor key = handler.anchor(anchor) - MapEntry.new(self, @record, key).tap do |h| + MapEntry.new(self, nil, @record, key).tap do |h| h.push_handler - end.result + end end # Begins a new map entry. - def scalar value, tag, quoted + def scalar value, tag, quoted, anchor value = scalar_value(value, tag, quoted, type) - MapEntry.new(self, @record, value).tap do |h| + MapEntry.new(self, anchor, @record, value).tap do |h| h.push_handler - end.result + end end def end_mapping parent.mapping @record + handler.anchor anchor, @record if anchor pop_handler end end # Processes a map entry. At this point, the parent record and the map key are known. class MapEntry < Base attr_reader :record, :key - def initialize parent, record, key - super parent + def initialize parent, anchor, record, key + super parent, anchor @record = record @key = key end - def result; nil; end - def sequence value value value end def mapping value value value end def value value parent.map_entry @key, value + handler.anchor anchor, value if anchor pop_handler end # Interpret the alias as the map value and populate in the parent. def alias anchor value handler.anchor(anchor) end # Start a mapping as a map value. - def start_mapping tag + def start_mapping tag, anchor if type = type_of(tag, yaml_field_type(key)) - Mapping.new(self, type).tap do |h| + Mapping.new(self, anchor, type).tap do |h| h.push_handler - end.result + end else # We got a mapping on a simple type raise "Attribute '#{key}' can't be a mapping" end end # Start a sequence as a map value. - def start_sequence - Sequence.new(self, yaml_field_type(key)).tap do |h| + def start_sequence anchor + Sequence.new(self, anchor, yaml_field_type(key)).tap do |h| h.push_handler - end.result + end end - def scalar value, tag, quoted + def scalar value, tag, quoted, anchor value scalar_value(value, tag, quoted, yaml_field_type(key)) end protected @@ -310,13 +307,17 @@ @handlers = [ @root ] @anchors = {} @filename = "<no-filename>" end + def result + @root.result + end + def push_handler handler - log {"#{indent}pushing handler #{handler.class}"} @handlers.push handler + log {"#{indent}pushed handler #{handler.class}"} end def pop_handler @handlers.pop log {"#{indent}popped to handler #{handler.class}"} @@ -336,32 +337,29 @@ else nil end end - def result; @root.result; end - def handler; @handlers.last; end def alias key + log {"#{indent}WARNING: anchor '#{key}' is not defined"} unless anchor(key) log {"#{indent}anchor '#{key}'=#{anchor(key)}"} handler.alias key end def start_mapping *args log {"#{indent}start mapping #{args}"} anchor, tag, _ = args tag = "!automatic-role" if %w(!managed-role !managed_role).include?(tag) - value = handler.start_mapping tag - anchor anchor, value + handler.start_mapping tag, anchor end def start_sequence *args log {"#{indent}start sequence : #{args}"} anchor, _ = args - value = handler.start_sequence - anchor anchor, value + handler.start_sequence anchor end def end_sequence log {"#{indent}end sequence"} handler.end_sequence @@ -374,11 +372,10 @@ def scalar *args # value, anchor, tag, plain, quoted, style value, anchor, tag, _, quoted = args log {"#{indent}got scalar #{tag ? tag + '=' : ''}#{value}#{anchor ? '#' + anchor : ''}"} - value = handler.scalar value, tag, quoted - anchor anchor, value + handler.scalar value, tag, quoted, anchor end def log &block logger.debug('conjur/policy/handler') { yield \ No newline at end of file