1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Initialize ActionController::Parameters with @logging_context

`params` contains `@logging_context` in its instance to notify
unpermitted parameters including the context through Rails
Instrumentation API. However, the logging context disappeared when
`params` is updated with some methods, such as `require`, `slice`,
`merge`, etc, so the subscriber of `unpermitted_parameters` could not
get the information.

This patch tries to initialize `Parameters` with `@logging_context`
where it makes sense to pass the information. The following methods will
be affected with this patch:

* `require`
* `deep_dup`
* `slice`
* `except`
* `extract!`
* `transform_values`
* `transform_keys`
* `deep_transform_keys`
* `select`
* `reject`
* `compact`
* `merge`
* `reverse_merge`
This commit is contained in:
Yutaka Kamei 2021-12-16 22:44:31 +09:00
parent 87d65e9b12
commit 0b7f37fbed
No known key found for this signature in database
GPG key ID: B4282A48C22883EE
2 changed files with 137 additions and 3 deletions

View file

@ -910,7 +910,7 @@ module ActionController
# Returns duplicate of object including all parameters.
def deep_dup
self.class.new(@parameters.deep_dup).tap do |duplicate|
self.class.new(@parameters.deep_dup, @logging_context).tap do |duplicate|
duplicate.permitted = @permitted
end
end
@ -932,7 +932,7 @@ module ActionController
private
def new_instance_with_inherited_permitted_status(hash)
self.class.new(hash).tap do |new_instance|
self.class.new(hash, @logging_context).tap do |new_instance|
new_instance.permitted = @permitted
end
end
@ -966,7 +966,7 @@ module ActionController
converted_arrays << converted.dup
converted
when Hash
self.class.new(value)
self.class.new(value, @logging_context)
else
value
end

View file

@ -50,6 +50,140 @@ class LogOnUnpermittedParamsTest < ActiveSupport::TestCase
end
end
test "logs on unexpected nested params with require" do
request_params = { book: { pages: 65, title: "Green Cats and where to find then.", author: "G. A. Dog" } }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameters: :title, :author. Context: { action: my_action, controller: my_controller }") do
params.require(:book).permit(:pages)
end
end
test "logs on unexpected param with deep_dup" do
request_params = { book: { pages: 3, author: "YY" } }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameter: :author. Context: { action: my_action, controller: my_controller }") do
params.deep_dup.permit(book: [:pages])
end
end
test "logs on unexpected params with slice" do
request_params = { food: "tomato", fishing: "Turnips", car: "Mercedes", music: "No. 9" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameters: :fishing, :car. Context: { action: my_action, controller: my_controller }") do
params.slice(:food, :fishing, :car).permit(:food)
end
end
test "logs on unexpected params with except" do
request_params = { food: "tomato", fishing: "Turnips", car: "Mercedes", music: "No. 9" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameters: :fishing, :car. Context: { action: my_action, controller: my_controller }") do
params.except(:music).permit(:food)
end
end
test "logs on unexpected params with extract!" do
request_params = { food: "tomato", fishing: "Turnips", car: "Mercedes", music: "No. 9" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameters: :fishing, :car. Context: { action: my_action, controller: my_controller }") do
params.extract!(:food, :fishing, :car).permit(:food)
end
assert_logged("Unpermitted parameter: :music. Context: { action: my_action, controller: my_controller }") do
params.permit(:food)
end
end
test "logs on unexpected params with transform_values" do
request_params = { food: "tomato", fishing: "Turnips", car: "Mercedes", music: "No. 9" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameters: :fishing, :car, :music. Context: { action: my_action, controller: my_controller }") do
params.transform_values { |v| v.upcase }.permit(:food)
end
end
test "logs on unexpected params with transform_keys" do
request_params = { food: "tomato", fishing: "Turnips", car: "Mercedes", music: "No. 9" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameters: :FISHING, :CAR, :MUSIC. Context: { action: my_action, controller: my_controller }") do
params.transform_keys { |k| k.upcase }.permit(:FOOD)
end
end
test "logs on unexpected param with deep_transform_keys" do
request_params = { book: { pages: 48, title: "Hope" } }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameter: :TITLE. Context: { action: my_action, controller: my_controller }") do
params.deep_transform_keys { |k| k.upcase }.permit(BOOK: [:PAGES])
end
end
test "logs on unexpected param with select" do
request_params = { food: "tomato", fishing: "Turnips", car: "Mercedes", music: "No. 9" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameter: :music. Context: { action: my_action, controller: my_controller }") do
params.select { |k| k == "music" }.permit(:food)
end
end
test "logs on unexpected params with reject" do
request_params = { food: "tomato", fishing: "Turnips", car: "Mercedes", music: "No. 9" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameters: :fishing, :car. Context: { action: my_action, controller: my_controller }") do
params.reject { |k| k == "music" }.permit(:food)
end
end
test "logs on unexpected param with compact" do
request_params = { food: "tomato", fishing: "Turnips", car: nil, music: nil }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameter: :fishing. Context: { action: my_action, controller: my_controller }") do
params.compact.permit(:food)
end
end
test "logs on unexpected param with merge" do
request_params = { food: "tomato" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameter: :album. Context: { action: my_action, controller: my_controller }") do
params.merge(album: "My favorites").permit(:food)
end
end
test "logs on unexpected param with reverse_merge" do
request_params = { food: "tomato" }
context = { "action" => "my_action", "controller" => "my_controller" }
params = ActionController::Parameters.new(request_params, context)
assert_logged("Unpermitted parameter: :album. Context: { action: my_action, controller: my_controller }") do
params.reverse_merge(album: "My favorites").permit(:food)
end
end
private
def assert_logged(message)
old_logger = ActionController::Base.logger