1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- module TriggerWebhookJob::CustomPayload::Parser
- # This module is used to scan, collect all replacment variables within a
- # custom payload, parse them for validity and replace, escape certain
- # characters in the final payload.
- private
- STRING_LIKE_CLASSES = %w[
- String
- ActiveSupport::TimeWithZone
- ActiveSupport::Duration
- ].freeze
- # This module validates the scanned replacement variables.
- def parse(variables, tracks)
- mappings = {}
- variables.each do |variable|
- methods = variable.split('.')
- object = methods.shift
- mappings[variable] = validate_object!(object, tracks)
- next if !mappings[variable].nil?
- reference = tracks[object.to_sym]
- mappings[variable] = validate_methods!(methods, reference, object)
- end
- mappings
- end
- # Replace, escape double quotes and whitespace characters to ensure the
- # payload is valid JSON.
- def replace(record, mappings)
- mappings.each do |variable, value|
- escaped_variable = Regexp.escape(variable)
- pattern = %r{("\#\{#{escaped_variable}\}"|\#\{#{escaped_variable}\})}
- is_string_like = value.class.to_s.in?(STRING_LIKE_CLASSES)
- record.gsub!(pattern) do |match|
- if match.start_with?('"')
- escaped_value = escape_replace_value(value, is_string_like:)
- is_string_like ? "\"#{escaped_value}\"" : escaped_value
- else
- escape_replace_value(value, is_string_like: true)
- end
- end
- end
- record
- end
- def escape_replace_value(value, is_string_like: false)
- if is_string_like
- value.to_s
- .gsub(%r{"}, '\"')
- .gsub(%r{\n}, '\n')
- .gsub(%r{\r}, '\r')
- .gsub(%r{\t}, '\t')
- .gsub(%r{\f}, '\f')
- .gsub(%r{\v}, '\v')
- else
- value.to_json
- end
- end
- # Scan the custom payload for replacement variables.
- def scan(record)
- placeholders = record.scan(%r{(#\{[a-z0-9_.?!]+\})}).flatten.uniq
- return [] if placeholders.blank?
- variables = []
- placeholders.each do |placeholder|
- next if !placeholder.match?(%r{^#\{(.+)\}$})
- placeholder.gsub!(%r{^#\{(.+)\}$}, '\1')
- variables.push(placeholder)
- end
- variables
- end
- end
|