protected_attributes_continued 1.4.0 → 1.8.1
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.
- checksums.yaml +4 -4
- data/README.md +29 -17
- data/lib/active_record/mass_assignment_security.rb +1 -0
- data/lib/active_record/mass_assignment_security/association_relation.rb +45 -0
- data/lib/active_record/mass_assignment_security/associations.rb +31 -15
- data/lib/active_record/mass_assignment_security/attribute_assignment.rb +11 -3
- data/lib/active_record/mass_assignment_security/core.rb +1 -0
- data/lib/active_record/mass_assignment_security/nested_attributes.rb +8 -2
- data/lib/protected_attributes/version.rb +1 -1
- metadata +4 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e881236bacf8378d98f06eb98269417a5082383de65360f522e524062fbcdfb
|
4
|
+
data.tar.gz: 45f598ce1954ed9542934e676af3ac8f53e6b5c6dea2c35e87b3100721d2522a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30fb108c2db47feeb17c7787dc1427a44e93b7ac47450d79f20d59a3bf814d3f8314eb42ee71a76bd3e1f54dbec508d56e917ab0f57d5a6c7c7e5a68a4ac2d8d
|
7
|
+
data.tar.gz: '0486645654d15f177a2ba9abd27069c598b9d08884a7beb4db9d7813ce79604265d0eab9263f937aa0957c963cbd66dc435d4628993381793789068d04d0573b'
|
data/README.md
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
# Protected Attributes Continued
|
2
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://
|
3
|
+
<a href='https://github.com/westonganger/protected_attributes_continued/actions' target='_blank'><img src="https://github.com/westonganger/protected_attributes_continued/workflows/Tests/badge.svg" style="max-width:100%;" height='21' style='border:0px;height:21px;' border='0' alt="CI Status"></a>
|
4
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>
|
5
5
|
|
6
|
-
This is the community continued version of `protected_attributes
|
6
|
+
> This is the community continued version of [`protected_attributes`](https://github.com/rails/protected_attributes) for Rails 5+. The Rails team dropped this feature and switched to `strong_parameters`. However some applications simply cannot be upgraded or the reduced granularity in params management is a non-issue. To continue supporting this feature going forward we continue the work here.
|
7
7
|
|
8
|
-
Protect attributes from mass-assignment in Active Record models.
|
9
|
-
|
10
|
-
This plugin adds the class methods `attr_accessible` and `attr_protected` to your models to be able to declare white or black lists of attributes.
|
8
|
+
Protect attributes from mass-assignment in Active Record models. This gem adds the class methods `attr_accessible` and `attr_protected` to declare white or black lists of attributes.
|
11
9
|
|
12
10
|
|
13
11
|
## Installation
|
@@ -98,10 +96,11 @@ config.active_record.mass_assignment_sanitizer = :strict
|
|
98
96
|
|
99
97
|
Any protected attributes violation raises `ActiveModel::MassAssignmentSecurity::Error` then.
|
100
98
|
|
101
|
-
|
102
99
|
## Contributing
|
103
100
|
|
104
|
-
|
101
|
+
For quicker feedback during gem development or debugging feel free to use the provided `rake console` task. It is defined within the [`Rakefile`](./Rakefile).
|
102
|
+
|
103
|
+
We test multiple versions of `Rails` using the `appraisal` gem. Please use the following steps to test using `appraisal`.
|
105
104
|
|
106
105
|
1. `bundle exec appraisal install`
|
107
106
|
2. `bundle exec appraisal rake test`
|
@@ -110,27 +109,41 @@ We use the `appraisal` gem for testing multiple versions of `Rails`. Please use
|
|
110
109
|
|
111
110
|
Created & Maintained by [Weston Ganger](https://westonganger.com) - [@westonganger](https://github.com/westonganger)
|
112
111
|
|
113
|
-
Originally forked from the dead/unmaintained `protected_attributes` gem by the Rails team.
|
112
|
+
Originally forked from the dead/unmaintained [`protected_attributes`](https://github.com/rails/protected_attributes) gem by the Rails team.
|
114
113
|
|
115
|
-
## A
|
114
|
+
## A Simple and Similar strong_params Alternative
|
116
115
|
|
117
|
-
While I do utilize this gem in some legacy projects I have adopted
|
116
|
+
While I do utilize this gem in some legacy projects. The latest approach I have adopted is similar to this gem but only utilizes Rails built-in `strong_params` which is a much more future proof way of doing things. The following is an example implementation.
|
118
117
|
|
119
118
|
```ruby
|
119
|
+
### Model
|
120
120
|
class Post < ActiveRecord::Base
|
121
|
+
has_many :comments
|
121
122
|
|
123
|
+
accepts_nested_attributes_for :comments, allow_destroy: true
|
124
|
+
|
122
125
|
def self.strong_params(params)
|
123
|
-
params.permit(:post).permit(
|
126
|
+
params.permit(:post).permit(*PERMITTED_ATTRIBUTES)
|
124
127
|
end
|
125
|
-
|
128
|
+
|
129
|
+
PERMITTED_PARAMETERS = [
|
130
|
+
:id,
|
131
|
+
:name,
|
132
|
+
:content,
|
133
|
+
:published_at,
|
134
|
+
{
|
135
|
+
comments_attributes: Comment::PERMITTED_PARAMETERS,
|
136
|
+
}
|
137
|
+
].freeze
|
138
|
+
|
126
139
|
end
|
127
140
|
|
141
|
+
### Controller
|
128
142
|
class PostsController < ApplicationController
|
129
|
-
|
130
143
|
def create
|
131
|
-
@post = Post.new
|
132
|
-
|
133
|
-
@post.
|
144
|
+
@post = Post.new(Post.strong_params(params))
|
145
|
+
|
146
|
+
@post.save
|
134
147
|
|
135
148
|
respond_with @post
|
136
149
|
end
|
@@ -142,6 +155,5 @@ class PostsController < ApplicationController
|
|
142
155
|
|
143
156
|
respond_with @post
|
144
157
|
end
|
145
|
-
|
146
158
|
end
|
147
159
|
```
|
@@ -7,6 +7,7 @@ require "active_record/mass_assignment_security/nested_attributes"
|
|
7
7
|
require "active_record/mass_assignment_security/persistence"
|
8
8
|
require "active_record/mass_assignment_security/reflection"
|
9
9
|
require "active_record/mass_assignment_security/relation"
|
10
|
+
require "active_record/mass_assignment_security/association_relation"
|
10
11
|
require "active_record/mass_assignment_security/validations"
|
11
12
|
require "active_record/mass_assignment_security/associations"
|
12
13
|
require "active_record/mass_assignment_security/inheritance"
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class AssociationRelation
|
3
|
+
undef :new
|
4
|
+
undef :create
|
5
|
+
undef :create!
|
6
|
+
|
7
|
+
def build(attributes = nil, options = {}, &block)
|
8
|
+
block = protected_attributes_scope_block('new', block)
|
9
|
+
scoping { @association.build(attributes, options, &block) }
|
10
|
+
end
|
11
|
+
alias new build
|
12
|
+
|
13
|
+
def create(attributes = nil, options = {}, &block)
|
14
|
+
block = protected_attributes_scope_block('create', block)
|
15
|
+
scoping { @association.create(attributes, options, &block) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def create!(attributes = nil, options = {}, &block)
|
19
|
+
block = protected_attributes_scope_block('create!', block)
|
20
|
+
scoping { @association.create!(attributes, options, &block) }
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
if ActiveRecord.gem_version < Gem::Version.new('6.0')
|
26
|
+
|
27
|
+
def protected_attributes_scope_block(_label, block)
|
28
|
+
block
|
29
|
+
end
|
30
|
+
|
31
|
+
elsif ActiveRecord.gem_version < Gem::Version.new('6.1')
|
32
|
+
|
33
|
+
def protected_attributes_scope_block(label, block)
|
34
|
+
_deprecated_scope_block(label, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
else
|
38
|
+
|
39
|
+
def protected_attributes_scope_block(_label, block)
|
40
|
+
current_scope_restoring_block(&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
### Original Rails Code - https://github.com/rails/rails/tree/master/activerecord/lib/active_record/associations
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Associations
|
3
5
|
class Association
|
@@ -10,7 +12,6 @@ module ActiveRecord
|
|
10
12
|
record.assign_attributes(attributes, without_protection: true)
|
11
13
|
end
|
12
14
|
end
|
13
|
-
|
14
15
|
private :build_record
|
15
16
|
end
|
16
17
|
|
@@ -53,7 +54,6 @@ module ActiveRecord
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
end
|
56
|
-
|
57
57
|
private :create_record
|
58
58
|
end
|
59
59
|
|
@@ -76,26 +76,41 @@ module ActiveRecord
|
|
76
76
|
end
|
77
77
|
|
78
78
|
module ThroughAssociation
|
79
|
-
|
79
|
+
### Cant use respond_to?(method, true) because its a module instead of a class
|
80
|
+
undef :build_record if self.private_instance_methods.include?(:build_record)
|
81
|
+
def build_record(attributes, options={})
|
82
|
+
inverse = source_reflection.inverse_of
|
83
|
+
target = through_association.target
|
80
84
|
|
81
|
-
|
85
|
+
if inverse && target && !target.is_a?(Array)
|
86
|
+
attributes[inverse.foreign_key] = target.id
|
87
|
+
end
|
82
88
|
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
super(attributes, options)
|
90
|
+
end
|
91
|
+
private :build_record
|
92
|
+
end
|
86
93
|
|
87
|
-
|
88
|
-
|
94
|
+
class HasManyThroughAssociation
|
95
|
+
if ActiveRecord.version >= Gem::Version.new('5.2.3')
|
96
|
+
undef :build_through_record
|
97
|
+
def build_through_record(record)
|
98
|
+
@through_records[record.object_id] ||= begin
|
99
|
+
ensure_mutable
|
100
|
+
|
101
|
+
attributes = through_scope_attributes
|
102
|
+
attributes[source_reflection.name] = record
|
103
|
+
attributes[source_reflection.foreign_type] = options[:source_type] if options[:source_type]
|
104
|
+
|
105
|
+
# Pass in `without_protection: true` here because `options_for_through_record`
|
106
|
+
# was removed in https://github.com/rails/rails/pull/35799
|
107
|
+
through_association.build(attributes, without_protection: true)
|
89
108
|
end
|
90
|
-
|
91
|
-
super(attributes, options)
|
92
109
|
end
|
93
|
-
|
110
|
+
private :build_through_record
|
111
|
+
end
|
94
112
|
|
95
|
-
class HasManyThroughAssociation
|
96
113
|
undef :build_record
|
97
|
-
undef :options_for_through_record if respond_to?(:options_for_through_record, false)
|
98
|
-
|
99
114
|
def build_record(attributes, options = {})
|
100
115
|
ensure_not_nested
|
101
116
|
|
@@ -114,6 +129,7 @@ module ActiveRecord
|
|
114
129
|
end
|
115
130
|
private :build_record
|
116
131
|
|
132
|
+
undef :options_for_through_record if respond_to?(:options_for_through_record, true)
|
117
133
|
def options_for_through_record
|
118
134
|
[through_scope_attributes, without_protection: true]
|
119
135
|
end
|
@@ -12,9 +12,17 @@ module ActiveRecord
|
|
12
12
|
|
13
13
|
# The primary key and inheritance column can never be set by mass-assignment for security reasons.
|
14
14
|
def attributes_protected_by_default
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
begin
|
16
|
+
default = [primary_key, inheritance_column]
|
17
|
+
|
18
|
+
if !primary_key.eql?('id')
|
19
|
+
default << 'id'
|
20
|
+
end
|
21
|
+
rescue ActiveRecord::NoDatabaseError
|
22
|
+
default = []
|
23
|
+
end
|
24
|
+
|
25
|
+
return default
|
18
26
|
end
|
19
27
|
end
|
20
28
|
|
@@ -54,6 +54,7 @@ module ActiveRecord
|
|
54
54
|
|
55
55
|
def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {})
|
56
56
|
options = self.nested_attributes_options[association_name]
|
57
|
+
|
57
58
|
if attributes.class.name == 'ActionController::Parameters'
|
58
59
|
attributes = attributes.to_unsafe_h
|
59
60
|
elsif !attributes.is_a?(Hash) && !attributes.is_a?(Array)
|
@@ -62,8 +63,7 @@ module ActiveRecord
|
|
62
63
|
|
63
64
|
attributes = attributes.with_indifferent_access
|
64
65
|
|
65
|
-
if
|
66
|
-
(options[:update_only] || record.id.to_s == attributes['id'].to_s)
|
66
|
+
if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) && (options[:update_only] || record.id.to_s == attributes['id'].to_s)
|
67
67
|
assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy], assignment_opts) unless call_reject_if(association_name, attributes)
|
68
68
|
|
69
69
|
elsif attributes['id'].present? && !assignment_opts[:without_protection]
|
@@ -122,6 +122,12 @@ module ActiveRecord
|
|
122
122
|
end
|
123
123
|
|
124
124
|
attributes_collection.each do |attributes|
|
125
|
+
if attributes.class.name == 'ActionController::Parameters'
|
126
|
+
attributes = attributes.to_unsafe_h
|
127
|
+
elsif !attributes.is_a?(Hash) && !attributes.is_a?(Array)
|
128
|
+
raise ArgumentError, "ActionController::Parameters or Hash or Array expected, got #{attributes.class.name} (#{attributes.inspect})"
|
129
|
+
end
|
130
|
+
|
125
131
|
attributes = attributes.with_indifferent_access
|
126
132
|
|
127
133
|
if attributes['id'].blank?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.8.1
|
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: 2021-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '5.0'
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: sqlite3
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: mocha
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +108,7 @@ files:
|
|
122
108
|
- lib/active_model/mass_assignment_security/permission_set.rb
|
123
109
|
- lib/active_model/mass_assignment_security/sanitizer.rb
|
124
110
|
- lib/active_record/mass_assignment_security.rb
|
111
|
+
- lib/active_record/mass_assignment_security/association_relation.rb
|
125
112
|
- lib/active_record/mass_assignment_security/associations.rb
|
126
113
|
- lib/active_record/mass_assignment_security/attribute_assignment.rb
|
127
114
|
- lib/active_record/mass_assignment_security/core.rb
|
@@ -154,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
141
|
- !ruby/object:Gem::Version
|
155
142
|
version: '0'
|
156
143
|
requirements: []
|
157
|
-
rubygems_version: 3.
|
144
|
+
rubygems_version: 3.1.2
|
158
145
|
signing_key:
|
159
146
|
specification_version: 4
|
160
147
|
summary: Protect attributes from mass assignment in Active Record models
|