class Blacklight::Parameters

Attributes

params[R]

rubocop:enable Naming/MethodParameterName

search_state[R]

rubocop:enable Naming/MethodParameterName

Public Class Methods

_deep_merge_permitted_param_hashes(h1, h2) click to toggle source
# File lib/blacklight/parameters.rb, line 32
                     def self._deep_merge_permitted_param_hashes(h1, h2)
  h1.merge(h2) do |_key, old_value, new_value|
    if (old_value.is_a?(Hash) && old_value.empty?) || (new_value.is_a?(Hash) && new_value.empty?)
      {}
    elsif old_value.is_a?(Hash) && new_value.is_a?(Hash)
      _deep_merge_permitted_param_hashes(old_value, new_value)
    elsif old_value.is_a?(Array) || new_value.is_a?(Array)
      deep_merge_permitted_params(old_value, new_value)
    else
      new_value
    end
  end
end
deep_merge_permitted_params(a, b) click to toggle source

rubocop:disable Naming/MethodParameterName Merge two Rails strong_params-style permissions into a single list of permitted parameters, deep-merging complex values as needed. @param [Array<Symbol, Hash>] a @param [Array<Symbol, Hash>] b @return [Array<Symbol, Hash>]

# File lib/blacklight/parameters.rb, line 20
def self.deep_merge_permitted_params(a, b)
  a = [a] if a.is_a? Hash
  b = [b] if b.is_a? Hash

  complex_params_from_a, scalar_params_from_a = a.flatten.uniq.partition { |x| x.is_a? Hash }
  complex_params_from_a = complex_params_from_a.inject({}) { |tmp, h| _deep_merge_permitted_param_hashes(h, tmp) }
  complex_params_from_b, scalar_params_from_b = b.flatten.uniq.partition { |x| x.is_a? Hash }
  complex_params_from_b = complex_params_from_b.inject({}) { |tmp, h| _deep_merge_permitted_param_hashes(h, tmp) }

  (scalar_params_from_a + scalar_params_from_b + [_deep_merge_permitted_param_hashes(complex_params_from_a, complex_params_from_b)]).compact_blank.uniq
end
new(params, search_state) click to toggle source
# File lib/blacklight/parameters.rb, line 51
def initialize(params, search_state)
  @params = params.is_a?(Hash) ? params.with_indifferent_access : params
  @search_state = search_state
end
sanitize(params) click to toggle source

Sanitize the search parameters by removing unnecessary parameters from the provided parameters. @param [Hash] params parameters

# File lib/blacklight/parameters.rb, line 9
def self.sanitize params
  params.reject { |_k, v| v.nil? } # not available in Rails 6.0
        .except(:action, :controller, :id, :commit, :utf8)
end

Public Instance Methods

permit_search_params() click to toggle source

@param [Hash] params with unknown structure (not declared in the blacklight config or filters) stripped out

# File lib/blacklight/parameters.rb, line 57
def permit_search_params
  # if the parameters were generated internally, we can (probably) trust that they're fine
  return params unless params.is_a?(ActionController::Parameters)

  # if the parameters were permitted already, we should be able to trust them
  return params if params.permitted?

  permitted_params = filter_fields.inject(blacklight_config.search_state_fields) do |allowlist, filter|
    Blacklight::Parameters.deep_merge_permitted_params(allowlist, filter.permitted_params)
  end

  deep_unmangle_params!(params, permitted_params)

  if blacklight_config.filter_search_state_fields
    params.permit(*permitted_params)
  else
    params.deep_dup.permit!
  end
end

Private Instance Methods

deep_unmangle_params!(params, permitted_params) click to toggle source

Facebook’s crawler turns array query parameters into a hash with numeric keys. Once we know the expected parameter structure, we can unmangle those parameters to match our expected values.

# File lib/blacklight/parameters.rb, line 81
def deep_unmangle_params!(params, permitted_params)
  permitted_params.select { |p| p.is_a?(Hash) }.each do |permission|
    permission.each do |key, permitted_value|
      next unless params[key].is_a?(ActionController::Parameters)

      if permitted_value.is_a?(Hash)
        deep_unmangle_params!(params[key], [permitted_value])
      elsif permitted_value.is_a?(Array) && permitted_value.empty? && params[key]&.keys&.all? { |k| k.to_s =~ /\A\d+\z/ }
        params[key] = params[key].values
      end
    end
  end
end