actionpack 7.0.2.3 → 7.0.4

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -0
  3. data/lib/abstract_controller/base.rb +6 -5
  4. data/lib/abstract_controller/callbacks.rb +1 -1
  5. data/lib/abstract_controller/helpers.rb +1 -1
  6. data/lib/action_controller/api.rb +5 -5
  7. data/lib/action_controller/base.rb +5 -4
  8. data/lib/action_controller/form_builder.rb +2 -2
  9. data/lib/action_controller/metal/conditional_get.rb +1 -1
  10. data/lib/action_controller/metal/content_security_policy.rb +35 -1
  11. data/lib/action_controller/metal/helpers.rb +1 -1
  12. data/lib/action_controller/metal/http_authentication.rb +56 -29
  13. data/lib/action_controller/metal/live.rb +1 -0
  14. data/lib/action_controller/metal/permissions_policy.rb +18 -27
  15. data/lib/action_controller/metal/redirecting.rb +4 -3
  16. data/lib/action_controller/metal/renderers.rb +10 -11
  17. data/lib/action_controller/metal/rendering.rb +3 -3
  18. data/lib/action_controller/metal/request_forgery_protection.rb +4 -4
  19. data/lib/action_controller/metal/streaming.rb +5 -5
  20. data/lib/action_controller/metal/strong_parameters.rb +13 -4
  21. data/lib/action_controller/metal/url_for.rb +3 -3
  22. data/lib/action_controller/metal.rb +3 -3
  23. data/lib/action_controller/renderer.rb +1 -1
  24. data/lib/action_controller/test_case.rb +3 -3
  25. data/lib/action_controller.rb +1 -0
  26. data/lib/action_dispatch/http/content_security_policy.rb +71 -8
  27. data/lib/action_dispatch/http/mime_negotiation.rb +2 -2
  28. data/lib/action_dispatch/http/permissions_policy.rb +16 -0
  29. data/lib/action_dispatch/http/request.rb +2 -2
  30. data/lib/action_dispatch/http/response.rb +2 -3
  31. data/lib/action_dispatch/middleware/cookies.rb +6 -3
  32. data/lib/action_dispatch/middleware/flash.rb +8 -7
  33. data/lib/action_dispatch/middleware/request_id.rb +1 -1
  34. data/lib/action_dispatch/middleware/server_timing.rb +53 -10
  35. data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
  36. data/lib/action_dispatch/routing/mapper.rb +5 -5
  37. data/lib/action_dispatch/routing/redirection.rb +5 -0
  38. data/lib/action_dispatch/routing/route_set.rb +3 -1
  39. data/lib/action_dispatch/routing/url_for.rb +3 -3
  40. data/lib/action_dispatch/routing.rb +3 -4
  41. data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
  42. data/lib/action_dispatch/testing/test_response.rb +20 -2
  43. data/lib/action_pack/gem_version.rb +3 -3
  44. data/lib/action_pack/version.rb +1 -1
  45. metadata +12 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 657cc8779a2d4862b16b9155972e5b6a433fb0804b961421bc9a21e4574b64b4
4
- data.tar.gz: 5421de1ffff6e80b4fe196618e8e1b7045ca88667bdde905f7f9676dd3c77808
3
+ metadata.gz: 1f920e0c8edecebb6708efc39f5bc4de2d9dd1beb20b11fac4c2408406ef4812
4
+ data.tar.gz: e87d2d36beb62a55feb9677d7009725531c2187692099d41682014822e478204
5
5
  SHA512:
6
- metadata.gz: bd6c836c0592e6f91611c11f3f10ce12f9bad8811f9ae4196f667e4f03ba78d58d896906f14567a21af70c5da3df2be78b00e118e9cff7444aea06413c6a5862
7
- data.tar.gz: 552b3c71b48abceeb9fda6ce141c23ea580e5f1085e933f99722bbcee6f6c50fec74d91c860e528f6c95d9e2a62b2620d2627d2334635b27ba5012519c338212
6
+ metadata.gz: 4ed2fb214470bb89c3a6c6101428806f6ebb2eb01044cc8426dddecdb189a541511aa7355b07f13e898a076a2a7f9b3eabefdfdfb7130918c216993da503e173
7
+ data.tar.gz: 0c4a9b5b27a03faec9e2d971cce098cb943fbdc7bf0cb25ba243755bfa72760c2a0eefc18e80134877f2a382d7d154deee64faaccacbe557768a978771873ee4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,89 @@
1
+ ## Rails 7.0.4 (September 09, 2022) ##
2
+
3
+ * Prevent `ActionDispatch::ServerTiming` from overwriting existing values in `Server-Timing`.
4
+
5
+ Previously, if another middleware down the chain set `Server-Timing` header,
6
+ it would overwritten by `ActionDispatch::ServerTiming`.
7
+
8
+ *Jakub Malinowski*
9
+
10
+
11
+ ## Rails 7.0.3.1 (July 12, 2022) ##
12
+
13
+ * No changes.
14
+
15
+
16
+ ## Rails 7.0.3 (May 09, 2022) ##
17
+
18
+ * Allow relative redirects when `raise_on_open_redirects` is enabled.
19
+
20
+ *Tom Hughes*
21
+
22
+ * Fix `authenticate_with_http_basic` to allow for missing password.
23
+
24
+ Before Rails 7.0 it was possible to handle basic authentication with only a username.
25
+
26
+ ```ruby
27
+ authenticate_with_http_basic do |token, _|
28
+ ApiClient.authenticate(token)
29
+ end
30
+ ```
31
+
32
+ This ability is restored.
33
+
34
+ *Jean Boussier*
35
+
36
+ * Fix `content_security_policy` returning invalid directives.
37
+
38
+ Directives such as `self`, `unsafe-eval` and few others were not
39
+ single quoted when the directive was the result of calling a lambda
40
+ returning an array.
41
+
42
+ ```ruby
43
+ content_security_policy do |policy|
44
+ policy.frame_ancestors lambda { [:self, "https://example.com"] }
45
+ end
46
+ ```
47
+
48
+ With this fix the policy generated from above will now be valid.
49
+
50
+ *Edouard Chin*
51
+
52
+ * Fix `skip_forgery_protection` to run without raising an error if forgery
53
+ protection has not been enabled / `verify_authenticity_token` is not a
54
+ defined callback.
55
+
56
+ This fix prevents the Rails 7.0 Welcome Page (`/`) from raising an
57
+ `ArgumentError` if `default_protect_from_forgery` is false.
58
+
59
+ *Brad Trick*
60
+
61
+ * Fix `ActionController::Live` to copy the IsolatedExecutionState in the ephemeral thread.
62
+
63
+ Since its inception `ActionController::Live` has been copying thread local variables
64
+ to keep things such as `CurrentAttributes` set from middlewares working in the controller action.
65
+
66
+ With the introduction of `IsolatedExecutionState` in 7.0, some of that global state was lost in
67
+ `ActionController::Live` controllers.
68
+
69
+ *Jean Boussier*
70
+
71
+ * Fix setting `trailing_slash: true` in route definition.
72
+
73
+ ```ruby
74
+ get '/test' => "test#index", as: :test, trailing_slash: true
75
+
76
+ test_path() # => "/test/"
77
+ ```
78
+
79
+ *Jean Boussier*
80
+
81
+ ## Rails 7.0.2.4 (April 26, 2022) ##
82
+
83
+ * Allow Content Security Policy DSL to generate for API responses.
84
+
85
+ *Tim Wade*
86
+
1
87
  ## Rails 7.0.2.3 (March 08, 2022) ##
2
88
 
3
89
  * No changes.
@@ -150,13 +150,14 @@ module AbstractController
150
150
 
151
151
  process_action(action_name, *args)
152
152
  end
153
+ ruby2_keywords(:process)
153
154
 
154
- # Delegates to the class' ::controller_path
155
+ # Delegates to the class's ::controller_path.
155
156
  def controller_path
156
157
  self.class.controller_path
157
158
  end
158
159
 
159
- # Delegates to the class' ::action_methods
160
+ # Delegates to the class's ::action_methods.
160
161
  def action_methods
161
162
  self.class.action_methods
162
163
  end
@@ -177,7 +178,7 @@ module AbstractController
177
178
 
178
179
  # Tests if a response body is set. Used to determine if the
179
180
  # +process_action+ callback needs to be terminated in
180
- # +AbstractController::Callbacks+.
181
+ # AbstractController::Callbacks.
181
182
  def performed?
182
183
  response_body
183
184
  end
@@ -210,8 +211,8 @@ module AbstractController
210
211
  #
211
212
  # Notice that the first argument is the method to be dispatched
212
213
  # which is *not* necessarily the same as the action name.
213
- def process_action(method_name, *args)
214
- send_action(method_name, *args)
214
+ def process_action(...)
215
+ send_action(...)
215
216
  end
216
217
 
217
218
  # Actually call the method associated with the action. Override
@@ -229,7 +229,7 @@ module AbstractController
229
229
  private
230
230
  # Override <tt>AbstractController::Base#process_action</tt> to run the
231
231
  # <tt>process_action</tt> callbacks around the normal behavior.
232
- def process_action(*)
232
+ def process_action(...)
233
233
  run_callbacks(:process_action) do
234
234
  super
235
235
  end
@@ -110,7 +110,7 @@ module AbstractController
110
110
  # The last two assume that <tt>"foo".camelize</tt> returns "Foo".
111
111
  #
112
112
  # When strings or symbols are passed, the method finds the actual module
113
- # object using +String#constantize+. Therefore, if the module has not been
113
+ # object using String#constantize. Therefore, if the module has not been
114
114
  # yet loaded, it has to be autoloadable, which is normally the case.
115
115
  #
116
116
  # Namespaces are supported. The following calls include +Foo::BarHelper+:
@@ -5,7 +5,7 @@ require "action_controller"
5
5
  require "action_controller/log_subscriber"
6
6
 
7
7
  module ActionController
8
- # API Controller is a lightweight version of <tt>ActionController::Base</tt>,
8
+ # API Controller is a lightweight version of ActionController::Base,
9
9
  # created for applications that don't require all functionalities that a complete
10
10
  # \Rails controller provides, allowing you to create controllers with just the
11
11
  # features that you need for API only applications.
@@ -32,7 +32,7 @@ module ActionController
32
32
  # end
33
33
  #
34
34
  # Request, response, and parameters objects all work the exact same way as
35
- # <tt>ActionController::Base</tt>.
35
+ # ActionController::Base.
36
36
  #
37
37
  # == Renders
38
38
  #
@@ -51,7 +51,7 @@ module ActionController
51
51
  #
52
52
  # Redirects are used to move from one action to another. You can use the
53
53
  # <tt>redirect_to</tt> method in your controllers in the same way as in
54
- # <tt>ActionController::Base</tt>. For example:
54
+ # ActionController::Base. For example:
55
55
  #
56
56
  # def create
57
57
  # redirect_to root_url and return if not_authorized?
@@ -61,7 +61,7 @@ module ActionController
61
61
  # == Adding New Behavior
62
62
  #
63
63
  # In some scenarios you may want to add back some functionality provided by
64
- # <tt>ActionController::Base</tt> that is not present by default in
64
+ # ActionController::Base that is not present by default in
65
65
  # <tt>ActionController::API</tt>, for instance <tt>MimeResponds</tt>. This
66
66
  # module gives you the <tt>respond_to</tt> method. Adding it is quite simple,
67
67
  # you just need to include the module in a specific controller or in
@@ -83,7 +83,7 @@ module ActionController
83
83
  # end
84
84
  # end
85
85
  #
86
- # Make sure to check the modules included in <tt>ActionController::Base</tt>
86
+ # Make sure to check the modules included in ActionController::Base
87
87
  # if you want to use any other functionality that is not provided
88
88
  # by <tt>ActionController::API</tt> out of the box.
89
89
  class API < Metal
@@ -87,10 +87,11 @@ module ActionController
87
87
  #
88
88
  # or you can remove the entire session with +reset_session+.
89
89
  #
90
- # Sessions are stored by default in a browser cookie that's cryptographically signed, but unencrypted.
91
- # This prevents the user from tampering with the session but also allows them to see its contents.
92
- #
93
- # Do not put secret information in cookie-based sessions!
90
+ # By default, sessions are stored in an encrypted browser cookie (see
91
+ # ActionDispatch::Session::CookieStore). Thus the user will not be able to
92
+ # read or edit the session data. However, the user can keep a copy of the
93
+ # cookie even after it has expired, so you should avoid storing sensitive
94
+ # information in cookie-based sessions.
94
95
  #
95
96
  # == Responses
96
97
  #
@@ -3,7 +3,7 @@
3
3
  module ActionController
4
4
  # Override the default form builder for all views rendered by this
5
5
  # controller and any of its descendants. Accepts a subclass of
6
- # +ActionView::Helpers::FormBuilder+.
6
+ # ActionView::Helpers::FormBuilder.
7
7
  #
8
8
  # For example, given a form builder:
9
9
  #
@@ -36,7 +36,7 @@ module ActionController
36
36
  # in the views rendered by this controller and its subclasses.
37
37
  #
38
38
  # ==== Parameters
39
- # * <tt>builder</tt> - Default form builder, an instance of +ActionView::Helpers::FormBuilder+
39
+ # * <tt>builder</tt> - Default form builder, an instance of ActionView::Helpers::FormBuilder
40
40
  def default_form_builder(builder)
41
41
  self._default_form_builder = builder
42
42
  end
@@ -268,7 +268,7 @@ module ActionController
268
268
  # expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds, stale_if_error: 5.minutes
269
269
  #
270
270
  # HTTP Cache-Control Extensions other values: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
271
- # Any additional key-value pairs are concatenated onto the `Cache-Control` header in the response:
271
+ # Any additional key-value pairs are concatenated onto the Cache-Control header in the response:
272
272
  #
273
273
  # expires_in 3.hours, public: true, "s-maxage": 3.hours, "no-transform": true
274
274
  #
@@ -2,7 +2,6 @@
2
2
 
3
3
  module ActionController # :nodoc:
4
4
  module ContentSecurityPolicy
5
- # TODO: Documentation
6
5
  extend ActiveSupport::Concern
7
6
 
8
7
  include AbstractController::Helpers
@@ -14,6 +13,29 @@ module ActionController # :nodoc:
14
13
  end
15
14
 
16
15
  module ClassMethods
16
+ # Overrides parts of the globally configured Content-Security-Policy
17
+ # header:
18
+ #
19
+ # class PostsController < ApplicationController
20
+ # content_security_policy do |policy|
21
+ # policy.base_uri "https://www.example.com"
22
+ # end
23
+ # end
24
+ #
25
+ # Options can be passed similar to +before_action+. For example, pass
26
+ # <tt>only: :index</tt> to override the header on the index action only:
27
+ #
28
+ # class PostsController < ApplicationController
29
+ # content_security_policy(only: :index) do |policy|
30
+ # policy.default_src :self, :https
31
+ # end
32
+ # end
33
+ #
34
+ # Pass +false+ to remove the Content-Security-Policy header:
35
+ #
36
+ # class PostsController < ApplicationController
37
+ # content_security_policy false, only: :index
38
+ # end
17
39
  def content_security_policy(enabled = true, **options, &block)
18
40
  before_action(options) do
19
41
  if block_given?
@@ -28,6 +50,18 @@ module ActionController # :nodoc:
28
50
  end
29
51
  end
30
52
 
53
+ # Overrides the globally configured Content-Security-Policy-Report-Only
54
+ # header:
55
+ #
56
+ # class PostsController < ApplicationController
57
+ # content_security_policy_report_only only: :index
58
+ # end
59
+ #
60
+ # Pass +false+ to remove the Content-Security-Policy-Report-Only header:
61
+ #
62
+ # class PostsController < ApplicationController
63
+ # content_security_policy_report_only false, only: :index
64
+ # end
31
65
  def content_security_policy_report_only(report_only = true, **options)
32
66
  before_action(options) do
33
67
  request.content_security_policy_report_only = report_only
@@ -91,7 +91,7 @@ module ActionController
91
91
  end
92
92
  end
93
93
 
94
- # Overwrite modules_for_helpers to accept :all as argument, which loads
94
+ # Override modules_for_helpers to accept +:all+ as argument, which loads
95
95
  # all helpers in helpers_path.
96
96
  #
97
97
  # ==== Parameters
@@ -5,9 +5,9 @@ require "active_support/security_utils"
5
5
  require "active_support/core_ext/array/access"
6
6
 
7
7
  module ActionController
8
- # HTTP Basic, Digest and Token authentication.
8
+ # HTTP Basic, Digest, and Token authentication.
9
9
  module HttpAuthentication
10
- # HTTP \Basic authentication.
10
+ # = HTTP \Basic authentication
11
11
  #
12
12
  # === Simple \Basic example
13
13
  #
@@ -70,7 +70,12 @@ module ActionController
70
70
  extend ActiveSupport::Concern
71
71
 
72
72
  module ClassMethods
73
+ # Enables HTTP \Basic authentication.
74
+ #
75
+ # See ActionController::HttpAuthentication::Basic for example usage.
73
76
  def http_basic_authenticate_with(name:, password:, realm: nil, **options)
77
+ raise ArgumentError, "Expected name: to be a String, got #{name.class}" unless name.is_a?(String)
78
+ raise ArgumentError, "Expected password: to be a String, got #{password.class}" unless password.is_a?(String)
74
79
  before_action(options) { http_basic_authenticate_or_request_with name: name, password: password, realm: realm }
75
80
  end
76
81
  end
@@ -79,8 +84,8 @@ module ActionController
79
84
  authenticate_or_request_with_http_basic(realm, message) do |given_name, given_password|
80
85
  # This comparison uses & so that it doesn't short circuit and
81
86
  # uses `secure_compare` so that length information isn't leaked.
82
- ActiveSupport::SecurityUtils.secure_compare(given_name, name) &
83
- ActiveSupport::SecurityUtils.secure_compare(given_password, password)
87
+ ActiveSupport::SecurityUtils.secure_compare(given_name.to_s, name) &
88
+ ActiveSupport::SecurityUtils.secure_compare(given_password.to_s, password)
84
89
  end
85
90
  end
86
91
 
@@ -104,7 +109,7 @@ module ActionController
104
109
  end
105
110
 
106
111
  def has_basic_credentials?(request)
107
- request.authorization.present? && (auth_scheme(request).downcase == "basic") && user_name_and_password(request).length == 2
112
+ request.authorization.present? && (auth_scheme(request).downcase == "basic")
108
113
  end
109
114
 
110
115
  def user_name_and_password(request)
@@ -135,7 +140,7 @@ module ActionController
135
140
  end
136
141
  end
137
142
 
138
- # HTTP \Digest authentication.
143
+ # = HTTP \Digest authentication
139
144
  #
140
145
  # === Simple \Digest example
141
146
  #
@@ -181,22 +186,28 @@ module ActionController
181
186
  extend self
182
187
 
183
188
  module ControllerMethods
189
+ # Authenticate using an HTTP \Digest, or otherwise render an HTTP header
190
+ # requesting the client to send a \Digest.
191
+ #
192
+ # See ActionController::HttpAuthentication::Digest for example usage.
184
193
  def authenticate_or_request_with_http_digest(realm = "Application", message = nil, &password_procedure)
185
194
  authenticate_with_http_digest(realm, &password_procedure) || request_http_digest_authentication(realm, message)
186
195
  end
187
196
 
188
- # Authenticate with HTTP Digest, returns true or false
197
+ # Authenticate using an HTTP \Digest. Returns true if authentication is
198
+ # successful, false otherwise.
189
199
  def authenticate_with_http_digest(realm = "Application", &password_procedure)
190
200
  HttpAuthentication::Digest.authenticate(request, realm, &password_procedure)
191
201
  end
192
202
 
193
- # Render output including the HTTP Digest authentication header
203
+ # Render an HTTP header requesting the client to send a \Digest for
204
+ # authentication.
194
205
  def request_http_digest_authentication(realm = "Application", message = nil)
195
206
  HttpAuthentication::Digest.authentication_request(self, realm, message)
196
207
  end
197
208
  end
198
209
 
199
- # Returns false on a valid response, true otherwise
210
+ # Returns false on a valid response, true otherwise.
200
211
  def authenticate(request, realm, &password_procedure)
201
212
  request.authorization && validate_digest_response(request, realm, &password_procedure)
202
213
  end
@@ -301,7 +312,7 @@ module ActionController
301
312
  #
302
313
  # An implementation might choose not to accept a previously used nonce or a previously used digest, in order to
303
314
  # protect against a replay attack. Or, an implementation might choose to use one-time nonces or digests for
304
- # POST, PUT, or PATCH requests and a time-stamp for GET requests. For more details on the issues involved see Section 4
315
+ # POST, PUT, or PATCH requests, and a time-stamp for GET requests. For more details on the issues involved see Section 4
305
316
  # of this document.
306
317
  #
307
318
  # The nonce is opaque to the client. Composed of Time, and hash of Time with secret
@@ -331,9 +342,9 @@ module ActionController
331
342
  end
332
343
  end
333
344
 
334
- # HTTP Token authentication.
345
+ # = HTTP \Token authentication
335
346
  #
336
- # Simple Token example:
347
+ # === Simple \Token example
337
348
  #
338
349
  # class PostsController < ApplicationController
339
350
  # TOKEN = "secret"
@@ -412,14 +423,22 @@ module ActionController
412
423
  extend self
413
424
 
414
425
  module ControllerMethods
426
+ # Authenticate using an HTTP Bearer token, or otherwise render an HTTP
427
+ # header requesting the client to send a Bearer token.
428
+ #
429
+ # See ActionController::HttpAuthentication::Token for example usage.
415
430
  def authenticate_or_request_with_http_token(realm = "Application", message = nil, &login_procedure)
416
431
  authenticate_with_http_token(&login_procedure) || request_http_token_authentication(realm, message)
417
432
  end
418
433
 
434
+ # Authenticate using an HTTP Bearer token. Returns true if
435
+ # authentication is successful, false otherwise.
419
436
  def authenticate_with_http_token(&login_procedure)
420
437
  Token.authenticate(self, &login_procedure)
421
438
  end
422
439
 
440
+ # Render an HTTP header requesting the client to send a Bearer token for
441
+ # authentication.
423
442
  def request_http_token_authentication(realm = "Application", message = nil)
424
443
  Token.authentication_request(self, realm, message)
425
444
  end
@@ -428,17 +447,17 @@ module ActionController
428
447
  # If token Authorization header is present, call the login
429
448
  # procedure with the present token and options.
430
449
  #
431
- # [controller]
432
- # ActionController::Base instance for the current request.
450
+ # Returns the return value of <tt>login_procedure</tt> if a
451
+ # token is found. Returns <tt>nil</tt> if no token is found.
452
+ #
453
+ # ==== Parameters
433
454
  #
434
- # [login_procedure]
435
- # Proc to call if a token is present. The Proc should take two arguments:
455
+ # * +controller+ - ActionController::Base instance for the current request.
456
+ # * +login_procedure+ - Proc to call if a token is present. The Proc
457
+ # should take two arguments:
436
458
  #
437
459
  # authenticate(controller) { |token, options| ... }
438
460
  #
439
- # Returns the return value of <tt>login_procedure</tt> if a
440
- # token is found. Returns <tt>nil</tt> if no token is found.
441
-
442
461
  def authenticate(controller, &login_procedure)
443
462
  token, options = token_and_options(controller.request)
444
463
  unless token.blank?
@@ -449,14 +468,18 @@ module ActionController
449
468
  # Parses the token and options out of the token Authorization header.
450
469
  # The value for the Authorization header is expected to have the prefix
451
470
  # <tt>"Token"</tt> or <tt>"Bearer"</tt>. If the header looks like this:
471
+ #
452
472
  # Authorization: Token token="abc", nonce="def"
453
- # Then the returned token is <tt>"abc"</tt>, and the options are
454
- # <tt>{nonce: "def"}</tt>
455
473
  #
456
- # request - ActionDispatch::Request instance with the current headers.
474
+ # Then the returned token is <tt>"abc"</tt>, and the options are
475
+ # <tt>{nonce: "def"}</tt>.
457
476
  #
458
477
  # Returns an +Array+ of <tt>[String, Hash]</tt> if a token is present.
459
478
  # Returns +nil+ if no token is found.
479
+ #
480
+ # ==== Parameters
481
+ #
482
+ # * +request+ - ActionDispatch::Request instance with the current headers.
460
483
  def token_and_options(request)
461
484
  authorization_request = request.authorization.to_s
462
485
  if authorization_request[TOKEN_REGEX]
@@ -469,7 +492,7 @@ module ActionController
469
492
  rewrite_param_values params_array_from raw_params auth
470
493
  end
471
494
 
472
- # Takes raw_params and turns it into an array of parameters
495
+ # Takes +raw_params+ and turns it into an array of parameters.
473
496
  def params_array_from(raw_params)
474
497
  raw_params.map { |param| param.split %r/=(.+)?/ }
475
498
  end
@@ -494,10 +517,12 @@ module ActionController
494
517
 
495
518
  # Encodes the given token and options into an Authorization header value.
496
519
  #
497
- # token - String token.
498
- # options - optional Hash of the options.
499
- #
500
520
  # Returns String.
521
+ #
522
+ # ==== Parameters
523
+ #
524
+ # * +token+ - String token.
525
+ # * +options+ - Optional Hash of the options.
501
526
  def encode_credentials(token, options = {})
502
527
  values = ["#{TOKEN_KEY}#{token.to_s.inspect}"] + options.map do |key, value|
503
528
  "#{key}=#{value.to_s.inspect}"
@@ -507,10 +532,12 @@ module ActionController
507
532
 
508
533
  # Sets a WWW-Authenticate header to let the client know a token is desired.
509
534
  #
510
- # controller - ActionController::Base instance for the outgoing response.
511
- # realm - String realm to use in the header.
512
- #
513
535
  # Returns nothing.
536
+ #
537
+ # ==== Parameters
538
+ #
539
+ # * +controller+ - ActionController::Base instance for the outgoing response.
540
+ # * +realm+ - String realm to use in the header.
514
541
  def authentication_request(controller, realm, message = nil)
515
542
  message ||= "HTTP Token: Access denied.\n"
516
543
  controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"', "")}")
@@ -261,6 +261,7 @@ module ActionController
261
261
  # Since we're processing the view in a different thread, copy the
262
262
  # thread locals from the main thread to the child thread. :'(
263
263
  locals.each { |k, v| t2[k] = v }
264
+ ActiveSupport::IsolatedExecutionState.share_with(t1)
264
265
 
265
266
  begin
266
267
  super(name)
@@ -1,37 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActionController # :nodoc:
4
- # HTTP Permissions Policy is a web standard for defining a mechanism to
5
- # allow and deny the use of browser permissions in its own context, and
6
- # in content within any <iframe> elements in the document.
7
- #
8
- # Full details of HTTP Permissions Policy specification and guidelines can
9
- # be found at MDN:
10
- #
11
- # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
12
- #
13
- # Examples of usage:
14
- #
15
- # # Global policy
16
- # Rails.application.config.permissions_policy do |f|
17
- # f.camera :none
18
- # f.gyroscope :none
19
- # f.microphone :none
20
- # f.usb :none
21
- # f.fullscreen :self
22
- # f.payment :self, "https://secure.example.com"
23
- # end
24
- #
25
- # # Controller level policy
26
- # class PagesController < ApplicationController
27
- # permissions_policy do |p|
28
- # p.geolocation "https://example.com"
29
- # end
30
- # end
31
4
  module PermissionsPolicy
32
5
  extend ActiveSupport::Concern
33
6
 
34
7
  module ClassMethods
8
+ # Overrides parts of the globally configured Feature-Policy
9
+ # header:
10
+ #
11
+ # class PagesController < ApplicationController
12
+ # permissions_policy do |policy|
13
+ # policy.geolocation "https://example.com"
14
+ # end
15
+ # end
16
+ #
17
+ # Options can be passed similar to +before_action+. For example, pass
18
+ # <tt>only: :index</tt> to override the header on the index action only:
19
+ #
20
+ # class PagesController < ApplicationController
21
+ # permissions_policy(only: :index) do |policy|
22
+ # policy.camera :self
23
+ # end
24
+ # end
25
+ #
35
26
  def permissions_policy(**options, &block)
36
27
  before_action(options) do
37
28
  if block_given?
@@ -74,7 +74,7 @@ module ActionController
74
74
  #
75
75
  # Raises UnsafeRedirectError in the case of an unsafe redirect.
76
76
  #
77
- # To allow any external redirects pass `allow_other_host: true`, though using a user-provided param in that case is unsafe.
77
+ # To allow any external redirects pass <tt>allow_other_host: true</tt>, though using a user-provided param in that case is unsafe.
78
78
  #
79
79
  # redirect_to "https://rubyonrails.org", allow_other_host: true
80
80
  #
@@ -117,7 +117,7 @@ module ActionController
117
117
  # * <tt>:allow_other_host</tt> - Allow or disallow redirection to the host that is different to the current host, defaults to true.
118
118
  #
119
119
  # All other options that can be passed to #redirect_to are accepted as
120
- # options and the behavior is identical.
120
+ # options, and the behavior is identical.
121
121
  def redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options)
122
122
  if request.referer && (allow_other_host || _url_host_allowed?(request.referer))
123
123
  redirect_to request.referer, allow_other_host: allow_other_host, **options
@@ -195,7 +195,8 @@ module ActionController
195
195
  end
196
196
 
197
197
  def _url_host_allowed?(url)
198
- URI(url.to_s).host == request.host
198
+ host = URI(url.to_s).host
199
+ host == request.host || host.nil? && url.to_s.start_with?("/")
199
200
  rescue ArgumentError, URI::Error
200
201
  false
201
202
  end