From e466354edb31f243899051e2119f4ce72bafd5f3 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 19 Jul 2010 13:33:26 -0700 Subject: Extract ParameterFilter class from FilterParameters mixin Signed-off-by: wycats --- actionpack/lib/action_dispatch.rb | 1 + .../lib/action_dispatch/http/filter_parameters.rb | 73 +++------------------- .../lib/action_dispatch/http/parameter_filter.rb | 72 +++++++++++++++++++++ actionpack/test/dispatch/request_test.rb | 8 +-- 4 files changed, 86 insertions(+), 68 deletions(-) create mode 100644 actionpack/lib/action_dispatch/http/parameter_filter.rb (limited to 'actionpack') diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb index cdf81c6648..1da4a0d4be 100644 --- a/actionpack/lib/action_dispatch.rb +++ b/actionpack/lib/action_dispatch.rb @@ -63,6 +63,7 @@ module ActionDispatch autoload :Headers autoload :MimeNegotiation autoload :Parameters + autoload :ParameterFilter autoload :FilterParameters autoload :Upload autoload :UploadedFile, 'action_dispatch/http/upload' diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 47643ce130..1ab48ae04d 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -26,85 +26,30 @@ module ActionDispatch module FilterParameters extend ActiveSupport::Concern - @@compiled_parameter_filter_for = {} + @@parameter_filter_for = {} # Return a hash of parameters with all sensitive data replaced. def filtered_parameters - @filtered_parameters ||= if filtering_parameters? - process_parameter_filter(parameters) - else - parameters.dup - end + @filtered_parameters ||= parameter_filter.filter(parameters) end # Return a hash of request.env with all sensitive data replaced. def filtered_env - filtered_env = @env.dup - filtered_env.each do |key, value| - if (key =~ /RAW_POST_DATA/i) - filtered_env[key] = '[FILTERED]' - elsif value.is_a?(Hash) - filtered_env[key] = process_parameter_filter(value) - end - end - filtered_env + @filtered_env ||= env_filter.filter(@env) end protected - def filtering_parameters? #:nodoc: - @env["action_dispatch.parameter_filter"].present? + def parameter_filter + parameter_filter_for(@env["action_dispatch.parameter_filter"]) end - def process_parameter_filter(params) #:nodoc: - compiled_parameter_filter_for(@env["action_dispatch.parameter_filter"]).call(params) + def env_filter + parameter_filter_for(Array.wrap(@env["action_dispatch.parameter_filter"]) << /RAW_POST_DATA/) end - def compile_parameter_filter(filters) #:nodoc: - strings, regexps, blocks = [], [], [] - - filters.each do |item| - case item - when NilClass - when Proc - blocks << item - when Regexp - regexps << item - else - strings << item.to_s - end - end - - regexps << Regexp.new(strings.join('|'), true) unless strings.empty? - [regexps, blocks] - end - - def compiled_parameter_filter_for(filters) #:nodoc: - @@compiled_parameter_filter_for[filters] ||= begin - regexps, blocks = compile_parameter_filter(filters) - - lambda do |original_params| - filtered_params = {} - - original_params.each do |key, value| - if regexps.find { |r| key =~ r } - value = '[FILTERED]' - elsif value.is_a?(Hash) - value = process_parameter_filter(value) - elsif value.is_a?(Array) - value = value.map { |v| v.is_a?(Hash) ? process_parameter_filter(v) : v } - elsif blocks.present? - key = key.dup - value = value.dup if value.duplicable? - blocks.each { |b| b.call(key, value) } - end - - filtered_params[key] = value - end - - filtered_params - end - end + def parameter_filter_for(filters) + @@parameter_filter_for[filters] ||= ParameterFilter.new(filters) end end diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb new file mode 100644 index 0000000000..1480e8f77c --- /dev/null +++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb @@ -0,0 +1,72 @@ +module ActionDispatch + module Http + class ParameterFilter + + def initialize(filters) + @filters = filters + end + + def filter(params) + if enabled? + compiled_filter.call(params) + else + params.dup + end + end + + private + + def enabled? + @filters.present? + end + + def compiled_filter + @compiled_filter ||= begin + regexps, blocks = compile_filter + + lambda do |original_params| + filtered_params = {} + + original_params.each do |key, value| + if regexps.find { |r| key =~ r } + value = '[FILTERED]' + elsif value.is_a?(Hash) + value = filter(value) + elsif value.is_a?(Array) + value = value.map { |v| v.is_a?(Hash) ? filter(v) : v } + elsif blocks.present? + key = key.dup + value = value.dup if value.duplicable? + blocks.each { |b| b.call(key, value) } + end + + filtered_params[key] = value + end + + filtered_params + end + end + end + + def compile_filter + strings, regexps, blocks = [], [], [] + + @filters.each do |item| + case item + when NilClass + when Proc + blocks << item + when Regexp + regexps << item + else + strings << item.to_s + end + end + + regexps << Regexp.new(strings.join('|'), true) unless strings.empty? + [regexps, blocks] + end + + end + end +end diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb index e5ee412021..c8947aac80 100644 --- a/actionpack/test/dispatch/request_test.rb +++ b/actionpack/test/dispatch/request_test.rb @@ -392,19 +392,19 @@ class RequestTest < ActiveSupport::TestCase [{'baz'=>[{'foo'=>'baz'}, "1"]}, {'baz'=>[{'foo'=>'[FILTERED]'}, "1"]}, [/foo/]]] test_hashes.each do |before_filter, after_filter, filter_words| - request = stub_request('action_dispatch.parameter_filter' => filter_words) - assert_equal after_filter, request.send(:process_parameter_filter, before_filter) + parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words) + assert_equal after_filter, parameter_filter.filter(before_filter) filter_words << 'blah' filter_words << lambda { |key, value| value.reverse! if key =~ /bargain/ } - request = stub_request('action_dispatch.parameter_filter' => filter_words) + parameter_filter = ActionDispatch::Http::ParameterFilter.new(filter_words) before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}} after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}} - assert_equal after_filter, request.send(:process_parameter_filter, before_filter) + assert_equal after_filter, parameter_filter.filter(before_filter) end end -- cgit v1.2.3