protected_attributes_continued 1.2.0
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 +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +104 -0
- data/lib/action_controller/accessible_params_wrapper.rb +31 -0
- data/lib/active_model/mass_assignment_security.rb +362 -0
- data/lib/active_model/mass_assignment_security/permission_set.rb +40 -0
- data/lib/active_model/mass_assignment_security/sanitizer.rb +75 -0
- data/lib/active_record/mass_assignment_security.rb +29 -0
- data/lib/active_record/mass_assignment_security/associations.rb +154 -0
- data/lib/active_record/mass_assignment_security/attribute_assignment.rb +88 -0
- data/lib/active_record/mass_assignment_security/core.rb +17 -0
- data/lib/active_record/mass_assignment_security/inheritance.rb +23 -0
- data/lib/active_record/mass_assignment_security/nested_attributes.rb +157 -0
- data/lib/active_record/mass_assignment_security/persistence.rb +83 -0
- data/lib/active_record/mass_assignment_security/reflection.rb +21 -0
- data/lib/active_record/mass_assignment_security/relation.rb +76 -0
- data/lib/active_record/mass_assignment_security/validations.rb +24 -0
- data/lib/protected_attributes.rb +14 -0
- data/lib/protected_attributes/railtie.rb +9 -0
- data/lib/protected_attributes/version.rb +3 -0
- metadata +173 -0
@@ -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
|
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: []
|