actionpack 5.2.3
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 +7 -0
- data/CHANGELOG.md +429 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +57 -0
- data/lib/abstract_controller.rb +27 -0
- data/lib/abstract_controller/asset_paths.rb +12 -0
- data/lib/abstract_controller/base.rb +265 -0
- data/lib/abstract_controller/caching.rb +66 -0
- data/lib/abstract_controller/caching/fragments.rb +166 -0
- data/lib/abstract_controller/callbacks.rb +212 -0
- data/lib/abstract_controller/collector.rb +43 -0
- data/lib/abstract_controller/error.rb +6 -0
- data/lib/abstract_controller/helpers.rb +194 -0
- data/lib/abstract_controller/logger.rb +14 -0
- data/lib/abstract_controller/railties/routes_helpers.rb +20 -0
- data/lib/abstract_controller/rendering.rb +127 -0
- data/lib/abstract_controller/translation.rb +31 -0
- data/lib/abstract_controller/url_for.rb +35 -0
- data/lib/action_controller.rb +66 -0
- data/lib/action_controller/api.rb +149 -0
- data/lib/action_controller/api/api_rendering.rb +16 -0
- data/lib/action_controller/base.rb +276 -0
- data/lib/action_controller/caching.rb +46 -0
- data/lib/action_controller/form_builder.rb +50 -0
- data/lib/action_controller/log_subscriber.rb +78 -0
- data/lib/action_controller/metal.rb +256 -0
- data/lib/action_controller/metal/basic_implicit_render.rb +13 -0
- data/lib/action_controller/metal/conditional_get.rb +274 -0
- data/lib/action_controller/metal/content_security_policy.rb +52 -0
- data/lib/action_controller/metal/cookies.rb +16 -0
- data/lib/action_controller/metal/data_streaming.rb +152 -0
- data/lib/action_controller/metal/etag_with_flash.rb +18 -0
- data/lib/action_controller/metal/etag_with_template_digest.rb +57 -0
- data/lib/action_controller/metal/exceptions.rb +53 -0
- data/lib/action_controller/metal/flash.rb +61 -0
- data/lib/action_controller/metal/force_ssl.rb +99 -0
- data/lib/action_controller/metal/head.rb +60 -0
- data/lib/action_controller/metal/helpers.rb +123 -0
- data/lib/action_controller/metal/http_authentication.rb +519 -0
- data/lib/action_controller/metal/implicit_render.rb +73 -0
- data/lib/action_controller/metal/instrumentation.rb +107 -0
- data/lib/action_controller/metal/live.rb +312 -0
- data/lib/action_controller/metal/mime_responds.rb +313 -0
- data/lib/action_controller/metal/parameter_encoding.rb +51 -0
- data/lib/action_controller/metal/params_wrapper.rb +293 -0
- data/lib/action_controller/metal/redirecting.rb +133 -0
- data/lib/action_controller/metal/renderers.rb +181 -0
- data/lib/action_controller/metal/rendering.rb +122 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +445 -0
- data/lib/action_controller/metal/rescue.rb +28 -0
- data/lib/action_controller/metal/streaming.rb +223 -0
- data/lib/action_controller/metal/strong_parameters.rb +1086 -0
- data/lib/action_controller/metal/testing.rb +16 -0
- data/lib/action_controller/metal/url_for.rb +58 -0
- data/lib/action_controller/railtie.rb +89 -0
- data/lib/action_controller/railties/helpers.rb +24 -0
- data/lib/action_controller/renderer.rb +117 -0
- data/lib/action_controller/template_assertions.rb +11 -0
- data/lib/action_controller/test_case.rb +629 -0
- data/lib/action_dispatch.rb +112 -0
- data/lib/action_dispatch/http/cache.rb +222 -0
- data/lib/action_dispatch/http/content_security_policy.rb +272 -0
- data/lib/action_dispatch/http/filter_parameters.rb +84 -0
- data/lib/action_dispatch/http/filter_redirect.rb +37 -0
- data/lib/action_dispatch/http/headers.rb +132 -0
- data/lib/action_dispatch/http/mime_negotiation.rb +175 -0
- data/lib/action_dispatch/http/mime_type.rb +342 -0
- data/lib/action_dispatch/http/mime_types.rb +50 -0
- data/lib/action_dispatch/http/parameter_filter.rb +86 -0
- data/lib/action_dispatch/http/parameters.rb +126 -0
- data/lib/action_dispatch/http/rack_cache.rb +63 -0
- data/lib/action_dispatch/http/request.rb +430 -0
- data/lib/action_dispatch/http/response.rb +519 -0
- data/lib/action_dispatch/http/upload.rb +84 -0
- data/lib/action_dispatch/http/url.rb +350 -0
- data/lib/action_dispatch/journey.rb +7 -0
- data/lib/action_dispatch/journey/formatter.rb +189 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +164 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +41 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +158 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +78 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +49 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +120 -0
- data/lib/action_dispatch/journey/nodes/node.rb +140 -0
- data/lib/action_dispatch/journey/parser.rb +199 -0
- data/lib/action_dispatch/journey/parser.y +50 -0
- data/lib/action_dispatch/journey/parser_extras.rb +31 -0
- data/lib/action_dispatch/journey/path/pattern.rb +198 -0
- data/lib/action_dispatch/journey/route.rb +203 -0
- data/lib/action_dispatch/journey/router.rb +156 -0
- data/lib/action_dispatch/journey/router/utils.rb +102 -0
- data/lib/action_dispatch/journey/routes.rb +82 -0
- data/lib/action_dispatch/journey/scanner.rb +64 -0
- data/lib/action_dispatch/journey/visitors.rb +268 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/middleware/callbacks.rb +36 -0
- data/lib/action_dispatch/middleware/cookies.rb +685 -0
- data/lib/action_dispatch/middleware/debug_exceptions.rb +205 -0
- data/lib/action_dispatch/middleware/debug_locks.rb +124 -0
- data/lib/action_dispatch/middleware/exception_wrapper.rb +147 -0
- data/lib/action_dispatch/middleware/executor.rb +21 -0
- data/lib/action_dispatch/middleware/flash.rb +300 -0
- data/lib/action_dispatch/middleware/public_exceptions.rb +57 -0
- data/lib/action_dispatch/middleware/reloader.rb +12 -0
- data/lib/action_dispatch/middleware/remote_ip.rb +183 -0
- data/lib/action_dispatch/middleware/request_id.rb +43 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +92 -0
- data/lib/action_dispatch/middleware/session/cache_store.rb +54 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +118 -0
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +28 -0
- data/lib/action_dispatch/middleware/show_exceptions.rb +62 -0
- data/lib/action_dispatch/middleware/ssl.rb +150 -0
- data/lib/action_dispatch/middleware/stack.rb +116 -0
- data/lib/action_dispatch/middleware/static.rb +130 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +22 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +27 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.text.erb +8 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +21 -0
- data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +13 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +161 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
- data/lib/action_dispatch/railtie.rb +55 -0
- data/lib/action_dispatch/request/session.rb +234 -0
- data/lib/action_dispatch/request/utils.rb +78 -0
- data/lib/action_dispatch/routing.rb +260 -0
- data/lib/action_dispatch/routing/endpoint.rb +17 -0
- data/lib/action_dispatch/routing/inspector.rb +225 -0
- data/lib/action_dispatch/routing/mapper.rb +2267 -0
- data/lib/action_dispatch/routing/polymorphic_routes.rb +352 -0
- data/lib/action_dispatch/routing/redirection.rb +201 -0
- data/lib/action_dispatch/routing/route_set.rb +890 -0
- data/lib/action_dispatch/routing/routes_proxy.rb +69 -0
- data/lib/action_dispatch/routing/url_for.rb +236 -0
- data/lib/action_dispatch/system_test_case.rb +147 -0
- data/lib/action_dispatch/system_testing/browser.rb +49 -0
- data/lib/action_dispatch/system_testing/driver.rb +59 -0
- data/lib/action_dispatch/system_testing/server.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +96 -0
- data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +31 -0
- data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +26 -0
- data/lib/action_dispatch/testing/assertion_response.rb +47 -0
- data/lib/action_dispatch/testing/assertions.rb +24 -0
- data/lib/action_dispatch/testing/assertions/response.rb +107 -0
- data/lib/action_dispatch/testing/assertions/routing.rb +222 -0
- data/lib/action_dispatch/testing/integration.rb +652 -0
- data/lib/action_dispatch/testing/request_encoder.rb +55 -0
- data/lib/action_dispatch/testing/test_process.rb +50 -0
- data/lib/action_dispatch/testing/test_request.rb +71 -0
- data/lib/action_dispatch/testing/test_response.rb +53 -0
- data/lib/action_pack.rb +26 -0
- data/lib/action_pack/gem_version.rb +17 -0
- data/lib/action_pack/version.rb +10 -0
- metadata +318 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController #:nodoc:
|
4
|
+
module ContentSecurityPolicy
|
5
|
+
# TODO: Documentation
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
include AbstractController::Helpers
|
9
|
+
include AbstractController::Callbacks
|
10
|
+
|
11
|
+
included do
|
12
|
+
helper_method :content_security_policy?
|
13
|
+
helper_method :content_security_policy_nonce
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def content_security_policy(enabled = true, **options, &block)
|
18
|
+
before_action(options) do
|
19
|
+
if block_given?
|
20
|
+
policy = current_content_security_policy
|
21
|
+
yield policy
|
22
|
+
request.content_security_policy = policy
|
23
|
+
end
|
24
|
+
|
25
|
+
unless enabled
|
26
|
+
request.content_security_policy = nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def content_security_policy_report_only(report_only = true, **options)
|
32
|
+
before_action(options) do
|
33
|
+
request.content_security_policy_report_only = report_only
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def content_security_policy?
|
41
|
+
request.content_security_policy
|
42
|
+
end
|
43
|
+
|
44
|
+
def content_security_policy_nonce
|
45
|
+
request.content_security_policy_nonce
|
46
|
+
end
|
47
|
+
|
48
|
+
def current_content_security_policy
|
49
|
+
request.content_security_policy.try(:clone) || ActionDispatch::ContentSecurityPolicy.new
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController #:nodoc:
|
4
|
+
module Cookies
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
helper_method :cookies if defined?(helper_method)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def cookies
|
13
|
+
request.cookie_jar
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_controller/metal/exceptions"
|
4
|
+
|
5
|
+
module ActionController #:nodoc:
|
6
|
+
# Methods for sending arbitrary data and for streaming files to the browser,
|
7
|
+
# instead of rendering.
|
8
|
+
module DataStreaming
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
include ActionController::Rendering
|
12
|
+
|
13
|
+
DEFAULT_SEND_FILE_TYPE = "application/octet-stream".freeze #:nodoc:
|
14
|
+
DEFAULT_SEND_FILE_DISPOSITION = "attachment".freeze #:nodoc:
|
15
|
+
|
16
|
+
private
|
17
|
+
# Sends the file. This uses a server-appropriate method (such as X-Sendfile)
|
18
|
+
# via the Rack::Sendfile middleware. The header to use is set via
|
19
|
+
# +config.action_dispatch.x_sendfile_header+.
|
20
|
+
# Your server can also configure this for you by setting the X-Sendfile-Type header.
|
21
|
+
#
|
22
|
+
# Be careful to sanitize the path parameter if it is coming from a web
|
23
|
+
# page. <tt>send_file(params[:path])</tt> allows a malicious user to
|
24
|
+
# download any file on your server.
|
25
|
+
#
|
26
|
+
# Options:
|
27
|
+
# * <tt>:filename</tt> - suggests a filename for the browser to use.
|
28
|
+
# Defaults to <tt>File.basename(path)</tt>.
|
29
|
+
# * <tt>:type</tt> - specifies an HTTP content type.
|
30
|
+
# You can specify either a string or a symbol for a registered type with <tt>Mime::Type.register</tt>, for example :json.
|
31
|
+
# If omitted, the type will be inferred from the file extension specified in <tt>:filename</tt>.
|
32
|
+
# If no content type is registered for the extension, the default type 'application/octet-stream' will be used.
|
33
|
+
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
|
34
|
+
# Valid values are 'inline' and 'attachment' (default).
|
35
|
+
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to 200.
|
36
|
+
# * <tt>:url_based_filename</tt> - set to +true+ if you want the browser to guess the filename from
|
37
|
+
# the URL, which is necessary for i18n filenames on certain browsers
|
38
|
+
# (setting <tt>:filename</tt> overrides this option).
|
39
|
+
#
|
40
|
+
# The default Content-Type and Content-Disposition headers are
|
41
|
+
# set to download arbitrary binary files in as many browsers as
|
42
|
+
# possible. IE versions 4, 5, 5.5, and 6 are all known to have
|
43
|
+
# a variety of quirks (especially when downloading over SSL).
|
44
|
+
#
|
45
|
+
# Simple download:
|
46
|
+
#
|
47
|
+
# send_file '/path/to.zip'
|
48
|
+
#
|
49
|
+
# Show a JPEG in the browser:
|
50
|
+
#
|
51
|
+
# send_file '/path/to.jpeg', type: 'image/jpeg', disposition: 'inline'
|
52
|
+
#
|
53
|
+
# Show a 404 page in the browser:
|
54
|
+
#
|
55
|
+
# send_file '/path/to/404.html', type: 'text/html; charset=utf-8', status: 404
|
56
|
+
#
|
57
|
+
# Read about the other Content-* HTTP headers if you'd like to
|
58
|
+
# provide the user with more information (such as Content-Description) in
|
59
|
+
# https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11.
|
60
|
+
#
|
61
|
+
# Also be aware that the document may be cached by proxies and browsers.
|
62
|
+
# The Pragma and Cache-Control headers declare how the file may be cached
|
63
|
+
# by intermediaries. They default to require clients to validate with
|
64
|
+
# the server before releasing cached responses. See
|
65
|
+
# https://www.mnot.net/cache_docs/ for an overview of web caching and
|
66
|
+
# https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
|
67
|
+
# for the Cache-Control header spec.
|
68
|
+
def send_file(path, options = {}) #:doc:
|
69
|
+
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) && File.readable?(path)
|
70
|
+
|
71
|
+
options[:filename] ||= File.basename(path) unless options[:url_based_filename]
|
72
|
+
send_file_headers! options
|
73
|
+
|
74
|
+
self.status = options[:status] || 200
|
75
|
+
self.content_type = options[:content_type] if options.key?(:content_type)
|
76
|
+
response.send_file path
|
77
|
+
end
|
78
|
+
|
79
|
+
# Sends the given binary data to the browser. This method is similar to
|
80
|
+
# <tt>render plain: data</tt>, but also allows you to specify whether
|
81
|
+
# the browser should display the response as a file attachment (i.e. in a
|
82
|
+
# download dialog) or as inline data. You may also set the content type,
|
83
|
+
# the file name, and other things.
|
84
|
+
#
|
85
|
+
# Options:
|
86
|
+
# * <tt>:filename</tt> - suggests a filename for the browser to use.
|
87
|
+
# * <tt>:type</tt> - specifies an HTTP content type. Defaults to 'application/octet-stream'.
|
88
|
+
# You can specify either a string or a symbol for a registered type with <tt>Mime::Type.register</tt>, for example :json.
|
89
|
+
# If omitted, type will be inferred from the file extension specified in <tt>:filename</tt>.
|
90
|
+
# If no content type is registered for the extension, the default type 'application/octet-stream' will be used.
|
91
|
+
# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
|
92
|
+
# Valid values are 'inline' and 'attachment' (default).
|
93
|
+
# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to 200.
|
94
|
+
#
|
95
|
+
# Generic data download:
|
96
|
+
#
|
97
|
+
# send_data buffer
|
98
|
+
#
|
99
|
+
# Download a dynamically-generated tarball:
|
100
|
+
#
|
101
|
+
# send_data generate_tgz('dir'), filename: 'dir.tgz'
|
102
|
+
#
|
103
|
+
# Display an image Active Record in the browser:
|
104
|
+
#
|
105
|
+
# send_data image.data, type: image.content_type, disposition: 'inline'
|
106
|
+
#
|
107
|
+
# See +send_file+ for more information on HTTP Content-* headers and caching.
|
108
|
+
def send_data(data, options = {}) #:doc:
|
109
|
+
send_file_headers! options
|
110
|
+
render options.slice(:status, :content_type).merge(body: data)
|
111
|
+
end
|
112
|
+
|
113
|
+
def send_file_headers!(options)
|
114
|
+
type_provided = options.has_key?(:type)
|
115
|
+
|
116
|
+
content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
|
117
|
+
self.content_type = content_type
|
118
|
+
response.sending_file = true
|
119
|
+
|
120
|
+
raise ArgumentError, ":type option required" if content_type.nil?
|
121
|
+
|
122
|
+
if content_type.is_a?(Symbol)
|
123
|
+
extension = Mime[content_type]
|
124
|
+
raise ArgumentError, "Unknown MIME type #{options[:type]}" unless extension
|
125
|
+
self.content_type = extension
|
126
|
+
else
|
127
|
+
if !type_provided && options[:filename]
|
128
|
+
# If type wasn't provided, try guessing from file extension.
|
129
|
+
content_type = Mime::Type.lookup_by_extension(File.extname(options[:filename]).downcase.delete(".")) || content_type
|
130
|
+
end
|
131
|
+
self.content_type = content_type
|
132
|
+
end
|
133
|
+
|
134
|
+
disposition = options.fetch(:disposition, DEFAULT_SEND_FILE_DISPOSITION)
|
135
|
+
unless disposition.nil?
|
136
|
+
disposition = disposition.to_s
|
137
|
+
disposition += %(; filename="#{options[:filename]}") if options[:filename]
|
138
|
+
headers["Content-Disposition"] = disposition
|
139
|
+
end
|
140
|
+
|
141
|
+
headers["Content-Transfer-Encoding"] = "binary"
|
142
|
+
|
143
|
+
# Fix a problem with IE 6.0 on opening downloaded files:
|
144
|
+
# If Cache-Control: no-cache is set (which Rails does by default),
|
145
|
+
# IE removes the file it just downloaded from its cache immediately
|
146
|
+
# after it displays the "open/save" dialog, which means that if you
|
147
|
+
# hit "open" the file isn't there anymore when the application that
|
148
|
+
# is called for handling the download is run, so let's workaround that
|
149
|
+
response.cache_control[:public] ||= false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
# When you're using the flash, it's generally used as a conditional on the view.
|
5
|
+
# This means the content of the view depends on the flash. Which in turn means
|
6
|
+
# that the ETag for a response should be computed with the content of the flash
|
7
|
+
# in mind. This does that by including the content of the flash as a component
|
8
|
+
# in the ETag that's generated for a response.
|
9
|
+
module EtagWithFlash
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
include ActionController::ConditionalGet
|
13
|
+
|
14
|
+
included do
|
15
|
+
etag { flash unless flash.empty? }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
# When our views change, they should bubble up into HTTP cache freshness
|
5
|
+
# and bust browser caches. So the template digest for the current action
|
6
|
+
# is automatically included in the ETag.
|
7
|
+
#
|
8
|
+
# Enabled by default for apps that use Action View. Disable by setting
|
9
|
+
#
|
10
|
+
# config.action_controller.etag_with_template_digest = false
|
11
|
+
#
|
12
|
+
# Override the template to digest by passing +:template+ to +fresh_when+
|
13
|
+
# and +stale?+ calls. For example:
|
14
|
+
#
|
15
|
+
# # We're going to render widgets/show, not posts/show
|
16
|
+
# fresh_when @post, template: 'widgets/show'
|
17
|
+
#
|
18
|
+
# # We're not going to render a template, so omit it from the ETag.
|
19
|
+
# fresh_when @post, template: false
|
20
|
+
#
|
21
|
+
module EtagWithTemplateDigest
|
22
|
+
extend ActiveSupport::Concern
|
23
|
+
|
24
|
+
include ActionController::ConditionalGet
|
25
|
+
|
26
|
+
included do
|
27
|
+
class_attribute :etag_with_template_digest, default: true
|
28
|
+
|
29
|
+
ActiveSupport.on_load :action_view, yield: true do
|
30
|
+
etag do |options|
|
31
|
+
determine_template_etag(options) if etag_with_template_digest
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def determine_template_etag(options)
|
38
|
+
if template = pick_template_for_etag(options)
|
39
|
+
lookup_and_digest_template(template)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Pick the template digest to include in the ETag. If the +:template+ option
|
44
|
+
# is present, use the named template. If +:template+ is +nil+ or absent, use
|
45
|
+
# the default controller/action template. If +:template+ is false, omit the
|
46
|
+
# template digest from the ETag.
|
47
|
+
def pick_template_for_etag(options)
|
48
|
+
unless options[:template] == false
|
49
|
+
options[:template] || "#{controller_path}/#{action_name}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def lookup_and_digest_template(template)
|
54
|
+
ActionView::Digestor.digest name: template, finder: lookup_context
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController
|
4
|
+
class ActionControllerError < StandardError #:nodoc:
|
5
|
+
end
|
6
|
+
|
7
|
+
class BadRequest < ActionControllerError #:nodoc:
|
8
|
+
def initialize(msg = nil)
|
9
|
+
super(msg)
|
10
|
+
set_backtrace $!.backtrace if $!
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class RenderError < ActionControllerError #:nodoc:
|
15
|
+
end
|
16
|
+
|
17
|
+
class RoutingError < ActionControllerError #:nodoc:
|
18
|
+
attr_reader :failures
|
19
|
+
def initialize(message, failures = [])
|
20
|
+
super(message)
|
21
|
+
@failures = failures
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ActionController::UrlGenerationError < ActionControllerError #:nodoc:
|
26
|
+
end
|
27
|
+
|
28
|
+
class MethodNotAllowed < ActionControllerError #:nodoc:
|
29
|
+
def initialize(*allowed_methods)
|
30
|
+
super("Only #{allowed_methods.to_sentence(locale: :en)} requests are allowed.")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class NotImplemented < MethodNotAllowed #:nodoc:
|
35
|
+
end
|
36
|
+
|
37
|
+
class MissingFile < ActionControllerError #:nodoc:
|
38
|
+
end
|
39
|
+
|
40
|
+
class SessionOverflowError < ActionControllerError #:nodoc:
|
41
|
+
DEFAULT_MESSAGE = "Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data."
|
42
|
+
|
43
|
+
def initialize(message = nil)
|
44
|
+
super(message || DEFAULT_MESSAGE)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class UnknownHttpMethod < ActionControllerError #:nodoc:
|
49
|
+
end
|
50
|
+
|
51
|
+
class UnknownFormat < ActionControllerError #:nodoc:
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionController #:nodoc:
|
4
|
+
module Flash
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :_flash_types, instance_accessor: false, default: []
|
9
|
+
|
10
|
+
delegate :flash, to: :request
|
11
|
+
add_flash_types(:alert, :notice)
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
# Creates new flash types. You can pass as many types as you want to create
|
16
|
+
# flash types other than the default <tt>alert</tt> and <tt>notice</tt> in
|
17
|
+
# your controllers and views. For instance:
|
18
|
+
#
|
19
|
+
# # in application_controller.rb
|
20
|
+
# class ApplicationController < ActionController::Base
|
21
|
+
# add_flash_types :warning
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # in your controller
|
25
|
+
# redirect_to user_path(@user), warning: "Incomplete profile"
|
26
|
+
#
|
27
|
+
# # in your view
|
28
|
+
# <%= warning %>
|
29
|
+
#
|
30
|
+
# This method will automatically define a new method for each of the given
|
31
|
+
# names, and it will be available in your views.
|
32
|
+
def add_flash_types(*types)
|
33
|
+
types.each do |type|
|
34
|
+
next if _flash_types.include?(type)
|
35
|
+
|
36
|
+
define_method(type) do
|
37
|
+
request.flash[type]
|
38
|
+
end
|
39
|
+
helper_method type
|
40
|
+
|
41
|
+
self._flash_types += [type]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def redirect_to(options = {}, response_status_and_flash = {}) #:doc:
|
48
|
+
self.class._flash_types.each do |flash_type|
|
49
|
+
if type = response_status_and_flash.delete(flash_type)
|
50
|
+
flash[flash_type] = type
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if other_flashes = response_status_and_flash.delete(:flash)
|
55
|
+
flash.update(other_flashes)
|
56
|
+
end
|
57
|
+
|
58
|
+
super(options, response_status_and_flash)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/except"
|
4
|
+
require "active_support/core_ext/hash/slice"
|
5
|
+
|
6
|
+
module ActionController
|
7
|
+
# This module provides a method which will redirect the browser to use the secured HTTPS
|
8
|
+
# protocol. This will ensure that users' sensitive information will be
|
9
|
+
# transferred safely over the internet. You _should_ always force the browser
|
10
|
+
# to use HTTPS when you're transferring sensitive information such as
|
11
|
+
# user authentication, account information, or credit card information.
|
12
|
+
#
|
13
|
+
# Note that if you are really concerned about your application security,
|
14
|
+
# you might consider using +config.force_ssl+ in your config file instead.
|
15
|
+
# That will ensure all the data is transferred via HTTPS, and will
|
16
|
+
# prevent the user from getting their session hijacked when accessing the
|
17
|
+
# site over unsecured HTTP protocol.
|
18
|
+
module ForceSSL
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
include AbstractController::Callbacks
|
21
|
+
|
22
|
+
ACTION_OPTIONS = [:only, :except, :if, :unless]
|
23
|
+
URL_OPTIONS = [:protocol, :host, :domain, :subdomain, :port, :path]
|
24
|
+
REDIRECT_OPTIONS = [:status, :flash, :alert, :notice]
|
25
|
+
|
26
|
+
module ClassMethods
|
27
|
+
# Force the request to this particular controller or specified actions to be
|
28
|
+
# through the HTTPS protocol.
|
29
|
+
#
|
30
|
+
# If you need to disable this for any reason (e.g. development) then you can use
|
31
|
+
# an +:if+ or +:unless+ condition.
|
32
|
+
#
|
33
|
+
# class AccountsController < ApplicationController
|
34
|
+
# force_ssl if: :ssl_configured?
|
35
|
+
#
|
36
|
+
# def ssl_configured?
|
37
|
+
# !Rails.env.development?
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# ==== URL Options
|
42
|
+
# You can pass any of the following options to affect the redirect URL
|
43
|
+
# * <tt>host</tt> - Redirect to a different host name
|
44
|
+
# * <tt>subdomain</tt> - Redirect to a different subdomain
|
45
|
+
# * <tt>domain</tt> - Redirect to a different domain
|
46
|
+
# * <tt>port</tt> - Redirect to a non-standard port
|
47
|
+
# * <tt>path</tt> - Redirect to a different path
|
48
|
+
#
|
49
|
+
# ==== Redirect Options
|
50
|
+
# You can pass any of the following options to affect the redirect status and response
|
51
|
+
# * <tt>status</tt> - Redirect with a custom status (default is 301 Moved Permanently)
|
52
|
+
# * <tt>flash</tt> - Set a flash message when redirecting
|
53
|
+
# * <tt>alert</tt> - Set an alert message when redirecting
|
54
|
+
# * <tt>notice</tt> - Set a notice message when redirecting
|
55
|
+
#
|
56
|
+
# ==== Action Options
|
57
|
+
# You can pass any of the following options to affect the before_action callback
|
58
|
+
# * <tt>only</tt> - The callback should be run only for this action
|
59
|
+
# * <tt>except</tt> - The callback should be run for all actions except this action
|
60
|
+
# * <tt>if</tt> - A symbol naming an instance method or a proc; the
|
61
|
+
# callback will be called only when it returns a true value.
|
62
|
+
# * <tt>unless</tt> - A symbol naming an instance method or a proc; the
|
63
|
+
# callback will be called only when it returns a false value.
|
64
|
+
def force_ssl(options = {})
|
65
|
+
action_options = options.slice(*ACTION_OPTIONS)
|
66
|
+
redirect_options = options.except(*ACTION_OPTIONS)
|
67
|
+
before_action(action_options) do
|
68
|
+
force_ssl_redirect(redirect_options)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Redirect the existing request to use the HTTPS protocol.
|
74
|
+
#
|
75
|
+
# ==== Parameters
|
76
|
+
# * <tt>host_or_options</tt> - Either a host name or any of the URL and
|
77
|
+
# redirect options available to the <tt>force_ssl</tt> method.
|
78
|
+
def force_ssl_redirect(host_or_options = nil)
|
79
|
+
unless request.ssl?
|
80
|
+
options = {
|
81
|
+
protocol: "https://",
|
82
|
+
host: request.host,
|
83
|
+
path: request.fullpath,
|
84
|
+
status: :moved_permanently
|
85
|
+
}
|
86
|
+
|
87
|
+
if host_or_options.is_a?(Hash)
|
88
|
+
options.merge!(host_or_options)
|
89
|
+
elsif host_or_options
|
90
|
+
options[:host] = host_or_options
|
91
|
+
end
|
92
|
+
|
93
|
+
secure_url = ActionDispatch::Http::URL.url_for(options.slice(*URL_OPTIONS))
|
94
|
+
flash.keep if respond_to?(:flash) && request.respond_to?(:flash)
|
95
|
+
redirect_to secure_url, options.slice(*REDIRECT_OPTIONS)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|