protected_attributes_continued 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE.txt +1 -1
- data/README.md +46 -6
- data/lib/active_record/mass_assignment_security/associations.rb +2 -1
- data/lib/active_record/mass_assignment_security/inheritance.rb +28 -7
- data/lib/active_record/mass_assignment_security/nested_attributes.rb +12 -2
- data/lib/active_record/mass_assignment_security/relation.rb +29 -0
- data/lib/protected_attributes/version.rb +1 -1
- metadata +26 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8e01eccbad4a21cdd10334379dc742f0edc97dd8a6b99b03e8d1e105d5a159a4
|
4
|
+
data.tar.gz: e41d9f31ea96a9ed1edbc30063ac258f820452554d64d58f6ce0e2945027e74c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9317411a772594accc0cbc59ca0c07a755b58f1b0c1b6553d5843cb37b6e7f3ec0defb4b5e84686a8564fafff6bb43cd803768fe230dd8b990ee236aa1281620
|
7
|
+
data.tar.gz: 608d732479681ce5d90a231e8f44862e54a7cb0a6ce323088c90f6dc22b52eaa85a0a7e471ee5cbe8979d6514f9f45be3fb6533a4def88dfcd2ae8a12a1ca13c
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# Protected Attributes Continued
|
2
|
+
<a href="https://badge.fury.io/rb/protected_attributes_continued" target="_blank"><img height="21" style='border:0px;height:21px;' border='0' src="https://badge.fury.io/rb/protected_attributes_continued.svg" alt="Gem Version"></a>
|
3
|
+
<a href='https://travis-ci.org/westonganger/protected_attributes_continued' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://api.travis-ci.org/westonganger/protected_attributes_continued.svg?branch=master' border='0' alt='Build Status' /></a>
|
4
|
+
<a href='https://rubygems.org/gems/protected_attributes_continued' target='_blank'><img height='21' style='border:0px;height:21px;' src='https://ruby-gem-downloads-badge.herokuapp.com/protected_attributes_continued?label=rubygems&type=total&total_label=downloads&color=brightgreen' border='0' alt='RubyGems Downloads' /></a>
|
2
5
|
|
3
|
-
|
4
|
-
|
5
|
-
This is the community continued version of `protected_attributes`. It works with Rails 5 only and I recommend you only use it to support legacy portions of your application that you do not want to upgrade. Note that this feature was dropped by the Rails team and switched to strong_parameters because of security issues, just so you understand your risks. This is in use successfully in some of my Rails 5 apps in which security like this is a non-issue. For people who would like to continue using this feature in their Rails 5 apps lets continue the work here.
|
6
|
+
This is the community continued version of `protected_attributes`. It works with Rails 5+ only and I recommend you only use it to support legacy portions of your application that you do not want to upgrade. Note that this feature was dropped by the Rails team and switched to strong_parameters because of security issues, just so you understand your risks. This is in use successfully in some of my Rails 5 apps in which security like this is a non-issue. For people who would like to continue using this feature in their Rails 5 apps lets continue the work here. If you are looking for a similar approach see my [recommended alternative](https://github.com/westonganger/protected_attributes_continued#a-better-alternative)
|
6
7
|
|
7
8
|
Protect attributes from mass-assignment in Active Record models.
|
8
9
|
|
@@ -98,10 +99,49 @@ config.active_record.mass_assignment_sanitizer = :strict
|
|
98
99
|
Any protected attributes violation raises `ActiveModel::MassAssignmentSecurity::Error` then.
|
99
100
|
|
100
101
|
|
101
|
-
|
102
|
+
## Contributing
|
103
|
+
|
104
|
+
We use the `appraisal` gem for testing multiple versions of `Rails`. Please use the following steps to test using `appraisal`.
|
105
|
+
|
106
|
+
1. `bundle exec appraisal install`
|
107
|
+
2. `bundle exec appraisal rake test`
|
102
108
|
|
103
|
-
|
109
|
+
## Credits
|
110
|
+
|
111
|
+
Created & Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
|
104
112
|
|
105
113
|
Originally forked from the dead/unmaintained `protected_attributes` gem by the Rails team.
|
106
114
|
|
107
|
-
|
115
|
+
## A Better Alternative
|
116
|
+
|
117
|
+
While I do utilize this gem in some legacy projects I have adopted an alternative approach that is similar to this gem but only utilizes Rails built-in `strong_params` which is a much more future proof way of doing things. See the following example for how to implement.
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
class Post < ActiveRecord::Base
|
121
|
+
|
122
|
+
def self.strong_params(params)
|
123
|
+
params.permit(:post).permit(:name, :content, :published_at)
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
class PostsController < ApplicationController
|
129
|
+
|
130
|
+
def create
|
131
|
+
@post = Post.new
|
132
|
+
|
133
|
+
@post.assign_attributes(Post.strong_params(params))
|
134
|
+
|
135
|
+
respond_with @post
|
136
|
+
end
|
137
|
+
|
138
|
+
def update
|
139
|
+
@post = Post.find(params[:id])
|
140
|
+
|
141
|
+
@post.update(Post.strong_params(params))
|
142
|
+
|
143
|
+
respond_with @post
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
```
|
@@ -5,7 +5,8 @@ module ActiveRecord
|
|
5
5
|
|
6
6
|
def build_record(attributes, options)
|
7
7
|
reflection.build_association(attributes, options) do |record|
|
8
|
-
|
8
|
+
the_scope = (ActiveRecord::VERSION::STRING.to_f >= 5.2 ? scope_for_create : create_scope)
|
9
|
+
attributes = the_scope.except(*(record.changed - [reflection.foreign_key]))
|
9
10
|
record.assign_attributes(attributes, without_protection: true)
|
10
11
|
end
|
11
12
|
end
|
@@ -4,20 +4,41 @@ module ActiveRecord
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
module ClassMethods
|
7
|
-
|
7
|
+
|
8
8
|
private
|
9
9
|
|
10
10
|
# Detect the subclass from the inheritance column of attrs. If the inheritance column value
|
11
11
|
# is not self or a valid subclass, raises ActiveRecord::SubclassNotFound
|
12
|
-
|
13
|
-
# this will ignore the inheritance column and return nil
|
14
|
-
def subclass_from_attributes?(attrs)
|
12
|
+
def subclass_from_attributes(attrs)
|
15
13
|
active_authorizer[:default].deny?(inheritance_column) ? nil : super
|
16
14
|
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
module ActiveRecord
|
21
|
+
module Inheritance
|
22
|
+
module ClassMethods
|
23
|
+
undef :new
|
24
|
+
|
25
|
+
def new(attributes = nil, options = {}, &block)
|
26
|
+
if abstract_class? || self == Base
|
27
|
+
raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
|
28
|
+
end
|
29
|
+
|
30
|
+
if has_attribute?(inheritance_column)
|
31
|
+
subclass = subclass_from_attributes(attributes)
|
32
|
+
|
33
|
+
if respond_to?(:column_defaults) && subclass.nil? && base_class == self
|
34
|
+
subclass = subclass_from_attributes(column_defaults)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if subclass && subclass != self
|
39
|
+
subclass.new(attributes, options, &block)
|
40
|
+
else
|
41
|
+
super
|
21
42
|
end
|
22
43
|
end
|
23
44
|
end
|
@@ -15,7 +15,11 @@ module ActiveRecord
|
|
15
15
|
|
16
16
|
attr_names.each do |association_name|
|
17
17
|
if reflection = reflect_on_association(association_name)
|
18
|
-
|
18
|
+
if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0
|
19
|
+
reflection.options[:autosave] = true
|
20
|
+
else
|
21
|
+
reflection.autosave = true
|
22
|
+
end
|
19
23
|
add_autosave_association_callbacks(reflection)
|
20
24
|
|
21
25
|
nested_attributes_options = self.nested_attributes_options.dup
|
@@ -24,7 +28,7 @@ module ActiveRecord
|
|
24
28
|
|
25
29
|
type = (reflection.collection? ? :collection : :one_to_one)
|
26
30
|
|
27
|
-
generated_methods_module = generated_association_methods
|
31
|
+
generated_methods_module = (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0) ? generated_feature_methods : generated_association_methods
|
28
32
|
|
29
33
|
# def pirate_attributes=(attributes)
|
30
34
|
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes, mass_assignment_options)
|
@@ -50,6 +54,12 @@ module ActiveRecord
|
|
50
54
|
|
51
55
|
def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {})
|
52
56
|
options = self.nested_attributes_options[association_name]
|
57
|
+
if attributes.class.name == 'ActionController::Parameters'
|
58
|
+
attributes = attributes.to_unsafe_h
|
59
|
+
elsif !attributes.is_a?(Hash) && !attributes.is_a?(Array)
|
60
|
+
raise ArgumentError, "ActionController::Parameters or Hash or Array expected, got #{attributes.class.name} (#{attributes.inspect})"
|
61
|
+
end
|
62
|
+
|
53
63
|
attributes = attributes.with_indifferent_access
|
54
64
|
|
55
65
|
if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) &&
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
class Relation
|
3
|
+
undef :new
|
4
|
+
undef :create
|
5
|
+
undef :create!
|
3
6
|
undef :first_or_create
|
4
7
|
undef :first_or_create!
|
5
8
|
undef :first_or_initialize
|
@@ -7,6 +10,32 @@ module ActiveRecord
|
|
7
10
|
undef :find_or_create_by
|
8
11
|
undef :find_or_create_by!
|
9
12
|
|
13
|
+
def new(attributes = nil, options = {}, &block)
|
14
|
+
attrs = respond_to?(:values_for_create) ? values_for_create(attributes) : attributes
|
15
|
+
|
16
|
+
scoping { klass.new(attrs, options, &block) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def create(attributes = nil, options = {}, &block)
|
20
|
+
if attributes.is_a?(Array)
|
21
|
+
attributes.collect { |attr| create(attr, options, &block) }
|
22
|
+
else
|
23
|
+
attrs = respond_to?(:values_for_create) ? values_for_create(attributes) : attributes
|
24
|
+
|
25
|
+
scoping { klass.create(attrs, options, &block) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def create!(attributes = nil, options = {}, &block)
|
30
|
+
if attributes.is_a?(Array)
|
31
|
+
attributes.collect { |attr| create!(attr, options, &block) }
|
32
|
+
else
|
33
|
+
attrs = respond_to?(:values_for_create) ? values_for_create(attributes) : attributes
|
34
|
+
|
35
|
+
scoping { klass.create!(attrs, options, &block) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
10
39
|
# Tries to load the first record; if it fails, then <tt>create</tt> is called with the same arguments as this method.
|
11
40
|
#
|
12
41
|
# Expects arguments in the same format as +Base.create+.
|
metadata
CHANGED
@@ -1,69 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protected_attributes_continued
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Weston Ganger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '5.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activerecord
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '5.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '5.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: actionpack
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '5.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: railties
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '5.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '5.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
@@ -82,6 +82,20 @@ dependencies:
|
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: mocha
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.4.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.4.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: appraisal
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - ">="
|
@@ -96,7 +110,7 @@ dependencies:
|
|
96
110
|
version: '0'
|
97
111
|
description: Protect attributes from mass assignment
|
98
112
|
email:
|
99
|
-
- westonganger
|
113
|
+
- weston@westonganger.com
|
100
114
|
executables: []
|
101
115
|
extensions: []
|
102
116
|
extra_rdoc_files: []
|
@@ -140,8 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
154
|
- !ruby/object:Gem::Version
|
141
155
|
version: '0'
|
142
156
|
requirements: []
|
143
|
-
|
144
|
-
rubygems_version: 2.6.8
|
157
|
+
rubygems_version: 3.0.1
|
145
158
|
signing_key:
|
146
159
|
specification_version: 4
|
147
160
|
summary: Protect attributes from mass assignment in Active Record models
|