From dcf02b8a46d8aa3480e03c059b3fcf4bb3a8430b Mon Sep 17 00:00:00 2001 From: Sascha Depold Date: Tue, 13 Oct 2015 15:24:26 +0200 Subject: [PATCH] Add possibility to trust a parameter branch This change introduces a way to mark a specific branch of the parameter hash as trusted. Using the added `StrongParameters::ANY` or `:*` allows to mark a value of the hash respectively. This functionality can be handy when your controllers already rely on strong_parameters and raising of errors is enabled. If the parameter hash contains in such a case a parameter value which is completely customizable by the consumer of the controller, it might be impossible to predefine keys. --- README.md | 20 ++++++++++++++++++++ lib/action_controller/parameters.rb | 3 +++ lib/strong_parameters.rb | 1 + lib/strong_parameters/any.rb | 3 +++ test/parameters_permit_test.rb | 17 +++++++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 lib/strong_parameters/any.rb diff --git a/README.md b/README.md index 8b7b582..ee371e2 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,26 @@ params.require(:token) params.require(:post).permit(:title) ``` +## Permitted parameter branches + +In some scenarios it can be useful to mark a branch of the parameter hash as trusted so that a key +is just permitted independent from whether or not it's value is a scalar or matches a specific structure. +You can express that trust like this: + +``` +params = ActionController::Parameters.new({ + :id => 'foo', + :custom_json => { + :bar => 'baz', + :very => 'customizable' + } +}) +params.permit({:custom_json => StrongParameters::ANY}) + +# ==> +# {:custom_json => {:bar => 'baz', :very => 'customizable'}} +``` + ## Handling of Unpermitted Keys By default parameter keys that are not explicitly permitted will be logged in the development and test environment. In other environments these parameters will simply be filtered out and ignored. diff --git a/lib/action_controller/parameters.rb b/lib/action_controller/parameters.rb index 9dc3d7d..4a6cee0 100644 --- a/lib/action_controller/parameters.rb +++ b/lib/action_controller/parameters.rb @@ -194,6 +194,9 @@ def hash_filter(params, filter) if filter[key] == [] # Declaration {:comment_ids => []}. array_of_permitted_scalars_filter(params, key) + elsif filter[key] == ::StrongParameters::ANY + # Declaration {:custom_json => :*} or {:custom_json => StrongParameters::ANY} + params[key] = value else # Declaration {:user => :name} or {:user => [:name, :age, {:adress => ...}]}. params[key] = each_element(value) do |element, index| diff --git a/lib/strong_parameters.rb b/lib/strong_parameters.rb index c428a40..aa9177a 100644 --- a/lib/strong_parameters.rb +++ b/lib/strong_parameters.rb @@ -1,4 +1,5 @@ require 'action_controller/parameters' require 'active_model/forbidden_attributes_protection' +require 'strong_parameters/any' require 'strong_parameters/railtie' require 'strong_parameters/log_subscriber' diff --git a/lib/strong_parameters/any.rb b/lib/strong_parameters/any.rb new file mode 100644 index 0000000..c8df9c7 --- /dev/null +++ b/lib/strong_parameters/any.rb @@ -0,0 +1,3 @@ +module StrongParameters + ANY = :* +end diff --git a/test/parameters_permit_test.rb b/test/parameters_permit_test.rb index b1905a9..001c9c9 100644 --- a/test/parameters_permit_test.rb +++ b/test/parameters_permit_test.rb @@ -346,4 +346,21 @@ def assert_filtered_out(params, key) assert !hash.permitted? end end + + test "trusted values of nested parameters" do + params = ActionController::Parameters.new({ + :resource => { + :id => 'foo', + :custom_json => { + :bar => 'baz', + :qux => { + quux: 1 + } + } + } + }) + permitted = params.permit(:resource => [{ :custom_json => StrongParameters::ANY }]) + assert_nil permitted[:resource][:id] + assert_not_nil permitted[:resource][:custom_json] + end end