actionpack 5.0.7.2 → 5.1.0.beta1
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 +5 -5
- data/CHANGELOG.md +189 -1002
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/lib/abstract_controller.rb +3 -3
- data/lib/abstract_controller/base.rb +10 -12
- data/lib/abstract_controller/caching.rb +6 -3
- data/lib/abstract_controller/caching/fragments.rb +1 -1
- data/lib/abstract_controller/callbacks.rb +2 -43
- data/lib/abstract_controller/collector.rb +2 -2
- data/lib/abstract_controller/helpers.rb +19 -19
- data/lib/abstract_controller/rendering.rb +9 -11
- data/lib/abstract_controller/translation.rb +3 -3
- data/lib/action_controller.rb +15 -13
- data/lib/action_controller/api.rb +3 -3
- data/lib/action_controller/base.rb +7 -12
- data/lib/action_controller/caching.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +2 -2
- data/lib/action_controller/metal.rb +34 -43
- data/lib/action_controller/metal/conditional_get.rb +10 -9
- data/lib/action_controller/metal/data_streaming.rb +8 -9
- data/lib/action_controller/metal/etag_with_flash.rb +16 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +15 -15
- data/lib/action_controller/metal/exceptions.rb +4 -14
- data/lib/action_controller/metal/flash.rb +1 -1
- data/lib/action_controller/metal/force_ssl.rb +6 -6
- data/lib/action_controller/metal/head.rb +13 -19
- data/lib/action_controller/metal/helpers.rb +6 -6
- data/lib/action_controller/metal/http_authentication.rb +22 -23
- data/lib/action_controller/metal/implicit_render.rb +2 -5
- data/lib/action_controller/metal/instrumentation.rb +14 -14
- data/lib/action_controller/metal/live.rb +15 -16
- data/lib/action_controller/metal/mime_responds.rb +3 -3
- data/lib/action_controller/metal/parameter_encoding.rb +49 -0
- data/lib/action_controller/metal/params_wrapper.rb +32 -32
- data/lib/action_controller/metal/redirecting.rb +8 -24
- data/lib/action_controller/metal/renderers.rb +2 -3
- data/lib/action_controller/metal/rendering.rb +50 -60
- data/lib/action_controller/metal/request_forgery_protection.rb +51 -49
- data/lib/action_controller/metal/rescue.rb +1 -1
- data/lib/action_controller/metal/streaming.rb +4 -4
- data/lib/action_controller/metal/strong_parameters.rb +117 -250
- data/lib/action_controller/metal/testing.rb +1 -1
- data/lib/action_controller/metal/url_for.rb +4 -4
- data/lib/action_controller/railtie.rb +9 -13
- data/lib/action_controller/renderer.rb +17 -16
- data/lib/action_controller/test_case.rb +75 -148
- data/lib/action_dispatch.rb +20 -19
- data/lib/action_dispatch/http/cache.rb +9 -10
- data/lib/action_dispatch/http/filter_parameters.rb +8 -8
- data/lib/action_dispatch/http/filter_redirect.rb +2 -4
- data/lib/action_dispatch/http/headers.rb +10 -10
- data/lib/action_dispatch/http/mime_negotiation.rb +17 -22
- data/lib/action_dispatch/http/mime_type.rb +27 -52
- data/lib/action_dispatch/http/parameter_filter.rb +8 -6
- data/lib/action_dispatch/http/parameters.rb +40 -17
- data/lib/action_dispatch/http/request.rb +38 -34
- data/lib/action_dispatch/http/response.rb +16 -16
- data/lib/action_dispatch/http/upload.rb +6 -10
- data/lib/action_dispatch/http/url.rb +48 -74
- data/lib/action_dispatch/journey.rb +5 -5
- data/lib/action_dispatch/journey/formatter.rb +8 -4
- data/lib/action_dispatch/journey/gtg/builder.rb +5 -5
- data/lib/action_dispatch/journey/gtg/simulator.rb +1 -1
- data/lib/action_dispatch/journey/gtg/transition_table.rb +15 -15
- data/lib/action_dispatch/journey/nfa/builder.rb +3 -3
- data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
- data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
- data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -2
- data/lib/action_dispatch/journey/nodes/node.rb +5 -5
- data/lib/action_dispatch/journey/parser.rb +23 -24
- data/lib/action_dispatch/journey/parser.y +3 -2
- data/lib/action_dispatch/journey/parser_extras.rb +2 -2
- data/lib/action_dispatch/journey/path/pattern.rb +10 -3
- data/lib/action_dispatch/journey/route.rb +19 -12
- data/lib/action_dispatch/journey/router.rb +19 -12
- data/lib/action_dispatch/journey/router/utils.rb +9 -9
- data/lib/action_dispatch/journey/scanner.rb +17 -15
- data/lib/action_dispatch/journey/visitors.rb +23 -23
- data/lib/action_dispatch/middleware/callbacks.rb +0 -12
- data/lib/action_dispatch/middleware/cookies.rb +39 -39
- data/lib/action_dispatch/middleware/debug_exceptions.rb +126 -112
- data/lib/action_dispatch/middleware/debug_locks.rb +8 -8
- data/lib/action_dispatch/middleware/exception_wrapper.rb +55 -55
- data/lib/action_dispatch/middleware/executor.rb +1 -1
- data/lib/action_dispatch/middleware/flash.rb +17 -16
- data/lib/action_dispatch/middleware/public_exceptions.rb +20 -20
- data/lib/action_dispatch/middleware/reloader.rb +3 -47
- data/lib/action_dispatch/middleware/remote_ip.rb +6 -8
- data/lib/action_dispatch/middleware/request_id.rb +6 -5
- data/lib/action_dispatch/middleware/session/abstract_store.rb +14 -26
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +35 -35
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +19 -19
- data/lib/action_dispatch/middleware/ssl.rb +9 -27
- data/lib/action_dispatch/middleware/stack.rb +7 -26
- data/lib/action_dispatch/middleware/static.rb +13 -24
- data/lib/action_dispatch/railtie.rb +9 -11
- data/lib/action_dispatch/request/session.rb +22 -22
- data/lib/action_dispatch/request/utils.rb +11 -2
- data/lib/action_dispatch/routing.rb +8 -6
- data/lib/action_dispatch/routing/inspector.rb +37 -37
- data/lib/action_dispatch/routing/mapper.rb +296 -203
- data/lib/action_dispatch/routing/polymorphic_routes.rb +160 -134
- data/lib/action_dispatch/routing/redirection.rb +27 -22
- data/lib/action_dispatch/routing/route_set.rb +206 -92
- data/lib/action_dispatch/routing/routes_proxy.rb +2 -2
- data/lib/action_dispatch/routing/url_for.rb +14 -12
- data/lib/action_dispatch/system_test_case.rb +119 -0
- data/lib/action_dispatch/system_testing/browser.rb +28 -0
- data/lib/action_dispatch/system_testing/driver.rb +18 -0
- data/lib/action_dispatch/system_testing/server.rb +32 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +61 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +20 -0
- data/lib/action_dispatch/testing/assertion_response.rb +6 -6
- data/lib/action_dispatch/testing/assertions.rb +4 -4
- data/lib/action_dispatch/testing/assertions/response.rb +8 -3
- data/lib/action_dispatch/testing/assertions/routing.rb +11 -11
- data/lib/action_dispatch/testing/integration.rb +47 -138
- data/lib/action_dispatch/testing/test_process.rb +2 -2
- data/lib/action_dispatch/testing/test_request.rb +16 -16
- data/lib/action_dispatch/testing/test_response.rb +1 -1
- data/lib/action_pack.rb +2 -2
- data/lib/action_pack/gem_version.rb +3 -3
- data/lib/action_pack/version.rb +1 -1
- metadata +20 -12
- data/lib/action_dispatch/middleware/params_parser.rb +0 -46
@@ -1,12 +1,4 @@
|
|
1
1
|
module ActionController
|
2
|
-
class RedirectBackError < AbstractController::Error #:nodoc:
|
3
|
-
DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify request.env["HTTP_REFERER"].'
|
4
|
-
|
5
|
-
def initialize(message = nil)
|
6
|
-
super(message || DEFAULT_MESSAGE)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
2
|
module Redirecting
|
11
3
|
extend ActiveSupport::Concern
|
12
4
|
|
@@ -24,10 +16,10 @@ module ActionController
|
|
24
16
|
# === Examples:
|
25
17
|
#
|
26
18
|
# redirect_to action: "show", id: 5
|
27
|
-
# redirect_to post
|
19
|
+
# redirect_to @post
|
28
20
|
# redirect_to "http://www.rubyonrails.org"
|
29
21
|
# redirect_to "/images/screenshot.jpg"
|
30
|
-
# redirect_to
|
22
|
+
# redirect_to posts_url
|
31
23
|
# redirect_to proc { edit_post_url(@post) }
|
32
24
|
#
|
33
25
|
# The redirection happens as a "302 Found" header unless otherwise specified using the <tt>:status</tt> option:
|
@@ -58,13 +50,13 @@ module ActionController
|
|
58
50
|
# redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id }
|
59
51
|
# redirect_to({ action: 'atom' }, alert: "Something serious happened")
|
60
52
|
#
|
61
|
-
def redirect_to(options = {}, response_status = {})
|
53
|
+
def redirect_to(options = {}, response_status = {})
|
62
54
|
raise ActionControllerError.new("Cannot redirect to nil!") unless options
|
63
55
|
raise AbstractController::DoubleRenderError if response_body
|
64
56
|
|
65
57
|
self.status = _extract_redirect_to_status(options, response_status)
|
66
58
|
self.location = _compute_redirect_to_location(request, options)
|
67
|
-
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(location)}\">redirected</a>.</body></html>"
|
59
|
+
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
|
68
60
|
end
|
69
61
|
|
70
62
|
# Redirects the browser to the page that issued the request (the referrer)
|
@@ -77,11 +69,11 @@ module ActionController
|
|
77
69
|
# is missing this header, the <tt>fallback_location</tt> will be used.
|
78
70
|
#
|
79
71
|
# redirect_back fallback_location: { action: "show", id: 5 }
|
80
|
-
# redirect_back fallback_location: post
|
72
|
+
# redirect_back fallback_location: @post
|
81
73
|
# redirect_back fallback_location: "http://www.rubyonrails.org"
|
82
|
-
# redirect_back fallback_location:
|
83
|
-
# redirect_back fallback_location:
|
84
|
-
# redirect_back fallback_location:
|
74
|
+
# redirect_back fallback_location: "/images/screenshot.jpg"
|
75
|
+
# redirect_back fallback_location: posts_url
|
76
|
+
# redirect_back fallback_location: proc { edit_post_url(@post) }
|
85
77
|
#
|
86
78
|
# All options that can be passed to <tt>redirect_to</tt> are accepted as
|
87
79
|
# options and the behavior is identical.
|
@@ -104,14 +96,6 @@ module ActionController
|
|
104
96
|
options
|
105
97
|
when String
|
106
98
|
request.protocol + request.host_with_port + options
|
107
|
-
when :back
|
108
|
-
ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
|
109
|
-
`redirect_to :back` is deprecated and will be removed from Rails 5.1.
|
110
|
-
Please use `redirect_back(fallback_location: fallback_location)` where
|
111
|
-
`fallback_location` represents the location to use if the request has
|
112
|
-
no HTTP referer information.
|
113
|
-
MESSAGE
|
114
|
-
request.headers["Referer"] or raise RedirectBackError
|
115
99
|
when Proc
|
116
100
|
_compute_redirect_to_location request, options.call
|
117
101
|
else
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "set"
|
2
2
|
|
3
3
|
module ActionController
|
4
4
|
# See <tt>Renderers.add</tt>
|
@@ -92,7 +92,6 @@ module ActionController
|
|
92
92
|
end
|
93
93
|
|
94
94
|
module ClassMethods
|
95
|
-
|
96
95
|
# Adds, by name, a renderer or renderers to the +_renderers+ available
|
97
96
|
# to call within controller actions.
|
98
97
|
#
|
@@ -105,7 +104,7 @@ module ActionController
|
|
105
104
|
#
|
106
105
|
# Since <tt>ActionController::Metal</tt> controllers cannot render, the controller
|
107
106
|
# must include <tt>AbstractController::Rendering</tt>, <tt>ActionController::Rendering</tt>,
|
108
|
-
# and <tt>ActionController::Renderers</tt>, and have at
|
107
|
+
# and <tt>ActionController::Renderers</tt>, and have at least one renderer.
|
109
108
|
#
|
110
109
|
# Rather than including <tt>ActionController::Renderers::All</tt> and including all renderers,
|
111
110
|
# you may specify which renderers to include by passing the renderer name or names to
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/core_ext/string/filters"
|
2
2
|
|
3
3
|
module ActionController
|
4
4
|
module Rendering
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
RENDER_FORMATS_IN_PRIORITY = [:body, :
|
7
|
+
RENDER_FORMATS_IN_PRIORITY = [:body, :plain, :html]
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
# Documentation at ActionController::Renderer#render
|
@@ -32,7 +32,7 @@ module ActionController
|
|
32
32
|
|
33
33
|
# Check for double render errors and set the content_type after rendering.
|
34
34
|
def render(*args) #:nodoc:
|
35
|
-
raise ::AbstractController::DoubleRenderError if
|
35
|
+
raise ::AbstractController::DoubleRenderError if response_body
|
36
36
|
super
|
37
37
|
end
|
38
38
|
|
@@ -49,84 +49,74 @@ module ActionController
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def render_to_body(options = {})
|
52
|
-
super || _render_in_priorities(options) ||
|
52
|
+
super || _render_in_priorities(options) || " "
|
53
53
|
end
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
def _process_variant(options)
|
58
|
+
if defined?(request) && !request.nil? && request.variant.present?
|
59
|
+
options[:variant] = request.variant
|
60
|
+
end
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
self.content_type = Mime[:html].to_s
|
67
|
-
end
|
63
|
+
def _render_in_priorities(options)
|
64
|
+
RENDER_FORMATS_IN_PRIORITY.each do |format|
|
65
|
+
return options[format] if options.key?(format)
|
66
|
+
end
|
68
67
|
|
69
|
-
|
70
|
-
if format && !response.content_type
|
71
|
-
self.content_type = format.to_s
|
68
|
+
nil
|
72
69
|
end
|
73
|
-
end
|
74
70
|
|
75
|
-
|
76
|
-
|
77
|
-
options = super
|
78
|
-
options[:update] = blk if block_given?
|
79
|
-
options
|
80
|
-
end
|
81
|
-
|
82
|
-
# Normalize both text and status options.
|
83
|
-
def _normalize_options(options) #:nodoc:
|
84
|
-
_normalize_text(options)
|
85
|
-
|
86
|
-
if options[:text]
|
87
|
-
ActiveSupport::Deprecation.warn <<-WARNING.squish
|
88
|
-
`render :text` is deprecated because it does not actually render a
|
89
|
-
`text/plain` response. Switch to `render plain: 'plain text'` to
|
90
|
-
render as `text/plain`, `render html: '<strong>HTML</strong>'` to
|
91
|
-
render as `text/html`, or `render body: 'raw'` to match the deprecated
|
92
|
-
behavior and render with the default Content-Type, which is
|
93
|
-
`text/html`.
|
94
|
-
WARNING
|
71
|
+
def _set_html_content_type
|
72
|
+
self.content_type = Mime[:html].to_s
|
95
73
|
end
|
96
74
|
|
97
|
-
|
98
|
-
|
75
|
+
def _set_rendered_content_type(format)
|
76
|
+
if format && !response.content_type
|
77
|
+
self.content_type = format.to_s
|
78
|
+
end
|
99
79
|
end
|
100
80
|
|
101
|
-
|
102
|
-
|
103
|
-
options
|
81
|
+
# Normalize arguments by catching blocks and setting them on :update.
|
82
|
+
def _normalize_args(action = nil, options = {}, &blk)
|
83
|
+
options = super
|
84
|
+
options[:update] = blk if block_given?
|
85
|
+
options
|
104
86
|
end
|
105
87
|
|
106
|
-
|
107
|
-
|
108
|
-
|
88
|
+
# Normalize both text and status options.
|
89
|
+
def _normalize_options(options)
|
90
|
+
_normalize_text(options)
|
109
91
|
|
110
|
-
|
111
|
-
|
92
|
+
if options[:html]
|
93
|
+
options[:html] = ERB::Util.html_escape(options[:html])
|
94
|
+
end
|
112
95
|
|
113
|
-
|
114
|
-
|
115
|
-
if options.key?(format) && options[format].respond_to?(:to_text)
|
116
|
-
options[format] = options[format].to_text
|
96
|
+
if options[:status]
|
97
|
+
options[:status] = Rack::Utils.status_code(options[:status])
|
117
98
|
end
|
99
|
+
|
100
|
+
super
|
118
101
|
end
|
119
|
-
end
|
120
102
|
|
121
|
-
|
122
|
-
|
123
|
-
|
103
|
+
def _normalize_text(options)
|
104
|
+
RENDER_FORMATS_IN_PRIORITY.each do |format|
|
105
|
+
if options.key?(format) && options[format].respond_to?(:to_text)
|
106
|
+
options[format] = options[format].to_text
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
124
110
|
|
125
|
-
|
126
|
-
|
127
|
-
|
111
|
+
# Process controller specific options, as status, content-type and location.
|
112
|
+
def _process_options(options)
|
113
|
+
status, content_type, location = options.values_at(:status, :content_type, :location)
|
128
114
|
|
129
|
-
|
130
|
-
|
115
|
+
self.status = status if status
|
116
|
+
self.content_type = content_type if content_type
|
117
|
+
headers["Location"] = url_for(location) if location
|
118
|
+
|
119
|
+
super
|
120
|
+
end
|
131
121
|
end
|
132
122
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "rack/session/abstract/id"
|
2
|
+
require "action_controller/metal/exceptions"
|
3
|
+
require "active_support/security_utils"
|
4
4
|
|
5
5
|
module ActionController #:nodoc:
|
6
6
|
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
|
@@ -130,11 +130,11 @@ module ActionController #:nodoc:
|
|
130
130
|
|
131
131
|
private
|
132
132
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
def protection_method_class(name)
|
134
|
+
ActionController::RequestForgeryProtection::ProtectionMethods.const_get(name.to_s.classify)
|
135
|
+
rescue NameError
|
136
|
+
raise ArgumentError, "Invalid request forgery protection method, use :null_session, :exception, or :reset_session"
|
137
|
+
end
|
138
138
|
end
|
139
139
|
|
140
140
|
module ProtectionMethods
|
@@ -152,28 +152,28 @@ module ActionController #:nodoc:
|
|
152
152
|
request.cookie_jar = NullCookieJar.build(request, {})
|
153
153
|
end
|
154
154
|
|
155
|
-
|
155
|
+
private
|
156
156
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
157
|
+
class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
|
158
|
+
def initialize(req)
|
159
|
+
super(nil, req)
|
160
|
+
@data = {}
|
161
|
+
@loaded = true
|
162
|
+
end
|
163
163
|
|
164
|
-
|
165
|
-
|
164
|
+
# no-op
|
165
|
+
def destroy; end
|
166
166
|
|
167
|
-
|
168
|
-
|
167
|
+
def exists?
|
168
|
+
true
|
169
|
+
end
|
169
170
|
end
|
170
|
-
end
|
171
171
|
|
172
|
-
|
173
|
-
|
174
|
-
|
172
|
+
class NullCookieJar < ActionDispatch::Cookies::CookieJar #:nodoc:
|
173
|
+
def write(*)
|
174
|
+
# nothing
|
175
|
+
end
|
175
176
|
end
|
176
|
-
end
|
177
177
|
end
|
178
178
|
|
179
179
|
class ResetSession
|
@@ -197,7 +197,7 @@ module ActionController #:nodoc:
|
|
197
197
|
end
|
198
198
|
end
|
199
199
|
|
200
|
-
|
200
|
+
private
|
201
201
|
# The actual before_action that is used to verify the CSRF token.
|
202
202
|
# Don't override this directly. Provide your own forgery protection
|
203
203
|
# strategy instead. If you override, you'll disable same-origin
|
@@ -208,7 +208,7 @@ module ActionController #:nodoc:
|
|
208
208
|
# enabled on an action, this before_action flags its after_action to
|
209
209
|
# verify that JavaScript responses are for XHR requests, ensuring they
|
210
210
|
# follow the browser's same-origin policy.
|
211
|
-
def verify_authenticity_token
|
211
|
+
def verify_authenticity_token # :doc:
|
212
212
|
mark_for_same_origin_verification!
|
213
213
|
|
214
214
|
if !verified_request?
|
@@ -219,7 +219,7 @@ module ActionController #:nodoc:
|
|
219
219
|
end
|
220
220
|
end
|
221
221
|
|
222
|
-
def handle_unverified_request
|
222
|
+
def handle_unverified_request # :doc:
|
223
223
|
forgery_protection_strategy.new(self).handle_unverified_request
|
224
224
|
end
|
225
225
|
|
@@ -233,26 +233,28 @@ module ActionController #:nodoc:
|
|
233
233
|
# If `verify_authenticity_token` was run (indicating that we have
|
234
234
|
# forgery protection enabled for this request) then also verify that
|
235
235
|
# we aren't serving an unauthorized cross-origin response.
|
236
|
-
def verify_same_origin_request
|
236
|
+
def verify_same_origin_request # :doc:
|
237
237
|
if marked_for_same_origin_verification? && non_xhr_javascript_response?
|
238
|
-
logger
|
238
|
+
if logger && log_warning_on_csrf_failure
|
239
|
+
logger.warn CROSS_ORIGIN_JAVASCRIPT_WARNING
|
240
|
+
end
|
239
241
|
raise ActionController::InvalidCrossOriginRequest, CROSS_ORIGIN_JAVASCRIPT_WARNING
|
240
242
|
end
|
241
243
|
end
|
242
244
|
|
243
245
|
# GET requests are checked for cross-origin JavaScript after rendering.
|
244
|
-
def mark_for_same_origin_verification!
|
246
|
+
def mark_for_same_origin_verification! # :doc:
|
245
247
|
@marked_for_same_origin_verification = request.get?
|
246
248
|
end
|
247
249
|
|
248
250
|
# If the `verify_authenticity_token` before_action ran, verify that
|
249
251
|
# JavaScript responses are only served to same-origin GET requests.
|
250
|
-
def marked_for_same_origin_verification?
|
252
|
+
def marked_for_same_origin_verification? # :doc:
|
251
253
|
@marked_for_same_origin_verification ||= false
|
252
254
|
end
|
253
255
|
|
254
256
|
# Check for cross-origin JavaScript responses.
|
255
|
-
def non_xhr_javascript_response?
|
257
|
+
def non_xhr_javascript_response? # :doc:
|
256
258
|
content_type =~ %r(\Atext/javascript) && !request.xhr?
|
257
259
|
end
|
258
260
|
|
@@ -263,20 +265,20 @@ module ActionController #:nodoc:
|
|
263
265
|
# * Is it a GET or HEAD request? Gets should be safe and idempotent
|
264
266
|
# * Does the form_authenticity_token match the given token value from the params?
|
265
267
|
# * Does the X-CSRF-Token header match the form_authenticity_token
|
266
|
-
def verified_request?
|
268
|
+
def verified_request? # :doc:
|
267
269
|
!protect_against_forgery? || request.get? || request.head? ||
|
268
270
|
(valid_request_origin? && any_authenticity_token_valid?)
|
269
271
|
end
|
270
272
|
|
271
273
|
# Checks if any of the authenticity tokens from the request are valid.
|
272
|
-
def any_authenticity_token_valid?
|
274
|
+
def any_authenticity_token_valid? # :doc:
|
273
275
|
request_authenticity_tokens.any? do |token|
|
274
276
|
valid_authenticity_token?(session, token)
|
275
277
|
end
|
276
278
|
end
|
277
279
|
|
278
280
|
# Possible authenticity tokens sent in the request.
|
279
|
-
def request_authenticity_tokens
|
281
|
+
def request_authenticity_tokens # :doc:
|
280
282
|
[form_authenticity_param, request.x_csrf_token]
|
281
283
|
end
|
282
284
|
|
@@ -288,7 +290,7 @@ module ActionController #:nodoc:
|
|
288
290
|
# Creates a masked version of the authenticity token that varies
|
289
291
|
# on each request. The masking is used to mitigate SSL attacks
|
290
292
|
# like BREACH.
|
291
|
-
def masked_authenticity_token(session, form_options: {})
|
293
|
+
def masked_authenticity_token(session, form_options: {}) # :doc:
|
292
294
|
action, method = form_options.values_at(:action, :method)
|
293
295
|
|
294
296
|
raw_token = if per_form_csrf_tokens && action && method
|
@@ -307,7 +309,7 @@ module ActionController #:nodoc:
|
|
307
309
|
# Checks the client's masked token to see if it matches the
|
308
310
|
# session token. Essentially the inverse of
|
309
311
|
# +masked_authenticity_token+.
|
310
|
-
def valid_authenticity_token?(session, encoded_masked_token)
|
312
|
+
def valid_authenticity_token?(session, encoded_masked_token) # :doc:
|
311
313
|
if encoded_masked_token.nil? || encoded_masked_token.empty? || !encoded_masked_token.is_a?(String)
|
312
314
|
return false
|
313
315
|
end
|
@@ -338,7 +340,7 @@ module ActionController #:nodoc:
|
|
338
340
|
end
|
339
341
|
end
|
340
342
|
|
341
|
-
def unmask_token(masked_token)
|
343
|
+
def unmask_token(masked_token) # :doc:
|
342
344
|
# Split the token into the one-time pad and the encrypted
|
343
345
|
# value and decrypt it
|
344
346
|
one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH]
|
@@ -346,11 +348,11 @@ module ActionController #:nodoc:
|
|
346
348
|
xor_byte_strings(one_time_pad, encrypted_csrf_token)
|
347
349
|
end
|
348
350
|
|
349
|
-
def compare_with_real_token(token, session)
|
351
|
+
def compare_with_real_token(token, session) # :doc:
|
350
352
|
ActiveSupport::SecurityUtils.secure_compare(token, real_csrf_token(session))
|
351
353
|
end
|
352
354
|
|
353
|
-
def valid_per_form_csrf_token?(token, session)
|
355
|
+
def valid_per_form_csrf_token?(token, session) # :doc:
|
354
356
|
if per_form_csrf_tokens
|
355
357
|
correct_token = per_form_csrf_token(
|
356
358
|
session,
|
@@ -364,12 +366,12 @@ module ActionController #:nodoc:
|
|
364
366
|
end
|
365
367
|
end
|
366
368
|
|
367
|
-
def real_csrf_token(session)
|
369
|
+
def real_csrf_token(session) # :doc:
|
368
370
|
session[:_csrf_token] ||= SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH)
|
369
371
|
Base64.strict_decode64(session[:_csrf_token])
|
370
372
|
end
|
371
373
|
|
372
|
-
def per_form_csrf_token(session, action_path, method)
|
374
|
+
def per_form_csrf_token(session, action_path, method) # :doc:
|
373
375
|
OpenSSL::HMAC.digest(
|
374
376
|
OpenSSL::Digest::SHA256.new,
|
375
377
|
real_csrf_token(session),
|
@@ -377,25 +379,25 @@ module ActionController #:nodoc:
|
|
377
379
|
)
|
378
380
|
end
|
379
381
|
|
380
|
-
def xor_byte_strings(s1, s2)
|
382
|
+
def xor_byte_strings(s1, s2) # :doc:
|
381
383
|
s2_bytes = s2.bytes
|
382
384
|
s1.each_byte.with_index { |c1, i| s2_bytes[i] ^= c1 }
|
383
|
-
s2_bytes.pack(
|
385
|
+
s2_bytes.pack("C*")
|
384
386
|
end
|
385
387
|
|
386
388
|
# The form's authenticity parameter. Override to provide your own.
|
387
|
-
def form_authenticity_param
|
389
|
+
def form_authenticity_param # :doc:
|
388
390
|
params[request_forgery_protection_token]
|
389
391
|
end
|
390
392
|
|
391
393
|
# Checks if the controller allows forgery protection.
|
392
|
-
def protect_against_forgery?
|
394
|
+
def protect_against_forgery? # :doc:
|
393
395
|
allow_forgery_protection
|
394
396
|
end
|
395
397
|
|
396
398
|
# Checks if the request originated from the same origin by looking at the
|
397
399
|
# Origin header.
|
398
|
-
def valid_request_origin?
|
400
|
+
def valid_request_origin? # :doc:
|
399
401
|
if forgery_protection_origin_check
|
400
402
|
# We accept blank origin headers because some user agents don't send it.
|
401
403
|
request.origin.nil? || request.origin == request.base_url
|
@@ -404,9 +406,9 @@ module ActionController #:nodoc:
|
|
404
406
|
end
|
405
407
|
end
|
406
408
|
|
407
|
-
def normalize_action_path(action_path)
|
409
|
+
def normalize_action_path(action_path) # :doc:
|
408
410
|
uri = URI.parse(action_path)
|
409
|
-
uri.path.chomp(
|
411
|
+
uri.path.chomp("/")
|
410
412
|
end
|
411
413
|
end
|
412
414
|
end
|