actionpack 7.0.0.alpha2 → 7.0.0.rc1
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 +139 -0
- data/lib/abstract_controller/callbacks.rb +15 -2
- data/lib/abstract_controller/translation.rb +4 -1
- data/lib/action_controller/log_subscriber.rb +1 -2
- data/lib/action_controller/metal/helpers.rb +1 -1
- data/lib/action_controller/metal/http_authentication.rb +2 -1
- data/lib/action_controller/metal/instrumentation.rb +2 -0
- data/lib/action_controller/metal/params_wrapper.rb +13 -4
- data/lib/action_controller/metal/redirecting.rb +58 -22
- data/lib/action_controller/metal/request_forgery_protection.rb +30 -34
- data/lib/action_controller/metal/strong_parameters.rb +60 -19
- data/lib/action_controller/railtie.rb +16 -10
- data/lib/action_controller/test_case.rb +13 -2
- data/lib/action_controller.rb +0 -1
- data/lib/action_dispatch/http/response.rb +0 -12
- data/lib/action_dispatch/http/url.rb +2 -9
- data/lib/action_dispatch/journey/nodes/node.rb +2 -2
- data/lib/action_dispatch/journey/route.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +1 -1
- data/lib/action_dispatch/middleware/executor.rb +3 -0
- data/lib/action_dispatch/middleware/host_authorization.rb +41 -21
- data/lib/action_dispatch/middleware/server_timing.rb +33 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +10 -0
- data/lib/action_dispatch/middleware/static.rb +0 -1
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +1 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +2 -0
- data/lib/action_dispatch/routing/inspector.rb +1 -1
- data/lib/action_dispatch/routing/mapper.rb +10 -6
- data/lib/action_dispatch/routing/route_set.rb +5 -0
- data/lib/action_dispatch/system_test_case.rb +7 -1
- data/lib/action_dispatch/system_testing/browser.rb +2 -12
- data/lib/action_dispatch/system_testing/driver.rb +13 -9
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +0 -8
- data/lib/action_dispatch/testing/test_process.rb +1 -27
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_pack/gem_version.rb +1 -1
- metadata +14 -13
- data/lib/action_controller/metal/query_tags.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a040a28754f07052c56e9ef1c1c940413642486fc047c3c844ed8beb37493f5d
|
4
|
+
data.tar.gz: 559e290b6f39a7bc50d3b1791dbb7fc48500ff38642e6ae28d4804dcb8429a33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ab82978fa296a09c177352859e3f8b39938250339ff4d67473ae174799f5a4fd102e545c83615f3ca83eaf00c01f3ab34c654a63e2872161a0758ab9fd8bd2a
|
7
|
+
data.tar.gz: e8b8ae155bd7c6ea6516bc3d980a40eec92b710057b8a461ca91541e4ce488105d09d47f72fb20a328845874420c7f576a0125c3ad92fe0ec444f78e79417927
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,142 @@
|
|
1
|
+
* `Rails.application.executor` hooks can now be called around every request in a `ActionController::TestCase`
|
2
|
+
|
3
|
+
This helps to better simulate request or job local state being reset between requests and prevent state
|
4
|
+
leaking from one request to another.
|
5
|
+
|
6
|
+
To enable this, set `config.active_support.executor_around_test_case = true` (this is the default in Rails 7).
|
7
|
+
|
8
|
+
*Alex Ghiculescu*
|
9
|
+
|
10
|
+
* Consider onion services secure for cookies.
|
11
|
+
|
12
|
+
*Justin Tracey*
|
13
|
+
|
14
|
+
* Remove deprecated `Rails.config.action_view.raise_on_missing_translations`.
|
15
|
+
|
16
|
+
*Rafael Mendonça França*
|
17
|
+
|
18
|
+
* Remove deprecated support to passing a path to `fixture_file_upload` relative to `fixture_path`.
|
19
|
+
|
20
|
+
*Rafael Mendonça França*
|
21
|
+
|
22
|
+
* Remove deprecated `ActionDispatch::SystemTestCase#host!`.
|
23
|
+
|
24
|
+
*Rafael Mendonça França*
|
25
|
+
|
26
|
+
* Remove deprecated `Rails.config.action_dispatch.hosts_response_app`.
|
27
|
+
|
28
|
+
*Rafael Mendonça França*
|
29
|
+
|
30
|
+
* Remove deprecated `ActionDispatch::Response.return_only_media_type_on_content_type`.
|
31
|
+
|
32
|
+
*Rafael Mendonça França*
|
33
|
+
|
34
|
+
* Raise `ActionController::Redirecting::UnsafeRedirectError` for unsafe `redirect_to` redirects.
|
35
|
+
|
36
|
+
This allows `rescue_from` to be used to add a default fallback route:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
rescue_from ActionController::Redirecting::UnsafeRedirectError do
|
40
|
+
redirect_to root_url
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
*Kasper Timm Hansen*, *Chris Oliver*
|
45
|
+
|
46
|
+
* Add `url_from` to verify a redirect location is internal.
|
47
|
+
|
48
|
+
Takes the open redirect protection from `redirect_to` so users can wrap a
|
49
|
+
param, and fall back to an alternate redirect URL when the param provided
|
50
|
+
one is unsafe.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
def create
|
54
|
+
redirect_to url_from(params[:redirect_url]) || root_url
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
*dmcge*, *Kasper Timm Hansen*
|
59
|
+
|
60
|
+
* Allow Capybara driver name overrides in `SystemTestCase::driven_by`
|
61
|
+
|
62
|
+
Allow users to prevent conflicts among drivers that use the same driver
|
63
|
+
type (selenium, poltergeist, webkit, rack test).
|
64
|
+
|
65
|
+
Fixes #42502
|
66
|
+
|
67
|
+
*Chris LaRose*
|
68
|
+
|
69
|
+
* Allow multiline to be passed in routes when using wildcard segments.
|
70
|
+
|
71
|
+
Previously routes with newlines weren't detected when using wildcard segments, returning
|
72
|
+
a `No route matches` error.
|
73
|
+
After this change, routes with newlines are detected on wildcard segments. Example
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
draw do
|
77
|
+
get "/wildcard/*wildcard_segment", to: SimpleApp.new("foo#index"), as: :wildcard
|
78
|
+
end
|
79
|
+
|
80
|
+
# After the change, the path matches.
|
81
|
+
assert_equal "/wildcard/a%0Anewline", url_helpers.wildcard_path(wildcard_segment: "a\nnewline")
|
82
|
+
```
|
83
|
+
|
84
|
+
Fixes #39103
|
85
|
+
|
86
|
+
*Ignacio Chiazzo*
|
87
|
+
|
88
|
+
* Treat html suffix in controller translation.
|
89
|
+
|
90
|
+
*Rui Onodera*, *Gavin Miller*
|
91
|
+
|
92
|
+
* Allow permitting numeric params.
|
93
|
+
|
94
|
+
Previously it was impossible to permit different fields on numeric parameters.
|
95
|
+
After this change you can specify different fields for each numbered parameter.
|
96
|
+
For example params like,
|
97
|
+
```ruby
|
98
|
+
book: {
|
99
|
+
authors_attributes: {
|
100
|
+
'0': { name: "William Shakespeare", age_of_death: "52" },
|
101
|
+
'1': { name: "Unattributed Assistant" },
|
102
|
+
'2': "Not a hash",
|
103
|
+
'new_record': { name: "Some name" }
|
104
|
+
}
|
105
|
+
}
|
106
|
+
```
|
107
|
+
|
108
|
+
Before you could permit name on each author with,
|
109
|
+
`permit book: { authors_attributes: [ :name ] }`
|
110
|
+
|
111
|
+
After this change you can permit different keys on each numbered element,
|
112
|
+
`permit book: { authors_attributes: { '1': [ :name ], '0': [ :name, :age_of_death ] } }`
|
113
|
+
|
114
|
+
Fixes #41625
|
115
|
+
|
116
|
+
*Adam Hess*
|
117
|
+
|
118
|
+
* Update `HostAuthorization` middleware to render debug info only
|
119
|
+
when `config.consider_all_requests_local` is set to true.
|
120
|
+
|
121
|
+
Also, blocked host info is always logged with level `error`.
|
122
|
+
|
123
|
+
Fixes #42813
|
124
|
+
|
125
|
+
*Nikita Vyrko*
|
126
|
+
|
127
|
+
* Add Server-Timing middleware
|
128
|
+
|
129
|
+
Server-Timing specification defines how the server can communicate to browsers performance metrics
|
130
|
+
about the request it is responding to.
|
131
|
+
|
132
|
+
The ServerTiming middleware is enabled by default on `development` environment by default using the
|
133
|
+
`config.server_timing` setting and set the relevant duration metrics in the `Server-Timing` header
|
134
|
+
|
135
|
+
The full specification for Server-Timing header can be found in: https://www.w3.org/TR/server-timing/#dfn-server-timing-header-field
|
136
|
+
|
137
|
+
*Sebastian Sogamoso*, *Guillermo Iguaran*
|
138
|
+
|
139
|
+
|
1
140
|
## Rails 7.0.0.alpha2 (September 15, 2021) ##
|
2
141
|
|
3
142
|
* No changes.
|
@@ -35,6 +35,20 @@ module AbstractController
|
|
35
35
|
skip_after_callbacks_if_terminated: true
|
36
36
|
end
|
37
37
|
|
38
|
+
class ActionFilter # :nodoc:
|
39
|
+
def initialize(actions)
|
40
|
+
@actions = Array(actions).map(&:to_s).to_set
|
41
|
+
end
|
42
|
+
|
43
|
+
def match?(controller)
|
44
|
+
@actions.include?(controller.action_name)
|
45
|
+
end
|
46
|
+
|
47
|
+
alias after match?
|
48
|
+
alias before match?
|
49
|
+
alias around match?
|
50
|
+
end
|
51
|
+
|
38
52
|
module ClassMethods
|
39
53
|
# If +:only+ or +:except+ are used, convert the options into the
|
40
54
|
# +:if+ and +:unless+ options of ActiveSupport::Callbacks.
|
@@ -62,8 +76,7 @@ module AbstractController
|
|
62
76
|
|
63
77
|
def _normalize_callback_option(options, from, to) # :nodoc:
|
64
78
|
if from = options.delete(from)
|
65
|
-
|
66
|
-
from = proc { |c| _from.include? c.action_name }
|
79
|
+
from = ActionFilter.new(from)
|
67
80
|
options[to] = Array(options[to]).unshift(from)
|
68
81
|
end
|
69
82
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/html_safe_translation"
|
4
|
+
|
3
5
|
module AbstractController
|
4
6
|
module Translation
|
5
7
|
mattr_accessor :raise_on_missing_translations, default: false
|
@@ -22,7 +24,8 @@ module AbstractController
|
|
22
24
|
end
|
23
25
|
|
24
26
|
i18n_raise = options.fetch(:raise, self.raise_on_missing_translations)
|
25
|
-
|
27
|
+
|
28
|
+
ActiveSupport::HtmlSafeTranslation.translate(key, **options, raise: i18n_raise)
|
26
29
|
end
|
27
30
|
alias :t :translate
|
28
31
|
|
@@ -62,8 +62,7 @@ module ActionController
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
%w(write_fragment read_fragment exist_fragment?
|
66
|
-
expire_fragment expire_page write_page).each do |method|
|
65
|
+
%w(write_fragment read_fragment exist_fragment? expire_fragment).each do |method|
|
67
66
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
68
67
|
def #{method}(event)
|
69
68
|
return unless logger.info? && ActionController::Base.enable_fragment_cache_logging
|
@@ -26,7 +26,7 @@ module ActionController
|
|
26
26
|
#
|
27
27
|
# module FormattedTimeHelper
|
28
28
|
# def format_time(time, format=:long, blank_message=" ")
|
29
|
-
# time.blank? ? blank_message : time.
|
29
|
+
# time.blank? ? blank_message : time.to_formatted_s(format)
|
30
30
|
# end
|
31
31
|
# end
|
32
32
|
#
|
@@ -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
|
# HTTP Basic, Digest and Token authentication.
|
@@ -103,7 +104,7 @@ module ActionController
|
|
103
104
|
end
|
104
105
|
|
105
106
|
def has_basic_credentials?(request)
|
106
|
-
request.authorization.present? && (auth_scheme(request).downcase == "basic")
|
107
|
+
request.authorization.present? && (auth_scheme(request).downcase == "basic") && user_name_and_password(request).length == 2
|
107
108
|
end
|
108
109
|
|
109
110
|
def user_name_and_password(request)
|
@@ -9,11 +9,14 @@ module ActionController
|
|
9
9
|
# Wraps the parameters hash into a nested hash. This will allow clients to
|
10
10
|
# submit requests without having to specify any root elements.
|
11
11
|
#
|
12
|
-
# This functionality is enabled
|
13
|
-
#
|
12
|
+
# This functionality is enabled by default for JSON, and can be customized by
|
13
|
+
# setting the format array:
|
14
14
|
#
|
15
|
-
#
|
16
|
-
#
|
15
|
+
# class ApplicationController < ActionController::Base
|
16
|
+
# wrap_parameters format: [:json, :xml]
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# You could also turn it on per controller:
|
17
20
|
#
|
18
21
|
# class UsersController < ApplicationController
|
19
22
|
# wrap_parameters format: [:json, :xml, :url_encoded_form, :multipart_form]
|
@@ -68,6 +71,12 @@ module ActionController
|
|
68
71
|
# will try to check if <tt>Admin::User</tt> or +User+ model exists, and use it to
|
69
72
|
# determine the wrapper key respectively. If both models don't exist,
|
70
73
|
# it will then fallback to use +user+ as the key.
|
74
|
+
#
|
75
|
+
# To disable this functionality for a controller:
|
76
|
+
#
|
77
|
+
# class UsersController < ApplicationController
|
78
|
+
# wrap_parameters false
|
79
|
+
# end
|
71
80
|
module ParamsWrapper
|
72
81
|
extend ActiveSupport::Concern
|
73
82
|
|
@@ -7,6 +7,8 @@ module ActionController
|
|
7
7
|
include AbstractController::Logger
|
8
8
|
include ActionController::UrlFor
|
9
9
|
|
10
|
+
class UnsafeRedirectError < StandardError; end
|
11
|
+
|
10
12
|
included do
|
11
13
|
mattr_accessor :raise_on_open_redirects, default: false
|
12
14
|
end
|
@@ -61,20 +63,34 @@ module ActionController
|
|
61
63
|
#
|
62
64
|
# redirect_to post_url(@post) and return
|
63
65
|
#
|
64
|
-
#
|
65
|
-
#
|
66
|
+
# === Open Redirect protection
|
67
|
+
#
|
68
|
+
# By default, Rails protects against redirecting to external hosts for your app's safety, so called open redirects.
|
69
|
+
# Note: this was a new default in Rails 7.0, after upgrading opt-in by uncommenting the line with +raise_on_open_redirects+ in <tt>config/initializers/new_framework_defaults_7_0.rb</tt>
|
70
|
+
#
|
71
|
+
# Here #redirect_to automatically validates the potentially-unsafe URL:
|
72
|
+
#
|
73
|
+
# redirect_to params[:redirect_url]
|
74
|
+
#
|
75
|
+
# Raises UnsafeRedirectError in the case of an unsafe redirect.
|
76
|
+
#
|
77
|
+
# To allow any external redirects pass `allow_other_host: true`, though using a user-provided param in that case is unsafe.
|
78
|
+
#
|
79
|
+
# redirect_to "https://rubyonrails.org", allow_other_host: true
|
80
|
+
#
|
81
|
+
# See #url_from for more information on what an internal and safe URL is, or how to fall back to an alternate redirect URL in the unsafe case.
|
66
82
|
def redirect_to(options = {}, response_options = {})
|
67
|
-
response_options[:allow_other_host] ||= _allow_other_host unless response_options.key?(:allow_other_host)
|
68
|
-
|
69
83
|
raise ActionControllerError.new("Cannot redirect to nil!") unless options
|
70
84
|
raise AbstractController::DoubleRenderError if response_body
|
71
85
|
|
86
|
+
allow_other_host = response_options.delete(:allow_other_host) { _allow_other_host }
|
87
|
+
|
72
88
|
self.status = _extract_redirect_to_status(options, response_options)
|
73
|
-
self.location =
|
89
|
+
self.location = _enforce_open_redirect_protection(_compute_redirect_to_location(request, options), allow_other_host: allow_other_host)
|
74
90
|
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
|
75
91
|
end
|
76
92
|
|
77
|
-
# Soft deprecated alias for
|
93
|
+
# Soft deprecated alias for #redirect_back_or_to where the +fallback_location+ location is supplied as a keyword argument instead
|
78
94
|
# of the first positional argument.
|
79
95
|
def redirect_back(fallback_location:, allow_other_host: _allow_other_host, **args)
|
80
96
|
redirect_back_or_to fallback_location, allow_other_host: allow_other_host, **args
|
@@ -103,23 +119,11 @@ module ActionController
|
|
103
119
|
# All other options that can be passed to #redirect_to are accepted as
|
104
120
|
# options and the behavior is identical.
|
105
121
|
def redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options)
|
106
|
-
|
107
|
-
|
108
|
-
allow_other_host = true if _allow_other_host && !allow_other_host # if the fallback is an open redirect
|
109
|
-
|
110
|
-
redirect_to location, allow_other_host: allow_other_host, **options
|
111
|
-
end
|
112
|
-
|
113
|
-
def _compute_safe_redirect_to_location(request, options, response_options)
|
114
|
-
location = _compute_redirect_to_location(request, options)
|
115
|
-
|
116
|
-
if response_options[:allow_other_host] || _url_host_allowed?(location)
|
117
|
-
location
|
122
|
+
if request.referer && (allow_other_host || _url_host_allowed?(request.referer))
|
123
|
+
redirect_to request.referer, allow_other_host: allow_other_host, **options
|
118
124
|
else
|
119
|
-
|
120
|
-
|
121
|
-
use :allow_other_host to redirect anyway.
|
122
|
-
MSG
|
125
|
+
# The method level `allow_other_host` doesn't apply in the fallback case, omit and let the `redirect_to` handling take over.
|
126
|
+
redirect_to fallback_location, **options
|
123
127
|
end
|
124
128
|
end
|
125
129
|
|
@@ -143,6 +147,30 @@ module ActionController
|
|
143
147
|
module_function :_compute_redirect_to_location
|
144
148
|
public :_compute_redirect_to_location
|
145
149
|
|
150
|
+
# Verifies the passed +location+ is an internal URL that's safe to redirect to and returns it, or nil if not.
|
151
|
+
# Useful to wrap a params provided redirect URL and fallback to an alternate URL to redirect to:
|
152
|
+
#
|
153
|
+
# redirect_to url_from(params[:redirect_url]) || root_url
|
154
|
+
#
|
155
|
+
# The +location+ is considered internal, and safe, if it's on the same host as <tt>request.host</tt>:
|
156
|
+
#
|
157
|
+
# # If request.host is example.com:
|
158
|
+
# url_from("https://example.com/profile") # => "https://example.com/profile"
|
159
|
+
# url_from("http://example.com/profile") # => "http://example.com/profile"
|
160
|
+
# url_from("http://evil.com/profile") # => nil
|
161
|
+
#
|
162
|
+
# Subdomains are considered part of the host:
|
163
|
+
#
|
164
|
+
# # If request.host is on https://example.com or https://app.example.com, you'd get:
|
165
|
+
# url_from("https://dev.example.com/profile") # => nil
|
166
|
+
#
|
167
|
+
# NOTE: there's a similarity with {url_for}[rdoc-ref:ActionDispatch::Routing::UrlFor#url_for], which generates an internal URL from various options from within the app, e.g. <tt>url_for(@post)</tt>.
|
168
|
+
# However, #url_from is meant to take an external parameter to verify as in <tt>url_from(params[:redirect_url])</tt>.
|
169
|
+
def url_from(location)
|
170
|
+
location = location.presence
|
171
|
+
location if location && _url_host_allowed?(location)
|
172
|
+
end
|
173
|
+
|
146
174
|
private
|
147
175
|
def _allow_other_host
|
148
176
|
!raise_on_open_redirects
|
@@ -158,6 +186,14 @@ module ActionController
|
|
158
186
|
end
|
159
187
|
end
|
160
188
|
|
189
|
+
def _enforce_open_redirect_protection(location, allow_other_host:)
|
190
|
+
if allow_other_host || _url_host_allowed?(location)
|
191
|
+
location
|
192
|
+
else
|
193
|
+
raise UnsafeRedirectError, "Unsafe redirect to #{location.truncate(100).inspect}, pass allow_other_host: true to redirect anyway."
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
161
197
|
def _url_host_allowed?(url)
|
162
198
|
URI(url.to_s).host == request.host
|
163
199
|
rescue ArgumentError, URI::Error
|
@@ -57,17 +57,6 @@ module ActionController # :nodoc:
|
|
57
57
|
module RequestForgeryProtection
|
58
58
|
extend ActiveSupport::Concern
|
59
59
|
|
60
|
-
class DisabledSessionError < StandardError
|
61
|
-
MESSAGE = <<~EOS.squish
|
62
|
-
Request forgery protection requires a working session store but your application has sessions disabled.
|
63
|
-
You need to either disable request forgery protection, or configure a working session store.
|
64
|
-
EOS
|
65
|
-
|
66
|
-
def initialize(message = MESSAGE)
|
67
|
-
super
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
60
|
include AbstractController::Helpers
|
72
61
|
include AbstractController::Callbacks
|
73
62
|
|
@@ -101,11 +90,6 @@ module ActionController # :nodoc:
|
|
101
90
|
config_accessor :default_protect_from_forgery
|
102
91
|
self.default_protect_from_forgery = false
|
103
92
|
|
104
|
-
# Controls whether trying to use forgery protection without a working session store
|
105
|
-
# issues a warning or raises an error.
|
106
|
-
config_accessor :silence_disabled_session_errors
|
107
|
-
self.silence_disabled_session_errors = true
|
108
|
-
|
109
93
|
# Controls whether URL-safe CSRF tokens are generated.
|
110
94
|
config_accessor :urlsafe_csrf_tokens, instance_writer: false
|
111
95
|
self.urlsafe_csrf_tokens = false
|
@@ -140,10 +124,26 @@ module ActionController # :nodoc:
|
|
140
124
|
# If you need to add verification to the beginning of the callback chain, use <tt>prepend: true</tt>.
|
141
125
|
# * <tt>:with</tt> - Set the method to handle unverified request.
|
142
126
|
#
|
143
|
-
#
|
127
|
+
# Built-in unverified request handling methods are:
|
144
128
|
# * <tt>:exception</tt> - Raises ActionController::InvalidAuthenticityToken exception.
|
145
129
|
# * <tt>:reset_session</tt> - Resets the session.
|
146
130
|
# * <tt>:null_session</tt> - Provides an empty session during request but doesn't reset it completely. Used as default if <tt>:with</tt> option is not specified.
|
131
|
+
#
|
132
|
+
# You can also implement custom strategy classes for unverified request handling:
|
133
|
+
#
|
134
|
+
# class CustomStrategy
|
135
|
+
# def initialize(controller)
|
136
|
+
# @controller = controller
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
# def handle_unverified_request
|
140
|
+
# # Custom behaviour for unverfied request
|
141
|
+
# end
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# class ApplicationController < ActionController:x:Base
|
145
|
+
# protect_from_forgery with: CustomStrategy
|
146
|
+
# end
|
147
147
|
def protect_from_forgery(options = {})
|
148
148
|
options = options.reverse_merge(prepend: false)
|
149
149
|
|
@@ -164,9 +164,18 @@ module ActionController # :nodoc:
|
|
164
164
|
|
165
165
|
private
|
166
166
|
def protection_method_class(name)
|
167
|
-
|
168
|
-
|
169
|
-
|
167
|
+
case name
|
168
|
+
when :null_session
|
169
|
+
ProtectionMethods::NullSession
|
170
|
+
when :reset_session
|
171
|
+
ProtectionMethods::ResetSession
|
172
|
+
when :exception
|
173
|
+
ProtectionMethods::Exception
|
174
|
+
when Class
|
175
|
+
name
|
176
|
+
else
|
177
|
+
raise ArgumentError, "Invalid request forgery protection method, use :null_session, :exception, :reset_session, or a custom forgery protection class."
|
178
|
+
end
|
170
179
|
end
|
171
180
|
end
|
172
181
|
|
@@ -469,20 +478,7 @@ module ActionController # :nodoc:
|
|
469
478
|
|
470
479
|
# Checks if the controller allows forgery protection.
|
471
480
|
def protect_against_forgery? # :doc:
|
472
|
-
allow_forgery_protection &&
|
473
|
-
end
|
474
|
-
|
475
|
-
def ensure_session_is_enabled!
|
476
|
-
if !session.respond_to?(:enabled?) || session.enabled?
|
477
|
-
true
|
478
|
-
else
|
479
|
-
if silence_disabled_session_errors
|
480
|
-
ActiveSupport::Deprecation.warn(DisabledSessionError::MESSAGE)
|
481
|
-
false
|
482
|
-
else
|
483
|
-
raise DisabledSessionError
|
484
|
-
end
|
485
|
-
end
|
481
|
+
allow_forgery_protection && (!session.respond_to?(:enabled?) || session.enabled?)
|
486
482
|
end
|
487
483
|
|
488
484
|
NULL_ORIGIN_MESSAGE = <<~MSG
|