protected_attributes 1.0.8 → 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -1
- data/lib/active_model/mass_assignment_security.rb +3 -3
- data/lib/active_model/mass_assignment_security/sanitizer.rb +1 -1
- data/lib/active_record/mass_assignment_security/associations.rb +16 -0
- data/lib/active_record/mass_assignment_security/persistence.rb +4 -2
- data/lib/active_record/mass_assignment_security/reflection.rb +11 -3
- data/lib/protected_attributes.rb +1 -1
- data/lib/protected_attributes/railtie.rb +0 -2
- data/lib/protected_attributes/version.rb +1 -1
- data/test/ar_helper.rb +1 -0
- data/test/attribute_sanitization_test.rb +113 -2
- data/test/mass_assignment_security_test.rb +0 -24
- data/test/models/pirate.rb +1 -1
- data/test/test_helper.rb +1 -0
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07a8c210afe27e08b760e2f61b86a60c6980ec1a
|
4
|
+
data.tar.gz: cb8ef9666fc6b0a73161f1d06a0cfd097edfc7cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6c29a159034c283fd0e77c2b5ddf1469655bce17916e801668d01e8e104c6e4142621c01c75966f0333413c0d7e7179b8c22aa4bf8a03966f0a71334850316b
|
7
|
+
data.tar.gz: d9e314e1e6b925ba6a34fb68b813999c1ffa00d29e4b32ca59eb8f523e35102d5c3098606410ae5cd702756737a1f0bacfa3d3e6b2d6ac01c1388c1bd42df771
|
data/README.md
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# ProtectedAttributes
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/rails/protected_attributes.
|
3
|
+
[![Build Status](https://api.travis-ci.org/rails/protected_attributes.svg?branch=master)](https://travis-ci.org/rails/protected_attributes)
|
4
4
|
|
5
5
|
Protect attributes from mass-assignment in ActiveRecord models.
|
6
6
|
|
7
7
|
This plugin adds `attr_accessible` and `attr_protected` in your models.
|
8
8
|
|
9
|
+
Note: This plugin will be officially supported until the release of Rails 5.0
|
10
|
+
|
9
11
|
## Installation
|
10
12
|
|
11
13
|
Add this line to your application's Gemfile:
|
@@ -105,6 +107,18 @@ class AccountsController < ApplicationController
|
|
105
107
|
end
|
106
108
|
end
|
107
109
|
```
|
110
|
+
|
111
|
+
### Errors
|
112
|
+
|
113
|
+
By default, errors will not be raised if the user passes attributes in the params hash which are not allowed to be updated.
|
114
|
+
If you want the functionality where exceptions (`ActiveModel::MassAssignmentSecurity::Error`) are raised. Add to your config
|
115
|
+
the strict flag:
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
config.active_record.mass_assignment_sanitizer = :strict
|
119
|
+
```
|
120
|
+
|
121
|
+
|
108
122
|
## Contributing
|
109
123
|
|
110
124
|
1. Fork it
|
@@ -206,7 +206,7 @@ module ActiveModel
|
|
206
206
|
# end
|
207
207
|
#
|
208
208
|
# Customer.protected_attributes
|
209
|
-
# #
|
209
|
+
# # => #<ActiveModel::MassAssignmentSecurity::BlackList: {"logins_count"}>
|
210
210
|
#
|
211
211
|
# Customer.protected_attributes(:default)
|
212
212
|
# # => #<ActiveModel::MassAssignmentSecurity::BlackList: {"logins_count"}>
|
@@ -255,10 +255,10 @@ module ActiveModel
|
|
255
255
|
# end
|
256
256
|
#
|
257
257
|
# Customer.active_authorizers
|
258
|
-
# #
|
258
|
+
# # => {
|
259
259
|
# # :admin=> #<ActiveModel::MassAssignmentSecurity::WhiteList: {"name", "credit_rating"}>,
|
260
260
|
# # :default=>#<ActiveModel::MassAssignmentSecurity::WhiteList: {"name"}>
|
261
|
-
# #
|
261
|
+
# # }
|
262
262
|
def active_authorizers
|
263
263
|
self._active_authorizer ||= protected_attributes_configs
|
264
264
|
end
|
@@ -65,6 +65,22 @@ module ActiveRecord
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
module ThroughAssociation
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def build_record(attributes, options={})
|
73
|
+
inverse = source_reflection.inverse_of
|
74
|
+
target = through_association.target
|
75
|
+
|
76
|
+
if inverse && target && !target.is_a?(Array)
|
77
|
+
attributes[inverse.foreign_key] = target.id
|
78
|
+
end
|
79
|
+
|
80
|
+
super(attributes, options)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
68
84
|
class HasManyThroughAssociation
|
69
85
|
def build_record(attributes, options = {})
|
70
86
|
ensure_not_nested
|
@@ -57,7 +57,7 @@ module ActiveRecord
|
|
57
57
|
# If no +:as+ option is supplied then the +:default+ role will be used.
|
58
58
|
# If you want to bypass the forbidden attributes protection then you can do so using
|
59
59
|
# the +:without_protection+ option.
|
60
|
-
def
|
60
|
+
def update(attributes, options = {})
|
61
61
|
# The following transaction covers any possible database side-effects of the
|
62
62
|
# attributes assignment. For example, setting the IDs of a child collection.
|
63
63
|
with_transaction_returning_status do
|
@@ -65,10 +65,11 @@ module ActiveRecord
|
|
65
65
|
save
|
66
66
|
end
|
67
67
|
end
|
68
|
+
alias :update_attributes :update
|
68
69
|
|
69
70
|
# Updates its receiver just like +update_attributes+ but calls <tt>save!</tt> instead
|
70
71
|
# of +save+, so an exception is raised if the record is invalid.
|
71
|
-
def
|
72
|
+
def update!(attributes, options = {})
|
72
73
|
# The following transaction covers any possible database side-effects of the
|
73
74
|
# attributes assignment. For example, setting the IDs of a child collection.
|
74
75
|
with_transaction_returning_status do
|
@@ -76,6 +77,7 @@ module ActiveRecord
|
|
76
77
|
save!
|
77
78
|
end
|
78
79
|
end
|
80
|
+
alias :update_attributes! :update!
|
79
81
|
end
|
80
82
|
end
|
81
83
|
end
|
@@ -1,8 +1,16 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Reflection
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
if defined?(AbstractReflection)
|
4
|
+
class AbstractReflection
|
5
|
+
def build_association(*options, &block)
|
6
|
+
klass.new(*options, &block)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
else
|
10
|
+
class AssociationReflection
|
11
|
+
def build_association(*options, &block)
|
12
|
+
klass.new(*options, &block)
|
13
|
+
end
|
6
14
|
end
|
7
15
|
end
|
8
16
|
end
|
data/lib/protected_attributes.rb
CHANGED
data/test/ar_helper.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'ar_helper'
|
3
3
|
require 'active_record/mass_assignment_security'
|
4
|
+
require 'models/battle'
|
4
5
|
require 'models/company'
|
5
|
-
require 'models/
|
6
|
+
require 'models/group'
|
6
7
|
require 'models/keyboard'
|
7
|
-
require 'models/
|
8
|
+
require 'models/membership'
|
8
9
|
require 'models/person'
|
10
|
+
require 'models/pirate'
|
11
|
+
require 'models/subscriber'
|
12
|
+
require 'models/task'
|
13
|
+
require 'models/team'
|
14
|
+
require 'models/vampire'
|
15
|
+
require 'models/wolf'
|
9
16
|
|
10
17
|
module MassAssignmentTestHelpers
|
11
18
|
def teardown
|
@@ -276,6 +283,86 @@ class AttributeSanitizationTest < ActiveSupport::TestCase
|
|
276
283
|
def test_new_with_unrelated_inheritance_column_class
|
277
284
|
assert_raise(ActiveRecord::SubclassNotFound) { Corporation.new(type: "Person") }
|
278
285
|
end
|
286
|
+
|
287
|
+
def test_update_attributes_as_admin
|
288
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
289
|
+
person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
|
290
|
+
person.reload
|
291
|
+
|
292
|
+
assert_equal 'Josh', person.first_name
|
293
|
+
assert_equal 'm', person.gender
|
294
|
+
assert_equal 'from NZ', person.comments
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_update_attributes_without_protection
|
298
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
299
|
+
person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
|
300
|
+
person.reload
|
301
|
+
|
302
|
+
assert_equal 'Josh', person.first_name
|
303
|
+
assert_equal 'm', person.gender
|
304
|
+
assert_equal 'from NZ', person.comments
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_update_attributes_with_bang_as_admin
|
308
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
309
|
+
person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
|
310
|
+
person.reload
|
311
|
+
|
312
|
+
assert_equal 'Josh', person.first_name
|
313
|
+
assert_equal 'm', person.gender
|
314
|
+
assert_equal 'from NZ', person.comments
|
315
|
+
end
|
316
|
+
|
317
|
+
def test_update_attributes_with_bang_without_protection
|
318
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
319
|
+
person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
|
320
|
+
person.reload
|
321
|
+
|
322
|
+
assert_equal 'Josh', person.first_name
|
323
|
+
assert_equal 'm', person.gender
|
324
|
+
assert_equal 'from NZ', person.comments
|
325
|
+
end
|
326
|
+
|
327
|
+
def test_update_as_admin
|
328
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
329
|
+
person.update({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
|
330
|
+
person.reload
|
331
|
+
|
332
|
+
assert_equal 'Josh', person.first_name
|
333
|
+
assert_equal 'm', person.gender
|
334
|
+
assert_equal 'from NZ', person.comments
|
335
|
+
end
|
336
|
+
|
337
|
+
def test_update_without_protection
|
338
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
339
|
+
person.update({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
|
340
|
+
person.reload
|
341
|
+
|
342
|
+
assert_equal 'Josh', person.first_name
|
343
|
+
assert_equal 'm', person.gender
|
344
|
+
assert_equal 'from NZ', person.comments
|
345
|
+
end
|
346
|
+
|
347
|
+
def test_update_with_bang_as_admin
|
348
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
349
|
+
person.update!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
|
350
|
+
person.reload
|
351
|
+
|
352
|
+
assert_equal 'Josh', person.first_name
|
353
|
+
assert_equal 'm', person.gender
|
354
|
+
assert_equal 'from NZ', person.comments
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_update_with_bang_without_protection
|
358
|
+
person = TightPerson.create({ "first_name" => 'Joshua' })
|
359
|
+
person.update!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
|
360
|
+
person.reload
|
361
|
+
|
362
|
+
assert_equal 'Josh', person.first_name
|
363
|
+
assert_equal 'm', person.gender
|
364
|
+
assert_equal 'from NZ', person.comments
|
365
|
+
end
|
279
366
|
end
|
280
367
|
|
281
368
|
|
@@ -595,6 +682,12 @@ class MassAssignmentSecurityHasManyRelationsTest < ActiveSupport::TestCase
|
|
595
682
|
end
|
596
683
|
end
|
597
684
|
|
685
|
+
def test_has_many_through_build_with_attr_accessible_attributes
|
686
|
+
group = Group.create!
|
687
|
+
pirate = group.members.build(name: "Murphy")
|
688
|
+
assert_equal "Murphy", pirate.name
|
689
|
+
end
|
690
|
+
|
598
691
|
# new
|
599
692
|
|
600
693
|
def test_has_many_new_with_attr_protected_attributes
|
@@ -697,6 +790,24 @@ class MassAssignmentSecurityHasManyRelationsTest < ActiveSupport::TestCase
|
|
697
790
|
end
|
698
791
|
end
|
699
792
|
|
793
|
+
# concat
|
794
|
+
|
795
|
+
def test_concat_has_many_through_association_member
|
796
|
+
group = Group.create!
|
797
|
+
pirate = Pirate.create!
|
798
|
+
group.members << pirate
|
799
|
+
assert_equal pirate.memberships.first, group.memberships.first
|
800
|
+
end
|
801
|
+
|
802
|
+
def test_concat_has_many_through_polymorphic_association
|
803
|
+
team = Team.create!
|
804
|
+
vampire = Vampire.create!
|
805
|
+
wolf = Wolf.create!
|
806
|
+
|
807
|
+
team.vampire_battles << vampire
|
808
|
+
wolf.teams << team
|
809
|
+
assert_equal team.wolf_battles.first, wolf
|
810
|
+
end
|
700
811
|
end
|
701
812
|
|
702
813
|
|
@@ -1,13 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'active_model/mass_assignment_security'
|
3
3
|
require 'models/mass_assignment_specific'
|
4
|
-
require 'models/pirate'
|
5
|
-
require 'models/group'
|
6
|
-
require 'models/membership'
|
7
|
-
require 'models/battle'
|
8
|
-
require 'models/vampire'
|
9
|
-
require 'models/wolf'
|
10
|
-
require 'models/team'
|
11
4
|
|
12
5
|
class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
|
13
6
|
|
@@ -122,21 +115,4 @@ class MassAssignmentSecurityTest < ActiveModel::TestCase
|
|
122
115
|
ensure
|
123
116
|
User.mass_assignment_sanitizer = old_sanitizer
|
124
117
|
end
|
125
|
-
|
126
|
-
def test_concat_has_many_through_association_member
|
127
|
-
group = Group.create!
|
128
|
-
pirate = Pirate.create!
|
129
|
-
group.members << pirate
|
130
|
-
assert_equal pirate.memberships.first, group.memberships.first
|
131
|
-
end
|
132
|
-
|
133
|
-
def test_concat_has_many_through_polymorphic_association
|
134
|
-
team = Team.create!
|
135
|
-
vampire = Vampire.create!
|
136
|
-
wolf = Wolf.create!
|
137
|
-
|
138
|
-
team.vampire_battles << vampire
|
139
|
-
wolf.teams << team
|
140
|
-
assert_equal team.wolf_battles.first, wolf
|
141
|
-
end
|
142
118
|
end
|
data/test/models/pirate.rb
CHANGED
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protected_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -70,6 +70,26 @@ dependencies:
|
|
70
70
|
- - "<"
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: '5.0'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: railties
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 4.0.1
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.0'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 4.0.1
|
90
|
+
- - "<"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '5.0'
|
73
93
|
- !ruby/object:Gem::Dependency
|
74
94
|
name: sqlite3
|
75
95
|
requirement: !ruby/object:Gem::Requirement
|
@@ -167,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
187
|
version: '0'
|
168
188
|
requirements: []
|
169
189
|
rubyforge_project:
|
170
|
-
rubygems_version: 2.
|
190
|
+
rubygems_version: 2.4.5
|
171
191
|
signing_key:
|
172
192
|
specification_version: 4
|
173
193
|
summary: Protect attributes from mass assignment in Active Record models
|