mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #40620 from Bahanix/permissions-policy
Rename HTTP Feature Policy to Permissions Policy
This commit is contained in:
commit
26fd55e02a
15 changed files with 82 additions and 82 deletions
actionpack
railties
|
@ -29,7 +29,7 @@ module ActionController
|
|||
autoload :DefaultHeaders
|
||||
autoload :EtagWithTemplateDigest
|
||||
autoload :EtagWithFlash
|
||||
autoload :FeaturePolicy
|
||||
autoload :PermissionsPolicy
|
||||
autoload :Flash
|
||||
autoload :Head
|
||||
autoload :Helpers
|
||||
|
|
|
@ -226,7 +226,7 @@ module ActionController
|
|||
FormBuilder,
|
||||
RequestForgeryProtection,
|
||||
ContentSecurityPolicy,
|
||||
FeaturePolicy,
|
||||
PermissionsPolicy,
|
||||
Streaming,
|
||||
DataStreaming,
|
||||
HttpAuthentication::Basic::ControllerMethods,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ActionController #:nodoc:
|
||||
# HTTP Feature Policy is a web standard for defining a mechanism to
|
||||
# allow and deny the use of browser features in its own context, and
|
||||
# HTTP Permissions Policy is a web standard for defining a mechanism to
|
||||
# allow and deny the use of browser permissions in its own context, and
|
||||
# in content within any <iframe> elements in the document.
|
||||
#
|
||||
# Full details of HTTP Feature Policy specification and guidelines can
|
||||
# Full details of HTTP Permissions Policy specification and guidelines can
|
||||
# be found at MDN:
|
||||
#
|
||||
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
|
||||
|
@ -13,7 +13,7 @@ module ActionController #:nodoc:
|
|||
# Examples of usage:
|
||||
#
|
||||
# # Global policy
|
||||
# Rails.application.config.feature_policy do |f|
|
||||
# Rails.application.config.permissions_policy do |f|
|
||||
# f.camera :none
|
||||
# f.gyroscope :none
|
||||
# f.microphone :none
|
||||
|
@ -24,20 +24,20 @@ module ActionController #:nodoc:
|
|||
#
|
||||
# # Controller level policy
|
||||
# class PagesController < ApplicationController
|
||||
# feature_policy do |p|
|
||||
# permissions_policy do |p|
|
||||
# p.geolocation "https://example.com"
|
||||
# end
|
||||
# end
|
||||
module FeaturePolicy
|
||||
module PermissionsPolicy
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
def feature_policy(**options, &block)
|
||||
def permissions_policy(**options, &block)
|
||||
before_action(options) do
|
||||
if block_given?
|
||||
policy = request.feature_policy.clone
|
||||
policy = request.permissions_policy.clone
|
||||
yield policy
|
||||
request.feature_policy = policy
|
||||
request.permissions_policy = policy
|
||||
end
|
||||
end
|
||||
end
|
|
@ -46,7 +46,7 @@ module ActionDispatch
|
|||
eager_autoload do
|
||||
autoload_under "http" do
|
||||
autoload :ContentSecurityPolicy
|
||||
autoload :FeaturePolicy
|
||||
autoload :PermissionsPolicy
|
||||
autoload :Request
|
||||
autoload :Response
|
||||
end
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
require "active_support/core_ext/object/deep_dup"
|
||||
|
||||
module ActionDispatch #:nodoc:
|
||||
class FeaturePolicy
|
||||
class PermissionsPolicy
|
||||
class Middleware
|
||||
CONTENT_TYPE = "Content-Type"
|
||||
POLICY = "Feature-Policy"
|
||||
POLICY = "Permissions-Policy"
|
||||
|
||||
def initialize(app)
|
||||
@app = app
|
||||
|
@ -19,7 +19,7 @@ module ActionDispatch #:nodoc:
|
|||
return response unless html_response?(headers)
|
||||
return response if policy_present?(headers)
|
||||
|
||||
if policy = request.feature_policy
|
||||
if policy = request.permissions_policy
|
||||
headers[POLICY] = policy.build(request.controller_instance)
|
||||
end
|
||||
|
||||
|
@ -47,13 +47,13 @@ module ActionDispatch #:nodoc:
|
|||
end
|
||||
|
||||
module Request
|
||||
POLICY = "action_dispatch.feature_policy"
|
||||
POLICY = "action_dispatch.permissions_policy"
|
||||
|
||||
def feature_policy
|
||||
def permissions_policy
|
||||
get_header(POLICY)
|
||||
end
|
||||
|
||||
def feature_policy=(policy)
|
||||
def permissions_policy=(policy)
|
||||
set_header(POLICY, policy)
|
||||
end
|
||||
end
|
||||
|
@ -63,8 +63,8 @@ module ActionDispatch #:nodoc:
|
|||
none: "'none'",
|
||||
}.freeze
|
||||
|
||||
# List of available features can be found at
|
||||
# https://github.com/WICG/feature-policy/blob/master/features.md#policy-controlled-features
|
||||
# List of available permissions can be found at
|
||||
# https://github.com/w3c/webappsec-permissions-policy/blob/master/features.md#policy-controlled-features
|
||||
DIRECTIVES = {
|
||||
accelerometer: "accelerometer",
|
||||
ambient_light_sensor: "ambient-light-sensor",
|
||||
|
@ -121,14 +121,14 @@ module ActionDispatch #:nodoc:
|
|||
when String, Proc
|
||||
source
|
||||
else
|
||||
raise ArgumentError, "Invalid HTTP feature policy source: #{source.inspect}"
|
||||
raise ArgumentError, "Invalid HTTP permissions policy source: #{source.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def apply_mapping(source)
|
||||
MAPPINGS.fetch(source) do
|
||||
raise ArgumentError, "Unknown HTTP feature policy source mapping: #{source.inspect}"
|
||||
raise ArgumentError, "Unknown HTTP permissions policy source mapping: #{source.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -156,12 +156,12 @@ module ActionDispatch #:nodoc:
|
|||
source.to_s
|
||||
when Proc
|
||||
if context.nil?
|
||||
raise RuntimeError, "Missing context for the dynamic feature policy source: #{source.inspect}"
|
||||
raise RuntimeError, "Missing context for the dynamic permissions policy source: #{source.inspect}"
|
||||
else
|
||||
context.instance_exec(&source)
|
||||
end
|
||||
else
|
||||
raise RuntimeError, "Unexpected feature policy source: #{source.inspect}"
|
||||
raise RuntimeError, "Unexpected permissions policy source: #{source.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -23,7 +23,7 @@ module ActionDispatch
|
|||
include ActionDispatch::Http::FilterParameters
|
||||
include ActionDispatch::Http::URL
|
||||
include ActionDispatch::ContentSecurityPolicy::Request
|
||||
include ActionDispatch::FeaturePolicy::Request
|
||||
include ActionDispatch::PermissionsPolicy::Request
|
||||
include Rack::Request::Env
|
||||
|
||||
autoload :Session, "action_dispatch/request/session"
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
require "abstract_unit"
|
||||
|
||||
class FeaturePolicyTest < ActiveSupport::TestCase
|
||||
class PermissionsPolicyTest < ActiveSupport::TestCase
|
||||
def setup
|
||||
@policy = ActionDispatch::FeaturePolicy.new
|
||||
@policy = ActionDispatch::PermissionsPolicy.new
|
||||
end
|
||||
|
||||
def test_mappings
|
||||
|
@ -37,22 +37,22 @@ class FeaturePolicyTest < ActiveSupport::TestCase
|
|||
@policy.vr [:non_existent]
|
||||
end
|
||||
|
||||
assert_equal "Invalid HTTP feature policy source: [:non_existent]", exception.message
|
||||
assert_equal "Invalid HTTP permissions policy source: [:non_existent]", exception.message
|
||||
end
|
||||
end
|
||||
|
||||
class FeaturePolicyIntegrationTest < ActionDispatch::IntegrationTest
|
||||
class PermissionsPolicyIntegrationTest < ActionDispatch::IntegrationTest
|
||||
class PolicyController < ActionController::Base
|
||||
feature_policy only: :index do |f|
|
||||
permissions_policy only: :index do |f|
|
||||
f.gyroscope :none
|
||||
end
|
||||
|
||||
feature_policy only: :sample_controller do |f|
|
||||
permissions_policy only: :sample_controller do |f|
|
||||
f.gyroscope nil
|
||||
f.usb :self
|
||||
end
|
||||
|
||||
feature_policy only: :multiple_directives do |f|
|
||||
permissions_policy only: :multiple_directives do |f|
|
||||
f.gyroscope nil
|
||||
f.usb :self
|
||||
f.autoplay "https://example.com"
|
||||
|
@ -74,14 +74,14 @@ class FeaturePolicyIntegrationTest < ActionDispatch::IntegrationTest
|
|||
|
||||
ROUTES = ActionDispatch::Routing::RouteSet.new
|
||||
ROUTES.draw do
|
||||
scope module: "feature_policy_integration_test" do
|
||||
scope module: "permissions_policy_integration_test" do
|
||||
get "/", to: "policy#index"
|
||||
get "/sample_controller", to: "policy#sample_controller"
|
||||
get "/multiple_directives", to: "policy#multiple_directives"
|
||||
end
|
||||
end
|
||||
|
||||
POLICY = ActionDispatch::FeaturePolicy.new do |p|
|
||||
POLICY = ActionDispatch::PermissionsPolicy.new do |p|
|
||||
p.gyroscope :self
|
||||
end
|
||||
|
||||
|
@ -91,7 +91,7 @@ class FeaturePolicyIntegrationTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
def call(env)
|
||||
env["action_dispatch.feature_policy"] = POLICY
|
||||
env["action_dispatch.permissions_policy"] = POLICY
|
||||
env["action_dispatch.show_exceptions"] = false
|
||||
|
||||
@app.call(env)
|
||||
|
@ -100,24 +100,24 @@ class FeaturePolicyIntegrationTest < ActionDispatch::IntegrationTest
|
|||
|
||||
APP = build_app(ROUTES) do |middleware|
|
||||
middleware.use PolicyConfigMiddleware
|
||||
middleware.use ActionDispatch::FeaturePolicy::Middleware
|
||||
middleware.use ActionDispatch::PermissionsPolicy::Middleware
|
||||
end
|
||||
|
||||
def app
|
||||
APP
|
||||
end
|
||||
|
||||
def test_generates_feature_policy_header
|
||||
def test_generates_permissions_policy_header
|
||||
get "/"
|
||||
assert_policy "gyroscope 'none'"
|
||||
end
|
||||
|
||||
def test_generates_per_controller_feature_policy_header
|
||||
def test_generates_per_controller_permissions_policy_header
|
||||
get "/sample_controller"
|
||||
assert_policy "usb 'self'"
|
||||
end
|
||||
|
||||
def test_generates_multiple_directives_feature_policy_header
|
||||
def test_generates_multiple_directives_permissions_policy_header
|
||||
get "/multiple_directives"
|
||||
assert_policy "usb 'self'; autoplay https://example.com; payment https://secure.example.com"
|
||||
end
|
||||
|
@ -127,16 +127,16 @@ class FeaturePolicyIntegrationTest < ActionDispatch::IntegrationTest
|
|||
Rails.application.env_config
|
||||
end
|
||||
|
||||
def feature_policy
|
||||
env_config["action_dispatch.feature_policy"]
|
||||
def permissions_policy
|
||||
env_config["action_dispatch.permissions_policy"]
|
||||
end
|
||||
|
||||
def feature_policy=(policy)
|
||||
env_config["action_dispatch.feature_policy"] = policy
|
||||
def permissions_policy=(policy)
|
||||
env_config["action_dispatch.permissions_policy"] = policy
|
||||
end
|
||||
|
||||
def assert_policy(expected)
|
||||
assert_response :success
|
||||
assert_equal expected, response.headers["Feature-Policy"]
|
||||
assert_equal expected, response.headers["Permissions-Policy"]
|
||||
end
|
||||
end
|
|
@ -286,7 +286,7 @@ module Rails
|
|||
"action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only,
|
||||
"action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator,
|
||||
"action_dispatch.content_security_policy_nonce_directives" => config.content_security_policy_nonce_directives,
|
||||
"action_dispatch.feature_policy" => config.feature_policy,
|
||||
"action_dispatch.permissions_policy" => config.permissions_policy,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -73,7 +73,7 @@ module Rails
|
|||
@autoloader = :classic
|
||||
@disable_sandbox = false
|
||||
@add_autoload_paths_to_load_path = true
|
||||
@feature_policy = nil
|
||||
@permissions_policy = nil
|
||||
@rake_eager_load = false
|
||||
end
|
||||
|
||||
|
@ -325,11 +325,11 @@ module Rails
|
|||
end
|
||||
end
|
||||
|
||||
def feature_policy(&block)
|
||||
def permissions_policy(&block)
|
||||
if block_given?
|
||||
@feature_policy = ActionDispatch::FeaturePolicy.new(&block)
|
||||
@permissions_policy = ActionDispatch::PermissionsPolicy.new(&block)
|
||||
else
|
||||
@feature_policy
|
||||
@permissions_policy
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ module Rails
|
|||
|
||||
unless config.api_only
|
||||
middleware.use ::ActionDispatch::ContentSecurityPolicy::Middleware
|
||||
middleware.use ::ActionDispatch::FeaturePolicy::Middleware
|
||||
middleware.use ::ActionDispatch::PermissionsPolicy::Middleware
|
||||
end
|
||||
|
||||
middleware.use ::Rack::Head
|
||||
|
|
|
@ -138,7 +138,7 @@ module Rails
|
|||
rack_cors_config_exist = File.exist?("config/initializers/cors.rb")
|
||||
assets_config_exist = File.exist?("config/initializers/assets.rb")
|
||||
csp_config_exist = File.exist?("config/initializers/content_security_policy.rb")
|
||||
feature_policy_config_exist = File.exist?("config/initializers/feature_policy.rb")
|
||||
permissions_policy_config_exist = File.exist?("config/initializers/permissions_policy.rb")
|
||||
|
||||
@config_target_version = Rails.application.config.loaded_config_version || "5.0"
|
||||
|
||||
|
@ -174,8 +174,8 @@ module Rails
|
|||
remove_file "config/initializers/content_security_policy.rb"
|
||||
end
|
||||
|
||||
unless feature_policy_config_exist
|
||||
remove_file "config/initializers/feature_policy.rb"
|
||||
unless permissions_policy_config_exist
|
||||
remove_file "config/initializers/permissions_policy.rb"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -527,7 +527,7 @@ module Rails
|
|||
if options[:api]
|
||||
remove_file "config/initializers/cookies_serializer.rb"
|
||||
remove_file "config/initializers/content_security_policy.rb"
|
||||
remove_file "config/initializers/feature_policy.rb"
|
||||
remove_file "config/initializers/permissions_policy.rb"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Define an application-wide HTTP feature policy. For further
|
||||
# Define an application-wide HTTP permissions policy. For further
|
||||
# information see https://developers.google.com/web/updates/2018/06/feature-policy
|
||||
#
|
||||
# Rails.application.config.feature_policy do |f|
|
||||
# Rails.application.config.permissions_policy do |f|
|
||||
# f.camera :none
|
||||
# f.gyroscope :none
|
||||
# f.microphone :none
|
|
@ -46,7 +46,7 @@ module ApplicationTests
|
|||
"ActionDispatch::Session::CookieStore",
|
||||
"ActionDispatch::Flash",
|
||||
"ActionDispatch::ContentSecurityPolicy::Middleware",
|
||||
"ActionDispatch::FeaturePolicy::Middleware",
|
||||
"ActionDispatch::PermissionsPolicy::Middleware",
|
||||
"Rack::Head",
|
||||
"Rack::ConditionalGet",
|
||||
"Rack::ETag",
|
||||
|
|
|
@ -4,7 +4,7 @@ require "isolation/abstract_unit"
|
|||
require "rack/test"
|
||||
|
||||
module ApplicationTests
|
||||
class FeaturePolicyTest < ActiveSupport::TestCase
|
||||
class PermissionsPolicyTest < ActiveSupport::TestCase
|
||||
include ActiveSupport::Testing::Isolation
|
||||
include Rack::Test::Methods
|
||||
|
||||
|
@ -16,7 +16,7 @@ module ApplicationTests
|
|||
teardown_app
|
||||
end
|
||||
|
||||
test "feature policy is not enabled by default" do
|
||||
test "permissions policy is not enabled by default" do
|
||||
controller :pages, <<-RUBY
|
||||
class PagesController < ApplicationController
|
||||
def index
|
||||
|
@ -34,10 +34,10 @@ module ApplicationTests
|
|||
app("development")
|
||||
|
||||
get "/"
|
||||
assert_nil last_response.headers["Feature-Policy"]
|
||||
assert_nil last_response.headers["Permissions-Policy"]
|
||||
end
|
||||
|
||||
test "global feature policy in an initializer" do
|
||||
test "global permissions policy in an initializer" do
|
||||
controller :pages, <<-RUBY
|
||||
class PagesController < ApplicationController
|
||||
def index
|
||||
|
@ -46,8 +46,8 @@ module ApplicationTests
|
|||
end
|
||||
RUBY
|
||||
|
||||
app_file "config/initializers/feature_policy.rb", <<-RUBY
|
||||
Rails.application.config.feature_policy do |p|
|
||||
app_file "config/initializers/permissions_policy.rb", <<-RUBY
|
||||
Rails.application.config.permissions_policy do |p|
|
||||
p.geolocation :none
|
||||
end
|
||||
RUBY
|
||||
|
@ -64,10 +64,10 @@ module ApplicationTests
|
|||
assert_policy "geolocation 'none'"
|
||||
end
|
||||
|
||||
test "override feature policy using same directive in a controller" do
|
||||
test "override permissions policy using same directive in a controller" do
|
||||
controller :pages, <<-RUBY
|
||||
class PagesController < ApplicationController
|
||||
feature_policy do |p|
|
||||
permissions_policy do |p|
|
||||
p.geolocation "https://example.com"
|
||||
end
|
||||
|
||||
|
@ -77,8 +77,8 @@ module ApplicationTests
|
|||
end
|
||||
RUBY
|
||||
|
||||
app_file "config/initializers/feature_policy.rb", <<-RUBY
|
||||
Rails.application.config.feature_policy do |p|
|
||||
app_file "config/initializers/permissions_policy.rb", <<-RUBY
|
||||
Rails.application.config.permissions_policy do |p|
|
||||
p.geolocation :none
|
||||
end
|
||||
RUBY
|
||||
|
@ -95,10 +95,10 @@ module ApplicationTests
|
|||
assert_policy "geolocation https://example.com"
|
||||
end
|
||||
|
||||
test "override feature policy by unsetting a directive in a controller" do
|
||||
test "override permissions policy by unsetting a directive in a controller" do
|
||||
controller :pages, <<-RUBY
|
||||
class PagesController < ApplicationController
|
||||
feature_policy do |p|
|
||||
permissions_policy do |p|
|
||||
p.geolocation nil
|
||||
end
|
||||
|
||||
|
@ -108,8 +108,8 @@ module ApplicationTests
|
|||
end
|
||||
RUBY
|
||||
|
||||
app_file "config/initializers/feature_policy.rb", <<-RUBY
|
||||
Rails.application.config.feature_policy do |p|
|
||||
app_file "config/initializers/permissions_policy.rb", <<-RUBY
|
||||
Rails.application.config.permissions_policy do |p|
|
||||
p.geolocation :none
|
||||
end
|
||||
RUBY
|
||||
|
@ -124,13 +124,13 @@ module ApplicationTests
|
|||
|
||||
get "/"
|
||||
assert_equal 200, last_response.status
|
||||
assert_nil last_response.headers["Feature-Policy"]
|
||||
assert_nil last_response.headers["Permissions-Policy"]
|
||||
end
|
||||
|
||||
test "override feature policy using different directives in a controller" do
|
||||
test "override permissions policy using different directives in a controller" do
|
||||
controller :pages, <<-RUBY
|
||||
class PagesController < ApplicationController
|
||||
feature_policy do |p|
|
||||
permissions_policy do |p|
|
||||
p.geolocation nil
|
||||
p.payment "https://secure.example.com"
|
||||
p.autoplay :none
|
||||
|
@ -142,8 +142,8 @@ module ApplicationTests
|
|||
end
|
||||
RUBY
|
||||
|
||||
app_file "config/initializers/feature_policy.rb", <<-RUBY
|
||||
Rails.application.config.feature_policy do |p|
|
||||
app_file "config/initializers/permissions_policy.rb", <<-RUBY
|
||||
Rails.application.config.permissions_policy do |p|
|
||||
p.geolocation :none
|
||||
end
|
||||
RUBY
|
||||
|
@ -160,9 +160,9 @@ module ApplicationTests
|
|||
assert_policy "payment https://secure.example.com; autoplay 'none'"
|
||||
end
|
||||
|
||||
test "global feature policy added to rack app" do
|
||||
app_file "config/initializers/feature_policy.rb", <<-RUBY
|
||||
Rails.application.config.feature_policy do |p|
|
||||
test "global permissions policy added to rack app" do
|
||||
app_file "config/initializers/permissions_policy.rb", <<-RUBY
|
||||
Rails.application.config.permissions_policy do |p|
|
||||
p.payment :none
|
||||
end
|
||||
RUBY
|
||||
|
@ -185,7 +185,7 @@ module ApplicationTests
|
|||
private
|
||||
def assert_policy(expected)
|
||||
assert_equal 200, last_response.status
|
||||
assert_equal expected, last_response.headers["Feature-Policy"]
|
||||
assert_equal expected, last_response.headers["Permissions-Policy"]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -96,7 +96,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
|
|||
assert_no_file "config/initializers/cookies_serializer.rb"
|
||||
assert_no_file "config/initializers/assets.rb"
|
||||
assert_no_file "config/initializers/content_security_policy.rb"
|
||||
assert_no_file "config/initializers/feature_policy.rb"
|
||||
assert_no_file "config/initializers/permissions_policy.rb"
|
||||
end
|
||||
|
||||
def test_app_update_does_not_generate_unnecessary_bin_files
|
||||
|
@ -172,7 +172,7 @@ class ApiAppGeneratorTest < Rails::Generators::TestCase
|
|||
config/initializers/assets.rb
|
||||
config/initializers/cookies_serializer.rb
|
||||
config/initializers/content_security_policy.rb
|
||||
config/initializers/feature_policy.rb
|
||||
config/initializers/permissions_policy.rb
|
||||
lib/assets
|
||||
test/helpers
|
||||
tmp/cache/assets
|
||||
|
|
Loading…
Reference in a new issue