Skip to content

Commit

Permalink
Extract ParameterFilter class from FilterParameters mixin
Browse files Browse the repository at this point in the history
Signed-off-by: wycats <wycats@gmail.com>
  • Loading branch information
brynary authored and wycats committed Jul 19, 2010
1 parent 202fb79 commit e466354
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 68 deletions.
1 change: 1 addition & 0 deletions actionpack/lib/action_dispatch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ module Http
autoload :Headers
autoload :MimeNegotiation
autoload :Parameters
autoload :ParameterFilter
autoload :FilterParameters
autoload :Upload
autoload :UploadedFile, 'action_dispatch/http/upload'
Expand Down
73 changes: 9 additions & 64 deletions actionpack/lib/action_dispatch/http/filter_parameters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,85 +26,30 @@ module Http
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
Expand Down
72 changes: 72 additions & 0 deletions actionpack/lib/action_dispatch/http/parameter_filter.rb
Original file line number Diff line number Diff line change
@@ -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
8 changes: 4 additions & 4 deletions actionpack/test/dispatch/request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit e466354

Please sign in to comment.