protected_attributes_continued 1.4.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e01eccbad4a21cdd10334379dc742f0edc97dd8a6b99b03e8d1e105d5a159a4
4
- data.tar.gz: e41d9f31ea96a9ed1edbc30063ac258f820452554d64d58f6ce0e2945027e74c
3
+ metadata.gz: 4cc976fa47e5942c610f0ba64d976c46e83797255c60fd504f79e30677164632
4
+ data.tar.gz: 3127f37fc4fb6222ed6fbef07fedbe449a65fd5caa919d3a43bc65c17f86c2c2
5
5
  SHA512:
6
- metadata.gz: 9317411a772594accc0cbc59ca0c07a755b58f1b0c1b6553d5843cb37b6e7f3ec0defb4b5e84686a8564fafff6bb43cd803768fe230dd8b990ee236aa1281620
7
- data.tar.gz: 608d732479681ce5d90a231e8f44862e54a7cb0a6ce323088c90f6dc22b52eaa85a0a7e471ee5cbe8979d6514f9f45be3fb6533a4def88dfcd2ae8a12a1ca13c
6
+ metadata.gz: f7776d77b1898ee1b0b9713102a1be01c9de945f7cb23160a00a3af4f205f15f05ca9e6f58bc5510e4cb68606174fe1d6a835a9a2756ff866cd7849a54fcadaf
7
+ data.tar.gz: c821bb84db6db202e524a535c7b098e2976cd423946e95325fc421f88d35077e645e166ae10f9f01f82de0e52d2decdb1781690806392a661ea9d8fecd8444de
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://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>
3
+ <a href='https://travis-ci.com/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
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`. 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
+ > This is the community continued version of [`protected_attributes`](https://github.com/rails/protected_attributes) for Rails 5+. I recommend you only use it to support legacy portions of your application that you do not want to upgrade. The Rails team dropped this feature and switched to `strong_parameters` because of security issues. However some applications simply cannot be upgraded or security like this is a non-issue. To continue supporting this feature going forward lets 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
- We use the `appraisal` gem for testing multiple versions of `Rails`. Please use the following steps to test using `appraisal`.
101
+ For quicker feedback during gem development or debugging feel free to use the provided `rake console` task. It is defined within the [`Rakefile`](https://github.com/westonganger/protected_attributes_continued/blob/master/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,26 @@ 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 Better Alternative
114
+ ## A Simple and Similar strong_params Alternative
116
115
 
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.
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
-
122
121
  def self.strong_params(params)
123
122
  params.permit(:post).permit(:name, :content, :published_at)
124
123
  end
125
-
126
124
  end
127
125
 
126
+ ### Controller
128
127
  class PostsController < ApplicationController
129
-
130
128
  def create
131
- @post = Post.new
132
-
133
- @post.assign_attributes(Post.strong_params(params))
129
+ @post = Post.new(Post.strong_params(params))
130
+
131
+ @post.save
134
132
 
135
133
  respond_with @post
136
134
  end
@@ -142,6 +140,5 @@ class PostsController < ApplicationController
142
140
 
143
141
  respond_with @post
144
142
  end
145
-
146
143
  end
147
144
  ```
@@ -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,27 @@
1
+ if ActiveRecord::VERSION::MAJOR >= 6
2
+
3
+ module ActiveRecord
4
+ class AssociationRelation
5
+ undef :new
6
+ undef :create
7
+ undef :create!
8
+
9
+ def build(attributes = nil, options = {}, &block)
10
+ block = _deprecated_scope_block("new", &block)
11
+ scoping { @association.build(attributes, options, &block) }
12
+ end
13
+ alias new build
14
+
15
+ def create(attributes = nil, options = {}, &block)
16
+ block = _deprecated_scope_block("create", &block)
17
+ scoping { @association.create(attributes, options, &block) }
18
+ end
19
+
20
+ def create!(attributes = nil, options = {}, &block)
21
+ block = _deprecated_scope_block("create!", &block)
22
+ scoping { @association.create!(attributes, options, &block) }
23
+ end
24
+ end
25
+ end
26
+
27
+ 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
- undef :build_record if respond_to?(:build_record, false)
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
- private
85
+ if inverse && target && !target.is_a?(Array)
86
+ attributes[inverse.foreign_key] = target.id
87
+ end
82
88
 
83
- def build_record(attributes, options={})
84
- inverse = source_reflection.inverse_of
85
- target = through_association.target
89
+ super(attributes, options)
90
+ end
91
+ private :build_record
92
+ end
86
93
 
87
- if inverse && target && !target.is_a?(Array)
88
- attributes[inverse.foreign_key] = target.id
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
- end
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
@@ -3,6 +3,7 @@ module ActiveRecord
3
3
  module Core
4
4
 
5
5
  def initialize(attributes = nil, options = {})
6
+ @new_record = true
6
7
  self.class.define_attribute_methods
7
8
  @attributes = self.class._default_attributes.deep_dup
8
9
 
@@ -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 (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) &&
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?
@@ -1,3 +1,3 @@
1
1
  module ProtectedAttributes
2
- VERSION = "1.4.0"
2
+ VERSION = "1.7.0".freeze
3
3
  end
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.0
4
+ version: 1.7.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: 2018-12-28 00:00:00.000000000 Z
11
+ date: 2020-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -122,6 +122,7 @@ files:
122
122
  - lib/active_model/mass_assignment_security/permission_set.rb
123
123
  - lib/active_model/mass_assignment_security/sanitizer.rb
124
124
  - lib/active_record/mass_assignment_security.rb
125
+ - lib/active_record/mass_assignment_security/association_relation.rb
125
126
  - lib/active_record/mass_assignment_security/associations.rb
126
127
  - lib/active_record/mass_assignment_security/attribute_assignment.rb
127
128
  - lib/active_record/mass_assignment_security/core.rb
@@ -154,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
155
  - !ruby/object:Gem::Version
155
156
  version: '0'
156
157
  requirements: []
157
- rubygems_version: 3.0.1
158
+ rubygems_version: 3.1.2
158
159
  signing_key:
159
160
  specification_version: 4
160
161
  summary: Protect attributes from mass assignment in Active Record models