actionpack 5.1.7 → 5.2.4.3

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +282 -362
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/lib/abstract_controller.rb +3 -0
  6. data/lib/abstract_controller/asset_paths.rb +2 -0
  7. data/lib/abstract_controller/base.rb +10 -2
  8. data/lib/abstract_controller/caching.rb +3 -2
  9. data/lib/abstract_controller/caching/fragments.rb +30 -7
  10. data/lib/abstract_controller/callbacks.rb +25 -3
  11. data/lib/abstract_controller/collector.rb +2 -0
  12. data/lib/abstract_controller/error.rb +2 -0
  13. data/lib/abstract_controller/helpers.rb +4 -5
  14. data/lib/abstract_controller/logger.rb +2 -0
  15. data/lib/abstract_controller/railties/routes_helpers.rb +2 -0
  16. data/lib/abstract_controller/rendering.rb +9 -16
  17. data/lib/abstract_controller/translation.rb +2 -0
  18. data/lib/abstract_controller/url_for.rb +2 -0
  19. data/lib/action_controller.rb +3 -0
  20. data/lib/action_controller/api.rb +2 -0
  21. data/lib/action_controller/api/api_rendering.rb +2 -0
  22. data/lib/action_controller/base.rb +3 -0
  23. data/lib/action_controller/caching.rb +2 -0
  24. data/lib/action_controller/form_builder.rb +2 -0
  25. data/lib/action_controller/log_subscriber.rb +5 -3
  26. data/lib/action_controller/metal.rb +13 -14
  27. data/lib/action_controller/metal/basic_implicit_render.rb +2 -0
  28. data/lib/action_controller/metal/conditional_get.rb +4 -3
  29. data/lib/action_controller/metal/content_security_policy.rb +52 -0
  30. data/lib/action_controller/metal/cookies.rb +2 -0
  31. data/lib/action_controller/metal/data_streaming.rb +7 -5
  32. data/lib/action_controller/metal/etag_with_flash.rb +2 -0
  33. data/lib/action_controller/metal/etag_with_template_digest.rb +3 -2
  34. data/lib/action_controller/metal/exceptions.rb +2 -3
  35. data/lib/action_controller/metal/flash.rb +3 -2
  36. data/lib/action_controller/metal/force_ssl.rb +4 -2
  37. data/lib/action_controller/metal/head.rb +2 -0
  38. data/lib/action_controller/metal/helpers.rb +4 -3
  39. data/lib/action_controller/metal/http_authentication.rb +8 -9
  40. data/lib/action_controller/metal/implicit_render.rb +2 -0
  41. data/lib/action_controller/metal/instrumentation.rb +4 -6
  42. data/lib/action_controller/metal/live.rb +3 -1
  43. data/lib/action_controller/metal/mime_responds.rb +3 -1
  44. data/lib/action_controller/metal/parameter_encoding.rb +2 -0
  45. data/lib/action_controller/metal/params_wrapper.rb +14 -10
  46. data/lib/action_controller/metal/redirecting.rb +22 -11
  47. data/lib/action_controller/metal/renderers.rb +4 -3
  48. data/lib/action_controller/metal/rendering.rb +2 -2
  49. data/lib/action_controller/metal/request_forgery_protection.rb +62 -10
  50. data/lib/action_controller/metal/rescue.rb +5 -3
  51. data/lib/action_controller/metal/streaming.rb +3 -1
  52. data/lib/action_controller/metal/strong_parameters.rb +36 -25
  53. data/lib/action_controller/metal/testing.rb +2 -6
  54. data/lib/action_controller/metal/url_for.rb +2 -0
  55. data/lib/action_controller/railtie.rb +16 -4
  56. data/lib/action_controller/railties/helpers.rb +2 -0
  57. data/lib/action_controller/renderer.rb +2 -0
  58. data/lib/action_controller/template_assertions.rb +2 -0
  59. data/lib/action_controller/test_case.rb +16 -10
  60. data/lib/action_dispatch.rb +9 -5
  61. data/lib/action_dispatch/http/cache.rb +22 -14
  62. data/lib/action_dispatch/http/content_security_policy.rb +272 -0
  63. data/lib/action_dispatch/http/filter_parameters.rb +4 -2
  64. data/lib/action_dispatch/http/filter_redirect.rb +2 -0
  65. data/lib/action_dispatch/http/headers.rb +2 -0
  66. data/lib/action_dispatch/http/mime_negotiation.rb +4 -8
  67. data/lib/action_dispatch/http/mime_type.rb +15 -13
  68. data/lib/action_dispatch/http/mime_types.rb +17 -2
  69. data/lib/action_dispatch/http/parameter_filter.rb +2 -0
  70. data/lib/action_dispatch/http/parameters.rb +6 -9
  71. data/lib/action_dispatch/http/rack_cache.rb +2 -0
  72. data/lib/action_dispatch/http/request.rb +36 -16
  73. data/lib/action_dispatch/http/response.rb +11 -9
  74. data/lib/action_dispatch/http/upload.rb +2 -0
  75. data/lib/action_dispatch/http/url.rb +5 -6
  76. data/lib/action_dispatch/journey.rb +2 -0
  77. data/lib/action_dispatch/journey/formatter.rb +4 -2
  78. data/lib/action_dispatch/journey/gtg/builder.rb +2 -0
  79. data/lib/action_dispatch/journey/gtg/simulator.rb +2 -8
  80. data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -2
  81. data/lib/action_dispatch/journey/nfa/builder.rb +2 -0
  82. data/lib/action_dispatch/journey/nfa/dot.rb +12 -10
  83. data/lib/action_dispatch/journey/nfa/simulator.rb +2 -0
  84. data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -0
  85. data/lib/action_dispatch/journey/nodes/node.rb +2 -0
  86. data/lib/action_dispatch/journey/parser_extras.rb +2 -0
  87. data/lib/action_dispatch/journey/path/pattern.rb +4 -1
  88. data/lib/action_dispatch/journey/route.rb +15 -6
  89. data/lib/action_dispatch/journey/router.rb +3 -1
  90. data/lib/action_dispatch/journey/router/utils.rb +14 -7
  91. data/lib/action_dispatch/journey/routes.rb +3 -1
  92. data/lib/action_dispatch/journey/scanner.rb +1 -0
  93. data/lib/action_dispatch/journey/visitors.rb +5 -3
  94. data/lib/action_dispatch/middleware/callbacks.rb +2 -0
  95. data/lib/action_dispatch/middleware/cookies.rb +148 -91
  96. data/lib/action_dispatch/middleware/debug_exceptions.rb +4 -2
  97. data/lib/action_dispatch/middleware/debug_locks.rb +9 -7
  98. data/lib/action_dispatch/middleware/exception_wrapper.rb +5 -6
  99. data/lib/action_dispatch/middleware/executor.rb +2 -0
  100. data/lib/action_dispatch/middleware/flash.rb +4 -2
  101. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -4
  102. data/lib/action_dispatch/middleware/reloader.rb +2 -0
  103. data/lib/action_dispatch/middleware/remote_ip.rb +7 -5
  104. data/lib/action_dispatch/middleware/request_id.rb +3 -1
  105. data/lib/action_dispatch/middleware/session/abstract_store.rb +17 -1
  106. data/lib/action_dispatch/middleware/session/cache_store.rb +13 -6
  107. data/lib/action_dispatch/middleware/session/cookie_store.rb +31 -32
  108. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -0
  109. data/lib/action_dispatch/middleware/show_exceptions.rb +3 -1
  110. data/lib/action_dispatch/middleware/ssl.rb +44 -38
  111. data/lib/action_dispatch/middleware/stack.rb +4 -2
  112. data/lib/action_dispatch/middleware/static.rb +14 -12
  113. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
  114. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
  115. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +1 -0
  116. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +6 -2
  117. data/lib/action_dispatch/railtie.rb +11 -1
  118. data/lib/action_dispatch/request/session.rb +16 -5
  119. data/lib/action_dispatch/request/utils.rb +6 -4
  120. data/lib/action_dispatch/routing.rb +3 -1
  121. data/lib/action_dispatch/routing/endpoint.rb +9 -2
  122. data/lib/action_dispatch/routing/inspector.rb +6 -4
  123. data/lib/action_dispatch/routing/mapper.rb +64 -52
  124. data/lib/action_dispatch/routing/polymorphic_routes.rb +2 -0
  125. data/lib/action_dispatch/routing/redirection.rb +7 -5
  126. data/lib/action_dispatch/routing/route_set.rb +29 -24
  127. data/lib/action_dispatch/routing/routes_proxy.rb +5 -2
  128. data/lib/action_dispatch/routing/url_for.rb +25 -5
  129. data/lib/action_dispatch/system_test_case.rb +22 -6
  130. data/lib/action_dispatch/system_testing/browser.rb +49 -0
  131. data/lib/action_dispatch/system_testing/driver.rb +9 -3
  132. data/lib/action_dispatch/system_testing/server.rb +2 -16
  133. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +12 -14
  134. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +8 -2
  135. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
  136. data/lib/action_dispatch/testing/assertion_response.rb +2 -0
  137. data/lib/action_dispatch/testing/assertions.rb +2 -0
  138. data/lib/action_dispatch/testing/assertions/response.rb +4 -2
  139. data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
  140. data/lib/action_dispatch/testing/integration.rb +24 -21
  141. data/lib/action_dispatch/testing/request_encoder.rb +3 -1
  142. data/lib/action_dispatch/testing/test_process.rb +2 -0
  143. data/lib/action_dispatch/testing/test_request.rb +3 -1
  144. data/lib/action_dispatch/testing/test_response.rb +23 -3
  145. data/lib/action_pack.rb +3 -1
  146. data/lib/action_pack/gem_version.rb +5 -3
  147. data/lib/action_pack/version.rb +2 -0
  148. metadata +23 -11
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionController
2
4
  module Redirecting
3
5
  extend ActiveSupport::Concern
@@ -29,7 +31,7 @@ module ActionController
29
31
  # redirect_to post_url(@post), status: 301
30
32
  # redirect_to action: 'atom', status: 302
31
33
  #
32
- # The status code can either be a standard {HTTP Status code}[http://www.iana.org/assignments/http-status-codes] as an
34
+ # The status code can either be a standard {HTTP Status code}[https://www.iana.org/assignments/http-status-codes] as an
33
35
  # integer, or a symbol representing the downcased, underscored and symbolized description.
34
36
  # Note that the status code must be a 3xx HTTP code, or redirection will not occur.
35
37
  #
@@ -66,7 +68,7 @@ module ActionController
66
68
  # if possible, otherwise redirects to the provided default fallback
67
69
  # location.
68
70
  #
69
- # The referrer information is pulled from the HTTP `Referer` (sic) header on
71
+ # The referrer information is pulled from the HTTP +Referer+ (sic) header on
70
72
  # the request. This is an optional header and its presence on the request is
71
73
  # subject to browser security settings and user preferences. If the request
72
74
  # is missing this header, the <tt>fallback_location</tt> will be used.
@@ -77,15 +79,18 @@ module ActionController
77
79
  # redirect_back fallback_location: "/images/screenshot.jpg"
78
80
  # redirect_back fallback_location: posts_url
79
81
  # redirect_back fallback_location: proc { edit_post_url(@post) }
82
+ # redirect_back fallback_location: '/', allow_other_host: false
83
+ #
84
+ # ==== Options
85
+ # * <tt>:fallback_location</tt> - The default fallback location that will be used on missing +Referer+ header.
86
+ # * <tt>:allow_other_host</tt> - Allow or disallow redirection to the host that is different to the current host, defaults to true.
80
87
  #
81
- # All options that can be passed to <tt>redirect_to</tt> are accepted as
88
+ # All other options that can be passed to <tt>redirect_to</tt> are accepted as
82
89
  # options and the behavior is identical.
83
- def redirect_back(fallback_location:, **args)
84
- if referer = request.headers["Referer"]
85
- redirect_to referer, **args
86
- else
87
- redirect_to fallback_location, **args
88
- end
90
+ def redirect_back(fallback_location:, allow_other_host: true, **args)
91
+ referer = request.headers["Referer"]
92
+ redirect_to_referer = referer && (allow_other_host || _url_host_allowed?(referer))
93
+ redirect_to redirect_to_referer ? referer : fallback_location, **args
89
94
  end
90
95
 
91
96
  def _compute_redirect_to_location(request, options) #:nodoc:
@@ -93,14 +98,14 @@ module ActionController
93
98
  # The scheme name consist of a letter followed by any combination of
94
99
  # letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
95
100
  # characters; and is terminated by a colon (":").
96
- # See http://tools.ietf.org/html/rfc3986#section-3.1
101
+ # See https://tools.ietf.org/html/rfc3986#section-3.1
97
102
  # The protocol relative scheme starts with a double slash "//".
98
103
  when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i
99
104
  options
100
105
  when String
101
106
  request.protocol + request.host_with_port + options
102
107
  when Proc
103
- _compute_redirect_to_location request, options.call
108
+ _compute_redirect_to_location request, instance_eval(&options)
104
109
  else
105
110
  url_for(options)
106
111
  end.delete("\0\r\n")
@@ -118,5 +123,11 @@ module ActionController
118
123
  302
119
124
  end
120
125
  end
126
+
127
+ def _url_host_allowed?(url)
128
+ URI(url.to_s).host == request.host
129
+ rescue ArgumentError, URI::Error
130
+ false
131
+ end
121
132
  end
122
133
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
 
3
5
  module ActionController
@@ -26,8 +28,7 @@ module ActionController
26
28
  RENDERERS = Set.new
27
29
 
28
30
  included do
29
- class_attribute :_renderers
30
- self._renderers = Set.new.freeze
31
+ class_attribute :_renderers, default: Set.new.freeze
31
32
  end
32
33
 
33
34
  # Used in <tt>ActionController::Base</tt>
@@ -84,7 +85,7 @@ module ActionController
84
85
  def self.remove(key)
85
86
  RENDERERS.delete(key.to_sym)
86
87
  method_name = _render_with_renderer_method_name(key)
87
- remove_method(method_name) if method_defined?(method_name)
88
+ remove_possible_method(method_name)
88
89
  end
89
90
 
90
91
  def self._render_with_renderer_method_name(key)
@@ -1,4 +1,4 @@
1
- require "active_support/core_ext/string/filters"
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActionController
4
4
  module Rendering
@@ -40,7 +40,7 @@ module ActionController
40
40
  def render_to_string(*)
41
41
  result = super
42
42
  if result.respond_to?(:each)
43
- string = ""
43
+ string = "".dup
44
44
  result.each { |r| string << r }
45
45
  string
46
46
  else
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rack/session/abstract/id"
2
4
  require "action_controller/metal/exceptions"
3
5
  require "active_support/security_utils"
6
+ require "active_support/core_ext/string/strip"
4
7
 
5
8
  module ActionController #:nodoc:
6
9
  class InvalidAuthenticityToken < ActionControllerError #:nodoc:
@@ -20,7 +23,7 @@ module ActionController #:nodoc:
20
23
  # Since HTML and JavaScript requests are typically made from the browser, we
21
24
  # need to ensure to verify request authenticity for the web browser. We can
22
25
  # use session-oriented authentication for these types of requests, by using
23
- # the `protect_from_forgery` method in our controllers.
26
+ # the <tt>protect_from_forgery</tt> method in our controllers.
24
27
  #
25
28
  # GET requests are not protected since they don't have side effects like writing
26
29
  # to the database and don't leak sensitive information. JavaScript requests are
@@ -85,6 +88,10 @@ module ActionController #:nodoc:
85
88
  config_accessor :per_form_csrf_tokens
86
89
  self.per_form_csrf_tokens = false
87
90
 
91
+ # Controls whether forgery protection is enabled by default.
92
+ config_accessor :default_protect_from_forgery
93
+ self.default_protect_from_forgery = false
94
+
88
95
  helper_method :form_authenticity_token
89
96
  helper_method :protect_against_forgery?
90
97
  end
@@ -128,6 +135,15 @@ module ActionController #:nodoc:
128
135
  append_after_action :verify_same_origin_request
129
136
  end
130
137
 
138
+ # Turn off request forgery protection. This is a wrapper for:
139
+ #
140
+ # skip_before_action :verify_authenticity_token
141
+ #
142
+ # See +skip_before_action+ for allowed options.
143
+ def skip_forgery_protection(options = {})
144
+ skip_before_action :verify_authenticity_token, options
145
+ end
146
+
131
147
  private
132
148
 
133
149
  def protection_method_class(name)
@@ -201,7 +217,7 @@ module ActionController #:nodoc:
201
217
  # The actual before_action that is used to verify the CSRF token.
202
218
  # Don't override this directly. Provide your own forgery protection
203
219
  # strategy instead. If you override, you'll disable same-origin
204
- # `<script>` verification.
220
+ # <tt><script></tt> verification.
205
221
  #
206
222
  # Lean on the protect_from_forgery declaration to mark which actions are
207
223
  # due for same-origin request verification. If protect_from_forgery is
@@ -233,8 +249,9 @@ module ActionController #:nodoc:
233
249
  "If you know what you're doing, go ahead and disable forgery " \
234
250
  "protection on this action to permit cross-origin JavaScript embedding."
235
251
  private_constant :CROSS_ORIGIN_JAVASCRIPT_WARNING
252
+ # :startdoc:
236
253
 
237
- # If `verify_authenticity_token` was run (indicating that we have
254
+ # If +verify_authenticity_token+ was run (indicating that we have
238
255
  # forgery protection enabled for this request) then also verify that
239
256
  # we aren't serving an unauthorized cross-origin response.
240
257
  def verify_same_origin_request # :doc:
@@ -251,7 +268,7 @@ module ActionController #:nodoc:
251
268
  @marked_for_same_origin_verification = request.get?
252
269
  end
253
270
 
254
- # If the `verify_authenticity_token` before_action ran, verify that
271
+ # If the +verify_authenticity_token+ before_action ran, verify that
255
272
  # JavaScript responses are only served to same-origin GET requests.
256
273
  def marked_for_same_origin_verification? # :doc:
257
274
  @marked_for_same_origin_verification ||= false
@@ -301,13 +318,15 @@ module ActionController #:nodoc:
301
318
  action_path = normalize_action_path(action)
302
319
  per_form_csrf_token(session, action_path, method)
303
320
  else
304
- real_csrf_token(session)
321
+ global_csrf_token(session)
305
322
  end
306
323
 
307
324
  one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
308
325
  encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
309
326
  masked_token = one_time_pad + encrypted_csrf_token
310
- Base64.strict_encode64(masked_token)
327
+ Base64.urlsafe_encode64(masked_token, padding: false)
328
+
329
+ mask_token(raw_token)
311
330
  end
312
331
 
313
332
  # Checks the client's masked token to see if it matches the
@@ -337,7 +356,8 @@ module ActionController #:nodoc:
337
356
  elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
338
357
  csrf_token = unmask_token(masked_token)
339
358
 
340
- compare_with_real_token(csrf_token, session) ||
359
+ compare_with_global_token(csrf_token, session) ||
360
+ compare_with_real_token(csrf_token, session) ||
341
361
  valid_per_form_csrf_token?(csrf_token, session)
342
362
  else
343
363
  false # Token is malformed.
@@ -352,8 +372,19 @@ module ActionController #:nodoc:
352
372
  xor_byte_strings(one_time_pad, encrypted_csrf_token)
353
373
  end
354
374
 
375
+ def mask_token(raw_token) # :doc:
376
+ one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
377
+ encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
378
+ masked_token = one_time_pad + encrypted_csrf_token
379
+ Base64.strict_encode64(masked_token)
380
+ end
381
+
355
382
  def compare_with_real_token(token, session) # :doc:
356
- ActiveSupport::SecurityUtils.secure_compare(token, real_csrf_token(session))
383
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, real_csrf_token(session))
384
+ end
385
+
386
+ def compare_with_global_token(token, session) # :doc:
387
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, global_csrf_token(session))
357
388
  end
358
389
 
359
390
  def valid_per_form_csrf_token?(token, session) # :doc:
@@ -364,7 +395,7 @@ module ActionController #:nodoc:
364
395
  request.request_method
365
396
  )
366
397
 
367
- ActiveSupport::SecurityUtils.secure_compare(token, correct_token)
398
+ ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, correct_token)
368
399
  else
369
400
  false
370
401
  end
@@ -376,10 +407,21 @@ module ActionController #:nodoc:
376
407
  end
377
408
 
378
409
  def per_form_csrf_token(session, action_path, method) # :doc:
410
+ csrf_token_hmac(session, [action_path, method.downcase].join("#"))
411
+ end
412
+
413
+ GLOBAL_CSRF_TOKEN_IDENTIFIER = "!real_csrf_token"
414
+ private_constant :GLOBAL_CSRF_TOKEN_IDENTIFIER
415
+
416
+ def global_csrf_token(session) # :doc:
417
+ csrf_token_hmac(session, GLOBAL_CSRF_TOKEN_IDENTIFIER)
418
+ end
419
+
420
+ def csrf_token_hmac(session, identifier) # :doc:
379
421
  OpenSSL::HMAC.digest(
380
422
  OpenSSL::Digest::SHA256.new,
381
423
  real_csrf_token(session),
382
- [action_path, method.downcase].join("#")
424
+ identifier
383
425
  )
384
426
  end
385
427
 
@@ -399,11 +441,21 @@ module ActionController #:nodoc:
399
441
  allow_forgery_protection
400
442
  end
401
443
 
444
+ NULL_ORIGIN_MESSAGE = <<-MSG.strip_heredoc
445
+ The browser returned a 'null' origin for a request with origin-based forgery protection turned on. This usually
446
+ means you have the 'no-referrer' Referrer-Policy header enabled, or that the request came from a site that
447
+ refused to give its origin. This makes it impossible for Rails to verify the source of the requests. Likely the
448
+ best solution is to change your referrer policy to something less strict like same-origin or strict-same-origin.
449
+ If you cannot change the referrer policy, you can disable origin checking with the
450
+ Rails.application.config.action_controller.forgery_protection_origin_check setting.
451
+ MSG
452
+
402
453
  # Checks if the request originated from the same origin by looking at the
403
454
  # Origin header.
404
455
  def valid_request_origin? # :doc:
405
456
  if forgery_protection_origin_check
406
457
  # We accept blank origin headers because some user agents don't send it.
458
+ raise InvalidAuthenticityToken, NULL_ORIGIN_MESSAGE if request.origin == "null"
407
459
  request.origin.nil? || request.origin == request.base_url
408
460
  else
409
461
  true
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActionController #:nodoc:
2
- # This module is responsible for providing `rescue_from` helpers
4
+ # This module is responsible for providing +rescue_from+ helpers
3
5
  # to controllers and configuring when detailed exceptions must be
4
6
  # shown.
5
7
  module Rescue
@@ -8,8 +10,8 @@ module ActionController #:nodoc:
8
10
 
9
11
  # Override this method if you want to customize when detailed
10
12
  # exceptions must be shown. This method is only called when
11
- # consider_all_requests_local is false. By default, it returns
12
- # false, but someone may set it to `request.local?` so local
13
+ # +consider_all_requests_local+ is +false+. By default, it returns
14
+ # +false+, but someone may set it to <tt>request.local?</tt> so local
13
15
  # requests in production still show the detailed exception pages.
14
16
  def show_detailed_exceptions?
15
17
  false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rack/chunked"
2
4
 
3
5
  module ActionController #:nodoc:
@@ -181,7 +183,7 @@ module ActionController #:nodoc:
181
183
  # unicorn_rails --config-file unicorn.config.rb
182
184
  #
183
185
  # You may also want to configure other parameters like <tt>:tcp_nodelay</tt>.
184
- # Please check its documentation for more information: http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-listen
186
+ # Please check its documentation for more information: https://bogomips.org/unicorn/Unicorn/Configurator.html#method-i-listen
185
187
  #
186
188
  # If you are using Unicorn with NGINX, you may need to tweak NGINX.
187
189
  # Streaming should work out of the box on Rainbows.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/indifferent_access"
2
4
  require "active_support/core_ext/hash/transform_values"
3
5
  require "active_support/core_ext/array/wrap"
@@ -119,8 +121,7 @@ module ActionController
119
121
  # params[:key] # => "value"
120
122
  # params["key"] # => "value"
121
123
  class Parameters
122
- cattr_accessor :permit_all_parameters, instance_accessor: false
123
- self.permit_all_parameters = false
124
+ cattr_accessor :permit_all_parameters, instance_accessor: false, default: false
124
125
 
125
126
  cattr_accessor :action_on_unpermitted_parameters, instance_accessor: false
126
127
 
@@ -185,6 +186,7 @@ module ActionController
185
186
  #
186
187
  # :call-seq:
187
188
  # to_s()
189
+ #
188
190
  # Returns the content of the parameters as a string.
189
191
 
190
192
  ##
@@ -212,8 +214,7 @@ module ActionController
212
214
  # config. For instance:
213
215
  #
214
216
  # config.always_permitted_parameters = %w( controller action format )
215
- cattr_accessor :always_permitted_parameters
216
- self.always_permitted_parameters = %w( controller action )
217
+ cattr_accessor :always_permitted_parameters, default: %w( controller action )
217
218
 
218
219
  # Returns a new instance of <tt>ActionController::Parameters</tt>.
219
220
  # Also, sets the +permitted+ attribute to the default value of
@@ -254,7 +255,7 @@ module ActionController
254
255
  # oddity: "Heavy stone crab"
255
256
  # })
256
257
  # params.to_h
257
- # # => ActionController::UnfilteredParameters: unable to convert unfiltered parameters to hash
258
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
258
259
  #
259
260
  # safe_params = params.permit(:name)
260
261
  # safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
@@ -274,7 +275,7 @@ module ActionController
274
275
  # oddity: "Heavy stone crab"
275
276
  # })
276
277
  # params.to_hash
277
- # # => ActionController::UnfilteredParameters: unable to convert unfiltered parameters to hash
278
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
278
279
  #
279
280
  # safe_params = params.permit(:name)
280
281
  # safe_params.to_hash # => {"name"=>"Senjougahara Hitagi"}
@@ -290,6 +291,10 @@ module ActionController
290
291
  # nationality: "Danish"
291
292
  # })
292
293
  # params.to_query
294
+ # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
295
+ #
296
+ # safe_params = params.permit(:name, :nationality)
297
+ # safe_params.to_query
293
298
  # # => "name=David&nationality=Danish"
294
299
  #
295
300
  # An optional namespace can be passed to enclose key names:
@@ -298,7 +303,8 @@ module ActionController
298
303
  # name: "David",
299
304
  # nationality: "Danish"
300
305
  # })
301
- # params.to_query("user")
306
+ # safe_params = params.permit(:name, :nationality)
307
+ # safe_params.to_query("user")
302
308
  # # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
303
309
  #
304
310
  # The string pairs "key=value" that conform the query string
@@ -329,8 +335,10 @@ module ActionController
329
335
  # the same way as <tt>Hash#each_pair</tt>.
330
336
  def each_pair(&block)
331
337
  @parameters.each_pair do |key, value|
332
- yield key, convert_hashes_to_parameters(key, value)
338
+ yield [key, convert_hashes_to_parameters(key, value)]
333
339
  end
340
+
341
+ self
334
342
  end
335
343
  alias_method :each, :each_pair
336
344
 
@@ -369,7 +377,7 @@ module ActionController
369
377
  # Person.new(params) # => #<Person id: nil, name: "Francesco">
370
378
  def permit!
371
379
  each_pair do |key, value|
372
- Array.wrap(value).each do |v|
380
+ Array.wrap(value).flatten.each do |v|
373
381
  v.permit! if v.respond_to? :permit!
374
382
  end
375
383
  end
@@ -555,12 +563,14 @@ module ActionController
555
563
  # Returns a parameter for the given +key+. If the +key+
556
564
  # can't be found, there are several options: With no other arguments,
557
565
  # it will raise an <tt>ActionController::ParameterMissing</tt> error;
558
- # if more arguments are given, then that will be returned; if a block
566
+ # if a second argument is given, then that is returned (converted to an
567
+ # instance of ActionController::Parameters if possible); if a block
559
568
  # is given, then that will be run and its result returned.
560
569
  #
561
570
  # params = ActionController::Parameters.new(person: { name: "Francesco" })
562
571
  # params.fetch(:person) # => <ActionController::Parameters {"name"=>"Francesco"} permitted: false>
563
572
  # params.fetch(:none) # => ActionController::ParameterMissing: param is missing or the value is empty: none
573
+ # params.fetch(:none, {}) # => <ActionController::Parameters {} permitted: false>
564
574
  # params.fetch(:none, "Francesco") # => "Francesco"
565
575
  # params.fetch(:none) { "Francesco" } # => "Francesco"
566
576
  def fetch(key, *args)
@@ -586,7 +596,8 @@ module ActionController
586
596
  # params2 = ActionController::Parameters.new(foo: [10, 11, 12])
587
597
  # params2.dig(:foo, 1) # => 11
588
598
  def dig(*keys)
589
- convert_value_to_parameters(@parameters.dig(*keys))
599
+ convert_hashes_to_parameters(keys.first, @parameters[keys.first])
600
+ @parameters.dig(*keys)
590
601
  end
591
602
  end
592
603
 
@@ -633,20 +644,18 @@ module ActionController
633
644
  # params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
634
645
  # params.transform_values { |x| x * 2 }
635
646
  # # => <ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
636
- def transform_values(&block)
637
- if block
638
- new_instance_with_inherited_permitted_status(
639
- @parameters.transform_values(&block)
640
- )
641
- else
642
- @parameters.transform_values
643
- end
647
+ def transform_values
648
+ return to_enum(:transform_values) unless block_given?
649
+ new_instance_with_inherited_permitted_status(
650
+ @parameters.transform_values { |v| yield convert_value_to_parameters(v) }
651
+ )
644
652
  end
645
653
 
646
654
  # Performs values transformation and returns the altered
647
655
  # <tt>ActionController::Parameters</tt> instance.
648
- def transform_values!(&block)
649
- @parameters.transform_values!(&block)
656
+ def transform_values!
657
+ return to_enum(:transform_values!) unless block_given?
658
+ @parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
650
659
  self
651
660
  end
652
661
 
@@ -669,10 +678,10 @@ module ActionController
669
678
  self
670
679
  end
671
680
 
672
- # Deletes and returns a key-value pair from +Parameters+ whose key is equal
673
- # to key. If the key is not found, returns the default value. If the
674
- # optional code block is given and the key is not found, pass in the key
675
- # and return the result of block.
681
+ # Deletes a key-value pair from +Parameters+ and returns the value. If
682
+ # +key+ is not found, returns +nil+ (or, with optional code block, yields
683
+ # +key+ and returns the result). Cf. +#extract!+, which returns the
684
+ # corresponding +ActionController::Parameters+ object.
676
685
  def delete(key, &block)
677
686
  convert_value_to_parameters(@parameters.delete(key, &block))
678
687
  end
@@ -731,6 +740,7 @@ module ActionController
731
740
  other_hash.to_h.merge(@parameters)
732
741
  )
733
742
  end
743
+ alias_method :with_defaults, :reverse_merge
734
744
 
735
745
  # Returns current <tt>ActionController::Parameters</tt> instance with
736
746
  # current hash merged into +other_hash+.
@@ -738,6 +748,7 @@ module ActionController
738
748
  @parameters.merge!(other_hash.to_h) { |key, left, right| left }
739
749
  self
740
750
  end
751
+ alias_method :with_defaults!, :reverse_merge!
741
752
 
742
753
  # This is required by ActiveModel attribute assignment, so that user can
743
754
  # pass +Parameters+ to a mass assignment methods in a model. It should not