From 107a3b39061f34c12d44d071103850fdcec36b6f Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Sun, 4 May 2014 14:13:24 +0400 Subject: [PATCH 01/10] implement query filtering, ref #905 --- padrino-core/lib/padrino-core/application.rb | 2 + .../application/params_protection.rb | 93 +++++++++++++++++++ padrino-core/test/test_reloader_simple.rb | 4 +- 3 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 padrino-core/lib/padrino-core/application/params_protection.rb diff --git a/padrino-core/lib/padrino-core/application.rb b/padrino-core/lib/padrino-core/application.rb index 4e3888a6e..2a9978266 100644 --- a/padrino-core/lib/padrino-core/application.rb +++ b/padrino-core/lib/padrino-core/application.rb @@ -3,6 +3,7 @@ require 'padrino-core/application/show_exceptions' require 'padrino-core/application/authenticity_token' require 'padrino-core/application/application_setup' +require 'padrino-core/application/params_protection' module Padrino ## @@ -14,6 +15,7 @@ module Padrino class Application < Sinatra::Base register Padrino::ApplicationSetup register Padrino::Routing + register Padrino::ParamsProtection ## # Returns the logger for this application. diff --git a/padrino-core/lib/padrino-core/application/params_protection.rb b/padrino-core/lib/padrino-core/application/params_protection.rb new file mode 100644 index 000000000..87a5c1b88 --- /dev/null +++ b/padrino-core/lib/padrino-core/application/params_protection.rb @@ -0,0 +1,93 @@ +module Padrino + ## + # Padrino application module providing means for mass-assignment protection. + # + module ParamsProtection + class << self + def registered(app) + included(app) + end + + def included(base) + base.send(:include, InstanceMethods) + base.extend(ClassMethods) + end + end + + module ClassMethods + ## + # Implements filtering of url query params. Can prevent mass-assignment. + # + # @example + # post :update, :allow => [:name, :email] + # post :update, :allow => [:name, :id => Integer] + # post :update, :allow => [:name => proc{ |v| v.reverse }] + # post :update, :allow => [:name, :parent => [:name, :position]] + # @example + # allow :name, :email, :password => prox{ |v| v.reverse } + # post :update + # + def allow(*allowed_params) + allowed_params = prepare_allowed_params(allowed_params) + condition do + filter_params!(params, allowed_params) + end + end + + private + + def prepare_allowed_params(allowed_params) + param_filter = {} + allowed_params.each do |key,value| + case + when key.kind_of?(Hash) && !value + param_filter.update(prepare_allowed_params(key)) + when value.kind_of?(Hash) || value.kind_of?(Array) + param_filter[key.to_s] = prepare_allowed_params(value) + else + param_filter[key.to_s] = value || true + end + end + param_filter.freeze + end + end + + module InstanceMethods + ## + # Filters a hash of parameters leaving only allowed ones and possibly + # typecasting and processing the others. + # + # @param [Hash] params + # Parameters to filter. + # Warning: this hash will be changed by deleting or replacing its values. + # @param [Hash] allowed_params + # A hash of allowed keys and value classes or processing procs. Supported + # scalar classes are: Integer (empty string is casted to nil). + # + # @example + # filter_params!( { "a" => "1", "b" => "abc", "d" => "drop" }, + # { "a" => Integer, "b" => true } ) + # # => { "a" => 1, "b" => "abc" } + # filter_params!( { "id" => "", "child" => { "name" => "manny" } }, + # { "id" => Integer, "child" => { "name" => proc{ |v| v.camelize } } } ) + # # => { "id" => nil, "child" => { "name" => "Manny" } } + # + def filter_params!(params, allowed_params) + params.each do |key,value| + type = allowed_params[key] + case + when type.kind_of?(Hash) + params[key] = filter_params!(value, type) + when type == Integer + params[key] = value.empty? ? nil : value.to_i + when type.kind_of?(Proc) + params[key] = type.call(value) + when type == true + else + params.delete(key) + end + end + end + end + end +end diff --git a/padrino-core/test/test_reloader_simple.rb b/padrino-core/test/test_reloader_simple.rb index 1d2b1ee48..51245b5c3 100644 --- a/padrino-core/test/test_reloader_simple.rb +++ b/padrino-core/test/test_reloader_simple.rb @@ -84,7 +84,7 @@ assert_equal 2, @app.filters[:after].size # app + content-type + padrino-flash assert_equal 0, @app.middleware.size assert_equal 4, @app.routes.size # GET+HEAD of "/" + GET+HEAD of "/rand" = 4 - assert_equal 3, @app.extensions.size # [Padrino::ApplicationSetup, Padrino::Routing, Padrino::Flash] + assert_equal 4, @app.extensions.size # [Padrino::ApplicationSetup, Padrino::ParamsProtection, Padrino::Routing, Padrino::Flash] assert_equal 0, @app.templates.size @app.reload! get "/rand" @@ -94,7 +94,7 @@ assert_equal 2, @app.filters[:after].size assert_equal 0, @app.middleware.size assert_equal 4, @app.routes.size # GET+HEAD of "/" = 2 - assert_equal 3, @app.extensions.size # [Padrino::ApplicationSetup, Padrino::Routing, Padrino::Flash] + assert_equal 4, @app.extensions.size # [Padrino::ApplicationSetup, Padrino::ParamsProtection, Padrino::Routing, Padrino::Flash] assert_equal 0, @app.templates.size end end From 820a49d85ec29db5ebb20bd099c273f54befee92 Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Tue, 6 May 2014 12:50:01 +0400 Subject: [PATCH 02/10] save original parameters --- .../padrino-core/application/params_protection.rb | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/padrino-core/lib/padrino-core/application/params_protection.rb b/padrino-core/lib/padrino-core/application/params_protection.rb index 87a5c1b88..7565744a7 100644 --- a/padrino-core/lib/padrino-core/application/params_protection.rb +++ b/padrino-core/lib/padrino-core/application/params_protection.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/deep_dup' + module Padrino ## # Padrino application module providing means for mass-assignment protection. @@ -30,6 +32,7 @@ module ClassMethods def allow(*allowed_params) allowed_params = prepare_allowed_params(allowed_params) condition do + @original_params = params.deep_dup filter_params!(params, allowed_params) end end @@ -62,7 +65,7 @@ module InstanceMethods # Warning: this hash will be changed by deleting or replacing its values. # @param [Hash] allowed_params # A hash of allowed keys and value classes or processing procs. Supported - # scalar classes are: Integer (empty string is casted to nil). + # scalar classes are: Integer (empty string is cast to nil). # # @example # filter_params!( { "a" => "1", "b" => "abc", "d" => "drop" }, @@ -88,6 +91,13 @@ def filter_params!(params, allowed_params) end end end + + ## + # Returns the original unfiltered query parameters hash. + # + def original_params + @original_params || params + end end end end From 36ddb2befa2df409c93d436418410ffbaed5e2ff Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Tue, 6 May 2014 12:50:42 +0400 Subject: [PATCH 03/10] add :with parameters to :allow if :allow is enabled --- padrino-core/lib/padrino-core/application/routing.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/padrino-core/lib/padrino-core/application/routing.rb b/padrino-core/lib/padrino-core/application/routing.rb index 403aaa57d..1aae87037 100644 --- a/padrino-core/lib/padrino-core/application/routing.rb +++ b/padrino-core/lib/padrino-core/application/routing.rb @@ -784,6 +784,8 @@ def route(verb, path, *args, &block) def parse_route(path, options, verb) route_options = {} + options[:allow] += options[:with] if options[:with] && options[:allow] + # We need check if path is a symbol, if that it's a named route. map = options.delete(:map) From da755757bc4d68cf249c8f50f66af5d5cf2834cf Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Tue, 6 May 2014 13:09:31 +0400 Subject: [PATCH 04/10] configure routes with controller options --- padrino-core/lib/padrino-core/application/routing.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/padrino-core/lib/padrino-core/application/routing.rb b/padrino-core/lib/padrino-core/application/routing.rb index 1aae87037..8b38650f5 100644 --- a/padrino-core/lib/padrino-core/application/routing.rb +++ b/padrino-core/lib/padrino-core/application/routing.rb @@ -399,6 +399,7 @@ def controller(*args, &block) @_conditions, original_conditions = options.delete(:conditions), @_conditions @_defaults, original_defaults = options, @_defaults @_accepts, original_accepts = options.delete(:accepts), @_accepts + @_allow, original_allow = options.delete(:allow), @_allow # Application defaults. @filters, original_filters = { :before => @filters[:before].dup, :after => @filters[:after].dup }, @filters @@ -414,6 +415,7 @@ def controller(*args, &block) @_controller, @_parents, @_cache = original_controller, original_parent, original_cache @_defaults, @_provides, @_map = original_defaults, original_provides, original_map @_conditions, @_use_format, @_accepts = original_conditions, original_use_format, original_accepts + @_allow = original_allow else include(*args) if extensions.any? end @@ -710,6 +712,7 @@ def route(verb, path, *args, &block) route_options = options.dup route_options[:provides] = @_provides if @_provides route_options[:accepts] = @_accepts if @_accepts + route_options[:allow] ||= @_allow if @_allow && verb != 'GET' # Add Sinatra condition to check rack-protection failure. if protect_from_csrf && (report_csrf_failure || allow_disabled_csrf) From d6691d0268e3d6817a6b39ec9f31b0f36912918a Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Tue, 6 May 2014 13:10:30 +0400 Subject: [PATCH 05/10] add tests form params protection --- padrino-core/test/test_params_protection.rb | 109 ++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 padrino-core/test/test_params_protection.rb diff --git a/padrino-core/test/test_params_protection.rb b/padrino-core/test/test_params_protection.rb new file mode 100644 index 000000000..8f6466f82 --- /dev/null +++ b/padrino-core/test/test_params_protection.rb @@ -0,0 +1,109 @@ +require File.expand_path(File.dirname(__FILE__) + '/helper') + +describe "Padrino::ParamsProtection" do + before do + @teri = { 'name' => 'Teri Bauer', 'position' => 'baby' } + @kim = { 'name' => 'Kim Bauer', 'position' => 'daughter', 'child' => @teri } + @jack = { 'name' => 'Jack Bauer', 'position' => 'terrorist', 'child' => @kim } + end + + it 'should drop all parameters except allowed ones' do + result = nil + mock_app do + post :basic, :allow => [ :name ] do + result = params + '' + end + end + post '/basic?' + @jack.to_query + assert_equal({ 'name' => @jack['name'] }, result) + end + + it 'should preserve original params' do + result = nil + mock_app do + post :basic, :allow => [ :name ] do + result = original_params + '' + end + end + post '/basic?' + @jack.to_query + assert_equal(@jack, result) + end + + it 'should work with recursive data' do + result = nil + mock_app do + post :basic, :allow => [ :name, :child => [ :name, :child => [ :name ] ] ] do + result = [params, original_params] + '' + end + end + post '/basic?' + @jack.to_query + assert_equal( + [ + { 'name' => @jack['name'], 'child' => { 'name' => @kim['name'], 'child' => { 'name' => @teri['name'] } } }, + @jack + ], + result + ) + end + + it 'should be able to process the data' do + result = nil + mock_app do + post :basic, :allow => [ :name, :position => proc{ |v| 'anti-'+v } ] do + result = params + '' + end + end + post '/basic?' + @jack.to_query + assert_equal({ 'name' => @jack['name'], 'position' => 'anti-terrorist' }, result) + end + + it 'should pass :with parameters' do + result = nil + mock_app do + post :basic, :with => [:id, :tag], :allow => [ :name ] do + result = params + '' + end + end + post '/basic/24/42?' + @jack.to_query + assert_equal({ 'name' => @jack['name'], 'id' => '24', 'tag' => '42' }, result) + end + + it 'should be configurable with controller options' do + result = nil + mock_app do + controller :persons, :allow => [ :name ] do + post :create, :allow => [ :name, :position ] do + result = params + '' + end + post :update, :with => [ :id ] do + result = params + '' + end + end + end + post '/persons/create?' + @jack.to_query + assert_equal({ 'name' => @jack['name'], 'position' => 'terrorist' }, result) + post '/persons/update/1?name=Chloe+O\'Brian&position=hacker' + assert_equal({ 'id' => '1', 'name' => 'Chloe O\'Brian' }, result) + end + + it 'should not touch GET params when configured with controller' do + result = nil + mock_app do + controller :persons, :allow => [ :name ] do + get :show, :with => [ :id ] do + result = params + '' + end + end + end + get '/persons/show/1?name=Chloe+O\'Brian&position=hacker' + assert_equal({ 'id' => '1', 'name' => 'Chloe O\'Brian', 'position' => 'hacker' }, result) + end +end From 58b3213a9d536912b9a937754dc8ae0e6485831e Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Wed, 7 May 2014 20:34:42 +0400 Subject: [PATCH 06/10] rename :allow to :params, allow filtering GET, parse true/false --- .../application/params_protection.rb | 14 +++-- .../lib/padrino-core/application/routing.rb | 13 +++-- padrino-core/test/test_params_protection.rb | 58 ++++++++++++------- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/padrino-core/lib/padrino-core/application/params_protection.rb b/padrino-core/lib/padrino-core/application/params_protection.rb index 7565744a7..7ad2ba95e 100644 --- a/padrino-core/lib/padrino-core/application/params_protection.rb +++ b/padrino-core/lib/padrino-core/application/params_protection.rb @@ -21,15 +21,17 @@ module ClassMethods # Implements filtering of url query params. Can prevent mass-assignment. # # @example - # post :update, :allow => [:name, :email] - # post :update, :allow => [:name, :id => Integer] - # post :update, :allow => [:name => proc{ |v| v.reverse }] - # post :update, :allow => [:name, :parent => [:name, :position]] + # post :update, :params => [:name, :email] + # post :update, :params => [:name, :id => Integer] + # post :update, :params => [:name => proc{ |v| v.reverse }] + # post :update, :params => [:name, :parent => [:name, :position]] + # post :update, :params => false + # post :update, :params => true # @example - # allow :name, :email, :password => prox{ |v| v.reverse } + # params :name, :email, :password => prox{ |v| v.reverse } # post :update # - def allow(*allowed_params) + def params(*allowed_params) allowed_params = prepare_allowed_params(allowed_params) condition do @original_params = params.deep_dup diff --git a/padrino-core/lib/padrino-core/application/routing.rb b/padrino-core/lib/padrino-core/application/routing.rb index 8b38650f5..8fe5c5aa4 100644 --- a/padrino-core/lib/padrino-core/application/routing.rb +++ b/padrino-core/lib/padrino-core/application/routing.rb @@ -399,7 +399,7 @@ def controller(*args, &block) @_conditions, original_conditions = options.delete(:conditions), @_conditions @_defaults, original_defaults = options, @_defaults @_accepts, original_accepts = options.delete(:accepts), @_accepts - @_allow, original_allow = options.delete(:allow), @_allow + @_params, original_params = options.delete(:params), @_params # Application defaults. @filters, original_filters = { :before => @filters[:before].dup, :after => @filters[:after].dup }, @filters @@ -415,7 +415,7 @@ def controller(*args, &block) @_controller, @_parents, @_cache = original_controller, original_parent, original_cache @_defaults, @_provides, @_map = original_defaults, original_provides, original_map @_conditions, @_use_format, @_accepts = original_conditions, original_use_format, original_accepts - @_allow = original_allow + @_params = original_params else include(*args) if extensions.any? end @@ -712,7 +712,7 @@ def route(verb, path, *args, &block) route_options = options.dup route_options[:provides] = @_provides if @_provides route_options[:accepts] = @_accepts if @_accepts - route_options[:allow] ||= @_allow if @_allow && verb != 'GET' + route_options[:params] = @_params if @_params && !route_options.include?(:params) # Add Sinatra condition to check rack-protection failure. if protect_from_csrf && (report_csrf_failure || allow_disabled_csrf) @@ -787,7 +787,12 @@ def route(verb, path, *args, &block) def parse_route(path, options, verb) route_options = {} - options[:allow] += options[:with] if options[:with] && options[:allow] + if options[:params] == true + options.delete(:params) + elsif options.include?(:params) + options[:params] ||= [] + options[:params] += options[:with] if options[:with] + end # We need check if path is a symbol, if that it's a named route. map = options.delete(:map) diff --git a/padrino-core/test/test_params_protection.rb b/padrino-core/test/test_params_protection.rb index 8f6466f82..0b77826be 100644 --- a/padrino-core/test/test_params_protection.rb +++ b/padrino-core/test/test_params_protection.rb @@ -10,7 +10,7 @@ it 'should drop all parameters except allowed ones' do result = nil mock_app do - post :basic, :allow => [ :name ] do + post :basic, :params => [ :name ] do result = params '' end @@ -22,7 +22,7 @@ it 'should preserve original params' do result = nil mock_app do - post :basic, :allow => [ :name ] do + post :basic, :params => [ :name ] do result = original_params '' end @@ -34,7 +34,7 @@ it 'should work with recursive data' do result = nil mock_app do - post :basic, :allow => [ :name, :child => [ :name, :child => [ :name ] ] ] do + post :basic, :params => [ :name, :child => [ :name, :child => [ :name ] ] ] do result = [params, original_params] '' end @@ -52,7 +52,7 @@ it 'should be able to process the data' do result = nil mock_app do - post :basic, :allow => [ :name, :position => proc{ |v| 'anti-'+v } ] do + post :basic, :params => [ :name, :position => proc{ |v| 'anti-'+v } ] do result = params '' end @@ -64,7 +64,7 @@ it 'should pass :with parameters' do result = nil mock_app do - post :basic, :with => [:id, :tag], :allow => [ :name ] do + post :basic, :with => [:id, :tag], :params => [ :name ] do result = params '' end @@ -73,11 +73,29 @@ assert_equal({ 'name' => @jack['name'], 'id' => '24', 'tag' => '42' }, result) end + it 'should understand true or false values' do + result = nil + mock_app do + get :hide, :with => [ :id ], :params => false do + result = params + '' + end + get :show, :with => [ :id ], :params => true do + result = params + '' + end + end + get '/hide/1?' + @jack.to_query + assert_equal({"id"=>"1"}, result) + get '/show/1?' + @jack.to_query + assert_equal({"id"=>"1"}.merge(@jack), result) + end + it 'should be configurable with controller options' do result = nil mock_app do - controller :persons, :allow => [ :name ] do - post :create, :allow => [ :name, :position ] do + controller :persons, :params => [ :name ] do + post :create, :params => [ :name, :position ] do result = params '' end @@ -85,25 +103,23 @@ result = params '' end + post :delete, :params => true do + result = params + '' + end + post :destroy, :with => [ :id ], :params => false do + result = params + '' + end end end post '/persons/create?' + @jack.to_query assert_equal({ 'name' => @jack['name'], 'position' => 'terrorist' }, result) post '/persons/update/1?name=Chloe+O\'Brian&position=hacker' assert_equal({ 'id' => '1', 'name' => 'Chloe O\'Brian' }, result) - end - - it 'should not touch GET params when configured with controller' do - result = nil - mock_app do - controller :persons, :allow => [ :name ] do - get :show, :with => [ :id ] do - result = params - '' - end - end - end - get '/persons/show/1?name=Chloe+O\'Brian&position=hacker' - assert_equal({ 'id' => '1', 'name' => 'Chloe O\'Brian', 'position' => 'hacker' }, result) + post '/persons/delete?' + @jack.to_query + assert_equal(@jack, result) + post '/persons/destroy/1?' + @jack.to_query + assert_equal({"id"=>"1"}, result) end end From cc6135056260c9cb645925653a2f4ed085980ecd Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Thu, 8 May 2014 11:07:18 +0400 Subject: [PATCH 07/10] filter collections and arrays properly --- .../application/params_protection.rb | 11 ++++++-- padrino-core/test/test_params_protection.rb | 25 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/padrino-core/lib/padrino-core/application/params_protection.rb b/padrino-core/lib/padrino-core/application/params_protection.rb index 7ad2ba95e..c13601fff 100644 --- a/padrino-core/lib/padrino-core/application/params_protection.rb +++ b/padrino-core/lib/padrino-core/application/params_protection.rb @@ -50,7 +50,7 @@ def prepare_allowed_params(allowed_params) when value.kind_of?(Hash) || value.kind_of?(Array) param_filter[key.to_s] = prepare_allowed_params(value) else - param_filter[key.to_s] = value || true + param_filter[key.to_s] = value == false ? false : (value || true) end end param_filter.freeze @@ -80,9 +80,16 @@ module InstanceMethods def filter_params!(params, allowed_params) params.each do |key,value| type = allowed_params[key] + next if value.kind_of?(Array) && type case when type.kind_of?(Hash) - params[key] = filter_params!(value, type) + if key == key.pluralize + value.each do |array_index,array_value| + value[array_index] = filter_params!(array_value, type) + end + else + params[key] = filter_params!(value, type) + end when type == Integer params[key] = value.empty? ? nil : value.to_i when type.kind_of?(Proc) diff --git a/padrino-core/test/test_params_protection.rb b/padrino-core/test/test_params_protection.rb index 0b77826be..af36618dd 100644 --- a/padrino-core/test/test_params_protection.rb +++ b/padrino-core/test/test_params_protection.rb @@ -5,6 +5,7 @@ @teri = { 'name' => 'Teri Bauer', 'position' => 'baby' } @kim = { 'name' => 'Kim Bauer', 'position' => 'daughter', 'child' => @teri } @jack = { 'name' => 'Jack Bauer', 'position' => 'terrorist', 'child' => @kim } + @family = { 'name' => 'Bauer', 'persons' => { 1 => @teri, 2 => @kim, 3 => @jack } } end it 'should drop all parameters except allowed ones' do @@ -122,4 +123,28 @@ post '/persons/destroy/1?' + @jack.to_query assert_equal({"id"=>"1"}, result) end + + it 'should successfully filter hashes' do + result = nil + mock_app do + post :family, :params => [ :persons => [ :name ] ] do + result = params + '' + end + end + post '/family?' + @family.to_query + assert_equal({"persons" => {"3" => {"name" => @jack["name"]}, "2" => {"name" => @kim["name"]}, "1" => {"name" => @teri["name"]}}}, result) + end + + it 'should pass arrays' do + result = nil + mock_app do + post :family, :params => [ :names => [] ] do + result = params + '' + end + end + post '/family?names[]=Jack&names[]=Kim&names[]=Teri' + assert_equal({"names" => %w[Jack Kim Teri]}, result) + end end From 18095fd2e30db0b47be981040c5902adbdb1ba98 Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Thu, 8 May 2014 13:52:23 +0400 Subject: [PATCH 08/10] allow false params with controller option --- padrino-core/lib/padrino-core/application/routing.rb | 2 +- padrino-core/test/test_params_protection.rb | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/padrino-core/lib/padrino-core/application/routing.rb b/padrino-core/lib/padrino-core/application/routing.rb index 8fe5c5aa4..b4ac30616 100644 --- a/padrino-core/lib/padrino-core/application/routing.rb +++ b/padrino-core/lib/padrino-core/application/routing.rb @@ -712,7 +712,7 @@ def route(verb, path, *args, &block) route_options = options.dup route_options[:provides] = @_provides if @_provides route_options[:accepts] = @_accepts if @_accepts - route_options[:params] = @_params if @_params && !route_options.include?(:params) + route_options[:params] = @_params unless @_params.nil? || route_options.include?(:params) # Add Sinatra condition to check rack-protection failure. if protect_from_csrf && (report_csrf_failure || allow_disabled_csrf) diff --git a/padrino-core/test/test_params_protection.rb b/padrino-core/test/test_params_protection.rb index af36618dd..d1d757b49 100644 --- a/padrino-core/test/test_params_protection.rb +++ b/padrino-core/test/test_params_protection.rb @@ -113,6 +113,12 @@ '' end end + controller :noparam, :params => false do + get :index do + result = params + '' + end + end end post '/persons/create?' + @jack.to_query assert_equal({ 'name' => @jack['name'], 'position' => 'terrorist' }, result) @@ -122,6 +128,8 @@ assert_equal(@jack, result) post '/persons/destroy/1?' + @jack.to_query assert_equal({"id"=>"1"}, result) + get '/noparam?a=1;b=2' + assert_equal({}, result) end it 'should successfully filter hashes' do From 7fb7160780a1981d909697c618c03247f1076ead Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Thu, 8 May 2014 14:05:13 +0400 Subject: [PATCH 09/10] update examples --- .../padrino-core/application/params_protection.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/padrino-core/lib/padrino-core/application/params_protection.rb b/padrino-core/lib/padrino-core/application/params_protection.rb index c13601fff..0f5d517ac 100644 --- a/padrino-core/lib/padrino-core/application/params_protection.rb +++ b/padrino-core/lib/padrino-core/application/params_protection.rb @@ -29,7 +29,14 @@ module ClassMethods # post :update, :params => true # @example # params :name, :email, :password => prox{ |v| v.reverse } - # post :update + # post :update + # @example + # App.controller :accounts, :params => [:name, :position] do + # post :create + # post :update, :with => [ :id ], :params => [:name, :position, :addition] + # get :show, :with => :id, :params => false + # get :search, :params => true + # end # def params(*allowed_params) allowed_params = prepare_allowed_params(allowed_params) @@ -76,6 +83,12 @@ module InstanceMethods # filter_params!( { "id" => "", "child" => { "name" => "manny" } }, # { "id" => Integer, "child" => { "name" => proc{ |v| v.camelize } } } ) # # => { "id" => nil, "child" => { "name" => "Manny" } } + # filter_params!( { "a" => ["1", "2", "3"] }, + # { "a" => true } ) + # # => { "a" => ["1", "2", "3"] } + # filter_params!( { "persons" => {"p-1" => { "name" => "manny", "age" => "50" }, "p-2" => { "name" => "richard", "age" => "50" } } }, + # { "persons" => { "name" => true } } ) + # # => { "persons" => {"p-1" => { "name" => "manny" }, "p-2" => { "name" => "richard" } } } # def filter_params!(params, allowed_params) params.each do |key,value| From c0044d683624952e5c6dad331353578ede82bde1 Mon Sep 17 00:00:00 2001 From: Igor Bochkariov Date: Thu, 8 May 2014 14:38:49 +0400 Subject: [PATCH 10/10] fix tests --- padrino-core/test/test_params_protection.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/padrino-core/test/test_params_protection.rb b/padrino-core/test/test_params_protection.rb index d1d757b49..54f0388af 100644 --- a/padrino-core/test/test_params_protection.rb +++ b/padrino-core/test/test_params_protection.rb @@ -1,4 +1,5 @@ require File.expand_path(File.dirname(__FILE__) + '/helper') +require 'active_support/core_ext/hash/conversions' describe "Padrino::ParamsProtection" do before do