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,67 +1,119 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
4
|
|
5
5
|
module ActionDispatch
|
6
6
|
module Http
|
7
7
|
module Parameters
|
8
|
-
|
8
|
+
extend ActiveSupport::Concern
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
PARAMETERS_KEY = "action_dispatch.request.path_parameters"
|
11
|
+
|
12
|
+
DEFAULT_PARSERS = {
|
13
|
+
Mime[:json].symbol => -> (raw_post) {
|
14
|
+
data = ActiveSupport::JSON.decode(raw_post)
|
15
|
+
data.is_a?(Hash) ? data : { _json: data }
|
16
|
+
}
|
17
|
+
}
|
18
|
+
|
19
|
+
# Raised when raw data from the request cannot be parsed by the parser defined
|
20
|
+
# for request's content MIME type.
|
21
|
+
class ParseError < StandardError
|
22
|
+
def initialize(message = $!.message)
|
23
|
+
super(message)
|
19
24
|
end
|
20
25
|
end
|
21
|
-
alias :params :parameters
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
27
|
+
included do
|
28
|
+
class << self
|
29
|
+
# Returns the parameter parsers.
|
30
|
+
attr_reader :parameter_parsers
|
31
|
+
end
|
32
|
+
|
33
|
+
self.parameter_parsers = DEFAULT_PARSERS
|
26
34
|
end
|
27
35
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
36
|
+
module ClassMethods
|
37
|
+
# Configure the parameter parser for a given MIME type.
|
38
|
+
#
|
39
|
+
# It accepts a hash where the key is the symbol of the MIME type and the value
|
40
|
+
# is a proc.
|
41
|
+
#
|
42
|
+
# original_parsers = ActionDispatch::Request.parameter_parsers
|
43
|
+
# xml_parser = -> (raw_post) { Hash.from_xml(raw_post) || {} }
|
44
|
+
# new_parsers = original_parsers.merge(xml: xml_parser)
|
45
|
+
# ActionDispatch::Request.parameter_parsers = new_parsers
|
46
|
+
def parameter_parsers=(parsers)
|
47
|
+
@parameter_parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
|
48
|
+
end
|
33
49
|
end
|
34
50
|
|
35
|
-
# Returns
|
36
|
-
|
51
|
+
# Returns both GET and POST parameters in a single hash.
|
52
|
+
def parameters
|
53
|
+
params = get_header("action_dispatch.request.parameters")
|
54
|
+
return params if params
|
55
|
+
|
56
|
+
params = begin
|
57
|
+
request_parameters.merge(query_parameters)
|
58
|
+
rescue EOFError
|
59
|
+
query_parameters.dup
|
60
|
+
end
|
61
|
+
params.merge!(path_parameters)
|
62
|
+
set_header("action_dispatch.request.parameters", params)
|
63
|
+
params
|
64
|
+
end
|
65
|
+
alias :params :parameters
|
66
|
+
|
67
|
+
def path_parameters=(parameters) # :nodoc:
|
68
|
+
delete_header("action_dispatch.request.parameters")
|
69
|
+
|
70
|
+
parameters = Request::Utils.set_binary_encoding(self, parameters, parameters[:controller], parameters[:action])
|
71
|
+
# If any of the path parameters has an invalid encoding then raise since it's
|
72
|
+
# likely to trigger errors further on.
|
73
|
+
Request::Utils.check_param_encoding(parameters)
|
74
|
+
|
75
|
+
set_header PARAMETERS_KEY, parameters
|
76
|
+
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
|
77
|
+
raise ActionController::BadRequest.new("Invalid path parameters: #{e.message}")
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns a hash with the parameters used to form the path of the request.
|
81
|
+
# Returned hash keys are symbols:
|
37
82
|
#
|
38
|
-
#
|
83
|
+
# { action: "my_action", controller: "my_controller" }
|
39
84
|
def path_parameters
|
40
|
-
|
85
|
+
get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
|
41
86
|
end
|
42
87
|
|
43
|
-
|
88
|
+
private
|
89
|
+
def parse_formatted_parameters(parsers)
|
90
|
+
return yield if content_length.zero? || content_mime_type.nil?
|
44
91
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
else
|
53
|
-
params.each_with_object({}) do |(key, val), new_hash|
|
54
|
-
new_hash[key] = if val.is_a?(Array)
|
55
|
-
val.map! { |el| normalize_encode_params(el) }
|
56
|
-
else
|
57
|
-
normalize_encode_params(val)
|
58
|
-
end
|
59
|
-
end.with_indifferent_access
|
92
|
+
strategy = parsers.fetch(content_mime_type.symbol) { return yield }
|
93
|
+
|
94
|
+
begin
|
95
|
+
strategy.call(raw_post)
|
96
|
+
rescue # JSON or Ruby code block errors.
|
97
|
+
log_parse_error_once
|
98
|
+
raise ParseError, "Error occurred while parsing request parameters"
|
60
99
|
end
|
61
|
-
else
|
62
|
-
params
|
63
100
|
end
|
64
|
-
|
101
|
+
|
102
|
+
def log_parse_error_once
|
103
|
+
@parse_error_logged ||= begin
|
104
|
+
parse_logger = logger || ActiveSupport::Logger.new($stderr)
|
105
|
+
parse_logger.debug <<~MSG.chomp
|
106
|
+
Error occurred while parsing request parameters.
|
107
|
+
Contents:
|
108
|
+
|
109
|
+
#{raw_post}
|
110
|
+
MSG
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def params_parsers
|
115
|
+
ActionDispatch::Request.parameter_parsers
|
116
|
+
end
|
65
117
|
end
|
66
118
|
end
|
67
119
|
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# :markup: markdown
|
4
|
+
|
5
|
+
require "active_support/core_ext/object/deep_dup"
|
6
|
+
|
7
|
+
module ActionDispatch # :nodoc:
|
8
|
+
# # Action Dispatch PermissionsPolicy
|
9
|
+
#
|
10
|
+
# Configures the HTTP
|
11
|
+
# [Feature-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy)
|
12
|
+
# response header to specify which browser features the current
|
13
|
+
# document and its iframes can use.
|
14
|
+
#
|
15
|
+
# Example global policy:
|
16
|
+
#
|
17
|
+
# Rails.application.config.permissions_policy do |policy|
|
18
|
+
# policy.camera :none
|
19
|
+
# policy.gyroscope :none
|
20
|
+
# policy.microphone :none
|
21
|
+
# policy.usb :none
|
22
|
+
# policy.fullscreen :self
|
23
|
+
# policy.payment :self, "https://secure.example.com"
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# The Feature-Policy header has been renamed to Permissions-Policy. The
|
27
|
+
# Permissions-Policy requires a different implementation and isn't yet supported
|
28
|
+
# by all browsers. To avoid having to rename this middleware in the future we
|
29
|
+
# use the new name for the middleware but keep the old header name and
|
30
|
+
# implementation for now.
|
31
|
+
class PermissionsPolicy
|
32
|
+
class Middleware
|
33
|
+
def initialize(app)
|
34
|
+
@app = app
|
35
|
+
end
|
36
|
+
|
37
|
+
def call(env)
|
38
|
+
_, headers, _ = response = @app.call(env)
|
39
|
+
|
40
|
+
return response if policy_present?(headers)
|
41
|
+
|
42
|
+
request = ActionDispatch::Request.new(env)
|
43
|
+
|
44
|
+
if policy = request.permissions_policy
|
45
|
+
headers[ActionDispatch::Constants::FEATURE_POLICY] = policy.build(request.controller_instance)
|
46
|
+
end
|
47
|
+
|
48
|
+
if policy_empty?(policy)
|
49
|
+
headers.delete(ActionDispatch::Constants::FEATURE_POLICY)
|
50
|
+
end
|
51
|
+
|
52
|
+
response
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def policy_present?(headers)
|
57
|
+
headers[ActionDispatch::Constants::FEATURE_POLICY]
|
58
|
+
end
|
59
|
+
|
60
|
+
def policy_empty?(policy)
|
61
|
+
policy&.directives&.empty?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module Request
|
66
|
+
POLICY = "action_dispatch.permissions_policy"
|
67
|
+
|
68
|
+
def permissions_policy
|
69
|
+
get_header(POLICY)
|
70
|
+
end
|
71
|
+
|
72
|
+
def permissions_policy=(policy)
|
73
|
+
set_header(POLICY, policy)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
MAPPINGS = {
|
78
|
+
self: "'self'",
|
79
|
+
none: "'none'",
|
80
|
+
}.freeze
|
81
|
+
|
82
|
+
# List of available permissions can be found at
|
83
|
+
# https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md#policy-controlled-features
|
84
|
+
DIRECTIVES = {
|
85
|
+
accelerometer: "accelerometer",
|
86
|
+
ambient_light_sensor: "ambient-light-sensor",
|
87
|
+
autoplay: "autoplay",
|
88
|
+
camera: "camera",
|
89
|
+
encrypted_media: "encrypted-media",
|
90
|
+
fullscreen: "fullscreen",
|
91
|
+
geolocation: "geolocation",
|
92
|
+
gyroscope: "gyroscope",
|
93
|
+
hid: "hid",
|
94
|
+
idle_detection: "idle-detection",
|
95
|
+
magnetometer: "magnetometer",
|
96
|
+
microphone: "microphone",
|
97
|
+
midi: "midi",
|
98
|
+
payment: "payment",
|
99
|
+
picture_in_picture: "picture-in-picture",
|
100
|
+
screen_wake_lock: "screen-wake-lock",
|
101
|
+
serial: "serial",
|
102
|
+
sync_xhr: "sync-xhr",
|
103
|
+
usb: "usb",
|
104
|
+
web_share: "web-share",
|
105
|
+
}.freeze
|
106
|
+
|
107
|
+
private_constant :MAPPINGS, :DIRECTIVES
|
108
|
+
|
109
|
+
attr_reader :directives
|
110
|
+
|
111
|
+
def initialize
|
112
|
+
@directives = {}
|
113
|
+
yield self if block_given?
|
114
|
+
end
|
115
|
+
|
116
|
+
def initialize_copy(other)
|
117
|
+
@directives = other.directives.deep_dup
|
118
|
+
end
|
119
|
+
|
120
|
+
DIRECTIVES.each do |name, directive|
|
121
|
+
define_method(name) do |*sources|
|
122
|
+
if sources.first
|
123
|
+
@directives[directive] = apply_mappings(sources)
|
124
|
+
else
|
125
|
+
@directives.delete(directive)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def build(context = nil)
|
131
|
+
build_directives(context).compact.join("; ")
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
def apply_mappings(sources)
|
136
|
+
sources.map do |source|
|
137
|
+
case source
|
138
|
+
when Symbol
|
139
|
+
apply_mapping(source)
|
140
|
+
when String, Proc
|
141
|
+
source
|
142
|
+
else
|
143
|
+
raise ArgumentError, "Invalid HTTP permissions policy source: #{source.inspect}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def apply_mapping(source)
|
149
|
+
MAPPINGS.fetch(source) do
|
150
|
+
raise ArgumentError, "Unknown HTTP permissions policy source mapping: #{source.inspect}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def build_directives(context)
|
155
|
+
@directives.map do |directive, sources|
|
156
|
+
if sources.is_a?(Array)
|
157
|
+
"#{directive} #{build_directive(sources, context).join(' ')}"
|
158
|
+
elsif sources
|
159
|
+
directive
|
160
|
+
else
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def build_directive(sources, context)
|
167
|
+
sources.map { |source| resolve_source(source, context) }
|
168
|
+
end
|
169
|
+
|
170
|
+
def resolve_source(source, context)
|
171
|
+
case source
|
172
|
+
when String
|
173
|
+
source
|
174
|
+
when Symbol
|
175
|
+
source.to_s
|
176
|
+
when Proc
|
177
|
+
if context.nil?
|
178
|
+
raise RuntimeError, "Missing context for the dynamic permissions policy source: #{source.inspect}"
|
179
|
+
else
|
180
|
+
context.instance_exec(&source)
|
181
|
+
end
|
182
|
+
else
|
183
|
+
raise RuntimeError, "Unexpected permissions policy source: #{source.inspect}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|