strong_parameters_rails2 0.1.6.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,83 @@
1
+ = Strong Parameters
2
+
3
+ With this plugin Action Controller parameters are forbidden to be used in Active Model mass assignments until they have been whitelisted. This means you'll have to make a conscious choice about which attributes to allow for mass updating and thus prevent accidentally exposing that which shouldn't be exposed.
4
+
5
+ In addition, parameters can be marked as required and flow through a predefined raise/rescue flow to end up as a 400 Bad Request with no effort.
6
+
7
+ class PeopleController < ActionController::Base
8
+ # This will raise an ActiveModel::ForbiddenAttributes exception because it's using mass assignment
9
+ # without an explicit permit step.
10
+ def create
11
+ Person.create(params[:person])
12
+ end
13
+
14
+ # This will pass with flying colors as long as there's a person key in the parameters, otherwise
15
+ # it'll raise a ActionController::MissingParameter exception, which will get caught by
16
+ # ActionController::Base and turned into that 400 Bad Request reply.
17
+ def update
18
+ redirect_to current_account.people.find(params[:id]).tap { |person|
19
+ person.update_attributes!(person_params)
20
+ }
21
+ end
22
+
23
+ private
24
+ # Using a private method to encapsulate the permissible parameters is just a good pattern
25
+ # since you'll be able to reuse the same permit list between create and update. Also, you
26
+ # can specialize this method with per-user checking of permissible attributes.
27
+ def person_params
28
+ params.require(:person).permit(:name, :age)
29
+ end
30
+ end
31
+
32
+ You can also use permit on nested parameters, like:
33
+
34
+ params.permit(:name, friends: [ :name, { family: [ :name ] }])
35
+
36
+ Thanks to Nick Kallen for the permit idea!
37
+
38
+ == Installation
39
+
40
+ In Gemfile:
41
+
42
+ gem 'strong_parameters_rails2', :require => 'strong_parameters'
43
+
44
+ and then run `bundle`. To activate the strong parameters, you need to include this module in
45
+ every model you want protected.
46
+
47
+ === Simple
48
+
49
+ class Post < ActiveRecord::Base
50
+ include ActiveRecord::ForbiddenAttributesProtection
51
+ end
52
+
53
+ === Rails 3 ready
54
+
55
+ StrongParameters::ModelExtension = if Rails::VERSION::MAJOR == 2
56
+ ActiveRecord::ForbiddenAttributesProtection
57
+ else
58
+ ActiveModel::ForbiddenAttributesProtection
59
+ end
60
+
61
+ class Post < ActiveRecord::Base
62
+ include StrongParameters::ModelExtension
63
+ end
64
+
65
+ === Just logging for existing models
66
+
67
+ ActiveRecord::ForbiddenAttributesProtection.class_eval do
68
+ remove_method :assign_attributes_with_permitted # more sure we overwrite the correct method
69
+ def assign_attributes_with_permitted(attributes)
70
+ if attributes.respond_to?(:permitted?) && !attributes.permitted?
71
+ if Rails.env.production?
72
+ Rails.logger.error("Failed permitted attributes check \n#{caller[0..-10].join("\n")}")
73
+ else
74
+ raise ActiveRecord::ForbiddenAttributes
75
+ end
76
+ end
77
+ assign_attributes_without_permitted(attributes)
78
+ end
79
+ end
80
+
81
+ == Compatibility
82
+
83
+ This gem only supports Rails 2
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'StrongParameters'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,145 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+ require 'action_controller'
3
+
4
+ module ActionController
5
+ class ParameterMissing < IndexError
6
+ attr_reader :param
7
+
8
+ def initialize(param)
9
+ @param = param
10
+ super("key not found: #{param}")
11
+ end
12
+ end
13
+
14
+ class Parameters < HashWithIndifferentAccess
15
+ attr_accessor :permitted
16
+ alias :permitted? :permitted
17
+
18
+ def initialize(attributes = nil)
19
+ super(attributes)
20
+ @permitted = false
21
+ end
22
+
23
+ def permit!
24
+ each_pair do |key, value|
25
+ convert_hashes_to_parameters(key, value)
26
+ self[key].permit! if self[key].respond_to? :permit!
27
+ end
28
+
29
+ @permitted = true
30
+ self
31
+ end
32
+
33
+ def require(key)
34
+ self[key].presence || raise(ActionController::ParameterMissing.new(key))
35
+ end
36
+
37
+ alias :required :require
38
+
39
+ def permit(*filters)
40
+ params = self.class.new
41
+
42
+ filters.each do |filter|
43
+ case filter
44
+ when Symbol, String then
45
+ params[filter] = self[filter] if has_key?(filter)
46
+ keys.grep(/\A#{Regexp.escape(filter.to_s)}\(\d+[if]?\)\z/).each { |key| params[key] = self[key] }
47
+ when Hash then
48
+ self.slice(*filter.keys).each do |key, value|
49
+ return unless value
50
+
51
+ key = key.to_sym
52
+
53
+ params[key] = each_element(value) do |value|
54
+ # filters are a Hash, so we expect value to be a Hash too
55
+ next if filter.is_a?(Hash) && !value.is_a?(Hash)
56
+
57
+ value = self.class.new(value) if !value.respond_to?(:permit)
58
+
59
+ value.permit(*Array.wrap(filter[key]))
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ params.permit!
66
+ end
67
+
68
+ def [](key)
69
+ convert_hashes_to_parameters(key, super)
70
+ end
71
+
72
+ def fetch(key, *args)
73
+ convert_hashes_to_parameters(key, super)
74
+ rescue KeyError, IndexError
75
+ raise ActionController::ParameterMissing.new(key)
76
+ end
77
+
78
+ def slice(*keys)
79
+ self.class.new(super).tap do |new_instance|
80
+ new_instance.instance_variable_set :@permitted, @permitted
81
+ end
82
+ end
83
+
84
+ def dup
85
+ duplicate = Parameters.new(self)
86
+ duplicate.instance_variable_set :@permitted, @permitted
87
+ duplicate
88
+ end
89
+
90
+ protected
91
+ def convert_value(value)
92
+ if value.class == Hash
93
+ self.class.new(value)
94
+ elsif value.is_a?(Array)
95
+ value.dup.replace(value.map { |e| convert_value(e) })
96
+ else
97
+ value
98
+ end
99
+ end
100
+
101
+ private
102
+ def convert_hashes_to_parameters(key, value)
103
+ if value.is_a?(Parameters) || !value.is_a?(Hash)
104
+ value
105
+ else
106
+ # Convert to Parameters on first access
107
+ self[key] = self.class.new(value)
108
+ end
109
+ end
110
+
111
+ def each_element(object)
112
+ if object.is_a?(Array)
113
+ object.map { |el| yield el }.compact
114
+ # fields_for on an array of records uses numeric hash keys
115
+ elsif object.is_a?(Hash) && object.keys.all? { |k| k =~ /\A-?\d+\z/ }
116
+ hash = object.class.new
117
+ object.each { |k,v| hash[k] = yield v }
118
+ hash
119
+ else
120
+ yield object
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ ActionController::Base
127
+ module ActionController
128
+ Base.class_eval do
129
+ rescue_from ActionController::ParameterMissing do |parameter_missing_exception|
130
+ render :text => "Required parameter missing: #{parameter_missing_exception.param}", :status => :bad_request
131
+ end
132
+
133
+ def params
134
+ if @_params.is_a?(Parameters)
135
+ @_params
136
+ else
137
+ @_params = Parameters.new(request.parameters)
138
+ end
139
+ end
140
+
141
+ def params=(val)
142
+ @_params = val.is_a?(Hash) ? Parameters.new(val) : val
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,22 @@
1
+ require 'active_record'
2
+
3
+ module ActiveRecord
4
+ class ForbiddenAttributes < StandardError
5
+ end
6
+
7
+ module ForbiddenAttributesProtection
8
+ private
9
+
10
+ def assign_attributes_with_permitted(attributes)
11
+ if !attributes.respond_to?(:permitted?) || attributes.permitted?
12
+ assign_attributes_without_permitted(attributes)
13
+ else
14
+ raise ActiveRecord::ForbiddenAttributes
15
+ end
16
+ end
17
+
18
+ def self.included(base)
19
+ base.alias_method_chain :assign_attributes, :permitted
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module StrongParameters
2
+ VERSION = "0.1.6.dev"
3
+ end
@@ -0,0 +1,2 @@
1
+ require 'action_controller/parameters'
2
+ require 'active_record/forbidden_attributes_protection'
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ class BooksController < ActionController::Base
4
+ def create
5
+ params.require(:book).require(:name)
6
+ head :ok
7
+ end
8
+ end
9
+
10
+ class ActionControllerRequiredParamsTest < ActionController::TestCase
11
+ tests BooksController
12
+
13
+ test "missing required parameters will raise exception" do
14
+ post :create, { :magazine => { :name => "Mjallo!" } }
15
+ assert_response :bad_request
16
+
17
+ post :create, { :book => { :title => "Mjallo!" } }
18
+ assert_response :bad_request
19
+ end
20
+
21
+ test "required parameters that are present will not raise" do
22
+ post :create, { :book => { :name => "Mjallo!" } }
23
+ assert_response :ok
24
+ end
25
+
26
+ test "missing parameters will be mentioned in the return" do
27
+ post :create, { :magazine => { :name => "Mjallo!" } }
28
+ assert_equal "Required parameter missing: book", response.body
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ require 'test_helper'
2
+
3
+ class PeopleController < ActionController::Base
4
+ def create
5
+ render :text => params[:person].permitted? ? "untainted" : "tainted"
6
+ end
7
+
8
+ def create_with_permit
9
+ render :text => params[:person].permit(:name).permitted? ? "untainted" : "tainted"
10
+ end
11
+ end
12
+
13
+ class ActionControllerTaintedParamsTest < ActionController::TestCase
14
+ tests PeopleController
15
+
16
+ test "parameters are tainted" do
17
+ post :create, { :person => { :name => "Mjallo!" } }
18
+ assert_equal "tainted", response.body
19
+ end
20
+
21
+ test "parameters can be permitted and are then not tainted" do
22
+ post :create_with_permit, { :person => { :name => "Mjallo!" } }
23
+ assert_equal "untainted", response.body
24
+ end
25
+ end
@@ -0,0 +1,50 @@
1
+ require 'test_helper'
2
+ require 'active_record/forbidden_attributes_protection'
3
+
4
+ ActiveRecord::Base.establish_connection(
5
+ :adapter => "sqlite3",
6
+ :database => ":memory:"
7
+ )
8
+
9
+ ActiveRecord::Schema.define(:version => 1) do
10
+ create_table :people do |t|
11
+ t.string :a
12
+ end
13
+ end
14
+
15
+ class Person < ActiveRecord::Base
16
+ include ActiveRecord::ForbiddenAttributesProtection
17
+ public :assign_attributes_with_permitted
18
+ end
19
+
20
+ class ActiveModelMassUpdateProtectionTest < ActiveSupport::TestCase
21
+ test "forbidden attributes cannot be used for mass updating via new" do
22
+ assert_raises(ActiveRecord::ForbiddenAttributes) do
23
+ Person.new(ActionController::Parameters.new(:a => "b"))
24
+ end
25
+ end
26
+
27
+ test "forbidden attributes cannot be used for mass updating via update_attributes" do
28
+ person = Person.create!
29
+ assert_raises(ActiveRecord::ForbiddenAttributes) do
30
+ person.update_attributes(ActionController::Parameters.new(:a => "b"))
31
+ end
32
+ end
33
+
34
+ test "forbidden attributes cannot be used for mass updating via attributes=" do
35
+ person = Person.new
36
+ assert_raises(ActiveRecord::ForbiddenAttributes) do
37
+ person.attributes = ActionController::Parameters.new(:a => "b")
38
+ end
39
+ end
40
+
41
+ test "permitted attributes can be used for mass updating" do
42
+ person = Person.new(ActionController::Parameters.new(:a => "b").permit(:a))
43
+ assert_equal({ "a" => "b" }, person.attributes.slice("a"))
44
+ end
45
+
46
+ test "regular attributes should still be allowed" do
47
+ person = Person.new(:a => "b")
48
+ assert_equal({ "a" => "b" }, person.attributes.slice("a"))
49
+ end
50
+ end
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+ require 'action_controller/parameters'
3
+
4
+ class MultiParameterAttributesTest < ActiveSupport::TestCase
5
+ test "permitted multi-parameter attribute keys" do
6
+ params = ActionController::Parameters.new({
7
+ :book => {
8
+ "shipped_at(1i)" => "2012",
9
+ "shipped_at(2i)" => "3",
10
+ "shipped_at(3i)" => "25",
11
+ "shipped_at(4i)" => "10",
12
+ "shipped_at(5i)" => "15",
13
+ "published_at(1i)" => "1999",
14
+ "published_at(2i)" => "2",
15
+ "published_at(3i)" => "5",
16
+ "price(1)" => "R$",
17
+ "price(2f)" => "2.02"
18
+ }
19
+ })
20
+
21
+ permitted = params.permit :book => [ :shipped_at, :price ]
22
+
23
+ assert permitted.permitted?
24
+
25
+ assert_equal "2012", permitted[:book]["shipped_at(1i)"]
26
+ assert_equal "3", permitted[:book]["shipped_at(2i)"]
27
+ assert_equal "25", permitted[:book]["shipped_at(3i)"]
28
+ assert_equal "10", permitted[:book]["shipped_at(4i)"]
29
+ assert_equal "15", permitted[:book]["shipped_at(5i)"]
30
+
31
+ assert_equal "R$", permitted[:book]["price(1)"]
32
+ assert_equal "2.02", permitted[:book]["price(2f)"]
33
+
34
+ assert_nil permitted[:book]["published_at(1i)"]
35
+ assert_nil permitted[:book]["published_at(2i)"]
36
+ assert_nil permitted[:book]["published_at(3i)"]
37
+ end
38
+ end
39
+
@@ -0,0 +1,131 @@
1
+ require 'test_helper'
2
+ require 'action_controller/parameters'
3
+
4
+ class NestedParametersTest < ActiveSupport::TestCase
5
+ test "permitted nested parameters" do
6
+ params = ActionController::Parameters.new({
7
+ :book => {
8
+ :title => "Romeo and Juliet",
9
+ :authors => [{
10
+ :name => "William Shakespeare",
11
+ :born => "1564-04-26"
12
+ }, {
13
+ :name => "Christopher Marlowe"
14
+ }],
15
+ :details => {
16
+ :pages => 200,
17
+ :genre => "Tragedy"
18
+ }
19
+ },
20
+ :magazine => "Mjallo!"
21
+ })
22
+
23
+ permitted = params.permit :book => [ :title, { :authors => [ :name ] }, { :details => :pages } ]
24
+
25
+ assert permitted.permitted?
26
+ assert_equal "Romeo and Juliet", permitted[:book][:title]
27
+ assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
28
+ assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]
29
+ assert_equal 200, permitted[:book][:details][:pages]
30
+ assert_nil permitted[:book][:details][:genre]
31
+ assert_nil permitted[:book][:authors][1][:born]
32
+ assert_nil permitted[:magazine]
33
+ end
34
+
35
+ test "nested arrays with strings" do
36
+ params = ActionController::Parameters.new({
37
+ :book => {
38
+ :genres => ["Tragedy"]
39
+ }
40
+ })
41
+
42
+ permitted = params.permit :book => :genres
43
+ assert_equal ["Tragedy"], permitted[:book][:genres]
44
+ end
45
+
46
+ test "permit may specify symbols or strings" do
47
+ params = ActionController::Parameters.new({
48
+ :book => {
49
+ :title => "Romeo and Juliet",
50
+ :author => "William Shakespeare"
51
+ },
52
+ :magazine => "Shakespeare Today"
53
+ })
54
+
55
+ permitted = params.permit({ :book => ["title", :author] }, "magazine")
56
+ assert_equal "Romeo and Juliet", permitted[:book][:title]
57
+ assert_equal "William Shakespeare", permitted[:book][:author]
58
+ assert_equal "Shakespeare Today", permitted[:magazine]
59
+ end
60
+
61
+ test "nested array with strings that should be hashes" do
62
+ params = ActionController::Parameters.new({
63
+ :book => {
64
+ :genres => ["Tragedy"]
65
+ }
66
+ })
67
+
68
+ permitted = params.permit :book => { :genres => :type }
69
+ assert permitted[:book][:genres].empty?
70
+ end
71
+
72
+ test "nested array with strings that should be hashes and additional values" do
73
+ params = ActionController::Parameters.new({
74
+ :book => {
75
+ :title => "Romeo and Juliet",
76
+ :genres => ["Tragedy"]
77
+ }
78
+ })
79
+
80
+ permitted = params.permit :book => [ :title, { :genres => :type } ]
81
+ assert_equal "Romeo and Juliet", permitted[:book][:title]
82
+ assert permitted[:book][:genres].empty?
83
+ end
84
+
85
+ test "nested string that should be a hash" do
86
+ params = ActionController::Parameters.new({
87
+ :book => {
88
+ :genre => "Tragedy"
89
+ }
90
+ })
91
+
92
+ permitted = params.permit :book => { :genre => :type }
93
+ assert_nil permitted[:book][:genre]
94
+ end
95
+
96
+ test "fields_for_style_nested_params" do
97
+ params = ActionController::Parameters.new({
98
+ :book => {
99
+ :authors_attributes => {
100
+ :'0' => { :name => 'William Shakespeare', :age_of_death => '52' },
101
+ :'1' => { :name => 'Unattributed Assistant' }
102
+ }
103
+ }
104
+ })
105
+ permitted = params.permit :book => { :authors_attributes => [ :name ] }
106
+
107
+ assert_not_nil permitted[:book][:authors_attributes]['0']
108
+ assert_not_nil permitted[:book][:authors_attributes]['1']
109
+ assert_nil permitted[:book][:authors_attributes]['0'][:age_of_death]
110
+ assert_equal 'William Shakespeare', permitted[:book][:authors_attributes]['0'][:name]
111
+ assert_equal 'Unattributed Assistant', permitted[:book][:authors_attributes]['1'][:name]
112
+ end
113
+
114
+ test "fields_for_style_nested_params with negative numbers" do
115
+ params = ActionController::Parameters.new({
116
+ :book => {
117
+ :authors_attributes => {
118
+ :'-1' => { :name => 'William Shakespeare', :age_of_death => '52' },
119
+ :'-2' => { :name => 'Unattributed Assistant' }
120
+ }
121
+ }
122
+ })
123
+ permitted = params.permit :book => { :authors_attributes => [:name] }
124
+
125
+ assert_not_nil permitted[:book][:authors_attributes]['-1']
126
+ assert_not_nil permitted[:book][:authors_attributes]['-2']
127
+ assert_nil permitted[:book][:authors_attributes]['-1'][:age_of_death]
128
+ assert_equal 'William Shakespeare', permitted[:book][:authors_attributes]['-1'][:name]
129
+ assert_equal 'Unattributed Assistant', permitted[:book][:authors_attributes]['-2'][:name]
130
+ end
131
+ end
@@ -0,0 +1,10 @@
1
+ require 'test_helper'
2
+ require 'action_controller/parameters'
3
+
4
+ class ParametersRequireTest < ActiveSupport::TestCase
5
+ test "required parameters must be present not merely not nil" do
6
+ assert_raises(ActionController::ParameterMissing) do
7
+ ActionController::Parameters.new(:person => {}).require(:person)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,93 @@
1
+ require 'test_helper'
2
+ require 'action_controller/parameters'
3
+
4
+ class ParametersTaintTest < ActiveSupport::TestCase
5
+ def setup
6
+ @params = ActionController::Parameters.new({ :person => {
7
+ :age => "32", :name => { :first => "David", :last => "Heinemeier Hansson" }
8
+ }})
9
+ end
10
+
11
+ test "fetch raises ParameterMissing exception" do
12
+ e = assert_raises(ActionController::ParameterMissing) do
13
+ @params.fetch :foo
14
+ end
15
+ assert_equal :foo, e.param
16
+ end
17
+
18
+ test "fetch doesnt raise ParameterMissing exception if there is a default" do
19
+ assert_nothing_raised do
20
+ assert_equal "monkey", @params.fetch(:foo, "monkey")
21
+ assert_equal "monkey", @params.fetch(:foo) { "monkey" }
22
+ end
23
+ end
24
+
25
+ test "not permitted is sticky on accessors" do
26
+ assert !@params.slice(:person).permitted?
27
+ assert !@params[:person][:name].permitted?
28
+ assert !@params[:person].except(:name).permitted?
29
+
30
+ @params.each { |key, value| assert(!value.permitted?) if key == "person" }
31
+
32
+ assert !@params.fetch(:person).permitted?
33
+
34
+ assert !@params.values_at(:person).first.permitted?
35
+ end
36
+
37
+ test "permitted is sticky on accessors" do
38
+ @params.permit!
39
+ assert @params.slice(:person).permitted?
40
+ assert @params[:person][:name].permitted?
41
+ assert @params[:person].except(:name).permitted?
42
+
43
+ @params.each { |key, value| assert(value.permitted?) if key == "person" }
44
+
45
+ assert @params.fetch(:person).permitted?
46
+
47
+ assert @params.values_at(:person).first.permitted?
48
+ end
49
+
50
+ test "not permitted is sticky on mutators" do
51
+ assert !@params.delete_if { |k, v| k == "person" }.permitted?
52
+ assert !@params.keep_if { |k, v| k == "person" }.permitted? if @params.respond_to?(:keep_if)
53
+ end
54
+
55
+ test "permitted is sticky on mutators" do
56
+ @params.permit!
57
+ assert @params.delete_if { |k, v| k == "person" }.permitted?
58
+ assert @params.keep_if { |k, v| k == "person" }.permitted? if @params.respond_to?(:keep_if)
59
+ end
60
+
61
+ test "not permitted is sticky beyond merges" do
62
+ assert !@params.merge(:a => "b").permitted?
63
+ end
64
+
65
+ test "permitted is sticky beyond merges" do
66
+ @params.permit!
67
+ assert @params.merge(:a => "b").permitted?
68
+ end
69
+
70
+ test "modifying the parameters" do
71
+ @params[:person][:hometown] = "Chicago"
72
+ @params[:person][:family] = { :brother => "Jonas" }
73
+
74
+ assert_equal "Chicago", @params[:person][:hometown]
75
+ assert_equal "Jonas", @params[:person][:family][:brother]
76
+ end
77
+
78
+ test "permitting parameters that are not there should not include the keys" do
79
+ assert !@params.permit(:person, :funky).has_key?(:funky)
80
+ end
81
+
82
+ test "permit state is kept on a dup" do
83
+ @params.permit!
84
+ assert_equal @params.permitted?, @params.dup.permitted?
85
+ end
86
+
87
+ test "permit is recursive" do
88
+ @params.permit!
89
+ assert @params.permitted?
90
+ assert @params[:person].permitted?
91
+ assert @params[:person][:name].permitted?
92
+ end
93
+ end
@@ -0,0 +1,18 @@
1
+ # Configure Rails Environment
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require 'test/unit'
5
+ require 'strong_parameters'
6
+ require 'mocha'
7
+ require 'active_support/test_case'
8
+ require 'action_controller/test_process'
9
+
10
+ ActionController::Routing::Routes.reload rescue nil
11
+
12
+ MissingSourceFile::REGEXPS << [/^cannot load such file -- (.+)$/i, 1]
13
+
14
+ ActionController::TestCase.class_eval do
15
+ def response
16
+ @response
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: strong_parameters_rails2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.6.dev
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Michael Grosser
9
+ - David Heinemeier Hansson
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-11-16 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: actionpack
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '2.3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '2.3'
31
+ - !ruby/object:Gem::Dependency
32
+ name: activerecord
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '2.3'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '2.3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: mocha
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: sqlite3
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ description:
96
+ email:
97
+ - michael@grosser.it
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - lib/action_controller/parameters.rb
103
+ - lib/active_record/forbidden_attributes_protection.rb
104
+ - lib/strong_parameters/version.rb
105
+ - lib/strong_parameters.rb
106
+ - MIT-LICENSE
107
+ - Rakefile
108
+ - README.rdoc
109
+ - test/action_controller_required_params_test.rb
110
+ - test/action_controller_tainted_params_test.rb
111
+ - test/active_record_mass_assignment_taint_protection_test.rb
112
+ - test/multi_parameter_attributes_test.rb
113
+ - test/nested_parameters_test.rb
114
+ - test/parameters_require_test.rb
115
+ - test/parameters_taint_test.rb
116
+ - test/test_helper.rb
117
+ homepage:
118
+ licenses:
119
+ - MIT
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ segments:
131
+ - 0
132
+ hash: 1783000803371322275
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>'
137
+ - !ruby/object:Gem::Version
138
+ version: 1.3.1
139
+ requirements: []
140
+ rubyforge_project:
141
+ rubygems_version: 1.8.24
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: Permitted and required parameters for Action Pack
145
+ test_files:
146
+ - test/action_controller_required_params_test.rb
147
+ - test/action_controller_tainted_params_test.rb
148
+ - test/active_record_mass_assignment_taint_protection_test.rb
149
+ - test/multi_parameter_attributes_test.rb
150
+ - test/nested_parameters_test.rb
151
+ - test/parameters_require_test.rb
152
+ - test/parameters_taint_test.rb
153
+ - test/test_helper.rb