actionpack 4.2.10 → 7.2.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 +5 -5
- data/CHANGELOG.md +86 -600
- data/MIT-LICENSE +1 -1
- data/README.rdoc +13 -14
- data/lib/abstract_controller/asset_paths.rb +5 -1
- data/lib/abstract_controller/base.rb +166 -136
- data/lib/abstract_controller/caching/fragments.rb +149 -0
- data/lib/abstract_controller/caching.rb +68 -0
- data/lib/abstract_controller/callbacks.rb +126 -57
- data/lib/abstract_controller/collector.rb +13 -15
- data/lib/abstract_controller/deprecator.rb +9 -0
- data/lib/abstract_controller/error.rb +8 -0
- data/lib/abstract_controller/helpers.rb +181 -132
- data/lib/abstract_controller/logger.rb +5 -1
- data/lib/abstract_controller/railties/routes_helpers.rb +10 -3
- data/lib/abstract_controller/rendering.rb +56 -56
- data/lib/abstract_controller/translation.rb +29 -15
- data/lib/abstract_controller/url_for.rb +15 -11
- data/lib/abstract_controller.rb +21 -5
- data/lib/action_controller/api/api_rendering.rb +18 -0
- data/lib/action_controller/api.rb +154 -0
- data/lib/action_controller/base.rb +219 -155
- data/lib/action_controller/caching.rb +28 -68
- data/lib/action_controller/deprecator.rb +9 -0
- data/lib/action_controller/form_builder.rb +55 -0
- data/lib/action_controller/log_subscriber.rb +35 -22
- data/lib/action_controller/metal/allow_browser.rb +119 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +17 -0
- data/lib/action_controller/metal/conditional_get.rb +259 -122
- data/lib/action_controller/metal/content_security_policy.rb +86 -0
- data/lib/action_controller/metal/cookies.rb +9 -5
- data/lib/action_controller/metal/data_streaming.rb +87 -104
- data/lib/action_controller/metal/default_headers.rb +21 -0
- data/lib/action_controller/metal/etag_with_flash.rb +22 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +35 -26
- data/lib/action_controller/metal/exceptions.rb +71 -24
- data/lib/action_controller/metal/flash.rb +26 -19
- data/lib/action_controller/metal/head.rb +45 -36
- data/lib/action_controller/metal/helpers.rb +80 -64
- data/lib/action_controller/metal/http_authentication.rb +297 -244
- data/lib/action_controller/metal/implicit_render.rb +57 -9
- data/lib/action_controller/metal/instrumentation.rb +76 -64
- data/lib/action_controller/metal/live.rb +238 -176
- data/lib/action_controller/metal/logging.rb +22 -0
- data/lib/action_controller/metal/mime_responds.rb +177 -166
- data/lib/action_controller/metal/parameter_encoding.rb +84 -0
- data/lib/action_controller/metal/params_wrapper.rb +145 -118
- data/lib/action_controller/metal/permissions_policy.rb +38 -0
- data/lib/action_controller/metal/rate_limiting.rb +62 -0
- data/lib/action_controller/metal/redirecting.rb +203 -64
- data/lib/action_controller/metal/renderers.rb +108 -65
- data/lib/action_controller/metal/rendering.rb +216 -56
- data/lib/action_controller/metal/request_forgery_protection.rb +496 -163
- data/lib/action_controller/metal/rescue.rb +19 -21
- data/lib/action_controller/metal/streaming.rb +179 -138
- data/lib/action_controller/metal/strong_parameters.rb +1058 -382
- data/lib/action_controller/metal/testing.rb +11 -17
- data/lib/action_controller/metal/url_for.rb +37 -21
- data/lib/action_controller/metal.rb +236 -138
- data/lib/action_controller/railtie.rb +89 -11
- data/lib/action_controller/railties/helpers.rb +5 -1
- data/lib/action_controller/renderer.rb +161 -0
- data/lib/action_controller/template_assertions.rb +13 -0
- data/lib/action_controller/test_case.rb +425 -497
- data/lib/action_controller.rb +44 -22
- data/lib/action_dispatch/constants.rb +34 -0
- data/lib/action_dispatch/deprecator.rb +9 -0
- data/lib/action_dispatch/http/cache.rb +119 -63
- data/lib/action_dispatch/http/content_disposition.rb +47 -0
- data/lib/action_dispatch/http/content_security_policy.rb +364 -0
- data/lib/action_dispatch/http/filter_parameters.rb +36 -34
- data/lib/action_dispatch/http/filter_redirect.rb +24 -12
- data/lib/action_dispatch/http/headers.rb +66 -31
- data/lib/action_dispatch/http/mime_negotiation.rb +106 -75
- data/lib/action_dispatch/http/mime_type.rb +196 -136
- data/lib/action_dispatch/http/mime_types.rb +25 -7
- data/lib/action_dispatch/http/parameters.rb +97 -45
- data/lib/action_dispatch/http/permissions_policy.rb +187 -0
- data/lib/action_dispatch/http/rack_cache.rb +6 -0
- data/lib/action_dispatch/http/request.rb +299 -170
- data/lib/action_dispatch/http/response.rb +311 -160
- data/lib/action_dispatch/http/upload.rb +52 -23
- data/lib/action_dispatch/http/url.rb +201 -125
- data/lib/action_dispatch/journey/formatter.rb +110 -50
- data/lib/action_dispatch/journey/gtg/builder.rb +37 -50
- data/lib/action_dispatch/journey/gtg/simulator.rb +20 -17
- data/lib/action_dispatch/journey/gtg/transition_table.rb +96 -36
- data/lib/action_dispatch/journey/nfa/dot.rb +5 -14
- data/lib/action_dispatch/journey/nodes/node.rb +100 -20
- data/lib/action_dispatch/journey/parser.rb +19 -17
- data/lib/action_dispatch/journey/parser.y +4 -3
- data/lib/action_dispatch/journey/parser_extras.rb +14 -4
- data/lib/action_dispatch/journey/path/pattern.rb +79 -63
- data/lib/action_dispatch/journey/route.rb +108 -44
- data/lib/action_dispatch/journey/router/utils.rb +41 -29
- data/lib/action_dispatch/journey/router.rb +64 -57
- data/lib/action_dispatch/journey/routes.rb +23 -21
- data/lib/action_dispatch/journey/scanner.rb +28 -17
- data/lib/action_dispatch/journey/visitors.rb +100 -54
- data/lib/action_dispatch/journey/visualizer/fsm.js +49 -24
- data/lib/action_dispatch/journey/visualizer/index.html.erb +1 -1
- data/lib/action_dispatch/journey.rb +7 -5
- data/lib/action_dispatch/log_subscriber.rb +25 -0
- data/lib/action_dispatch/middleware/actionable_exceptions.rb +46 -0
- data/lib/action_dispatch/middleware/assume_ssl.rb +27 -0
- data/lib/action_dispatch/middleware/callbacks.rb +7 -6
- data/lib/action_dispatch/middleware/cookies.rb +471 -328
- data/lib/action_dispatch/middleware/debug_exceptions.rb +149 -66
- data/lib/action_dispatch/middleware/debug_locks.rb +129 -0
- data/lib/action_dispatch/middleware/debug_view.rb +73 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +275 -73
- data/lib/action_dispatch/middleware/executor.rb +32 -0
- data/lib/action_dispatch/middleware/flash.rb +143 -101
- data/lib/action_dispatch/middleware/host_authorization.rb +171 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +36 -27
- data/lib/action_dispatch/middleware/reloader.rb +10 -92
- data/lib/action_dispatch/middleware/remote_ip.rb +133 -107
- data/lib/action_dispatch/middleware/request_id.rb +29 -15
- data/lib/action_dispatch/middleware/server_timing.rb +78 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +49 -27
- data/lib/action_dispatch/middleware/session/cache_store.rb +33 -16
- data/lib/action_dispatch/middleware/session/cookie_store.rb +86 -80
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +15 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +66 -36
- data/lib/action_dispatch/middleware/ssl.rb +134 -36
- data/lib/action_dispatch/middleware/stack.rb +109 -44
- data/lib/action_dispatch/middleware/static.rb +159 -90
- data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
- data/lib/action_dispatch/middleware/templates/rescues/_message_and_suggestions.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +7 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +36 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +46 -36
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +12 -0
- data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -7
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +24 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +139 -15
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +6 -6
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +7 -7
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +9 -9
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +4 -4
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +1 -1
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +7 -4
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +125 -93
- data/lib/action_dispatch/railtie.rb +44 -16
- data/lib/action_dispatch/request/session.rb +159 -69
- data/lib/action_dispatch/request/utils.rb +97 -23
- data/lib/action_dispatch/routing/endpoint.rb +11 -2
- data/lib/action_dispatch/routing/inspector.rb +195 -106
- data/lib/action_dispatch/routing/mapper.rb +1338 -955
- data/lib/action_dispatch/routing/polymorphic_routes.rb +234 -201
- data/lib/action_dispatch/routing/redirection.rb +78 -51
- data/lib/action_dispatch/routing/route_set.rb +460 -374
- data/lib/action_dispatch/routing/routes_proxy.rb +36 -12
- data/lib/action_dispatch/routing/url_for.rb +172 -124
- data/lib/action_dispatch/routing.rb +159 -158
- data/lib/action_dispatch/system_test_case.rb +206 -0
- data/lib/action_dispatch/system_testing/browser.rb +84 -0
- data/lib/action_dispatch/system_testing/driver.rb +85 -0
- data/lib/action_dispatch/system_testing/server.rb +33 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +164 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +23 -0
- data/lib/action_dispatch/testing/assertion_response.rb +48 -0
- data/lib/action_dispatch/testing/assertions/response.rb +71 -39
- data/lib/action_dispatch/testing/assertions/routing.rb +228 -103
- data/lib/action_dispatch/testing/assertions.rb +9 -6
- data/lib/action_dispatch/testing/integration.rb +486 -306
- data/lib/action_dispatch/testing/request_encoder.rb +60 -0
- data/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb +35 -0
- data/lib/action_dispatch/testing/test_process.rb +35 -22
- data/lib/action_dispatch/testing/test_request.rb +29 -34
- data/lib/action_dispatch/testing/test_response.rb +48 -15
- data/lib/action_dispatch.rb +82 -40
- data/lib/action_pack/gem_version.rb +8 -4
- data/lib/action_pack/version.rb +6 -2
- data/lib/action_pack.rb +21 -18
- metadata +146 -56
- data/lib/action_controller/caching/fragments.rb +0 -103
- data/lib/action_controller/metal/force_ssl.rb +0 -97
- data/lib/action_controller/metal/hide_actions.rb +0 -40
- data/lib/action_controller/metal/rack_delegation.rb +0 -32
- data/lib/action_controller/middleware.rb +0 -39
- data/lib/action_controller/model_naming.rb +0 -12
- data/lib/action_dispatch/http/parameter_filter.rb +0 -72
- data/lib/action_dispatch/journey/backwards.rb +0 -5
- data/lib/action_dispatch/journey/nfa/builder.rb +0 -76
- data/lib/action_dispatch/journey/nfa/simulator.rb +0 -47
- data/lib/action_dispatch/journey/nfa/transition_table.rb +0 -163
- data/lib/action_dispatch/journey/router/strexp.rb +0 -27
- data/lib/action_dispatch/middleware/params_parser.rb +0 -60
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +0 -27
- data/lib/action_dispatch/testing/assertions/dom.rb +0 -3
- data/lib/action_dispatch/testing/assertions/selector.rb +0 -3
- data/lib/action_dispatch/testing/assertions/tag.rb +0 -3
@@ -1,26 +1,27 @@
|
|
1
|
-
|
2
|
-
require 'rack/request'
|
3
|
-
require 'rack/session/abstract/id'
|
4
|
-
require 'action_dispatch/middleware/cookies'
|
5
|
-
require 'action_dispatch/request/session'
|
1
|
+
# frozen_string_literal: true
|
6
2
|
|
7
|
-
|
8
|
-
module Session
|
9
|
-
class SessionRestoreError < StandardError #:nodoc:
|
10
|
-
attr_reader :original_exception
|
3
|
+
# :markup: markdown
|
11
4
|
|
12
|
-
|
13
|
-
|
5
|
+
require "rack/utils"
|
6
|
+
require "rack/request"
|
7
|
+
require "rack/session/abstract/id"
|
8
|
+
require "action_dispatch/middleware/cookies"
|
9
|
+
require "action_dispatch/request/session"
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
module ActionDispatch
|
12
|
+
module Session
|
13
|
+
class SessionRestoreError < StandardError # :nodoc:
|
14
|
+
def initialize
|
15
|
+
super("Session contains objects whose class definition isn't available.\n" \
|
16
|
+
"Remember to require the classes for all objects kept in the session.\n" \
|
17
|
+
"(Original exception: #{$!.message} [#{$!.class}])\n")
|
18
|
+
set_backtrace $!.backtrace
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
22
|
module Compatibility
|
22
23
|
def initialize(app, options = {})
|
23
|
-
options[:key] ||=
|
24
|
+
options[:key] ||= "_session_id"
|
24
25
|
super
|
25
26
|
end
|
26
27
|
|
@@ -30,12 +31,15 @@ module ActionDispatch
|
|
30
31
|
sid
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
def initialize_sid
|
34
|
+
private
|
35
|
+
def initialize_sid # :doc:
|
36
36
|
@default_options.delete(:sidbits)
|
37
37
|
@default_options.delete(:secure_random)
|
38
38
|
end
|
39
|
+
|
40
|
+
def make_request(env)
|
41
|
+
ActionDispatch::Request.new env
|
42
|
+
end
|
39
43
|
end
|
40
44
|
|
41
45
|
module StaleSessionCheck
|
@@ -52,10 +56,10 @@ module ActionDispatch
|
|
52
56
|
rescue ArgumentError => argument_error
|
53
57
|
if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
|
54
58
|
begin
|
55
|
-
# Note that the regexp does not allow $1 to end with a ':'
|
59
|
+
# Note that the regexp does not allow $1 to end with a ':'.
|
56
60
|
$1.constantize
|
57
|
-
rescue LoadError, NameError
|
58
|
-
raise ActionDispatch::Session::SessionRestoreError
|
61
|
+
rescue LoadError, NameError
|
62
|
+
raise ActionDispatch::Session::SessionRestoreError
|
59
63
|
end
|
60
64
|
retry
|
61
65
|
else
|
@@ -65,8 +69,13 @@ module ActionDispatch
|
|
65
69
|
end
|
66
70
|
|
67
71
|
module SessionObject # :nodoc:
|
68
|
-
def
|
69
|
-
|
72
|
+
def commit_session(req, res)
|
73
|
+
req.commit_csrf_token
|
74
|
+
super(req, res)
|
75
|
+
end
|
76
|
+
|
77
|
+
def prepare_session(req)
|
78
|
+
Request::Session.create(self, req, @default_options)
|
70
79
|
end
|
71
80
|
|
72
81
|
def loaded_session?(session)
|
@@ -74,17 +83,30 @@ module ActionDispatch
|
|
74
83
|
end
|
75
84
|
end
|
76
85
|
|
77
|
-
class AbstractStore < Rack::Session::Abstract::
|
86
|
+
class AbstractStore < Rack::Session::Abstract::Persisted
|
78
87
|
include Compatibility
|
79
88
|
include StaleSessionCheck
|
80
89
|
include SessionObject
|
81
90
|
|
82
91
|
private
|
92
|
+
def set_cookie(request, response, cookie)
|
93
|
+
request.cookie_jar[key] = cookie
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class AbstractSecureStore < Rack::Session::Abstract::PersistedSecure
|
98
|
+
include Compatibility
|
99
|
+
include StaleSessionCheck
|
100
|
+
include SessionObject
|
83
101
|
|
84
|
-
def
|
85
|
-
|
86
|
-
request.cookie_jar[key] = cookie
|
102
|
+
def generate_sid
|
103
|
+
Rack::Session::SessionId.new(super)
|
87
104
|
end
|
105
|
+
|
106
|
+
private
|
107
|
+
def set_cookie(request, response, cookie)
|
108
|
+
request.cookie_jar[key] = cookie
|
109
|
+
end
|
88
110
|
end
|
89
111
|
end
|
90
112
|
end
|
@@ -1,13 +1,25 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "action_dispatch/middleware/session/abstract_store"
|
2
6
|
|
3
7
|
module ActionDispatch
|
4
8
|
module Session
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
# # Action Dispatch Session CacheStore
|
10
|
+
#
|
11
|
+
# A session store that uses an ActiveSupport::Cache::Store to store the
|
12
|
+
# sessions. This store is most useful if you don't store critical data in your
|
13
|
+
# sessions and you don't need them to live for extended periods of time.
|
14
|
+
#
|
15
|
+
# #### Options
|
16
|
+
# * `cache` - The cache to use. If it is not specified, `Rails.cache`
|
17
|
+
# will be used.
|
18
|
+
# * `expire_after` - The length of time a session will be stored before
|
19
|
+
# automatically expiring. By default, the `:expires_in` option of the cache
|
20
|
+
# is used.
|
21
|
+
#
|
22
|
+
class CacheStore < AbstractSecureStore
|
11
23
|
def initialize(app, options = {})
|
12
24
|
@cache = options[:cache] || Rails.cache
|
13
25
|
options[:expire_after] ||= @cache.options[:expires_in]
|
@@ -15,18 +27,18 @@ module ActionDispatch
|
|
15
27
|
end
|
16
28
|
|
17
29
|
# Get a session from the cache.
|
18
|
-
def
|
19
|
-
unless sid
|
30
|
+
def find_session(env, sid)
|
31
|
+
unless sid && (session = get_session_with_fallback(sid))
|
20
32
|
sid, session = generate_sid, {}
|
21
33
|
end
|
22
34
|
[sid, session]
|
23
35
|
end
|
24
36
|
|
25
37
|
# Set a session in the cache.
|
26
|
-
def
|
27
|
-
key = cache_key(sid)
|
38
|
+
def write_session(env, sid, session, options)
|
39
|
+
key = cache_key(sid.private_id)
|
28
40
|
if session
|
29
|
-
@cache.write(key, session, :
|
41
|
+
@cache.write(key, session, expires_in: options[:expire_after])
|
30
42
|
else
|
31
43
|
@cache.delete(key)
|
32
44
|
end
|
@@ -34,15 +46,20 @@ module ActionDispatch
|
|
34
46
|
end
|
35
47
|
|
36
48
|
# Remove a session from the cache.
|
37
|
-
def
|
38
|
-
@cache.delete(cache_key(sid))
|
49
|
+
def delete_session(env, sid, options)
|
50
|
+
@cache.delete(cache_key(sid.private_id))
|
51
|
+
@cache.delete(cache_key(sid.public_id))
|
39
52
|
generate_sid
|
40
53
|
end
|
41
54
|
|
42
55
|
private
|
43
56
|
# Turn the session id into a cache key.
|
44
|
-
def cache_key(
|
45
|
-
"_session_id:#{
|
57
|
+
def cache_key(id)
|
58
|
+
"_session_id:#{id}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_session_with_fallback(sid)
|
62
|
+
@cache.read(cache_key(sid.private_id)) || @cache.read(cache_key(sid.public_id))
|
46
63
|
end
|
47
64
|
end
|
48
65
|
end
|
@@ -1,123 +1,129 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/core_ext/hash/keys"
|
6
|
+
require "action_dispatch/middleware/session/abstract_store"
|
7
|
+
require "rack/session/cookie"
|
4
8
|
|
5
9
|
module ActionDispatch
|
6
10
|
module Session
|
7
|
-
#
|
8
|
-
# dramatically faster than the alternatives.
|
11
|
+
# # Action Dispatch Session CookieStore
|
9
12
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# you attempt to store more than 4K of data.
|
13
|
+
# This cookie-based session store is the Rails default. It is dramatically
|
14
|
+
# faster than the alternatives.
|
13
15
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
+
# Sessions typically contain at most a user ID and flash message; both fit
|
17
|
+
# within the 4096 bytes cookie size limit. A `CookieOverflow` exception is
|
18
|
+
# raised if you attempt to store more than 4096 bytes of data.
|
16
19
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# knowing your app's secret key, but can easily read their +user_id+. This
|
20
|
-
# was the default for Rails 3 apps.
|
20
|
+
# The cookie jar used for storage is automatically configured to be the best
|
21
|
+
# possible option given your application's configuration.
|
21
22
|
#
|
22
|
-
#
|
23
|
-
# goes a step further than signed cookies in that encrypted cookies cannot
|
23
|
+
# Your cookies will be encrypted using your application's `secret_key_base`.
|
24
|
+
# This goes a step further than signed cookies in that encrypted cookies cannot
|
24
25
|
# be altered or read by users. This is the default starting in Rails 4.
|
25
26
|
#
|
26
|
-
#
|
27
|
-
# be encrypted, and signed cookies generated by Rails 3 will be
|
28
|
-
# transparently read and encrypted to provide a smooth upgrade path.
|
27
|
+
# Configure your session store in an initializer:
|
29
28
|
#
|
30
|
-
#
|
29
|
+
# Rails.application.config.session_store :cookie_store, key: '_your_app_session'
|
31
30
|
#
|
32
|
-
#
|
31
|
+
# In the development and test environments your application's `secret_key_base`
|
32
|
+
# is generated by Rails and stored in a temporary file in
|
33
|
+
# `tmp/local_secret.txt`. In all other environments, it is stored encrypted in
|
34
|
+
# the `config/credentials.yml.enc` file.
|
33
35
|
#
|
34
|
-
#
|
36
|
+
# If your application was not updated to Rails 5.2 defaults, the
|
37
|
+
# `secret_key_base` will be found in the old `config/secrets.yml` file.
|
35
38
|
#
|
36
|
-
#
|
37
|
-
#
|
39
|
+
# Note that changing your `secret_key_base` will invalidate all existing
|
40
|
+
# session. Additionally, you should take care to make sure you are not relying
|
41
|
+
# on the ability to decode signed cookies generated by your app in external
|
42
|
+
# applications or JavaScript before changing it.
|
38
43
|
#
|
39
|
-
#
|
44
|
+
# Because CookieStore extends `Rack::Session::Abstract::Persisted`, many of the
|
45
|
+
# options described there can be used to customize the session cookie that is
|
46
|
+
# generated. For example:
|
40
47
|
#
|
41
|
-
#
|
42
|
-
# existing secret_token in place and simply add the new secret_key_base.
|
43
|
-
# Note that you should wait to set secret_key_base until you have 100% of
|
44
|
-
# your userbase on Rails 4 and are reasonably sure you will not need to
|
45
|
-
# rollback to Rails 3. This is because cookies signed based on the new
|
46
|
-
# secret_key_base in Rails 4 are not backwards compatible with Rails 3.
|
47
|
-
# You are free to leave your existing secret_token in place, not set the
|
48
|
-
# new secret_key_base, and ignore the deprecation warnings until you are
|
49
|
-
# reasonably sure that your upgrade is otherwise complete. Additionally,
|
50
|
-
# you should take care to make sure you are not relying on the ability to
|
51
|
-
# decode signed cookies generated by your app in external applications or
|
52
|
-
# JavaScript before upgrading.
|
48
|
+
# Rails.application.config.session_store :cookie_store, expire_after: 14.days
|
53
49
|
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
50
|
+
# would set the session cookie to expire automatically 14 days after creation.
|
51
|
+
# Other useful options include `:key`, `:secure`, `:httponly`, and `:same_site`.
|
52
|
+
class CookieStore < AbstractSecureStore
|
53
|
+
class SessionId < DelegateClass(Rack::Session::SessionId)
|
54
|
+
attr_reader :cookie_value
|
55
|
+
|
56
|
+
def initialize(session_id, cookie_value = {})
|
57
|
+
super(session_id)
|
58
|
+
@cookie_value = cookie_value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
DEFAULT_SAME_SITE = proc { |request| request.cookies_same_site_protection } # :nodoc:
|
59
63
|
|
60
|
-
def initialize(app, options={})
|
61
|
-
|
64
|
+
def initialize(app, options = {})
|
65
|
+
options[:cookie_only] = true
|
66
|
+
options[:same_site] = DEFAULT_SAME_SITE if !options.key?(:same_site)
|
67
|
+
super
|
62
68
|
end
|
63
69
|
|
64
|
-
def
|
70
|
+
def delete_session(req, session_id, options)
|
65
71
|
new_sid = generate_sid unless options[:drop]
|
66
72
|
# Reset hash and Assign the new session id
|
67
|
-
|
73
|
+
req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid.public_id } : {})
|
68
74
|
new_sid
|
69
75
|
end
|
70
76
|
|
71
|
-
def load_session(
|
77
|
+
def load_session(req)
|
72
78
|
stale_session_check! do
|
73
|
-
data = unpacked_cookie_data(
|
79
|
+
data = unpacked_cookie_data(req)
|
74
80
|
data = persistent_session_id!(data)
|
75
|
-
[data["session_id"], data]
|
81
|
+
[Rack::Session::SessionId.new(data["session_id"]), data]
|
76
82
|
end
|
77
83
|
end
|
78
84
|
|
79
85
|
private
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
86
|
+
def extract_session_id(req)
|
87
|
+
stale_session_check! do
|
88
|
+
sid = unpacked_cookie_data(req)["session_id"]
|
89
|
+
sid && Rack::Session::SessionId.new(sid)
|
90
|
+
end
|
84
91
|
end
|
85
|
-
end
|
86
92
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
93
|
+
def unpacked_cookie_data(req)
|
94
|
+
req.fetch_header("action_dispatch.request.unsigned_session_cookie") do |k|
|
95
|
+
v = stale_session_check! do
|
96
|
+
if data = get_cookie(req)
|
97
|
+
data.stringify_keys!
|
98
|
+
end
|
99
|
+
data || {}
|
92
100
|
end
|
93
|
-
|
101
|
+
req.set_header k, v
|
94
102
|
end
|
95
103
|
end
|
96
|
-
end
|
97
104
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
105
|
+
def persistent_session_id!(data, sid = nil)
|
106
|
+
data ||= {}
|
107
|
+
data["session_id"] ||= sid || generate_sid.public_id
|
108
|
+
data
|
109
|
+
end
|
103
110
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
111
|
+
def write_session(req, sid, session_data, options)
|
112
|
+
session_data["session_id"] = sid.public_id
|
113
|
+
SessionId.new(sid, session_data)
|
114
|
+
end
|
108
115
|
|
109
|
-
|
110
|
-
|
111
|
-
|
116
|
+
def set_cookie(request, session_id, cookie)
|
117
|
+
cookie_jar(request)[@key] = cookie
|
118
|
+
end
|
112
119
|
|
113
|
-
|
114
|
-
|
115
|
-
|
120
|
+
def get_cookie(req)
|
121
|
+
cookie_jar(req)[@key]
|
122
|
+
end
|
116
123
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
124
|
+
def cookie_jar(request)
|
125
|
+
request.cookie_jar.signed_or_encrypted
|
126
|
+
end
|
121
127
|
end
|
122
128
|
end
|
123
129
|
end
|
@@ -1,13 +1,25 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "action_dispatch/middleware/session/abstract_store"
|
2
6
|
begin
|
3
|
-
require
|
7
|
+
require "rack/session/dalli"
|
4
8
|
rescue LoadError => e
|
5
|
-
|
9
|
+
warn "You don't have dalli installed in your application. Please add it to your Gemfile and run bundle install"
|
6
10
|
raise e
|
7
11
|
end
|
8
12
|
|
9
13
|
module ActionDispatch
|
10
14
|
module Session
|
15
|
+
# # Action Dispatch Session MemCacheStore
|
16
|
+
#
|
17
|
+
# A session store that uses MemCache to implement storage.
|
18
|
+
#
|
19
|
+
# #### Options
|
20
|
+
# * `expire_after` - The length of time a session will be stored before
|
21
|
+
# automatically expiring.
|
22
|
+
#
|
11
23
|
class MemCacheStore < Rack::Session::Dalli
|
12
24
|
include Compatibility
|
13
25
|
include StaleSessionCheck
|
@@ -1,26 +1,28 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "action_dispatch/middleware/exception_wrapper"
|
3
6
|
|
4
7
|
module ActionDispatch
|
5
|
-
#
|
6
|
-
#
|
8
|
+
# # Action Dispatch ShowExceptions
|
9
|
+
#
|
10
|
+
# This middleware rescues any exception returned by the application and calls an
|
11
|
+
# exceptions app that will wrap it in a format for the end user.
|
12
|
+
#
|
13
|
+
# The exceptions app should be passed as a parameter on initialization of
|
14
|
+
# `ShowExceptions`. Every time there is an exception, `ShowExceptions` will
|
15
|
+
# store the exception in `env["action_dispatch.exception"]`, rewrite the
|
16
|
+
# `PATH_INFO` to the exception status code, and call the Rack app.
|
7
17
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# store the exception in env["action_dispatch.exception"], rewrite the
|
11
|
-
# PATH_INFO to the exception status code and call the rack app.
|
18
|
+
# In Rails applications, the exceptions app can be configured with
|
19
|
+
# `config.exceptions_app`, which defaults to ActionDispatch::PublicExceptions.
|
12
20
|
#
|
13
|
-
# If the application returns a
|
14
|
-
# will send an empty response as result with the
|
15
|
-
# If any exception happens inside the exceptions app, this
|
16
|
-
# catches the exceptions and returns a
|
21
|
+
# If the application returns a response with the `X-Cascade` header set to
|
22
|
+
# `"pass"`, this middleware will send an empty response as a result with the
|
23
|
+
# correct status code. If any exception happens inside the exceptions app, this
|
24
|
+
# middleware catches the exceptions and returns a failsafe response.
|
17
25
|
class ShowExceptions
|
18
|
-
FAILSAFE_RESPONSE = [500, { 'Content-Type' => 'text/plain' },
|
19
|
-
["500 Internal Server Error\n" \
|
20
|
-
"If you are the administrator of this website, then please read this web " \
|
21
|
-
"application's log file and/or the web server's log file to find out what " \
|
22
|
-
"went wrong."]]
|
23
|
-
|
24
26
|
def initialize(app, exceptions_app)
|
25
27
|
@app = app
|
26
28
|
@exceptions_app = exceptions_app
|
@@ -29,30 +31,58 @@ module ActionDispatch
|
|
29
31
|
def call(env)
|
30
32
|
@app.call(env)
|
31
33
|
rescue Exception => exception
|
32
|
-
|
33
|
-
|
34
|
+
request = ActionDispatch::Request.new env
|
35
|
+
backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
|
36
|
+
wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
|
37
|
+
request.set_header "action_dispatch.exception", wrapper.unwrapped_exception
|
38
|
+
request.set_header "action_dispatch.report_exception", !wrapper.rescue_response?
|
39
|
+
|
40
|
+
if wrapper.show?(request)
|
41
|
+
render_exception(request.dup, wrapper)
|
34
42
|
else
|
35
|
-
|
43
|
+
raise exception
|
36
44
|
end
|
37
45
|
end
|
38
46
|
|
39
47
|
private
|
48
|
+
def render_exception(request, wrapper)
|
49
|
+
status = wrapper.status_code
|
50
|
+
request.set_header "action_dispatch.original_path", request.path_info
|
51
|
+
request.set_header "action_dispatch.original_request_method", request.raw_request_method
|
52
|
+
fallback_to_html_format_if_invalid_mime_type(request)
|
53
|
+
request.path_info = "/#{status}"
|
54
|
+
request.request_method = "GET"
|
55
|
+
response = @exceptions_app.call(request.env)
|
56
|
+
response[1][Constants::X_CASCADE] == "pass" ? pass_response(status) : response
|
57
|
+
rescue Exception => failsafe_error
|
58
|
+
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
|
40
59
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
response = @exceptions_app.call(env)
|
48
|
-
response[1]['X-Cascade'] == 'pass' ? pass_response(status) : response
|
49
|
-
rescue Exception => failsafe_error
|
50
|
-
$stderr.puts "Error during failsafe response: #{failsafe_error}\n #{failsafe_error.backtrace * "\n "}"
|
51
|
-
FAILSAFE_RESPONSE
|
52
|
-
end
|
60
|
+
[500, { Rack::CONTENT_TYPE => "text/plain; charset=utf-8" },
|
61
|
+
["500 Internal Server Error\n" \
|
62
|
+
"If you are the administrator of this website, then please read this web " \
|
63
|
+
"application's log file and/or the web server's log file to find out what " \
|
64
|
+
"went wrong."]]
|
65
|
+
end
|
53
66
|
|
54
|
-
|
55
|
-
|
56
|
-
|
67
|
+
def fallback_to_html_format_if_invalid_mime_type(request)
|
68
|
+
# If the MIME type for the request is invalid then the @exceptions_app may not
|
69
|
+
# be able to handle it. To make it easier to handle, we switch to HTML.
|
70
|
+
begin
|
71
|
+
request.content_mime_type
|
72
|
+
rescue ActionDispatch::Http::MimeNegotiation::InvalidType
|
73
|
+
request.set_header "CONTENT_TYPE", "text/html"
|
74
|
+
end
|
75
|
+
|
76
|
+
begin
|
77
|
+
request.formats
|
78
|
+
rescue ActionDispatch::Http::MimeNegotiation::InvalidType
|
79
|
+
request.set_header "HTTP_ACCEPT", "text/html"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def pass_response(status)
|
84
|
+
[status, { Rack::CONTENT_TYPE => "text/html; charset=#{Response.default_charset}",
|
85
|
+
Rack::CONTENT_LENGTH => "0" }, []]
|
86
|
+
end
|
57
87
|
end
|
58
88
|
end
|