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