actionpack 4.0.13 → 4.1.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +131 -1636
- data/README.rdoc +1 -6
- data/lib/abstract_controller.rb +1 -2
- data/lib/abstract_controller/base.rb +3 -25
- data/lib/abstract_controller/callbacks.rb +4 -2
- data/lib/abstract_controller/collector.rb +11 -1
- data/lib/abstract_controller/helpers.rb +18 -15
- data/lib/abstract_controller/rendering.rb +48 -127
- data/lib/action_controller.rb +1 -17
- data/lib/action_controller/base.rb +14 -6
- data/lib/action_controller/caching.rb +1 -11
- data/lib/action_controller/log_subscriber.rb +1 -1
- data/lib/action_controller/metal.rb +0 -4
- data/lib/action_controller/metal/flash.rb +17 -0
- data/lib/action_controller/metal/force_ssl.rb +1 -1
- data/lib/action_controller/metal/head.rb +1 -3
- data/lib/action_controller/metal/helpers.rb +6 -2
- data/lib/action_controller/metal/http_authentication.rb +7 -14
- data/lib/action_controller/metal/instrumentation.rb +1 -1
- data/lib/action_controller/metal/live.rb +74 -0
- data/lib/action_controller/metal/mime_responds.rb +93 -16
- data/lib/action_controller/metal/params_wrapper.rb +4 -11
- data/lib/action_controller/metal/rack_delegation.rb +1 -1
- data/lib/action_controller/metal/redirecting.rb +20 -20
- data/lib/action_controller/metal/renderers.rb +8 -5
- data/lib/action_controller/metal/rendering.rb +14 -11
- data/lib/action_controller/metal/request_forgery_protection.rb +67 -13
- data/lib/action_controller/metal/responder.rb +12 -2
- data/lib/action_controller/metal/streaming.rb +18 -20
- data/lib/action_controller/metal/strong_parameters.rb +22 -34
- data/lib/action_controller/railtie.rb +0 -1
- data/lib/action_controller/test_case.rb +0 -15
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_dispatch/http/headers.rb +1 -3
- data/lib/action_dispatch/http/mime_negotiation.rb +16 -2
- data/lib/action_dispatch/http/mime_type.rb +4 -22
- data/lib/action_dispatch/http/mime_types.rb +1 -0
- data/lib/action_dispatch/http/parameters.rb +18 -19
- data/lib/action_dispatch/http/request.rb +16 -25
- data/lib/action_dispatch/http/response.rb +21 -8
- data/lib/action_dispatch/http/upload.rb +0 -13
- data/lib/action_dispatch/http/url.rb +10 -18
- data/lib/action_dispatch/journey/formatter.rb +3 -3
- data/lib/action_dispatch/journey/gtg/transition_table.rb +3 -5
- data/lib/action_dispatch/journey/parser.rb +1 -1
- data/lib/action_dispatch/journey/parser.y +1 -0
- data/lib/action_dispatch/journey/router.rb +7 -1
- data/lib/action_dispatch/journey/router/utils.rb +1 -1
- data/lib/action_dispatch/journey/visitors.rb +26 -47
- data/lib/action_dispatch/middleware/callbacks.rb +6 -6
- data/lib/action_dispatch/middleware/cookies.rb +15 -15
- data/lib/action_dispatch/middleware/debug_exceptions.rb +21 -13
- data/lib/action_dispatch/middleware/exception_wrapper.rb +1 -1
- data/lib/action_dispatch/middleware/flash.rb +5 -11
- data/lib/action_dispatch/middleware/params_parser.rb +1 -1
- data/lib/action_dispatch/middleware/public_exceptions.rb +1 -5
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +4 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +5 -2
- data/lib/action_dispatch/middleware/ssl.rb +1 -1
- data/lib/action_dispatch/middleware/static.rb +5 -25
- data/lib/action_dispatch/middleware/templates/rescues/{_request_and_response.erb → _request_and_response.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/{_trace.erb → _trace.html.erb} +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +15 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/{missing_template.erb → missing_template.html.erb} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/{routing_error.erb → routing_error.html.erb} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/{template_error.erb → template_error.html.erb} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/{unknown_action.erb → unknown_action.html.erb} +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +3 -3
- data/lib/action_dispatch/railtie.rb +1 -2
- data/lib/action_dispatch/request/session.rb +12 -0
- data/lib/action_dispatch/request/utils.rb +24 -0
- data/lib/action_dispatch/routing.rb +7 -6
- data/lib/action_dispatch/routing/inspector.rb +4 -4
- data/lib/action_dispatch/routing/mapper.rb +81 -138
- data/lib/action_dispatch/routing/polymorphic_routes.rb +13 -0
- data/lib/action_dispatch/routing/redirection.rb +34 -27
- data/lib/action_dispatch/routing/route_set.rb +43 -37
- data/lib/action_dispatch/routing/url_for.rb +3 -1
- data/lib/action_dispatch/testing/assertions/response.rb +8 -15
- data/lib/action_dispatch/testing/assertions/selector.rb +4 -4
- data/lib/action_dispatch/testing/integration.rb +1 -7
- data/lib/action_pack/version.rb +1 -1
- metadata +43 -167
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- data/lib/action_controller/deprecated.rb +0 -7
- data/lib/action_controller/deprecated/integration_test.rb +0 -5
- data/lib/action_controller/record_identifier.rb +0 -31
- data/lib/action_controller/vendor/html-scanner.rb +0 -5
- data/lib/action_view.rb +0 -93
- data/lib/action_view/base.rb +0 -205
- data/lib/action_view/buffers.rb +0 -49
- data/lib/action_view/context.rb +0 -36
- data/lib/action_view/dependency_tracker.rb +0 -93
- data/lib/action_view/digestor.rb +0 -113
- data/lib/action_view/flows.rb +0 -76
- data/lib/action_view/helpers.rb +0 -58
- data/lib/action_view/helpers/active_model_helper.rb +0 -49
- data/lib/action_view/helpers/asset_tag_helper.rb +0 -320
- data/lib/action_view/helpers/asset_url_helper.rb +0 -355
- data/lib/action_view/helpers/atom_feed_helper.rb +0 -203
- data/lib/action_view/helpers/cache_helper.rb +0 -196
- data/lib/action_view/helpers/capture_helper.rb +0 -216
- data/lib/action_view/helpers/controller_helper.rb +0 -25
- data/lib/action_view/helpers/csrf_helper.rb +0 -32
- data/lib/action_view/helpers/date_helper.rb +0 -1087
- data/lib/action_view/helpers/debug_helper.rb +0 -39
- data/lib/action_view/helpers/form_helper.rb +0 -1882
- data/lib/action_view/helpers/form_options_helper.rb +0 -838
- data/lib/action_view/helpers/form_tag_helper.rb +0 -785
- data/lib/action_view/helpers/javascript_helper.rb +0 -117
- data/lib/action_view/helpers/number_helper.rb +0 -451
- data/lib/action_view/helpers/output_safety_helper.rb +0 -38
- data/lib/action_view/helpers/record_tag_helper.rb +0 -106
- data/lib/action_view/helpers/rendering_helper.rb +0 -90
- data/lib/action_view/helpers/sanitize_helper.rb +0 -256
- data/lib/action_view/helpers/tag_helper.rb +0 -173
- data/lib/action_view/helpers/tags.rb +0 -39
- data/lib/action_view/helpers/tags/base.rb +0 -148
- data/lib/action_view/helpers/tags/check_box.rb +0 -64
- data/lib/action_view/helpers/tags/checkable.rb +0 -16
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +0 -53
- data/lib/action_view/helpers/tags/collection_helpers.rb +0 -84
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +0 -36
- data/lib/action_view/helpers/tags/collection_select.rb +0 -28
- data/lib/action_view/helpers/tags/color_field.rb +0 -25
- data/lib/action_view/helpers/tags/date_field.rb +0 -13
- data/lib/action_view/helpers/tags/date_select.rb +0 -72
- data/lib/action_view/helpers/tags/datetime_field.rb +0 -22
- data/lib/action_view/helpers/tags/datetime_local_field.rb +0 -19
- data/lib/action_view/helpers/tags/datetime_select.rb +0 -8
- data/lib/action_view/helpers/tags/email_field.rb +0 -8
- data/lib/action_view/helpers/tags/file_field.rb +0 -8
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +0 -29
- data/lib/action_view/helpers/tags/hidden_field.rb +0 -8
- data/lib/action_view/helpers/tags/label.rb +0 -65
- data/lib/action_view/helpers/tags/month_field.rb +0 -13
- data/lib/action_view/helpers/tags/number_field.rb +0 -18
- data/lib/action_view/helpers/tags/password_field.rb +0 -12
- data/lib/action_view/helpers/tags/radio_button.rb +0 -31
- data/lib/action_view/helpers/tags/range_field.rb +0 -8
- data/lib/action_view/helpers/tags/search_field.rb +0 -22
- data/lib/action_view/helpers/tags/select.rb +0 -40
- data/lib/action_view/helpers/tags/tel_field.rb +0 -8
- data/lib/action_view/helpers/tags/text_area.rb +0 -18
- data/lib/action_view/helpers/tags/text_field.rb +0 -30
- data/lib/action_view/helpers/tags/time_field.rb +0 -13
- data/lib/action_view/helpers/tags/time_select.rb +0 -8
- data/lib/action_view/helpers/tags/time_zone_select.rb +0 -20
- data/lib/action_view/helpers/tags/url_field.rb +0 -8
- data/lib/action_view/helpers/tags/week_field.rb +0 -13
- data/lib/action_view/helpers/text_helper.rb +0 -448
- data/lib/action_view/helpers/translation_helper.rb +0 -112
- data/lib/action_view/helpers/url_helper.rb +0 -635
- data/lib/action_view/locale/en.yml +0 -56
- data/lib/action_view/log_subscriber.rb +0 -30
- data/lib/action_view/lookup_context.rb +0 -248
- data/lib/action_view/model_naming.rb +0 -12
- data/lib/action_view/path_set.rb +0 -77
- data/lib/action_view/railtie.rb +0 -43
- data/lib/action_view/record_identifier.rb +0 -84
- data/lib/action_view/renderer/abstract_renderer.rb +0 -47
- data/lib/action_view/renderer/partial_renderer.rb +0 -500
- data/lib/action_view/renderer/renderer.rb +0 -50
- data/lib/action_view/renderer/streaming_template_renderer.rb +0 -103
- data/lib/action_view/renderer/template_renderer.rb +0 -96
- data/lib/action_view/routing_url_for.rb +0 -107
- data/lib/action_view/tasks/dependencies.rake +0 -17
- data/lib/action_view/template.rb +0 -339
- data/lib/action_view/template/error.rb +0 -138
- data/lib/action_view/template/handlers.rb +0 -53
- data/lib/action_view/template/handlers/builder.rb +0 -26
- data/lib/action_view/template/handlers/erb.rb +0 -146
- data/lib/action_view/template/handlers/raw.rb +0 -11
- data/lib/action_view/template/resolver.rb +0 -340
- data/lib/action_view/template/text.rb +0 -34
- data/lib/action_view/template/types.rb +0 -57
- data/lib/action_view/test_case.rb +0 -270
- data/lib/action_view/testing/resolvers.rb +0 -50
- data/lib/action_view/vendor/html-scanner.rb +0 -20
- data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
- data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
|
@@ -231,12 +231,7 @@ module ActionController
|
|
|
231
231
|
# by the metal call stack.
|
|
232
232
|
def process_action(*args)
|
|
233
233
|
if _wrapper_enabled?
|
|
234
|
-
|
|
235
|
-
wrapped_hash = _extract_parameters(request.parameters)
|
|
236
|
-
else
|
|
237
|
-
wrapped_hash = _wrap_parameters request.request_parameters
|
|
238
|
-
end
|
|
239
|
-
|
|
234
|
+
wrapped_hash = _wrap_parameters request.request_parameters
|
|
240
235
|
wrapped_keys = request.request_parameters.keys
|
|
241
236
|
wrapped_filtered_hash = _wrap_parameters request.filtered_parameters.slice(*wrapped_keys)
|
|
242
237
|
|
|
@@ -264,16 +259,14 @@ module ActionController
|
|
|
264
259
|
|
|
265
260
|
# Returns the list of parameters which will be selected for wrapped.
|
|
266
261
|
def _wrap_parameters(parameters)
|
|
267
|
-
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
def _extract_parameters(parameters)
|
|
271
|
-
if include_only = _wrapper_options.include
|
|
262
|
+
value = if include_only = _wrapper_options.include
|
|
272
263
|
parameters.slice(*include_only)
|
|
273
264
|
else
|
|
274
265
|
exclude = _wrapper_options.exclude || []
|
|
275
266
|
parameters.except(*(exclude + EXCLUDE_PARAMETERS))
|
|
276
267
|
end
|
|
268
|
+
|
|
269
|
+
{ _wrapper_key => value }
|
|
277
270
|
end
|
|
278
271
|
|
|
279
272
|
# Checks if we should perform parameters wrapping.
|
|
@@ -6,7 +6,7 @@ module ActionController
|
|
|
6
6
|
extend ActiveSupport::Concern
|
|
7
7
|
|
|
8
8
|
delegate :headers, :status=, :location=, :content_type=,
|
|
9
|
-
:status, :location, :content_type, :
|
|
9
|
+
:status, :location, :content_type, :to => "@_response"
|
|
10
10
|
|
|
11
11
|
def dispatch(action, request)
|
|
12
12
|
set_response!(request)
|
|
@@ -64,7 +64,6 @@ module ActionController
|
|
|
64
64
|
# behavior for this case by rescuing ActionController::RedirectBackError.
|
|
65
65
|
def redirect_to(options = {}, response_status = {}) #:doc:
|
|
66
66
|
raise ActionControllerError.new("Cannot redirect to nil!") unless options
|
|
67
|
-
raise ActionControllerError.new("Cannot redirect to a parameter hash!") if options.is_a?(ActionController::Parameters)
|
|
68
67
|
raise AbstractController::DoubleRenderError if response_body
|
|
69
68
|
|
|
70
69
|
self.status = _extract_redirect_to_status(options, response_status)
|
|
@@ -72,6 +71,26 @@ module ActionController
|
|
|
72
71
|
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.h(location)}\">redirected</a>.</body></html>"
|
|
73
72
|
end
|
|
74
73
|
|
|
74
|
+
def _compute_redirect_to_location(options) #:nodoc:
|
|
75
|
+
case options
|
|
76
|
+
# The scheme name consist of a letter followed by any combination of
|
|
77
|
+
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
|
|
78
|
+
# characters; and is terminated by a colon (":").
|
|
79
|
+
# See http://tools.ietf.org/html/rfc3986#section-3.1
|
|
80
|
+
# The protocol relative scheme starts with a double slash "//".
|
|
81
|
+
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i
|
|
82
|
+
options
|
|
83
|
+
when String
|
|
84
|
+
request.protocol + request.host_with_port + options
|
|
85
|
+
when :back
|
|
86
|
+
request.headers["Referer"] or raise RedirectBackError
|
|
87
|
+
when Proc
|
|
88
|
+
_compute_redirect_to_location options.call
|
|
89
|
+
else
|
|
90
|
+
url_for(options)
|
|
91
|
+
end.delete("\0\r\n")
|
|
92
|
+
end
|
|
93
|
+
|
|
75
94
|
private
|
|
76
95
|
def _extract_redirect_to_status(options, response_status)
|
|
77
96
|
if options.is_a?(Hash) && options.key?(:status)
|
|
@@ -82,24 +101,5 @@ module ActionController
|
|
|
82
101
|
302
|
|
83
102
|
end
|
|
84
103
|
end
|
|
85
|
-
|
|
86
|
-
def _compute_redirect_to_location(options)
|
|
87
|
-
case options
|
|
88
|
-
# The scheme name consist of a letter followed by any combination of
|
|
89
|
-
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
|
|
90
|
-
# characters; and is terminated by a colon (":").
|
|
91
|
-
# The protocol relative scheme starts with a double slash "//"
|
|
92
|
-
when %r{\A(\w[\w+.-]*:|//).*}
|
|
93
|
-
options
|
|
94
|
-
when String
|
|
95
|
-
request.protocol + request.host_with_port + options
|
|
96
|
-
when :back
|
|
97
|
-
request.headers["Referer"] or raise RedirectBackError
|
|
98
|
-
when Proc
|
|
99
|
-
_compute_redirect_to_location options.call
|
|
100
|
-
else
|
|
101
|
-
url_for(options)
|
|
102
|
-
end.delete("\0\r\n")
|
|
103
|
-
end
|
|
104
104
|
end
|
|
105
105
|
end
|
|
@@ -6,6 +6,12 @@ module ActionController
|
|
|
6
6
|
Renderers.add(key, &block)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
class MissingRenderer < LoadError
|
|
10
|
+
def initialize(format)
|
|
11
|
+
super "No renderer defined for format: #{format}"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
9
15
|
module Renderers
|
|
10
16
|
extend ActiveSupport::Concern
|
|
11
17
|
|
|
@@ -90,11 +96,8 @@ module ActionController
|
|
|
90
96
|
json = json.to_json(options) unless json.kind_of?(String)
|
|
91
97
|
|
|
92
98
|
if options[:callback].present?
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
"/**/#{options[:callback]}(#{json})"
|
|
99
|
+
self.content_type ||= Mime::JS
|
|
100
|
+
"#{options[:callback]}(#{json})"
|
|
98
101
|
else
|
|
99
102
|
self.content_type ||= Mime::JSON
|
|
100
103
|
json
|
|
@@ -2,8 +2,6 @@ module ActionController
|
|
|
2
2
|
module Rendering
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
|
-
include AbstractController::Rendering
|
|
6
|
-
|
|
7
5
|
# Before processing, set the request formats in current controller formats.
|
|
8
6
|
def process_action(*) #:nodoc:
|
|
9
7
|
self.formats = request.formats.map(&:ref).compact
|
|
@@ -12,29 +10,34 @@ module ActionController
|
|
|
12
10
|
|
|
13
11
|
# Check for double render errors and set the content_type after rendering.
|
|
14
12
|
def render(*args) #:nodoc:
|
|
15
|
-
raise ::AbstractController::DoubleRenderError if response_body
|
|
13
|
+
raise ::AbstractController::DoubleRenderError if self.response_body
|
|
16
14
|
super
|
|
17
|
-
self.content_type ||= Mime[lookup_context.rendered_format].to_s
|
|
18
|
-
response_body
|
|
19
15
|
end
|
|
20
16
|
|
|
21
17
|
# Overwrite render_to_string because body can now be set to a rack body.
|
|
22
18
|
def render_to_string(*)
|
|
23
|
-
|
|
19
|
+
result = super
|
|
20
|
+
if result.respond_to?(:each)
|
|
24
21
|
string = ""
|
|
25
|
-
|
|
22
|
+
result.each { |r| string << r }
|
|
26
23
|
string
|
|
24
|
+
else
|
|
25
|
+
result
|
|
27
26
|
end
|
|
28
|
-
ensure
|
|
29
|
-
self.response_body = nil
|
|
30
27
|
end
|
|
31
28
|
|
|
32
|
-
def render_to_body(
|
|
33
|
-
super ||
|
|
29
|
+
def render_to_body(options = {})
|
|
30
|
+
super || options[:text].presence || ' '
|
|
34
31
|
end
|
|
35
32
|
|
|
36
33
|
private
|
|
37
34
|
|
|
35
|
+
def _process_format(format)
|
|
36
|
+
super
|
|
37
|
+
# format is a Mime::NullType instance here then this condition can't be changed to `if format`
|
|
38
|
+
self.content_type ||= format.to_s unless format.nil?
|
|
39
|
+
end
|
|
40
|
+
|
|
38
41
|
# Normalize arguments by catching blocks and setting them on :update.
|
|
39
42
|
def _normalize_args(action=nil, options={}, &blk) #:nodoc:
|
|
40
43
|
options = super
|
|
@@ -5,14 +5,24 @@ module ActionController #:nodoc:
|
|
|
5
5
|
class InvalidAuthenticityToken < ActionControllerError #:nodoc:
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
class InvalidCrossOriginRequest < ActionControllerError #:nodoc:
|
|
9
|
+
end
|
|
10
|
+
|
|
8
11
|
# Controller actions are protected from Cross-Site Request Forgery (CSRF) attacks
|
|
9
12
|
# by including a token in the rendered html for your application. This token is
|
|
10
13
|
# stored as a random string in the session, to which an attacker does not have
|
|
11
14
|
# access. When a request reaches your application, \Rails verifies the received
|
|
12
15
|
# token with the token in the session. Only HTML and JavaScript requests are checked,
|
|
13
16
|
# so this will not protect your XML API (presumably you'll have a different
|
|
14
|
-
# authentication scheme there anyway).
|
|
15
|
-
#
|
|
17
|
+
# authentication scheme there anyway).
|
|
18
|
+
#
|
|
19
|
+
# GET requests are not protected since they don't have side effects like writing
|
|
20
|
+
# to the database and don't leak sensitive information. JavaScript requests are
|
|
21
|
+
# an exception: a third-party site can use a <script> tag to reference a JavaScript
|
|
22
|
+
# URL on your site. When your JavaScript response loads on their site, it executes.
|
|
23
|
+
# With carefully crafted JavaScript on their end, sensitive data in your JavaScript
|
|
24
|
+
# response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or
|
|
25
|
+
# Ajax) requests are allowed to make GET requests for JavaScript responses.
|
|
16
26
|
#
|
|
17
27
|
# It's important to remember that XML or JSON requests are also affected and if
|
|
18
28
|
# you're building an API you'll need something like:
|
|
@@ -65,17 +75,16 @@ module ActionController #:nodoc:
|
|
|
65
75
|
module ClassMethods
|
|
66
76
|
# Turn on request forgery protection. Bear in mind that only non-GET, HTML/JavaScript requests are checked.
|
|
67
77
|
#
|
|
78
|
+
# class ApplicationController < ActionController::Base
|
|
79
|
+
# protect_from_forgery
|
|
80
|
+
# end
|
|
81
|
+
#
|
|
68
82
|
# class FooController < ApplicationController
|
|
69
83
|
# protect_from_forgery except: :index
|
|
70
84
|
#
|
|
71
|
-
# You can disable
|
|
72
|
-
#
|
|
85
|
+
# You can disable CSRF protection on controller by skipping the verification before_action:
|
|
73
86
|
# skip_before_action :verify_authenticity_token
|
|
74
87
|
#
|
|
75
|
-
# It can also be disabled for specific controller actions:
|
|
76
|
-
#
|
|
77
|
-
# skip_before_action :verify_authenticity_token, except: [:create]
|
|
78
|
-
#
|
|
79
88
|
# Valid Options:
|
|
80
89
|
#
|
|
81
90
|
# * <tt>:only/:except</tt> - Passed to the <tt>before_action</tt> call. Set which actions are verified.
|
|
@@ -89,6 +98,7 @@ module ActionController #:nodoc:
|
|
|
89
98
|
self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
|
|
90
99
|
self.request_forgery_protection_token ||= :authenticity_token
|
|
91
100
|
prepend_before_action :verify_authenticity_token, options
|
|
101
|
+
append_after_action :verify_same_origin_request
|
|
92
102
|
end
|
|
93
103
|
|
|
94
104
|
private
|
|
@@ -169,18 +179,61 @@ module ActionController #:nodoc:
|
|
|
169
179
|
end
|
|
170
180
|
|
|
171
181
|
protected
|
|
182
|
+
# The actual before_action that is used to verify the CSRF token.
|
|
183
|
+
# Don't override this directly. Provide your own forgery protection
|
|
184
|
+
# strategy instead. If you override, you'll disable same-origin
|
|
185
|
+
# `<script>` verification.
|
|
186
|
+
#
|
|
187
|
+
# Lean on the protect_from_forgery declaration to mark which actions are
|
|
188
|
+
# due for same-origin request verification. If protect_from_forgery is
|
|
189
|
+
# enabled on an action, this before_action flags its after_action to
|
|
190
|
+
# verify that JavaScript responses are for XHR requests, ensuring they
|
|
191
|
+
# follow the browser's same-origin policy.
|
|
192
|
+
def verify_authenticity_token
|
|
193
|
+
mark_for_same_origin_verification!
|
|
194
|
+
|
|
195
|
+
if !verified_request?
|
|
196
|
+
logger.warn "Can't verify CSRF token authenticity" if logger
|
|
197
|
+
handle_unverified_request
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
172
201
|
def handle_unverified_request
|
|
173
202
|
forgery_protection_strategy.new(self).handle_unverified_request
|
|
174
203
|
end
|
|
175
204
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
205
|
+
CROSS_ORIGIN_JAVASCRIPT_WARNING = "Security warning: an embedded " \
|
|
206
|
+
"<script> tag on another site requested protected JavaScript. " \
|
|
207
|
+
"If you know what you're doing, go ahead and disable forgery " \
|
|
208
|
+
"protection on this action to permit cross-origin JavaScript embedding."
|
|
209
|
+
private_constant :CROSS_ORIGIN_JAVASCRIPT_WARNING
|
|
210
|
+
|
|
211
|
+
# If `verify_authenticity_token` was run (indicating that we have
|
|
212
|
+
# forgery protection enabled for this request) then also verify that
|
|
213
|
+
# we aren't serving an unauthorized cross-origin response.
|
|
214
|
+
def verify_same_origin_request
|
|
215
|
+
if marked_for_same_origin_verification? && non_xhr_javascript_response?
|
|
216
|
+
logger.warn CROSS_ORIGIN_JAVASCRIPT_WARNING if logger
|
|
217
|
+
raise ActionController::InvalidCrossOriginRequest, CROSS_ORIGIN_JAVASCRIPT_WARNING
|
|
181
218
|
end
|
|
182
219
|
end
|
|
183
220
|
|
|
221
|
+
# GET requests are checked for cross-origin JavaScript after rendering.
|
|
222
|
+
def mark_for_same_origin_verification!
|
|
223
|
+
@marked_for_same_origin_verification = request.get?
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# If the `verify_authenticity_token` before_action ran, verify that
|
|
227
|
+
# JavaScript responses are only served to same-origin GET requests.
|
|
228
|
+
def marked_for_same_origin_verification?
|
|
229
|
+
@marked_for_same_origin_verification ||= false
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Check for cross-origin JavaScript responses.
|
|
233
|
+
def non_xhr_javascript_response?
|
|
234
|
+
content_type =~ %r(\Atext/javascript) && !request.xhr?
|
|
235
|
+
end
|
|
236
|
+
|
|
184
237
|
# Returns true or false if a request is verified. Checks:
|
|
185
238
|
#
|
|
186
239
|
# * is it a GET or HEAD request? Gets should be safe and idempotent
|
|
@@ -202,6 +255,7 @@ module ActionController #:nodoc:
|
|
|
202
255
|
params[request_forgery_protection_token]
|
|
203
256
|
end
|
|
204
257
|
|
|
258
|
+
# Checks if the controller allows forgery protection.
|
|
205
259
|
def protect_against_forgery?
|
|
206
260
|
allow_forgery_protection
|
|
207
261
|
end
|
|
@@ -97,8 +97,12 @@ module ActionController #:nodoc:
|
|
|
97
97
|
#
|
|
98
98
|
# This will return status 201 if the task was saved successfully. If not,
|
|
99
99
|
# it will simply ignore the given options and return status 422 and the
|
|
100
|
-
# resource errors.
|
|
101
|
-
#
|
|
100
|
+
# resource errors. You can also override the location to redirect to:
|
|
101
|
+
#
|
|
102
|
+
# respond_with(@project, location: root_path)
|
|
103
|
+
#
|
|
104
|
+
# To customize the failure scenario, you can pass a block to
|
|
105
|
+
# <code>respond_with</code>:
|
|
102
106
|
#
|
|
103
107
|
# def create
|
|
104
108
|
# @project = Project.find(params[:project_id])
|
|
@@ -198,6 +202,7 @@ module ActionController #:nodoc:
|
|
|
198
202
|
# This is the common behavior for formats associated with APIs, such as :xml and :json.
|
|
199
203
|
def api_behavior(error)
|
|
200
204
|
raise error unless resourceful?
|
|
205
|
+
raise MissingRenderer.new(format) unless has_renderer?
|
|
201
206
|
|
|
202
207
|
if get?
|
|
203
208
|
display resource
|
|
@@ -265,6 +270,11 @@ module ActionController #:nodoc:
|
|
|
265
270
|
resource.respond_to?(:errors) && !resource.errors.empty?
|
|
266
271
|
end
|
|
267
272
|
|
|
273
|
+
# Check whether the necessary Renderer is available
|
|
274
|
+
def has_renderer?
|
|
275
|
+
Renderers::RENDERERS.include?(format)
|
|
276
|
+
end
|
|
277
|
+
|
|
268
278
|
# By default, render the <code>:edit</code> action for HTML requests with errors, unless
|
|
269
279
|
# the verb was POST.
|
|
270
280
|
#
|
|
@@ -193,31 +193,29 @@ module ActionController #:nodoc:
|
|
|
193
193
|
module Streaming
|
|
194
194
|
extend ActiveSupport::Concern
|
|
195
195
|
|
|
196
|
-
include AbstractController::Rendering
|
|
197
|
-
|
|
198
196
|
protected
|
|
199
197
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
198
|
+
# Set proper cache control and transfer encoding when streaming
|
|
199
|
+
def _process_options(options) #:nodoc:
|
|
200
|
+
super
|
|
201
|
+
if options[:stream]
|
|
202
|
+
if env["HTTP_VERSION"] == "HTTP/1.0"
|
|
203
|
+
options.delete(:stream)
|
|
204
|
+
else
|
|
205
|
+
headers["Cache-Control"] ||= "no-cache"
|
|
206
|
+
headers["Transfer-Encoding"] = "chunked"
|
|
207
|
+
headers.delete("Content-Length")
|
|
208
|
+
end
|
|
210
209
|
end
|
|
211
210
|
end
|
|
212
|
-
end
|
|
213
211
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
212
|
+
# Call render_body if we are streaming instead of usual +render+.
|
|
213
|
+
def _render_template(options) #:nodoc:
|
|
214
|
+
if options.delete(:stream)
|
|
215
|
+
Rack::Chunked::Body.new view_renderer.render_body(view_context, options)
|
|
216
|
+
else
|
|
217
|
+
super
|
|
218
|
+
end
|
|
220
219
|
end
|
|
221
|
-
end
|
|
222
220
|
end
|
|
223
221
|
end
|
|
@@ -3,7 +3,6 @@ require 'active_support/core_ext/array/wrap'
|
|
|
3
3
|
require 'active_support/rescuable'
|
|
4
4
|
require 'action_dispatch/http/upload'
|
|
5
5
|
require 'stringio'
|
|
6
|
-
require 'set'
|
|
7
6
|
|
|
8
7
|
module ActionController
|
|
9
8
|
# Raised when a required parameter is missing.
|
|
@@ -126,13 +125,6 @@ module ActionController
|
|
|
126
125
|
@permitted = self.class.permit_all_parameters
|
|
127
126
|
end
|
|
128
127
|
|
|
129
|
-
# Attribute that keeps track of converted arrays, if any, to avoid double
|
|
130
|
-
# looping in the common use case permit + mass-assignment. Defined in a
|
|
131
|
-
# method to instantiate it only if needed.
|
|
132
|
-
def converted_arrays
|
|
133
|
-
@converted_arrays ||= Set.new
|
|
134
|
-
end
|
|
135
|
-
|
|
136
128
|
# Returns +true+ if the parameter is permitted, +false+ otherwise.
|
|
137
129
|
#
|
|
138
130
|
# params = ActionController::Parameters.new
|
|
@@ -157,10 +149,8 @@ module ActionController
|
|
|
157
149
|
# Person.new(params) # => #<Person id: nil, name: "Francesco">
|
|
158
150
|
def permit!
|
|
159
151
|
each_pair do |key, value|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
_.permit! if _.respond_to? :permit!
|
|
163
|
-
end
|
|
152
|
+
convert_hashes_to_parameters(key, value)
|
|
153
|
+
self[key].permit! if self[key].respond_to? :permit!
|
|
164
154
|
end
|
|
165
155
|
|
|
166
156
|
@permitted = true
|
|
@@ -180,12 +170,7 @@ module ActionController
|
|
|
180
170
|
# ActionController::Parameters.new(person: {}).require(:person)
|
|
181
171
|
# # => ActionController::ParameterMissing: param not found: person
|
|
182
172
|
def require(key)
|
|
183
|
-
|
|
184
|
-
if value.present? || value == false
|
|
185
|
-
value
|
|
186
|
-
else
|
|
187
|
-
raise ParameterMissing.new(key)
|
|
188
|
-
end
|
|
173
|
+
self[key].presence || raise(ParameterMissing.new(key))
|
|
189
174
|
end
|
|
190
175
|
|
|
191
176
|
# Alias of #require.
|
|
@@ -299,7 +284,14 @@ module ActionController
|
|
|
299
284
|
# params.fetch(:none, 'Francesco') # => "Francesco"
|
|
300
285
|
# params.fetch(:none) { 'Francesco' } # => "Francesco"
|
|
301
286
|
def fetch(key, *args)
|
|
302
|
-
|
|
287
|
+
value = super
|
|
288
|
+
# Don't rely on +convert_hashes_to_parameters+
|
|
289
|
+
# so as to not mutate via a +fetch+
|
|
290
|
+
if value.is_a?(Hash)
|
|
291
|
+
value = self.class.new(value)
|
|
292
|
+
value.permit! if permitted?
|
|
293
|
+
end
|
|
294
|
+
value
|
|
303
295
|
rescue KeyError
|
|
304
296
|
raise ActionController::ParameterMissing.new(key)
|
|
305
297
|
end
|
|
@@ -313,7 +305,7 @@ module ActionController
|
|
|
313
305
|
# params.slice(:d) # => {}
|
|
314
306
|
def slice(*keys)
|
|
315
307
|
self.class.new(super).tap do |new_instance|
|
|
316
|
-
new_instance.
|
|
308
|
+
new_instance.permitted = @permitted
|
|
317
309
|
end
|
|
318
310
|
end
|
|
319
311
|
|
|
@@ -327,26 +319,22 @@ module ActionController
|
|
|
327
319
|
# copy_params.permitted? # => true
|
|
328
320
|
def dup
|
|
329
321
|
super.tap do |duplicate|
|
|
330
|
-
duplicate.
|
|
322
|
+
duplicate.permitted = @permitted
|
|
331
323
|
end
|
|
332
324
|
end
|
|
333
325
|
|
|
334
|
-
|
|
335
|
-
def
|
|
336
|
-
|
|
337
|
-
self[key] = converted if assign_if_converted && !converted.equal?(value)
|
|
338
|
-
converted
|
|
326
|
+
protected
|
|
327
|
+
def permitted=(new_permitted)
|
|
328
|
+
@permitted = new_permitted
|
|
339
329
|
end
|
|
340
330
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
converted_arrays << converted
|
|
345
|
-
converted
|
|
346
|
-
elsif value.is_a?(Parameters) || !value.is_a?(Hash)
|
|
331
|
+
private
|
|
332
|
+
def convert_hashes_to_parameters(key, value)
|
|
333
|
+
if value.is_a?(Parameters) || !value.is_a?(Hash)
|
|
347
334
|
value
|
|
348
335
|
else
|
|
349
|
-
|
|
336
|
+
# Convert to Parameters on first access
|
|
337
|
+
self[key] = self.class.new(value)
|
|
350
338
|
end
|
|
351
339
|
end
|
|
352
340
|
|
|
@@ -502,7 +490,7 @@ module ActionController
|
|
|
502
490
|
# end
|
|
503
491
|
# end
|
|
504
492
|
#
|
|
505
|
-
# In order to use <tt>
|
|
493
|
+
# In order to use <tt>accepts_nested_attribute_for</tt> with Strong \Parameters, you
|
|
506
494
|
# will need to specify which nested attributes should be whitelisted.
|
|
507
495
|
#
|
|
508
496
|
# class Person
|