protected_attributes_continued 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,83 @@
1
+ require 'active_support/concern'
2
+
3
+ module ActiveRecord
4
+ module MassAssignmentSecurity
5
+ # = Active Record Persistence
6
+ module Persistence
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ # Creates an object (or multiple objects) and saves it to the database, if validations pass.
11
+ # The resulting object is returned whether the object was saved successfully to the database or not.
12
+ #
13
+ # The +attributes+ parameter can be either a Hash or an Array of Hashes. These Hashes describe the
14
+ # attributes on the objects that are to be created.
15
+ #
16
+ # +create+ respects mass-assignment security and accepts either +:as+ or +:without_protection+ options
17
+ # in the +options+ parameter.
18
+ #
19
+ # ==== Examples
20
+ # # Create a single new object
21
+ # User.create(:first_name => 'Jamie')
22
+ #
23
+ # # Create a single new object using the :admin mass-assignment security role
24
+ # User.create({ :first_name => 'Jamie', :is_admin => true }, :as => :admin)
25
+ #
26
+ # # Create a single new object bypassing mass-assignment security
27
+ # User.create({ :first_name => 'Jamie', :is_admin => true }, :without_protection => true)
28
+ #
29
+ # # Create an Array of new objects
30
+ # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
31
+ #
32
+ # # Create a single object and pass it into a block to set other attributes.
33
+ # User.create(:first_name => 'Jamie') do |u|
34
+ # u.is_admin = false
35
+ # end
36
+ #
37
+ # # Creating an Array of new objects using a block, where the block is executed for each object:
38
+ # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
39
+ # u.is_admin = false
40
+ # end
41
+ def create(attributes = nil, options = {}, &block)
42
+ if attributes.is_a?(Array)
43
+ attributes.collect { |attr| create(attr, options, &block) }
44
+ else
45
+ object = new(attributes, options, &block)
46
+ object.save
47
+ object
48
+ end
49
+ end
50
+ end
51
+
52
+ # Updates the attributes of the model from the passed-in hash and saves the
53
+ # record, all wrapped in a transaction. If the object is invalid, the saving
54
+ # will fail and false will be returned.
55
+ #
56
+ # When updating model attributes, mass-assignment security protection is respected.
57
+ # If no +:as+ option is supplied then the +:default+ role will be used.
58
+ # If you want to bypass the forbidden attributes protection then you can do so using
59
+ # the +:without_protection+ option.
60
+ def update(attributes, options = {})
61
+ # The following transaction covers any possible database side-effects of the
62
+ # attributes assignment. For example, setting the IDs of a child collection.
63
+ with_transaction_returning_status do
64
+ assign_attributes(attributes, options)
65
+ save
66
+ end
67
+ end
68
+ alias :update_attributes :update
69
+
70
+ # Updates its receiver just like +update_attributes+ but calls <tt>save!</tt> instead
71
+ # of +save+, so an exception is raised if the record is invalid.
72
+ def update!(attributes, options = {})
73
+ # The following transaction covers any possible database side-effects of the
74
+ # attributes assignment. For example, setting the IDs of a child collection.
75
+ with_transaction_returning_status do
76
+ assign_attributes(attributes, options)
77
+ save!
78
+ end
79
+ end
80
+ alias :update_attributes! :update!
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveRecord
2
+ module Reflection
3
+ if defined?(AbstractReflection)
4
+ class AbstractReflection
5
+ undef :build_association
6
+
7
+ def build_association(*options, &block)
8
+ klass.new(*options, &block)
9
+ end
10
+ end
11
+ else
12
+ class AssociationReflection
13
+ undef :build_association
14
+
15
+ def build_association(*options, &block)
16
+ klass.new(*options, &block)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,76 @@
1
+ module ActiveRecord
2
+ class Relation
3
+ undef :first_or_create
4
+ undef :first_or_create!
5
+ undef :first_or_initialize
6
+ undef :find_or_initialize_by
7
+ undef :find_or_create_by
8
+ undef :find_or_create_by!
9
+
10
+ # Tries to load the first record; if it fails, then <tt>create</tt> is called with the same arguments as this method.
11
+ #
12
+ # Expects arguments in the same format as +Base.create+.
13
+ #
14
+ # ==== Examples
15
+ # # Find the first user named Penélope or create a new one.
16
+ # User.where(:first_name => 'Penélope').first_or_create
17
+ # # => <User id: 1, first_name: 'Penélope', last_name: nil>
18
+ #
19
+ # # Find the first user named Penélope or create a new one.
20
+ # # We already have one so the existing record will be returned.
21
+ # User.where(:first_name => 'Penélope').first_or_create
22
+ # # => <User id: 1, first_name: 'Penélope', last_name: nil>
23
+ #
24
+ # # Find the first user named Scarlett or create a new one with a particular last name.
25
+ # User.where(:first_name => 'Scarlett').first_or_create(:last_name => 'Johansson')
26
+ # # => <User id: 2, first_name: 'Scarlett', last_name: 'Johansson'>
27
+ #
28
+ # # Find the first user named Scarlett or create a new one with a different last name.
29
+ # # We already have one so the existing record will be returned.
30
+ # User.where(:first_name => 'Scarlett').first_or_create do |user|
31
+ # user.last_name = "O'Hara"
32
+ # end
33
+ # # => <User id: 2, first_name: 'Scarlett', last_name: 'Johansson'>
34
+ def first_or_create(attributes = nil, options = {}, &block)
35
+ first || create(attributes, options, &block)
36
+ end
37
+
38
+ # Like <tt>first_or_create</tt> but calls <tt>create!</tt> so an exception is raised if the created record is invalid.
39
+ #
40
+ # Expects arguments in the same format as <tt>Base.create!</tt>.
41
+ def first_or_create!(attributes = nil, options = {}, &block)
42
+ first || create!(attributes, options, &block)
43
+ end
44
+
45
+ # Like <tt>first_or_create</tt> but calls <tt>new</tt> instead of <tt>create</tt>.
46
+ #
47
+ # Expects arguments in the same format as <tt>Base.new</tt>.
48
+ def first_or_initialize(attributes = nil, options = {}, &block)
49
+ first || new(attributes, options, &block)
50
+ end
51
+
52
+ def find_or_initialize_by(attributes, options = {}, &block)
53
+ find_by(attributes) || new(attributes, options, &block)
54
+ end
55
+
56
+ def find_or_create_by(attributes, options = {}, &block)
57
+ find_by(attributes) || create(attributes, options, &block)
58
+ end
59
+
60
+ def find_or_create_by!(attributes, options = {}, &block)
61
+ find_by(attributes) || create!(attributes, options, &block)
62
+ end
63
+ end
64
+
65
+ module QueryMethods
66
+ protected
67
+
68
+ def sanitize_forbidden_attributes(attributes) #:nodoc:
69
+ if !model._uses_mass_assignment_security
70
+ sanitize_for_mass_assignment(attributes)
71
+ else
72
+ attributes
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_support/concern'
2
+
3
+ module ActiveRecord
4
+ module MassAssignmentSecurity
5
+ module Validations
6
+ extend ActiveSupport::Concern
7
+
8
+ module ClassMethods
9
+ # Creates an object just like Base.create but calls <tt>save!</tt> instead of +save+
10
+ # so an exception is raised if the record is invalid.
11
+ def create!(attributes = nil, options = {}, &block)
12
+ if attributes.is_a?(Array)
13
+ attributes.collect { |attr| create!(attr, options, &block) }
14
+ else
15
+ object = new(attributes, options)
16
+ yield(object) if block_given?
17
+ object.save!
18
+ object
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ require "active_model/mass_assignment_security"
2
+ require "protected_attributes/railtie" if defined? Rails::Railtie
3
+ require "protected_attributes/version"
4
+
5
+ ActiveSupport.on_load :active_record do
6
+ require "active_record/mass_assignment_security"
7
+ end
8
+
9
+ ActiveSupport.on_load :action_controller do
10
+ require "action_controller/accessible_params_wrapper"
11
+ end
12
+
13
+ module ProtectedAttributes
14
+ end
@@ -0,0 +1,9 @@
1
+ module ProtectedAttributes
2
+ class Railtie < ::Rails::Railtie
3
+ initializer "protected_attributes.active_record", :before => "active_record.set_configs" do |app|
4
+ if app.config.respond_to?(:active_record) && app.config.active_record.delete(:whitelist_attributes)
5
+ ActiveSupport::Deprecation.warn "config.active_record.whitelist_attributes is deprecated and have no effect. Remove its call from the configuration."
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module ProtectedAttributes
2
+ VERSION = "1.2.0"
3
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: protected_attributes_continued
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ platform: ruby
6
+ authors:
7
+ - David Heinemeier Hansson
8
+ - Weston Ganger
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-08-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activemodel
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 4.0.1
21
+ - - "<"
22
+ - !ruby/object:Gem::Version
23
+ version: '6.0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 4.0.1
31
+ - - "<"
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ - !ruby/object:Gem::Dependency
35
+ name: activerecord
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 4.0.1
41
+ - - "<"
42
+ - !ruby/object:Gem::Version
43
+ version: '6.0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 4.0.1
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '6.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: actionpack
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 4.0.1
61
+ - - "<"
62
+ - !ruby/object:Gem::Version
63
+ version: '6.0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 4.0.1
71
+ - - "<"
72
+ - !ruby/object:Gem::Version
73
+ version: '6.0'
74
+ - !ruby/object:Gem::Dependency
75
+ name: railties
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 4.0.1
81
+ - - "<"
82
+ - !ruby/object:Gem::Version
83
+ version: '6.0'
84
+ type: :development
85
+ prerelease: false
86
+ version_requirements: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 4.0.1
91
+ - - "<"
92
+ - !ruby/object:Gem::Version
93
+ version: '6.0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: sqlite3
96
+ requirement: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ - !ruby/object:Gem::Dependency
109
+ name: mocha
110
+ requirement: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ type: :development
116
+ prerelease: false
117
+ version_requirements: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ description: Protect attributes from mass assignment
123
+ email:
124
+ - david@loudthinking.com
125
+ - westonganger@gmail.com
126
+ executables: []
127
+ extensions: []
128
+ extra_rdoc_files: []
129
+ files:
130
+ - LICENSE.txt
131
+ - README.md
132
+ - lib/action_controller/accessible_params_wrapper.rb
133
+ - lib/active_model/mass_assignment_security.rb
134
+ - lib/active_model/mass_assignment_security/permission_set.rb
135
+ - lib/active_model/mass_assignment_security/sanitizer.rb
136
+ - lib/active_record/mass_assignment_security.rb
137
+ - lib/active_record/mass_assignment_security/associations.rb
138
+ - lib/active_record/mass_assignment_security/attribute_assignment.rb
139
+ - lib/active_record/mass_assignment_security/core.rb
140
+ - lib/active_record/mass_assignment_security/inheritance.rb
141
+ - lib/active_record/mass_assignment_security/nested_attributes.rb
142
+ - lib/active_record/mass_assignment_security/persistence.rb
143
+ - lib/active_record/mass_assignment_security/reflection.rb
144
+ - lib/active_record/mass_assignment_security/relation.rb
145
+ - lib/active_record/mass_assignment_security/validations.rb
146
+ - lib/protected_attributes.rb
147
+ - lib/protected_attributes/railtie.rb
148
+ - lib/protected_attributes/version.rb
149
+ homepage: https://github.com/westonganger/protected_attributes_continued
150
+ licenses:
151
+ - MIT
152
+ metadata: {}
153
+ post_install_message:
154
+ rdoc_options: []
155
+ require_paths:
156
+ - lib
157
+ required_ruby_version: !ruby/object:Gem::Requirement
158
+ requirements:
159
+ - - ">="
160
+ - !ruby/object:Gem::Version
161
+ version: '0'
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ requirements: []
168
+ rubyforge_project:
169
+ rubygems_version: 2.5.1
170
+ signing_key:
171
+ specification_version: 4
172
+ summary: Protect attributes from mass assignment in Active Record models
173
+ test_files: []