actionpack 7.0.2.4 → 7.0.4
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.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +80 -0
- data/lib/abstract_controller/base.rb +6 -5
- data/lib/abstract_controller/callbacks.rb +1 -1
- data/lib/abstract_controller/helpers.rb +1 -1
- data/lib/action_controller/api.rb +5 -5
- data/lib/action_controller/base.rb +5 -4
- data/lib/action_controller/form_builder.rb +2 -2
- data/lib/action_controller/metal/conditional_get.rb +1 -1
- data/lib/action_controller/metal/content_security_policy.rb +35 -1
- data/lib/action_controller/metal/helpers.rb +1 -1
- data/lib/action_controller/metal/http_authentication.rb +56 -29
- data/lib/action_controller/metal/live.rb +1 -0
- data/lib/action_controller/metal/permissions_policy.rb +18 -27
- data/lib/action_controller/metal/redirecting.rb +4 -3
- data/lib/action_controller/metal/renderers.rb +10 -11
- data/lib/action_controller/metal/rendering.rb +3 -3
- data/lib/action_controller/metal/request_forgery_protection.rb +4 -4
- data/lib/action_controller/metal/streaming.rb +5 -5
- data/lib/action_controller/metal/strong_parameters.rb +13 -4
- data/lib/action_controller/metal/url_for.rb +3 -3
- data/lib/action_controller/metal.rb +3 -3
- data/lib/action_controller/renderer.rb +1 -1
- data/lib/action_controller/test_case.rb +3 -3
- data/lib/action_controller.rb +1 -0
- data/lib/action_dispatch/http/content_security_policy.rb +71 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +2 -2
- data/lib/action_dispatch/http/permissions_policy.rb +16 -0
- data/lib/action_dispatch/http/request.rb +2 -2
- data/lib/action_dispatch/http/response.rb +2 -3
- data/lib/action_dispatch/middleware/cookies.rb +6 -3
- data/lib/action_dispatch/middleware/flash.rb +8 -7
- data/lib/action_dispatch/middleware/request_id.rb +1 -1
- data/lib/action_dispatch/middleware/server_timing.rb +53 -10
- data/lib/action_dispatch/middleware/session/cookie_store.rb +9 -9
- data/lib/action_dispatch/routing/mapper.rb +5 -5
- data/lib/action_dispatch/routing/redirection.rb +5 -0
- data/lib/action_dispatch/routing/route_set.rb +3 -1
- data/lib/action_dispatch/routing/url_for.rb +3 -3
- data/lib/action_dispatch/routing.rb +3 -4
- data/lib/action_dispatch/testing/assertions/routing.rb +3 -2
- data/lib/action_dispatch/testing/test_response.rb +20 -2
- data/lib/action_pack/gem_version.rb +3 -3
- data/lib/action_pack/version.rb +1 -1
- metadata +12 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f920e0c8edecebb6708efc39f5bc4de2d9dd1beb20b11fac4c2408406ef4812
|
4
|
+
data.tar.gz: e87d2d36beb62a55feb9677d7009725531c2187692099d41682014822e478204
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ed2fb214470bb89c3a6c6101428806f6ebb2eb01044cc8426dddecdb189a541511aa7355b07f13e898a076a2a7f9b3eabefdfdfb7130918c216993da503e173
|
7
|
+
data.tar.gz: 0c4a9b5b27a03faec9e2d971cce098cb943fbdc7bf0cb25ba243755bfa72760c2a0eefc18e80134877f2a382d7d154deee64faaccacbe557768a978771873ee4
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,83 @@
|
|
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
|
+
|
1
81
|
## Rails 7.0.2.4 (April 26, 2022) ##
|
2
82
|
|
3
83
|
* Allow Content Security Policy DSL to generate for API responses.
|
@@ -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
|
-
#
|
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(
|
214
|
-
send_action(
|
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
|
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
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
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
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
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
|
-
#
|
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
|
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
|
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
|
@@ -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")
|
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
|
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
|
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
|
-
#
|
432
|
-
#
|
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
|
-
#
|
435
|
-
#
|
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
|
-
#
|
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
|
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
|
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
|