提交 a58db74c 编写于 作者: G Genadi Samokovarov

Don't expect defined protect_against_forgery? in {token,csrf_meta}_tag

The `#csrf_meta_tags` and `#token_tag` Action View helper methods are
expecting the class in which are included to explicitly define the
method `#protect_against_forgery?` or else they will fail with
`NoMethodError`.

This is a problem if you want to use Action View outside of Rails
applications. For example, in #34788 I used the `#button_to` helper
inside of the error pages templates that have a custom
`ActionView::Base` subclass, which did not defined
`#protect_against_forgery?` and trying to call the button failed.

I had to dig inside of Action View to find-out what's was going on. I
think we should either set a default method implementation in the
helpers or check for the method definition, but don't explicitly require
the presence of `#protect_against_forgery?` in every `ActionViews::Base`
subclass as the errors are hard to figure out.
上级 b5ed4684
* Fix the need of `#protect_against_forgery?` method defined in
`ActionView::Base` subclasses. This prevents the use of forms and buttons.
*Genadi Samokovarov*
* Fix UJS permanently showing disabled text in a[data-remote][data-disable-with] elements within forms.
Fixes #33889
*Wolfgang Hobmaier*
* Prevent non-primary mouse keys from triggering Rails UJS click handlers.
Firefox fires click events even if the click was triggered by non-primary mouse keys such as right- or scroll-wheel-clicks.
For example, right-clicking a link such as the one described below (with an underlying ajax request registered on click) should not cause that request to occur.
......@@ -16,7 +20,6 @@
*Wolfgang Hobmaier*
* Prevent `ActionView::TextHelper#word_wrap` from unexpectedly stripping white space from the _left_ side of lines.
For example, given input like this:
......@@ -34,7 +37,6 @@
*Lyle Mullican*
* Add allocations to template rendering instrumentation.
Adds the allocations for template and partial rendering to the server output on render.
......
......@@ -20,7 +20,7 @@ module CsrfHelper
# "X-CSRF-Token" HTTP header. If you are using rails-ujs this happens automatically.
#
def csrf_meta_tags
if protect_against_forgery?
if defined?(protect_against_forgery?) && protect_against_forgery?
[
tag("meta", name: "csrf-param", content: request_forgery_protection_token),
tag("meta", name: "csrf-token", content: form_authenticity_token)
......
......@@ -618,7 +618,7 @@ def method_not_get_method?(method)
end
def token_tag(token = nil, form_options: {})
if token != false && protect_against_forgery?
if token != false && defined?(protect_against_forgery?) && protect_against_forgery?
token ||= form_authenticity_token(form_options: form_options)
tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
else
......
# frozen_string_literal: true
require "abstract_unit"
class CsrfHelperTest < ActiveSupport::TestCase
cattr_accessor :request_forgery, default: false
include ActionView::Helpers::CsrfHelper
include ActionView::Helpers::TagHelper
include Rails::Dom::Testing::Assertions::DomAssertions
def test_csrf_meta_tags_without_request_forgery_protection
assert_dom_equal "", csrf_meta_tags
end
def test_csrf_meta_tags_with_request_forgery_protection
self.request_forgery = true
assert_dom_equal <<~DOM.chomp, csrf_meta_tags
<meta name="csrf-param" content="form_token" />
<meta name="csrf-token" content="secret" />
DOM
ensure
self.request_forgery = false
end
def test_csrf_meta_tags_without_protect_against_forgery_method
self.class.undef_method(:protect_against_forgery?)
assert_dom_equal "", csrf_meta_tags
ensure
self.class.define_method(:protect_against_forgery?) { request_forgery }
end
def protect_against_forgery?
request_forgery
end
def form_authenticity_token(*args)
"secret"
end
def request_forgery_protection_token
"form_token"
end
end
......@@ -119,6 +119,16 @@ def test_to_form_params_with_namespace
)
end
def test_button_to_without_protect_against_forgery_method
self.class.undef_method(:protect_against_forgery?)
assert_dom_equal(
%{<form method="post" action="http://www.example.com" class="button_to"><input type="submit" value="Hello" /></form>},
button_to("Hello", "http://www.example.com")
)
ensure
self.class.define_method(:protect_against_forgery?) { request_forgery }
end
def test_button_to_with_straight_url
assert_dom_equal %{<form method="post" action="http://www.example.com" class="button_to"><input type="submit" value="Hello" /></form>}, button_to("Hello", "http://www.example.com")
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册