lib/gooddata/helpers/global_helpers_params.rb in gooddata-0.6.49 vs lib/gooddata/helpers/global_helpers_params.rb in gooddata-0.6.50

- old
+ new

@@ -1,8 +1,8 @@ # encoding: UTF-8 # -# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved. +# Copyright (c) 2010-2017 GoodData Corporation. All rights reserved. # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. module GoodData module Helpers @@ -50,13 +50,35 @@ # @return [Hash] Encoded parameters def encode_hidden_params(params) encode_params(params, ENCODED_HIDDEN_PARAMS_KEY) end - # Decodes params as they came from the platform - # The "data" key is supposed to be json and it's parsed - if this - def decode_params(params) + # Decodes params as they came from the platform. + # @params Parameter hash need to be decoded + # @option options [Boolean] :resolve_reference_params Resolve reference parameters in gd_encoded_params or not + # @return [Hash] Decoded parameters + def decode_params(params, options = {}) + convert_secure_params = lambda do |args| + args = args.select { |k, _| k.include? "|" } + lines = args.keys.map do |key| + hash = {} + last_a = nil + last_e = nil + key.split("|").reduce(hash) do |a, e| + last_a = a + last_e = e + a[e] = {} + end + last_a[last_e] = args[key] + hash + end + + lines.reduce({}) do |a, e| + a.deep_merge(e) + end + end + key = ENCODED_PARAMS_KEY.to_s hidden_key = ENCODED_HIDDEN_PARAMS_KEY.to_s data_params = params[key] || '{}' hidden_data_params = if params.key?(hidden_key) && params[hidden_key].nil? "{\"#{hidden_key}\" : null}" @@ -64,22 +86,66 @@ params[hidden_key] else '{}' end + # Replace reference parameters by the actual values. Use backslash to escape a reference parameter, e.g: \${not_a_param}, + # the ${not_a_param} will not be replaced + if options[:resolve_reference_params] + regexps = Regexp.union(/\\\\/, /\\\$/, /\$\{(\w+)\}/) + resolve_reference = lambda do |v| + if v.is_a? Hash + Hash[ + v.map do |k, v2| + [k, resolve_reference.call(v2)] + end + ] + elsif v.is_a? Array + v.map do |v2| + resolve_reference.call(v2) + end + else + v.gsub(regexps) do |match| + if match =~ /\\\\/ + data_params.is_a?(Hash) ? '\\' : '\\\\' # rubocop: disable Metrics/BlockNesting + elsif match =~ /\\\$/ + '$' + elsif match =~ /\$\{(\w+)\}/ + params["#{$1}"] || raise("The gd_encoded_params parameter contains unknow reference #{$1}") # rubocop: disable Style/PerlBackrefs + end + end + end + end + + data_params = if data_params.is_a? Hash + Hash[ + data_params.map do |k, v| + [k, resolve_reference.call(v)] + end + ] + else + resolve_reference.call(data_params) + end + end + begin - parsed_data_params = JSON.parse(data_params) - parsed_hidden_data_params = JSON.parse(hidden_data_params) + parsed_data_params = data_params.is_a?(Hash) ? data_params : JSON.parse(data_params) + parsed_hidden_data_params = hidden_data_params.is_a?(Hash) ? hidden_data_params : JSON.parse(hidden_data_params) rescue JSON::ParserError => e raise e.class, "Error reading json from '#{key}' or '#{hidden_key}', reason: #{e.message}" end # Add the nil on ENCODED_HIDDEN_PARAMS_KEY # if the data was retrieved from API You will not have the actual values so encode -> decode is not losless. The nil on the key prevents the server from deleting the key parsed_hidden_data_params[ENCODED_HIDDEN_PARAMS_KEY] = nil unless parsed_hidden_data_params.empty? + secure_params = convert_secure_params.call(params) + params.delete_if do |k, _| + k.include?('|') + end + params.delete(key) params.delete(hidden_key) - params.merge(parsed_data_params).merge(parsed_hidden_data_params) + params.deep_merge(parsed_data_params).deep_merge(parsed_hidden_data_params).deep_merge(secure_params) end # A helper which allows you to diff two lists of objects. The objects # can be arbitrary objects as long as they respond to to_hash because # the diff is eventually done on hashes. It allows you to specify