actionpack 6.0.5.1 → 6.1.7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +382 -253
- data/MIT-LICENSE +1 -2
- data/lib/abstract_controller/base.rb +35 -2
- data/lib/abstract_controller/callbacks.rb +2 -2
- data/lib/abstract_controller/collector.rb +4 -2
- data/lib/abstract_controller/helpers.rb +105 -90
- data/lib/abstract_controller/railties/routes_helpers.rb +17 -1
- data/lib/abstract_controller/rendering.rb +9 -9
- data/lib/abstract_controller/translation.rb +8 -2
- data/lib/abstract_controller.rb +1 -0
- data/lib/action_controller/api.rb +2 -2
- data/lib/action_controller/base.rb +4 -2
- data/lib/action_controller/caching.rb +0 -1
- data/lib/action_controller/log_subscriber.rb +3 -3
- data/lib/action_controller/metal/conditional_get.rb +11 -3
- data/lib/action_controller/metal/content_security_policy.rb +1 -1
- data/lib/action_controller/metal/cookies.rb +3 -1
- data/lib/action_controller/metal/data_streaming.rb +1 -1
- data/lib/action_controller/metal/etag_with_template_digest.rb +3 -5
- data/lib/action_controller/metal/exceptions.rb +33 -0
- data/lib/action_controller/metal/head.rb +7 -4
- data/lib/action_controller/metal/helpers.rb +11 -1
- data/lib/action_controller/metal/http_authentication.rb +5 -2
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +11 -9
- data/lib/action_controller/metal/live.rb +10 -1
- data/lib/action_controller/metal/logging.rb +20 -0
- data/lib/action_controller/metal/mime_responds.rb +6 -2
- data/lib/action_controller/metal/parameter_encoding.rb +35 -4
- data/lib/action_controller/metal/params_wrapper.rb +14 -8
- data/lib/action_controller/metal/permissions_policy.rb +46 -0
- data/lib/action_controller/metal/redirecting.rb +1 -1
- data/lib/action_controller/metal/rendering.rb +6 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +1 -1
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/strong_parameters.rb +104 -16
- data/lib/action_controller/metal.rb +2 -2
- data/lib/action_controller/renderer.rb +23 -13
- data/lib/action_controller/test_case.rb +65 -56
- data/lib/action_controller.rb +2 -3
- data/lib/action_dispatch/http/cache.rb +17 -16
- data/lib/action_dispatch/http/content_security_policy.rb +6 -1
- data/lib/action_dispatch/http/filter_parameters.rb +1 -1
- data/lib/action_dispatch/http/filter_redirect.rb +1 -1
- data/lib/action_dispatch/http/headers.rb +3 -2
- data/lib/action_dispatch/http/mime_negotiation.rb +14 -8
- data/lib/action_dispatch/http/mime_type.rb +29 -16
- data/lib/action_dispatch/http/parameters.rb +1 -19
- data/lib/action_dispatch/http/permissions_policy.rb +173 -0
- data/lib/action_dispatch/http/request.rb +24 -8
- data/lib/action_dispatch/http/response.rb +17 -16
- data/lib/action_dispatch/http/url.rb +3 -2
- data/lib/action_dispatch/journey/formatter.rb +55 -30
- data/lib/action_dispatch/journey/gtg/builder.rb +22 -36
- data/lib/action_dispatch/journey/gtg/simulator.rb +8 -7
- data/lib/action_dispatch/journey/gtg/transition_table.rb +6 -4
- data/lib/action_dispatch/journey/nfa/dot.rb +0 -11
- data/lib/action_dispatch/journey/nodes/node.rb +4 -3
- data/lib/action_dispatch/journey/parser.rb +13 -13
- data/lib/action_dispatch/journey/parser.y +1 -1
- data/lib/action_dispatch/journey/path/pattern.rb +13 -18
- data/lib/action_dispatch/journey/route.rb +7 -18
- data/lib/action_dispatch/journey/router/utils.rb +6 -4
- data/lib/action_dispatch/journey/router.rb +26 -30
- data/lib/action_dispatch/journey/visitors.rb +1 -1
- data/lib/action_dispatch/journey.rb +0 -2
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +67 -32
- data/lib/action_dispatch/middleware/debug_exceptions.rb +8 -15
- data/lib/action_dispatch/middleware/debug_view.rb +1 -1
- data/lib/action_dispatch/middleware/exception_wrapper.rb +28 -16
- data/lib/action_dispatch/middleware/host_authorization.rb +63 -14
- data/lib/action_dispatch/middleware/remote_ip.rb +5 -4
- data/lib/action_dispatch/middleware/request_id.rb +4 -5
- data/lib/action_dispatch/middleware/session/abstract_store.rb +2 -2
- data/lib/action_dispatch/middleware/session/cookie_store.rb +2 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +12 -0
- data/lib/action_dispatch/middleware/ssl.rb +12 -7
- data/lib/action_dispatch/middleware/stack.rb +19 -1
- data/lib/action_dispatch/middleware/static.rb +154 -93
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +2 -5
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +2 -2
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +100 -8
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +21 -1
- data/lib/action_dispatch/railtie.rb +3 -2
- data/lib/action_dispatch/request/session.rb +2 -8
- data/lib/action_dispatch/request/utils.rb +26 -2
- data/lib/action_dispatch/routing/inspector.rb +8 -7
- data/lib/action_dispatch/routing/mapper.rb +102 -71
- data/lib/action_dispatch/routing/polymorphic_routes.rb +12 -11
- data/lib/action_dispatch/routing/redirection.rb +4 -4
- data/lib/action_dispatch/routing/route_set.rb +49 -41
- data/lib/action_dispatch/system_test_case.rb +35 -24
- data/lib/action_dispatch/system_testing/browser.rb +33 -27
- data/lib/action_dispatch/system_testing/driver.rb +6 -7
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +47 -6
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +4 -7
- data/lib/action_dispatch/testing/assertions/response.rb +2 -4
- data/lib/action_dispatch/testing/assertions/routing.rb +5 -5
- data/lib/action_dispatch/testing/assertions.rb +1 -1
- data/lib/action_dispatch/testing/integration.rb +40 -29
- data/lib/action_dispatch/testing/test_process.rb +32 -4
- data/lib/action_dispatch/testing/test_request.rb +3 -3
- data/lib/action_dispatch.rb +3 -2
- data/lib/action_pack/gem_version.rb +3 -3
- data/lib/action_pack.rb +1 -1
- metadata +17 -18
- data/lib/action_controller/metal/force_ssl.rb +0 -58
- data/lib/action_dispatch/http/parameter_filter.rb +0 -12
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -78
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -119
@@ -53,7 +53,7 @@ module ActionController #:nodoc:
|
|
53
53
|
#
|
54
54
|
# Show a 404 page in the browser:
|
55
55
|
#
|
56
|
-
# send_file '/path/to/404.html', type: 'text/html; charset=utf-8', status: 404
|
56
|
+
# send_file '/path/to/404.html', type: 'text/html; charset=utf-8', disposition: 'inline', status: 404
|
57
57
|
#
|
58
58
|
# Read about the other Content-* HTTP headers if you'd like to
|
59
59
|
# provide the user with more information (such as Content-Description) in
|
@@ -26,10 +26,8 @@ module ActionController
|
|
26
26
|
included do
|
27
27
|
class_attribute :etag_with_template_digest, default: true
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
determine_template_etag(options) if etag_with_template_digest
|
32
|
-
end
|
29
|
+
etag do |options|
|
30
|
+
determine_template_etag(options) if etag_with_template_digest
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -46,7 +44,7 @@ module ActionController
|
|
46
44
|
# template digest from the ETag.
|
47
45
|
def pick_template_for_etag(options)
|
48
46
|
unless options[:template] == false
|
49
|
-
options[:template] ||
|
47
|
+
options[:template] || lookup_context.find_all(action_name, _prefixes).first&.virtual_path
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
@@ -23,6 +23,39 @@ module ActionController
|
|
23
23
|
end
|
24
24
|
|
25
25
|
class UrlGenerationError < ActionControllerError #:nodoc:
|
26
|
+
attr_reader :routes, :route_name, :method_name
|
27
|
+
|
28
|
+
def initialize(message, routes = nil, route_name = nil, method_name = nil)
|
29
|
+
@routes = routes
|
30
|
+
@route_name = route_name
|
31
|
+
@method_name = method_name
|
32
|
+
|
33
|
+
super(message)
|
34
|
+
end
|
35
|
+
|
36
|
+
class Correction
|
37
|
+
def initialize(error)
|
38
|
+
@error = error
|
39
|
+
end
|
40
|
+
|
41
|
+
def corrections
|
42
|
+
if @error.method_name
|
43
|
+
maybe_these = @error.routes.named_routes.helper_names.grep(/#{@error.route_name}/)
|
44
|
+
maybe_these -= [@error.method_name.to_s] # remove exact match
|
45
|
+
|
46
|
+
maybe_these.sort_by { |n|
|
47
|
+
DidYouMean::Jaro.distance(@error.route_name, n)
|
48
|
+
}.reverse.first(4)
|
49
|
+
else
|
50
|
+
[]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# We may not have DYM, and DYM might not let us register error handlers
|
56
|
+
if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
|
57
|
+
DidYouMean.correct_error(self, Correction)
|
58
|
+
end
|
26
59
|
end
|
27
60
|
|
28
61
|
class MethodNotAllowed < ActionControllerError #:nodoc:
|
@@ -29,19 +29,22 @@ module ActionController
|
|
29
29
|
content_type = options.delete(:content_type)
|
30
30
|
|
31
31
|
options.each do |key, value|
|
32
|
-
headers[key.to_s.
|
32
|
+
headers[key.to_s.split(/[-_]/).each { |v| v[0] = v[0].upcase }.join("-")] = value.to_s
|
33
33
|
end
|
34
34
|
|
35
35
|
self.status = status
|
36
36
|
self.location = url_for(location) if location
|
37
37
|
|
38
|
-
self.response_body = ""
|
39
|
-
|
40
38
|
if include_content?(response_code)
|
41
|
-
self.
|
39
|
+
unless self.media_type
|
40
|
+
self.content_type = content_type || (Mime[formats.first] if formats) || Mime[:html]
|
41
|
+
end
|
42
|
+
|
42
43
|
response.charset = false
|
43
44
|
end
|
44
45
|
|
46
|
+
self.response_body = ""
|
47
|
+
|
45
48
|
true
|
46
49
|
end
|
47
50
|
|
@@ -11,7 +11,12 @@ module ActionController
|
|
11
11
|
#
|
12
12
|
# In previous versions of \Rails the controller will include a helper which
|
13
13
|
# matches the name of the controller, e.g., <tt>MyController</tt> will automatically
|
14
|
-
# include <tt>MyHelper</tt>.
|
14
|
+
# include <tt>MyHelper</tt>. You can revert to the old behavior with the following:
|
15
|
+
#
|
16
|
+
# # config/application.rb
|
17
|
+
# class Application < Rails::Application
|
18
|
+
# config.action_controller.include_all_helpers = false
|
19
|
+
# end
|
15
20
|
#
|
16
21
|
# Additional helpers can be specified using the +helper+ class method in ActionController::Base or any
|
17
22
|
# controller which inherits from it.
|
@@ -73,6 +78,11 @@ module ActionController
|
|
73
78
|
end
|
74
79
|
|
75
80
|
# Provides a proxy to access helper methods from outside the view.
|
81
|
+
#
|
82
|
+
# Note that the proxy is rendered under a different view context.
|
83
|
+
# This may cause incorrect behaviour with capture methods. Consider
|
84
|
+
# using {helper}[rdoc-ref:AbstractController::Helpers::ClassMethods#helper]
|
85
|
+
# instead when using +capture+.
|
76
86
|
def helpers
|
77
87
|
@helper_proxy ||= begin
|
78
88
|
proxy = ActionView::Base.empty
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "base64"
|
4
4
|
require "active_support/security_utils"
|
5
|
+
require "active_support/core_ext/array/access"
|
5
6
|
|
6
7
|
module ActionController
|
7
8
|
# Makes it dead easy to do HTTP Basic, Digest and Token authentication.
|
@@ -76,6 +77,8 @@ module ActionController
|
|
76
77
|
|
77
78
|
def http_basic_authenticate_or_request_with(name:, password:, realm: nil, message: nil)
|
78
79
|
authenticate_or_request_with_http_basic(realm, message) do |given_name, given_password|
|
80
|
+
# This comparison uses & so that it doesn't short circuit and
|
81
|
+
# uses `secure_compare` so that length information isn't leaked.
|
79
82
|
ActiveSupport::SecurityUtils.secure_compare(given_name, name) &
|
80
83
|
ActiveSupport::SecurityUtils.secure_compare(given_password, password)
|
81
84
|
end
|
@@ -136,7 +139,7 @@ module ActionController
|
|
136
139
|
#
|
137
140
|
# === Simple \Digest example
|
138
141
|
#
|
139
|
-
# require
|
142
|
+
# require "digest/md5"
|
140
143
|
# class PostsController < ApplicationController
|
141
144
|
# REALM = "SuperSecret"
|
142
145
|
# USERS = {"dhh" => "secret", #plain text password
|
@@ -482,7 +485,7 @@ module ActionController
|
|
482
485
|
def raw_params(auth)
|
483
486
|
_raw_params = auth.sub(TOKEN_REGEX, "").split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
|
484
487
|
|
485
|
-
if !
|
488
|
+
if !_raw_params.first&.start_with?(TOKEN_KEY)
|
486
489
|
_raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
|
487
490
|
end
|
488
491
|
|
@@ -22,7 +22,7 @@ module ActionController
|
|
22
22
|
# Third, if we DON'T find a template AND the request is a page load in a web
|
23
23
|
# browser (technically, a non-XHR GET request for an HTML response) where
|
24
24
|
# you reasonably expect to have rendered a template, then we raise
|
25
|
-
# <tt>
|
25
|
+
# <tt>ActionController::MissingExactTemplate</tt> with an explanation.
|
26
26
|
#
|
27
27
|
# Finally, if we DON'T find a template AND the request isn't a browser page
|
28
28
|
# load, then we implicitly respond with <tt>204 No Content</tt>.
|
@@ -16,10 +16,11 @@ module ActionController
|
|
16
16
|
|
17
17
|
attr_internal :view_runtime
|
18
18
|
|
19
|
-
def process_action(*
|
19
|
+
def process_action(*)
|
20
20
|
raw_payload = {
|
21
21
|
controller: self.class.name,
|
22
22
|
action: action_name,
|
23
|
+
request: request,
|
23
24
|
params: request.filtered_parameters,
|
24
25
|
headers: request.headers,
|
25
26
|
format: request.format.ref,
|
@@ -27,18 +28,19 @@ module ActionController
|
|
27
28
|
path: request.fullpath
|
28
29
|
}
|
29
30
|
|
30
|
-
ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload
|
31
|
+
ActiveSupport::Notifications.instrument("start_processing.action_controller", raw_payload)
|
31
32
|
|
32
33
|
ActiveSupport::Notifications.instrument("process_action.action_controller", raw_payload) do |payload|
|
33
|
-
super
|
34
|
-
|
35
|
-
|
34
|
+
result = super
|
35
|
+
payload[:response] = response
|
36
|
+
payload[:status] = response.status
|
37
|
+
result
|
36
38
|
ensure
|
37
39
|
append_info_to_payload(payload)
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
def render(*
|
43
|
+
def render(*)
|
42
44
|
render_output = nil
|
43
45
|
self.view_runtime = cleanup_view_runtime do
|
44
46
|
Benchmark.ms { render_output = super }
|
@@ -59,8 +61,8 @@ module ActionController
|
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
62
|
-
def redirect_to(*
|
63
|
-
ActiveSupport::Notifications.instrument("redirect_to.action_controller") do |payload|
|
64
|
+
def redirect_to(*)
|
65
|
+
ActiveSupport::Notifications.instrument("redirect_to.action_controller", request: request) do |payload|
|
64
66
|
result = super
|
65
67
|
payload[:status] = response.status
|
66
68
|
payload[:location] = response.filtered_location
|
@@ -70,7 +72,7 @@ module ActionController
|
|
70
72
|
|
71
73
|
private
|
72
74
|
# A hook invoked every time a before callback is halted.
|
73
|
-
def halted_callback_hook(filter)
|
75
|
+
def halted_callback_hook(filter, _)
|
74
76
|
ActiveSupport::Notifications.instrument("halted_callback.action_controller", filter: filter)
|
75
77
|
end
|
76
78
|
|
@@ -127,6 +127,11 @@ module ActionController
|
|
127
127
|
class Buffer < ActionDispatch::Response::Buffer #:nodoc:
|
128
128
|
include MonitorMixin
|
129
129
|
|
130
|
+
class << self
|
131
|
+
attr_accessor :queue_size
|
132
|
+
end
|
133
|
+
@queue_size = 10
|
134
|
+
|
130
135
|
# Ignore that the client has disconnected.
|
131
136
|
#
|
132
137
|
# If this value is `true`, calling `write` after the client
|
@@ -136,11 +141,11 @@ module ActionController
|
|
136
141
|
attr_accessor :ignore_disconnect
|
137
142
|
|
138
143
|
def initialize(response)
|
144
|
+
super(response, build_queue(self.class.queue_size))
|
139
145
|
@error_callback = lambda { true }
|
140
146
|
@cv = new_cond
|
141
147
|
@aborted = false
|
142
148
|
@ignore_disconnect = false
|
143
|
-
super(response, SizedQueue.new(10))
|
144
149
|
end
|
145
150
|
|
146
151
|
def write(string)
|
@@ -214,6 +219,10 @@ module ActionController
|
|
214
219
|
yield str
|
215
220
|
end
|
216
221
|
end
|
222
|
+
|
223
|
+
def build_queue(queue_size)
|
224
|
+
queue_size ? SizedQueue.new(queue_size) : Queue.new
|
225
|
+
end
|
217
226
|
end
|
218
227
|
|
219
228
|
class Response < ActionDispatch::Response #:nodoc: all
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
module Logging
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Set a different log level per request.
|
9
|
+
#
|
10
|
+
# # Use the debug log level if a particular cookie is set.
|
11
|
+
# class ApplicationController < ActionController::Base
|
12
|
+
# log_at :debug, if: -> { cookies[:debug] }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
def log_at(level, **options)
|
16
|
+
around_action ->(_, action) { logger.log_at(level, &action) }, **options
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -142,7 +142,7 @@ module ActionController #:nodoc:
|
|
142
142
|
#
|
143
143
|
# You can set the variant in a +before_action+:
|
144
144
|
#
|
145
|
-
# request.variant = :tablet if request.user_agent
|
145
|
+
# request.variant = :tablet if /iPad/.match?(request.user_agent)
|
146
146
|
#
|
147
147
|
# Respond to variants in the action just like you respond to formats:
|
148
148
|
#
|
@@ -209,7 +209,7 @@ module ActionController #:nodoc:
|
|
209
209
|
raise ActionController::RespondToMismatchError
|
210
210
|
end
|
211
211
|
_process_format(format)
|
212
|
-
_set_rendered_content_type
|
212
|
+
_set_rendered_content_type(format) unless collector.any_response?
|
213
213
|
response = collector.response
|
214
214
|
response.call if response
|
215
215
|
else
|
@@ -268,6 +268,10 @@ module ActionController #:nodoc:
|
|
268
268
|
end
|
269
269
|
end
|
270
270
|
|
271
|
+
def any_response?
|
272
|
+
!@responses.fetch(format, false) && @responses[Mime::ALL]
|
273
|
+
end
|
274
|
+
|
271
275
|
def response
|
272
276
|
response = @responses.fetch(format, @responses[Mime::ALL])
|
273
277
|
if response.is_a?(VariantCollector) # `format.html.phone` - variant inline syntax
|
@@ -12,11 +12,13 @@ module ActionController
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def setup_param_encode # :nodoc:
|
15
|
-
@_parameter_encodings = {}
|
15
|
+
@_parameter_encodings = Hash.new { |h, k| h[k] = {} }
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
@_parameter_encodings
|
18
|
+
def action_encoding_template(action) # :nodoc:
|
19
|
+
if @_parameter_encodings.has_key?(action.to_s)
|
20
|
+
@_parameter_encodings[action.to_s]
|
21
|
+
end
|
20
22
|
end
|
21
23
|
|
22
24
|
# Specify that a given action's parameters should all be encoded as
|
@@ -44,7 +46,36 @@ module ActionController
|
|
44
46
|
# encoded as ASCII-8BIT. This is useful in the case where an application
|
45
47
|
# must handle data but encoding of the data is unknown, like file system data.
|
46
48
|
def skip_parameter_encoding(action)
|
47
|
-
@_parameter_encodings[action.to_s] =
|
49
|
+
@_parameter_encodings[action.to_s] = Hash.new { Encoding::ASCII_8BIT }
|
50
|
+
end
|
51
|
+
|
52
|
+
# Specify the encoding for a parameter on an action.
|
53
|
+
# If not specified the default is UTF-8.
|
54
|
+
#
|
55
|
+
# You can specify a binary (ASCII_8BIT) parameter with:
|
56
|
+
#
|
57
|
+
# class RepositoryController < ActionController::Base
|
58
|
+
# # This specifies that file_path is not UTF-8 and is instead ASCII_8BIT
|
59
|
+
# param_encoding :show, :file_path, Encoding::ASCII_8BIT
|
60
|
+
#
|
61
|
+
# def show
|
62
|
+
# @repo = Repository.find_by_filesystem_path params[:file_path]
|
63
|
+
#
|
64
|
+
# # params[:repo_name] remains UTF-8 encoded
|
65
|
+
# @repo_name = params[:repo_name]
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# def index
|
69
|
+
# @repositories = Repository.all
|
70
|
+
# end
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# The file_path parameter on the show action would be encoded as ASCII-8BIT,
|
74
|
+
# but all other arguments will remain UTF-8 encoded.
|
75
|
+
# This is useful in the case where an application must handle data
|
76
|
+
# but encoding of the data is unknown, like file system data.
|
77
|
+
def param_encoding(action, param, encoding)
|
78
|
+
@_parameter_encodings[action.to_s][param.to_s] = encoding
|
48
79
|
end
|
49
80
|
end
|
50
81
|
end
|
@@ -107,10 +107,14 @@ module ActionController
|
|
107
107
|
|
108
108
|
unless super || exclude
|
109
109
|
if m.respond_to?(:attribute_names) && m.attribute_names.any?
|
110
|
+
self.include = m.attribute_names
|
111
|
+
|
110
112
|
if m.respond_to?(:stored_attributes) && !m.stored_attributes.empty?
|
111
|
-
self.include
|
112
|
-
|
113
|
-
|
113
|
+
self.include += m.stored_attributes.values.flatten.map(&:to_s)
|
114
|
+
end
|
115
|
+
|
116
|
+
if m.respond_to?(:attribute_aliases) && m.attribute_aliases.any?
|
117
|
+
self.include += m.attribute_aliases.keys
|
114
118
|
end
|
115
119
|
|
116
120
|
if m.respond_to?(:nested_attributes_options) && m.nested_attributes_options.keys.any?
|
@@ -151,7 +155,7 @@ module ActionController
|
|
151
155
|
# try to find Foo::Bar::User, Foo::User and finally User.
|
152
156
|
def _default_wrap_model
|
153
157
|
return nil if klass.anonymous?
|
154
|
-
model_name = klass.name.
|
158
|
+
model_name = klass.name.delete_suffix("Controller").classify
|
155
159
|
|
156
160
|
begin
|
157
161
|
if model_klass = model_name.safe_constantize
|
@@ -189,7 +193,7 @@ module ActionController
|
|
189
193
|
#
|
190
194
|
# wrap_parameters Person
|
191
195
|
# # wraps parameters by determining the wrapper key from Person class
|
192
|
-
# (+person+, in this case) and the list of attribute names
|
196
|
+
# # (+person+, in this case) and the list of attribute names
|
193
197
|
#
|
194
198
|
# wrap_parameters include: [:username, :title]
|
195
199
|
# # wraps only +:username+ and +:title+ attributes from parameters.
|
@@ -240,7 +244,7 @@ module ActionController
|
|
240
244
|
|
241
245
|
# Performs parameters wrapping upon the request. Called automatically
|
242
246
|
# by the metal call stack.
|
243
|
-
def process_action(*
|
247
|
+
def process_action(*)
|
244
248
|
_perform_parameter_wrapping if _wrapper_enabled?
|
245
249
|
super
|
246
250
|
end
|
@@ -264,9 +268,11 @@ module ActionController
|
|
264
268
|
def _extract_parameters(parameters)
|
265
269
|
if include_only = _wrapper_options.include
|
266
270
|
parameters.slice(*include_only)
|
271
|
+
elsif _wrapper_options.exclude
|
272
|
+
exclude = _wrapper_options.exclude + EXCLUDE_PARAMETERS
|
273
|
+
parameters.except(*exclude)
|
267
274
|
else
|
268
|
-
|
269
|
-
parameters.except(*(exclude + EXCLUDE_PARAMETERS))
|
275
|
+
parameters.except(*EXCLUDE_PARAMETERS)
|
270
276
|
end
|
271
277
|
end
|
272
278
|
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
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
|
+
module PermissionsPolicy
|
32
|
+
extend ActiveSupport::Concern
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
def permissions_policy(**options, &block)
|
36
|
+
before_action(options) do
|
37
|
+
if block_given?
|
38
|
+
policy = request.permissions_policy.clone
|
39
|
+
yield policy
|
40
|
+
request.permissions_policy = policy
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -85,7 +85,7 @@ module ActionController
|
|
85
85
|
# * <tt>:fallback_location</tt> - The default fallback location that will be used on missing +Referer+ header.
|
86
86
|
# * <tt>:allow_other_host</tt> - Allow or disallow redirection to the host that is different to the current host, defaults to true.
|
87
87
|
#
|
88
|
-
# All other options that can be passed to
|
88
|
+
# All other options that can be passed to #redirect_to are accepted as
|
89
89
|
# options and the behavior is identical.
|
90
90
|
def redirect_back(fallback_location:, allow_other_host: true, **args)
|
91
91
|
referer = request.headers["Referer"]
|
@@ -77,6 +77,12 @@ module ActionController
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
def _set_vary_header
|
81
|
+
if response.headers["Vary"].blank? && request.should_apply_vary_header?
|
82
|
+
response.headers["Vary"] = "Accept"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
80
86
|
# Normalize arguments by catching blocks and setting them on :update.
|
81
87
|
def _normalize_args(action = nil, options = {}, &blk)
|
82
88
|
options = super
|