aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2010-01-21 16:50:11 +0100
committerJosé Valim <jose.valim@gmail.com>2010-01-21 16:52:49 +0100
commitfc4f237864541f5012f9b8cc8e0ec81960377e55 (patch)
treeaf89be8dd26fe96044d4b9114f1cea1a4e6910cc
parent04063393f9392b83cf5ccd0a16f217cc7261e15c (diff)
downloadrails-fc4f237864541f5012f9b8cc8e0ec81960377e55.tar.gz
rails-fc4f237864541f5012f9b8cc8e0ec81960377e55.tar.bz2
rails-fc4f237864541f5012f9b8cc8e0ec81960377e55.zip
Make filter parameters based on request, so they can be modified for anything in the middleware stack.
-rw-r--r--actionpack/lib/action_controller/base.rb6
-rw-r--r--actionpack/lib/action_controller/railties/subscriber.rb6
-rw-r--r--actionpack/lib/action_dispatch/http/filter_parameters.rb128
-rw-r--r--actionpack/test/controller/base_test.rb21
-rw-r--r--actionpack/test/controller/subscriber_test.rb5
-rw-r--r--actionpack/test/dispatch/request_test.rb39
-rw-r--r--railties/lib/generators/rails/app/templates/config/application.rb2
-rw-r--r--railties/lib/rails/application.rb1
-rw-r--r--railties/lib/rails/configuration.rb7
-rw-r--r--railties/test/application/configuration_test.rb4
10 files changed, 115 insertions, 104 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index cf66e99fa5..a66aafd80e 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -74,8 +74,12 @@ module ActionController
end
# This method has been moved to ActionDispatch::Request.filter_parameters
- def self.filter_parameter_logging(*)
+ def self.filter_parameter_logging(*args, &block)
ActiveSupport::Deprecation.warn("Setting filter_parameter_logging in ActionController is deprecated and has no longer effect, please set 'config.filter_parameters' in config/application.rb instead", caller)
+ filter = Rails.application.config.filter_parameters
+ filter.concat(args)
+ filter << block if block
+ filter
end
def _normalize_options(action=nil, options={}, &blk)
diff --git a/actionpack/lib/action_controller/railties/subscriber.rb b/actionpack/lib/action_controller/railties/subscriber.rb
index d257d6ac2c..1f0e6bf51a 100644
--- a/actionpack/lib/action_controller/railties/subscriber.rb
+++ b/actionpack/lib/action_controller/railties/subscriber.rb
@@ -1,10 +1,14 @@
module ActionController
module Railties
class Subscriber < Rails::Subscriber
+ INTERNAL_PARAMS = %w(controller action format _method only_path)
+
def start_processing(event)
payload = event.payload
+ params = payload[:params].except(*INTERNAL_PARAMS)
+
info " Processing by #{payload[:controller]}##{payload[:action]} as #{payload[:formats].first.to_s.upcase}"
- info " Parameters: #{payload[:params].inspect}" unless payload[:params].blank?
+ info " Parameters: #{params.inspect}" unless params.empty?
end
def process_action(event)
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index 0f4afb01d9..1958e1668d 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -1,69 +1,30 @@
+require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/hash/keys'
module ActionDispatch
module Http
+ # Allows you to specify sensitive parameters which will be replaced from
+ # the request log by looking in all subhashes of the param hash for keys
+ # to filter. If a block is given, each key and value of the parameter
+ # hash and all subhashes is passed to it, the value or key can be replaced
+ # using String#replace or similar method.
+ #
+ # Examples:
+ #
+ # env["action_dispatch.parameter_filter"] = [:password]
+ # => replaces the value to all keys matching /password/i with "[FILTERED]"
+ #
+ # env["action_dispatch.parameter_filter"] = [:foo, "bar"]
+ # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
+ #
+ # env["action_dispatch.parameter_filter"] = lambda do |k,v|
+ # v.reverse! if k =~ /secret/i
+ # end
+ # => reverses the value to all keys matching /secret/i
+ #
module FilterParameters
extend ActiveSupport::Concern
- INTERNAL_PARAMS = %w(controller action format _method only_path)
-
- module ClassMethods
- # Specify sensitive parameters which will be replaced from the request log.
- # Filters parameters that have any of the arguments as a substring.
- # Looks in all subhashes of the param hash for keys to filter.
- # If a block is given, each key and value of the parameter hash and all
- # subhashes is passed to it, the value or key
- # can be replaced using String#replace or similar method.
- #
- # Examples:
- #
- # ActionDispatch::Request.filter_parameters :password
- # => replaces the value to all keys matching /password/i with "[FILTERED]"
- #
- # ActionDispatch::Request.filter_parameters :foo, "bar"
- # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- #
- # ActionDispatch::Request.filter_parameters do |k,v|
- # v.reverse! if k =~ /secret/i
- # end
- # => reverses the value to all keys matching /secret/i
- #
- # ActionDispatch::Request.filter_parameters(:foo, "bar") do |k,v|
- # v.reverse! if k =~ /secret/i
- # end
- # => reverses the value to all keys matching /secret/i, and
- # replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
- def filter_parameters(*filter_words, &block)
- raise "You must filter at least one word" if filter_words.empty?
-
- parameter_filter = Regexp.new(filter_words.join('|'), true)
-
- define_method(:process_parameter_filter) do |original_params|
- filtered_params = {}
-
- original_params.each do |key, value|
- if key =~ parameter_filter
- value = '[FILTERED]'
- elsif value.is_a?(Hash)
- value = process_parameter_filter(value)
- elsif value.is_a?(Array)
- value = value.map { |i| process_parameter_filter(i) }
- elsif block_given?
- key = key.dup
- value = value.dup if value.duplicable?
- yield key, value
- end
-
- filtered_params[key] = value
- end
-
- filtered_params.except!(*INTERNAL_PARAMS)
- end
-
- protected :process_parameter_filter
- end
- end
-
# Return a hash of parameters with all sensitive data replaced.
def filtered_parameters
@filtered_parameters ||= process_parameter_filter(parameters)
@@ -71,7 +32,6 @@ module ActionDispatch
alias :fitered_params :filtered_parameters
# Return a hash of request.env with all sensitive data replaced.
- # TODO Josh should white list env to remove stuff like rack.input and rack.errors
def filtered_env
filtered_env = @env.dup
filtered_env.each do |key, value|
@@ -86,8 +46,52 @@ module ActionDispatch
protected
- def process_parameter_filter(original_parameters)
- original_parameters.except(*INTERNAL_PARAMS)
+ def compile_parameter_filter #:nodoc:
+ strings, regexps, blocks = [], [], []
+
+ Array(@env["action_dispatch.parameter_filter"]).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 filtering_parameters? #:nodoc:
+ @env["action_dispatch.parameter_filter"].present?
+ end
+
+ def process_parameter_filter(original_params) #:nodoc:
+ return original_params.dup unless filtering_parameters?
+
+ filtered_params = {}
+ regexps, blocks = compile_parameter_filter
+
+ 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 { |i| process_parameter_filter(i) }
+ 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
diff --git a/actionpack/test/controller/base_test.rb b/actionpack/test/controller/base_test.rb
index 1510a6a7e0..4fcfbacf4e 100644
--- a/actionpack/test/controller/base_test.rb
+++ b/actionpack/test/controller/base_test.rb
@@ -2,6 +2,9 @@ require 'abstract_unit'
require 'logger'
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
+module Rails
+end
+
# Provide some controller to run the tests on.
module Submodule
class ContainedEmptyController < ActionController::Base
@@ -63,7 +66,7 @@ class DefaultUrlOptionsController < ActionController::Base
end
end
-class ControllerClassTests < Test::Unit::TestCase
+class ControllerClassTests < ActiveSupport::TestCase
def test_controller_path
assert_equal 'empty', EmptyController.controller_path
assert_equal EmptyController.controller_path, EmptyController.new.controller_path
@@ -74,7 +77,21 @@ class ControllerClassTests < Test::Unit::TestCase
def test_controller_name
assert_equal 'empty', EmptyController.controller_name
assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name
- end
+ end
+
+ def test_filter_parameter_logging
+ parameters = []
+ config = mock(:config => mock(:filter_parameters => parameters))
+ Rails.expects(:application).returns(config)
+
+ assert_deprecated do
+ Class.new(ActionController::Base) do
+ filter_parameter_logging :password
+ end
+ end
+
+ assert_equal [:password], parameters
+ end
end
class ControllerInstanceTests < Test::Unit::TestCase
diff --git a/actionpack/test/controller/subscriber_test.rb b/actionpack/test/controller/subscriber_test.rb
index bd0c83413c..152a0d0c04 100644
--- a/actionpack/test/controller/subscriber_test.rb
+++ b/actionpack/test/controller/subscriber_test.rb
@@ -97,8 +97,7 @@ class ACSubscriberTest < ActionController::TestCase
end
def test_process_action_with_filter_parameters
- ActionDispatch::Request.class_eval "alias :safe_process_parameter_filter :process_parameter_filter"
- ActionDispatch::Request.filter_parameters(:lifo, :amount)
+ @request.env["action_dispatch.parameter_filter"] = [:lifo, :amount]
get :show, :lifo => 'Pratik', :amount => '420', :step => '1'
wait
@@ -107,8 +106,6 @@ class ACSubscriberTest < ActionController::TestCase
assert_match /"amount"=>"\[FILTERED\]"/, params
assert_match /"lifo"=>"\[FILTERED\]"/, params
assert_match /"step"=>"1"/, params
- ensure
- ActionDispatch::Request.class_eval "alias :process_parameter_filter :safe_process_parameter_filter"
end
def test_redirect_to
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index c5a75f5d21..2b5c19361a 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -454,18 +454,7 @@ class RequestTest < ActiveSupport::TestCase
assert_equal Mime::XML, request.negotiate_mime([Mime::XML, Mime::CSV])
end
- class FilterRequest < ActionDispatch::Request
- end
-
- test "filter_parameters raises error without arguments" do
- assert_raises RuntimeError do
- FilterRequest.filter_parameters
- end
- end
-
test "process parameter filter" do
- request = FilterRequest.new({})
-
test_hashes = [
[{'foo'=>'bar'},{'foo'=>'bar'},%w'food'],
[{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'],
@@ -473,18 +462,18 @@ class RequestTest < ActiveSupport::TestCase
[{'foo'=>'bar', 'baz'=>'foo'},{'foo'=>'[FILTERED]', 'baz'=>'[FILTERED]'},%w'foo baz'],
[{'bar'=>{'foo'=>'bar','bar'=>'foo'}},{'bar'=>{'foo'=>'[FILTERED]','bar'=>'foo'}},%w'fo'],
[{'foo'=>{'foo'=>'bar','bar'=>'foo'}},{'foo'=>'[FILTERED]'},%w'f banana'],
- [{'baz'=>[{'foo'=>'baz'}]}, {'baz'=>[{'foo'=>'[FILTERED]'}]}, %w(foo)]]
+ [{'baz'=>[{'foo'=>'baz'}]}, {'baz'=>[{'foo'=>'[FILTERED]'}]}, [/foo/]]]
test_hashes.each do |before_filter, after_filter, filter_words|
- FilterRequest.filter_parameters(*filter_words)
+ request = stub_request('action_dispatch.parameter_filter' => filter_words)
assert_equal after_filter, request.send(:process_parameter_filter, before_filter)
- filter_words.push('blah')
-
- FilterRequest.filter_parameters(*filter_words) do |key, value|
+ filter_words << 'blah'
+ filter_words << lambda { |key, value|
value.reverse! if key =~ /bargain/
- end
+ }
+ request = stub_request('action_dispatch.parameter_filter' => filter_words)
before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}}
after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}}
@@ -493,10 +482,9 @@ class RequestTest < ActiveSupport::TestCase
end
test "filtered_parameters returns params filtered" do
- FilterRequest.filter_parameters(:lifo, :amount)
-
- request = FilterRequest.new('action_dispatch.request.parameters' =>
- { 'lifo' => 'Pratik', 'amount' => '420', 'step' => '1' })
+ request = stub_request('action_dispatch.request.parameters' =>
+ { 'lifo' => 'Pratik', 'amount' => '420', 'step' => '1' },
+ 'action_dispatch.parameter_filter' => [:lifo, :amount])
params = request.filtered_parameters
assert_equal "[FILTERED]", params["lifo"]
@@ -505,12 +493,11 @@ class RequestTest < ActiveSupport::TestCase
end
test "filtered_env filters env as a whole" do
- FilterRequest.filter_parameters(:lifo, :amount)
-
- request = FilterRequest.new('action_dispatch.request.parameters' =>
- { 'amount' => '420', 'step' => '1' }, "RAW_POST_DATA" => "yada yada")
+ request = stub_request('action_dispatch.request.parameters' =>
+ { 'amount' => '420', 'step' => '1' }, "RAW_POST_DATA" => "yada yada",
+ 'action_dispatch.parameter_filter' => [:lifo, :amount])
- request = FilterRequest.new(request.filtered_env)
+ request = stub_request(request.filtered_env)
assert_equal "[FILTERED]", request.raw_post
assert_equal "[FILTERED]", request.params["amount"]
diff --git a/railties/lib/generators/rails/app/templates/config/application.rb b/railties/lib/generators/rails/app/templates/config/application.rb
index ecebbc6146..78a355d2f4 100644
--- a/railties/lib/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/generators/rails/app/templates/config/application.rb
@@ -32,6 +32,6 @@ module <%= app_const_base %>
# end
# Configure sensitive parameters which will be filtered from the log file.
- config.filter_parameters :password
+ config.filter_parameters << :password
end
end
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 743681359c..5c9892c630 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -110,6 +110,7 @@ module Rails
end
def call(env)
+ env["action_dispatch.parameter_filter"] = config.filter_parameters
app.call(env)
end
diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb
index c7331f79c5..7f1783a6b9 100644
--- a/railties/lib/rails/configuration.rb
+++ b/railties/lib/rails/configuration.rb
@@ -69,7 +69,7 @@ module Rails
class Configuration < Railtie::Configuration
attr_accessor :after_initialize_blocks, :cache_classes, :colorize_logging,
- :consider_all_requests_local, :dependency_loading,
+ :consider_all_requests_local, :dependency_loading, :filter_parameters,
:load_once_paths, :logger, :metals, :plugins,
:preload_frameworks, :reload_plugins, :serve_static_assets,
:time_zone, :whiny_nils
@@ -83,6 +83,7 @@ module Rails
super
@load_once_paths = []
@after_initialize_blocks = []
+ @filter_parameters = []
@dependency_loading = true
@serve_static_assets = true
end
@@ -252,10 +253,6 @@ module Rails
i18n
end
end
-
- def filter_parameters(*filter_words, &block)
- ActionDispatch::Request.filter_parameters(*filter_words, &block)
- end
def environment_path
"#{root}/config/environments/#{Rails.env}.rb"
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 8c08fe5acc..6968e87986 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -125,9 +125,9 @@ module ApplicationTests
test "filter_parameters should be able to set via config.filter_parameters" do
add_to_config <<-RUBY
- config.filter_parameters :foo, 'bar' do |key, value|
+ config.filter_parameters += [ :foo, 'bar', lambda { |key, value|
value = value.reverse if key =~ /baz/
- end
+ }]
RUBY
assert_nothing_raised do