From 660b72116824727bf80c27528d933612325d45c1 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Wed, 11 Apr 2012 16:06:14 -0400 Subject: [PATCH 1/2] Add regex support for permitting params --- README.rdoc | 4 ++++ lib/action_controller/parameters.rb | 24 ++++++++++++++++--- test/regexp_parameters_test.rb | 36 +++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 test/regexp_parameters_test.rb diff --git a/README.rdoc b/README.rdoc index 8c719bf..a046c36 100644 --- a/README.rdoc +++ b/README.rdoc @@ -35,6 +35,10 @@ You can also use permit on nested parameters, like: Thanks to Nick Kallen for the permit idea! +You can also easily permit similarly named parameters using regular expressions: + + params.permit(/^company_\d$/ => [:name, :location, /^quarter_\d_profit$/]) + == Todos * Automatically permit parameters coming from a signed form [Yehuda] diff --git a/lib/action_controller/parameters.rb b/lib/action_controller/parameters.rb index daaf901..fd5664c 100644 --- a/lib/action_controller/parameters.rb +++ b/lib/action_controller/parameters.rb @@ -39,19 +39,25 @@ def permit(*filters) case filter when Symbol then params[filter] = self[filter] if has_key?(filter) + when Regexp then + self.each do |key, value| + params[key] = self[key] if key =~ filter + end when Hash then - self.slice(*filter.keys).each do |key, value| + expanded_filter = expand_regexp_filters(filter) + + self.slice(*expanded_filter.keys).each do |key, value| return unless value key = key.to_sym params[key] = each_element(value) do |value| # filters are a Hash, so we expect value to be a Hash too - next if filter.is_a?(Hash) && !value.is_a?(Hash) + next if expanded_filter.is_a?(Hash) && !value.is_a?(Hash) value = self.class.new(value) if !value.respond_to?(:permit) - value.permit(*Array.wrap(filter[key])) + value.permit(*Array.wrap(expanded_filter[key])) end end end @@ -97,6 +103,18 @@ def each_element(object) yield object end end + + def expand_regexp_filters(filter) + expanded_filter = filter.select{|k,v| !k.is_a?(Regexp) } + filter.each do |filter_key, filter_value| + if filter_key.is_a?(Regexp) + self.select {|k,v| k =~ filter_key }.each do |k, v| + expanded_filter[k] = filter_value + end + end + end + self.class.new(expanded_filter) + end end module StrongParameters diff --git a/test/regexp_parameters_test.rb b/test/regexp_parameters_test.rb new file mode 100644 index 0000000..8328653 --- /dev/null +++ b/test/regexp_parameters_test.rb @@ -0,0 +1,36 @@ +require 'test_helper' +require 'action_controller/parameters' + +class RegexpParametersTest < ActiveSupport::TestCase + test "permitted parameters defined by regexp" do + params = ActionController::Parameters.new({ + object_1: { + safe_param_1: 'value', + safe_param_2: 'value', + malicious: 'haxored!' + }, + object_2: { + safe_param_1: 'value', + safe_param_2: 'value', + malicious: 'haxored!' + }, + bad_object: { + param: 'value' + } + }) + + expected = ActionController::Parameters.new({ + object_1: { + safe_param_1: 'value', + safe_param_2: 'value' + }, + object_2: { + safe_param_1: 'value', + safe_param_2: 'value' + } + }) + + permitted = params.permit(/^object_\d$/ => [/^safe_param_\d$/]) + assert_equal expected, permitted + end +end From 929332d0f2a6528c1300209e624930ad1ec3e438 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Mon, 14 May 2012 14:28:31 -0400 Subject: [PATCH 2/2] Revert to 1.8 hash syntax ec7b957bf113240d8cc3ed2017d9866e83e2edf7 made strong_parameters 1.8 compatible --- test/regexp_parameters_test.rb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/regexp_parameters_test.rb b/test/regexp_parameters_test.rb index 8328653..b342d0d 100644 --- a/test/regexp_parameters_test.rb +++ b/test/regexp_parameters_test.rb @@ -4,29 +4,29 @@ class RegexpParametersTest < ActiveSupport::TestCase test "permitted parameters defined by regexp" do params = ActionController::Parameters.new({ - object_1: { - safe_param_1: 'value', - safe_param_2: 'value', - malicious: 'haxored!' + :object_1 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value', + :malicious => 'haxored!' }, - object_2: { - safe_param_1: 'value', - safe_param_2: 'value', - malicious: 'haxored!' + :object_2 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value', + :malicious => 'haxored!' }, - bad_object: { - param: 'value' + :bad_object => { + :param => 'value' } }) expected = ActionController::Parameters.new({ - object_1: { - safe_param_1: 'value', - safe_param_2: 'value' + :object_1 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value' }, - object_2: { - safe_param_1: 'value', - safe_param_2: 'value' + :object_2 => { + :safe_param_1 => 'value', + :safe_param_2 => 'value' } })