stronger_parameters 2.8.0 → 2.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0765498e474bdda1bbd86952faeb949bb8dee68d
4
- data.tar.gz: 552b525dd274336986326681a21a334139bfbb25
3
+ metadata.gz: a12c5ef2ac847c635c4913a85339c97fbf57779a
4
+ data.tar.gz: 8451750358aebf9a07138bf2336723426684fcb7
5
5
  SHA512:
6
- metadata.gz: f1317839557a9579b3710b15c314de07a02766e6ac511a84ef3b98fe3dd8fe8dd5c00c442d3c952d67f0287cc57589944eac80e41fe2e2eaa27101f8bb612f06
7
- data.tar.gz: 5abbe1cc2b805bf72ff355c4d79de711bb09c18aaa1a4e97aceaf13d4e7bfe8c321d890f7d118fcef69036fb19ee5613f86dce9cfa2065c7e1f5d6f6c47d8e74
6
+ metadata.gz: dc96fc9fa934ad431203d375653a0bf6ca2f95ddf22439f41d6dccb4632dbc7e309afd81327ac6a9b84ff7ea89dc098bb611634883109b5685a9685c6f34e76c
7
+ data.tar.gz: b2adbe65b3cc872823db2127deddb565614cd2e4a9840e70c93b5e9f40527fe54287b1446ef976b2f957580dfe07f9e859f4090ead0da84938b2f9466219ba1c
data/README.md CHANGED
@@ -25,12 +25,11 @@ params.permit(
25
25
  This will allow an array of id parameters that all are IDs (integer less than 2**31, greater than 0) and convert to Fixnum (`'2' --> 2`).
26
26
 
27
27
  ### Empty array -> nil
28
- Rails converts empty arrays to nil unless `config.action_dispatch.perform_deep_munge = false` is set
29
- (available in Rails 4.1+). Either use this or `Parameters.array | Parameters.nil` to deal with this.
28
+ Rails converts empty arrays to nil, so often `Parameters.array | Parameters.nil` is needed.
30
29
 
31
30
  ### Allowing nils
32
31
 
33
- It can be convenient to allow nil to be passed as all kinds of attributes since ActiveRecord converts it to false/0 behind the scenes.
32
+ It can be convenient to allow nil for all attributes since ActiveRecord converts it to false/0.
34
33
  `ActionController::Parameters.allow_nil_for_everything = true`
35
34
 
36
35
  ## Nested Parameters
@@ -44,7 +43,7 @@ params.permit(
44
43
  name: Parameters.string,
45
44
  family: Parameters.map(
46
45
  name: Parameters.string
47
- )
46
+ ),
48
47
  hobbies: Parameters.array(Parameters.string)
49
48
  )
50
49
  )
@@ -149,7 +148,7 @@ This will permit these parameters:
149
148
  }
150
149
  ```
151
150
 
152
- ## Production rollout
151
+ ## Rollout in log-only mode
153
152
 
154
153
  Just want to log violations in production:
155
154
 
@@ -158,7 +157,7 @@ Just want to log violations in production:
158
157
  ActionController::Parameters.action_on_invalid_parameters = :log
159
158
  ```
160
159
 
161
- ## Controller support (compatible with Rails 3 and 4, untested on Rails 5)
160
+ ## Controller support
162
161
 
163
162
  Include `PermittedParameters` into a controller to force the developer
164
163
  to explicitly permit params for every action.
@@ -183,19 +182,20 @@ class TestController < ApplicationController
183
182
  def index
184
183
  end
185
184
 
186
- permitted_parameters :update, :anything # all parameters permitted, use when migrating old controllers/actions
185
+ permitted_parameters :update, :skip # use when migrating old controllers/actions
187
186
  def update
188
187
  end
188
+ end
189
189
  ```
190
190
 
191
191
 
192
- ### Log only mode
192
+ ### Log only mode for invalid parameters
193
193
 
194
- Just want to log violations in production, let all params pass through:
194
+ To only log invalid (not unpermitted) parameters during rollout of stronger_parameters:
195
195
 
196
196
  ```ruby
197
197
  class MyController < ApplicationController
198
- log_unpermitted_parameters! if Rails.env.production? # Still want other environments to raise
198
+ log_invalid_parameters! if Rails.env.production? # Still want other environments and controllers to raise
199
199
 
200
200
  permitted_parameters :update, user: { name: Parameters.string }
201
201
  def update
@@ -205,7 +205,7 @@ end
205
205
 
206
206
  ### Notifying users about unpermitted params
207
207
 
208
- Add headers to all requests that have unpermitted params:
208
+ Add headers to all requests that have unpermitted params (does not log invalid):
209
209
 
210
210
  ```Ruby
211
211
  # config/application.rb
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/errors'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -6,13 +7,9 @@ module StrongerParameters
6
7
  FALSE_VALUES = [false, 'false', '0', 0].freeze
7
8
 
8
9
  def value(v)
9
- if TRUE_VALUES.include?(v)
10
- return true
11
- end
10
+ return true if TRUE_VALUES.include?(v)
12
11
 
13
- if FALSE_VALUES.include?(v)
14
- return false
15
- end
12
+ return false if FALSE_VALUES.include?(v)
16
13
 
17
14
  InvalidValue.new(v, "must be either true or false")
18
15
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -7,7 +8,7 @@ module StrongerParameters
7
8
  StringIO,
8
9
  Rack::Test::UploadedFile,
9
10
  ActionDispatch::Http::UploadedFile
10
- ]
11
+ ].freeze
11
12
 
12
13
  def value(v)
13
14
  if VALID_FILE_TYPES.any? { |valid_file_type| v.is_a?(valid_file_type) }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -9,11 +10,10 @@ module StrongerParameters
9
10
  end
10
11
 
11
12
  def value(v)
12
- case
13
- when v.is_a?(Hash)
13
+ if v.is_a?(Hash)
14
14
  return ActionController::Parameters.new(v).permit! if constraints.nil?
15
15
  return ActionController::Parameters.new(v).permit(constraints)
16
- when ActionPack::VERSION::MAJOR >= 5 && v.is_a?(ActionController::Parameters)
16
+ elsif ActionPack::VERSION::MAJOR >= 5 && v.is_a?(ActionController::Parameters)
17
17
  return v.permit! if constraints.nil?
18
18
  return v.permit(constraints)
19
19
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
4
5
  class NilStringConstraint < Constraint
5
- NULL_VALUES = [nil, '', 'undefined']
6
+ NULL_VALUES = [nil, '', 'undefined'].freeze
6
7
 
7
8
  def value(v)
8
9
  if NULL_VALUES.include?(v)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
 
3
4
  module StrongerParameters
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraint'
2
3
  require 'stronger_parameters/constraints/string_constraint'
3
4
  require 'stronger_parameters/constraints/float_constraint'
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/constraints'
2
3
 
3
4
  module StrongerParameters
@@ -5,86 +6,62 @@ module StrongerParameters
5
6
  module PermittedParameters
6
7
  def self.included(klass)
7
8
  klass.extend ClassMethods
8
- if klass.respond_to?(:before_action)
9
- klass.before_action :permit_parameters
10
- else
11
- klass.before_filter :permit_parameters
12
- end
9
+ method = (klass.respond_to?(:before_action) ? :before_action : :before_filter)
10
+ klass.public_send method, :permit_parameters
13
11
  end
14
12
 
15
- class PermittedParametersHash < Hash
16
- def initialize(other = nil)
17
- super()
18
- merge!(other) unless other.nil?
19
- end
20
-
21
- def merge!(other)
22
- other.each do |key, value|
23
- value = sugar(value)
24
-
25
- if value.is_a?(StrongerParameters::Constraint)
26
- self[key] = value
27
- else
28
- self[key] ||= self.class.new
29
- self[key].merge!(value)
30
- end
31
- end
32
-
33
- self
34
- end
35
-
36
- def merge(other)
37
- dup.merge!(other)
38
- end
39
-
40
- private
41
-
42
- def sugar(value)
43
- case value
44
- when Array
45
- ActionController::Parameters.array(*value.map { |v| sugar(v) })
46
- when Hash
47
- constraints = value.each_with_object({}) do |(key, v), memo|
48
- memo[key] = sugar(v)
49
- end
50
- ActionController::Parameters.map(constraints)
51
- else
52
- value
13
+ def self.sugar(value)
14
+ case value
15
+ when Array
16
+ ActionController::Parameters.array(*value.map { |v| sugar(v) })
17
+ when Hash
18
+ constraints = value.each_with_object({}) do |(key, v), memo|
19
+ memo[key] = sugar(v)
53
20
  end
21
+ ActionController::Parameters.map(constraints)
22
+ else
23
+ value
54
24
  end
55
25
  end
56
26
 
57
- DEFAULT_PERMITTED = PermittedParametersHash.new(
27
+ DEFAULT_PERMITTED = {
58
28
  controller: ActionController::Parameters.anything,
59
29
  action: ActionController::Parameters.anything,
60
30
  format: ActionController::Parameters.anything,
61
31
  authenticity_token: ActionController::Parameters.string
62
- )
32
+ }.freeze
63
33
 
64
34
  module ClassMethods
65
35
  def self.extended(base)
66
36
  base.send :class_attribute, :log_unpermitted_parameters, instance_accessor: false
67
37
  end
68
38
 
69
- def log_unpermitted_parameters!
39
+ def log_invalid_parameters!
70
40
  self.log_unpermitted_parameters = true
71
41
  end
72
42
 
73
43
  def permitted_parameters(action, permitted)
74
- if permit_parameters[action] == :anything && permitted != :anything
75
- raise ArgumentError, "#{self}/#{action} can not add to :anything"
44
+ if permit_parameters[action] == :skip || permitted == :skip
45
+ permit_parameters[action] = permitted
46
+ else
47
+ action_permitted = (permit_parameters[action] ||= {})
48
+ action_permitted.deep_merge!(permitted)
76
49
  end
77
-
78
- permit_parameters.deep_merge!(action => permitted)
79
50
  end
80
51
 
81
52
  def permitted_parameters_for(action)
82
53
  unless for_action = permit_parameters[action]
83
54
  location = instance_method(action).source_location
84
- raise KeyError, "Action #{action} for #{self} does not have any permitted parameters (#{location.join(":")})"
55
+ raise(
56
+ KeyError,
57
+ "Action #{action} for #{self} does not have any permitted parameters (#{location.join(":")})"
58
+ )
85
59
  end
86
- return :anything if for_action == :anything
87
- permit_parameters[:all].merge(for_action)
60
+ return :skip if for_action == :skip
61
+
62
+ # FYI: we should be able to call sugar on the result of deep_merge, but it breaks tests
63
+ permit_parameters[:all].deep_merge(for_action).
64
+ each_with_object({}) { |(k, v), a| a[k] = PermittedParameters.sugar(v) }
88
65
  end
89
66
 
90
67
  private
@@ -93,7 +70,7 @@ module StrongerParameters
93
70
  @permit_parameters ||= if superclass.respond_to?(:permit_parameters, true)
94
71
  superclass.send(:permit_parameters).deep_dup
95
72
  else
96
- { all: DEFAULT_PERMITTED.dup }
73
+ {all: DEFAULT_PERMITTED.deep_dup}
97
74
  end
98
75
  end
99
76
  end
@@ -101,23 +78,20 @@ module StrongerParameters
101
78
  private
102
79
 
103
80
  def permit_parameters
104
- action = params[:action].to_sym
81
+ action = params.fetch(:action).to_sym
105
82
  permitted = self.class.permitted_parameters_for(action)
83
+ return if permitted == :skip
106
84
 
107
- if permitted == :anything
108
- Rails.logger.warn("#{params[:controller]}/#{params[:action]} does not filter parameters")
109
- return
110
- end
111
-
112
- permitted_params = without_invalid_parameter_exceptions { params.permit(permitted) }
113
- unpermitted_keys = flat_keys(params) - flat_keys(permitted_params)
85
+ # TODO: invalid values should also be logged, but atm only invalid keys are
114
86
  log_unpermitted = self.class.log_unpermitted_parameters
87
+ permitted_params = without_invalid_parameter_exceptions(log_unpermitted) { params.permit(permitted) }
88
+ unpermitted_keys = flat_keys(params) - flat_keys(permitted_params)
115
89
 
116
90
  show_unpermitted_keys(unpermitted_keys, log_unpermitted)
117
91
 
118
92
  return if log_unpermitted
119
93
 
120
- params.replace(permitted_params)
94
+ (ActionPack::VERSION::MAJOR >= 5 ? params.send(:parameters) : params).replace(permitted_params)
121
95
  params.permit!
122
96
  request.params.replace(permitted_params)
123
97
 
@@ -129,16 +103,19 @@ module StrongerParameters
129
103
  return if unpermitted_keys.empty?
130
104
 
131
105
  log_prefix = (log_unpermitted ? 'Found' : 'Removed')
132
- message = "#{log_prefix} restricted keys #{unpermitted_keys.inspect} from parameters according to permitted list"
106
+ message =
107
+ "#{log_prefix} restricted keys #{unpermitted_keys.inspect} from parameters according to permitted list"
133
108
 
134
- header = Rails.configuration.stronger_parameters_violation_header if Rails.configuration.respond_to?(:stronger_parameters_violation_header)
109
+ if Rails.configuration.respond_to?(:stronger_parameters_violation_header)
110
+ header = Rails.configuration.stronger_parameters_violation_header
111
+ end
135
112
  response.headers[header] = message if response && header
136
113
 
137
114
  Rails.logger.info(" #{message}")
138
115
  end
139
116
 
140
- def without_invalid_parameter_exceptions
141
- if self.class.log_unpermitted_parameters
117
+ def without_invalid_parameter_exceptions(log)
118
+ if log
142
119
  begin
143
120
  old = ActionController::Parameters.action_on_invalid_parameters
144
121
  ActionController::Parameters.action_on_invalid_parameters = :log
@@ -152,6 +129,7 @@ module StrongerParameters
152
129
  end
153
130
 
154
131
  def flat_keys(hash)
132
+ hash = hash.send(:parameters) if ActionPack::VERSION::MAJOR >= 5 && hash.is_a?(ActionController::Parameters)
155
133
  hash.flat_map { |k, v| v.is_a?(Hash) ? flat_keys(v).map { |x| "#{k}.#{x}" }.push(k) : k }
156
134
  end
157
135
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module StrongerParameters
2
3
  class InvalidValue
3
4
  attr_accessor :value, :message
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'action_pack'
2
3
 
3
4
  if ActionPack::VERSION::MAJOR == 3
@@ -17,8 +18,8 @@ module StrongerParameters
17
18
  included do
18
19
  alias_method :hash_filter_without_stronger_parameters, :hash_filter
19
20
  alias_method :hash_filter, :hash_filter_with_stronger_parameters
20
- cattr_accessor :action_on_invalid_parameters, :instance_accessor => false
21
- cattr_accessor :allow_nil_for_everything, :instance_accessor => false
21
+ cattr_accessor :action_on_invalid_parameters, instance_accessor: false
22
+ cattr_accessor :allow_nil_for_everything, instance_accessor: false
22
23
  end
23
24
 
24
25
  module ClassMethods
@@ -59,33 +60,33 @@ module StrongerParameters
59
60
  end
60
61
 
61
62
  def integer32
62
- integer & lt(2 ** 31) & gte(-2 ** 31)
63
+ integer & lt(2**31) & gte(-2**31)
63
64
  end
64
65
 
65
66
  def integer64
66
- integer & lt(2 ** 63) & gte(-2 ** 63)
67
+ integer & lt(2**63) & gte(-2**63)
67
68
  end
68
69
 
69
70
  def id
70
- integer & lt(2 ** 31) & gte(0)
71
+ integer & lt(2**31) & gte(0)
71
72
  end
72
73
 
73
74
  def uid
74
- integer & lt(2 ** 32) & gte(0)
75
+ integer & lt(2**32) & gte(0)
75
76
  end
76
77
 
77
78
  def bigid
78
- integer & lt(2 ** 63) & gte(0)
79
+ integer & lt(2**63) & gte(0)
79
80
  end
80
81
 
81
82
  def ubigid
82
- integer & lt(2 ** 64) & gte(0)
83
+ integer & lt(2**64) & gte(0)
83
84
  end
84
85
 
85
86
  def enumeration(*allowed)
86
87
  EnumerationConstraint.new(*allowed)
87
88
  end
88
- alias_method :enum, :enumeration
89
+ alias enum enumeration
89
90
 
90
91
  def boolean
91
92
  BooleanConstraint.new
@@ -115,7 +116,7 @@ module StrongerParameters
115
116
  FileConstraint.new
116
117
  end
117
118
 
118
- def decimal(precision = 8, scale =2)
119
+ def decimal(precision = 8, scale = 2)
119
120
  DecimalConstraint.new(precision, scale)
120
121
  end
121
122
 
@@ -128,7 +129,7 @@ module StrongerParameters
128
129
  stronger_filter = ActiveSupport::HashWithIndifferentAccess.new
129
130
  other_filter = ActiveSupport::HashWithIndifferentAccess.new
130
131
 
131
- filter.each do |k,v|
132
+ filter.each do |k, v|
132
133
  if v.is_a?(Constraint)
133
134
  stronger_filter[k] = v
134
135
  else
@@ -148,7 +149,7 @@ module StrongerParameters
148
149
  result = constraint.value(value)
149
150
  if result.is_a?(InvalidValue)
150
151
  name = "invalid_parameter.action_controller"
151
- ActiveSupport::Notifications.publish(name, :key => key, :value => value, :message => result.message)
152
+ ActiveSupport::Notifications.publish(name, key: key, value: value, message: result.message)
152
153
 
153
154
  action = self.class.action_on_invalid_parameters
154
155
  case action
@@ -176,8 +177,11 @@ module StrongerParameters
176
177
  Parameters = ActionController::Parameters
177
178
 
178
179
  included do
180
+ # TODO: this is not consistent with the behavior of raising ActionController::UnpermittedParameters
181
+ # should have the same render vs raise behavior in test/dev ... see permitted_parameters_test.rb
179
182
  rescue_from(StrongerParameters::InvalidParameter) do |e|
180
- render (ActiveSupport::VERSION::MAJOR < 5 ? :text : :plain) => e.message, :status => :bad_request
183
+ type = (ActiveSupport::VERSION::MAJOR < 5 ? :text : :plain)
184
+ render type => e.message, :status => :bad_request
181
185
  end
182
186
  end
183
187
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module StrongerParameters
2
- VERSION = '2.8.0'
3
+ VERSION = '2.9.0'
3
4
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'stronger_parameters/version'
2
3
  require 'action_pack'
3
4
  require 'strong_parameters' if ActionPack::VERSION::MAJOR == 3
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stronger_parameters
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mick Staugaard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-17 00:00:00.000000000 Z
11
+ date: 2017-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,34 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: single_cov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: actionpack
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -184,7 +212,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
184
212
  requirements:
185
213
  - - ">="
186
214
  - !ruby/object:Gem::Version
187
- version: '0'
215
+ version: 2.0.0
188
216
  required_rubygems_version: !ruby/object:Gem::Requirement
189
217
  requirements:
190
218
  - - ">="