diff options
author | Gonçalo Silva <goncalossilva@gmail.com> | 2011-03-28 04:20:49 +0100 |
---|---|---|
committer | Gonçalo Silva <goncalossilva@gmail.com> | 2011-03-28 04:20:49 +0100 |
commit | 6f0caa1a534a065753d51430b649114bc8bf54ac (patch) | |
tree | af9657373436a38ef7828b26a804d1fe12e479ad /actionpack | |
parent | 726b7ede54031eecfcee34eec80040553e9ad19f (diff) | |
parent | 245542ea2994961731be105db6c076256a22a7a9 (diff) | |
download | rails-6f0caa1a534a065753d51430b649114bc8bf54ac.tar.gz rails-6f0caa1a534a065753d51430b649114bc8bf54ac.tar.bz2 rails-6f0caa1a534a065753d51430b649114bc8bf54ac.zip |
Merge branch 'master' of https://github.com/rails/rails into performance_test
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/CHANGELOG | 8 | ||||
-rw-r--r-- | actionpack/lib/action_controller.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_controller/base.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_controller/caching/actions.rb | 13 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/force_ssl.rb | 35 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb | 2 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/form_helper.rb | 15 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/javascript_helper.rb | 5 | ||||
-rw-r--r-- | actionpack/lib/action_view/template/resolver.rb | 4 | ||||
-rw-r--r-- | actionpack/test/controller/force_ssl_test.rb | 83 | ||||
-rw-r--r-- | actionpack/test/dispatch/show_exceptions_test.rb | 16 | ||||
-rw-r--r-- | actionpack/test/template/form_helper_test.rb | 21 | ||||
-rw-r--r-- | actionpack/test/template/javascript_helper_test.rb | 1 |
13 files changed, 191 insertions, 14 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 5ab92c8cfc..a90a7b37f7 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,13 @@ *Rails 3.1.0 (unreleased)* +* Allow you to add `force_ssl` into controller to force browser to transfer data via HTTPS protocol on that particular controller. You can also specify `:only` or `:except` to specific it to particular action. [DHH and Prem Sichanugrist] + +* Allow FormHelper#form_for to specify the :method as a direct option instead of through the :html hash [DHH] + + form_for(@post, remote: true, method: :delete) instead of form_for(@post, remote: true, html: { method: :delete }) + +* Make JavaScriptHelper#j() an alias for JavaScriptHelper#escape_javascript() -- note this then supersedes the Object#j() method that the JSON gem adds within templates using the JavaScriptHelper [DHH] + * Sensitive query string parameters (specified in config.filter_parameters) will now be filtered out from the request paths in the log file. [Prem Sichanugrist, fxn] * URL parameters which return false for to_param now appear in the query string (previously they were removed) [Andrew White] diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index 5b81cd39f4..62cc18b253 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -14,6 +14,7 @@ module ActionController autoload :ConditionalGet autoload :Cookies autoload :Flash + autoload :ForceSSL autoload :Head autoload :Helpers autoload :HideActions diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 81c0698fb8..e6523e56d2 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -198,6 +198,7 @@ module ActionController Cookies, Flash, RequestForgeryProtection, + ForceSSL, Streaming, RecordIdentifier, HttpAuthentication::Basic::ControllerMethods, diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb index 2c8a6e4d4d..5fc6956266 100644 --- a/actionpack/lib/action_controller/caching/actions.rb +++ b/actionpack/lib/action_controller/caching/actions.rb @@ -56,19 +56,18 @@ module ActionController #:nodoc: # # caches_page :public # - # caches_action :index, :if => proc do |c| - # !c.request.format.json? # cache if is not a JSON request + # caches_action :index, :if => proc do + # !request.format.json? # cache if is not a JSON request # end # # caches_action :show, :cache_path => { :project => 1 }, # :expires_in => 1.hour # - # caches_action :feed, :cache_path => proc do |c| - # if c.params[:user_id] - # c.send(:user_list_url, - # c.params[:user_id], c.params[:id]) + # caches_action :feed, :cache_path => proc do + # if params[:user_id] + # user_list_url(params[:user_id, params[:id]) # else - # c.send(:list_url, c.params[:id]) + # list_url(params[:id]) # end # end # end diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb new file mode 100644 index 0000000000..eb8ed7dfbd --- /dev/null +++ b/actionpack/lib/action_controller/metal/force_ssl.rb @@ -0,0 +1,35 @@ +module ActionController + # This module provides a method which will redirects browser to use HTTPS + # protocol. This will ensure that user's sensitive information will be + # transferred safely over the internet. You _should_ always force browser + # to use HTTPS when you're transferring sensitive information such as + # user authentication, account information, or credit card information. + # + # Note that if you really concern about your application safety, you might + # consider using +config.force_ssl+ in your configuration config file instead. + # That will ensure all the data transferred via HTTPS protocol and prevent + # user from getting session hijacked when accessing the site under unsecured + # HTTP protocol. + module ForceSSL + extend ActiveSupport::Concern + include AbstractController::Callbacks + + module ClassMethods + # Force the request to this particular controller or specified actions to be + # under HTTPS protocol. + # + # Note that this method will not be effective on development environment. + # + # ==== Options + # * <tt>only</tt> - The callback should be run only for this action + # * <tt>except<tt> - The callback should be run for all actions except this action + def force_ssl(options = {}) + before_filter(options) do + if !request.ssl? && !Rails.env.development? + redirect_to :protocol => 'https://', :status => :moved_permanently + end + end + end + end + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb index 50d8ca9484..2099fd069a 100644 --- a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb @@ -1,7 +1,7 @@ <h1> <%=h @exception.class.to_s %> <% if @request.parameters['controller'] %> - in <%=h @request.parameters['controller'].humanize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %> + in <%=h @request.parameters['controller'].classify.pluralize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %> <% end %> </h1> <pre><%=h @exception.message %></pre> diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 48abf119f1..9025d9e24c 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -185,7 +185,7 @@ module ActionView # # is equivalent to something like: # - # <%= form_for @post, :as => :post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %> + # <%= form_for @post, :as => :post, :url => post_path(@post), :method => :put, :html => { :class => "edit_post", :id => "edit_post_45" } do |f| %> # ... # <% end %> # @@ -236,6 +236,16 @@ module ActionView # Where <tt>@document = Document.find(params[:id])</tt> and # <tt>@comment = Comment.new</tt>. # + # === Setting the method + # + # You can force the form to use the full array of HTTP verbs by setting + # + # :method => (:get|:post|:put|:delete) + # + # in the options hash. If the verb is not GET or POST, which are natively supported by HTML forms, the + # form will be set to POST and a hidden input called _method will carry the intended verb for the server + # to interpret. + # # === Unobtrusive JavaScript # # Specifying: @@ -298,7 +308,7 @@ module ActionView # # In this case, if you use this: # - # <%= render :partial => f %> + # <%= render f %> # # The rendered template is <tt>people/_labelling_form</tt> and the local # variable referencing the form builder is called @@ -350,6 +360,7 @@ module ActionView end options[:html][:remote] = options.delete(:remote) + options[:html][:method] = options.delete(:method) if options.has_key?(:method) options[:html][:authenticity_token] = options.delete(:authenticity_token) builder = options[:parent_builder] = instantiate_builder(object_name, object, options, &proc) diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index cd3a3eac80..a19ba7a968 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -47,6 +47,9 @@ module ActionView "'" => "\\'" } # Escape carrier returns and single and double quotes for JavaScript segments. + # Also available through the alias j(). This is particularly helpful in JavaScript responses, like: + # + # $('some_element').replaceWith('<%=j render 'some/element_template' %>'); def escape_javascript(javascript) if javascript javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] } @@ -55,6 +58,8 @@ module ActionView end end + alias_method :j, :escape_javascript + # Returns a JavaScript tag with the +content+ inside. Example: # javascript_tag "alert('All is good')" # diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb index 6c1063592f..41c6310ae2 100644 --- a/actionpack/lib/action_view/template/resolver.rb +++ b/actionpack/lib/action_view/template/resolver.rb @@ -157,8 +157,8 @@ module ActionView query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}") } - query.gsub!(/\.{html,/, ".{html,text.html,") - query.gsub!(/\.{text,/, ".{text,text.plain,") + query.gsub!('.{html,', '.{html,text.html,') + query.gsub!('.{text,', '.{text,text.plain,') File.expand_path(query, @path) end diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb new file mode 100644 index 0000000000..3e723e20d9 --- /dev/null +++ b/actionpack/test/controller/force_ssl_test.rb @@ -0,0 +1,83 @@ +require 'abstract_unit' + +class ForceSSLController < ActionController::Base + def banana + render :text => "monkey" + end + + def cheeseburger + render :text => "sikachu" + end +end + +class ForceSSLControllerLevel < ForceSSLController + force_ssl +end + +class ForceSSLOnlyAction < ForceSSLController + force_ssl :only => :cheeseburger +end + +class ForceSSLExceptAction < ForceSSLController + force_ssl :except => :banana +end + +class ForceSSLControllerLevelTest < ActionController::TestCase + tests ForceSSLControllerLevel + + def test_banana_redirects_to_https + get :banana + assert_response 301 + assert_equal "https://test.host/force_ssl_controller_level/banana", redirect_to_url + end + + def test_cheeseburger_redirects_to_https + get :cheeseburger + assert_response 301 + assert_equal "https://test.host/force_ssl_controller_level/cheeseburger", redirect_to_url + end +end + +class ForceSSLOnlyActionTest < ActionController::TestCase + tests ForceSSLOnlyAction + + def test_banana_not_redirects_to_https + get :banana + assert_response 200 + end + + def test_cheeseburger_redirects_to_https + get :cheeseburger + assert_response 301 + assert_equal "https://test.host/force_ssl_only_action/cheeseburger", redirect_to_url + end +end + +class ForceSSLExceptActionTest < ActionController::TestCase + tests ForceSSLExceptAction + + def test_banana_not_redirects_to_https + get :banana + assert_response 200 + end + + def test_cheeseburger_redirects_to_https + get :cheeseburger + assert_response 301 + assert_equal "https://test.host/force_ssl_except_action/cheeseburger", redirect_to_url + end +end + +class ForceSSLExcludeDevelopmentTest < ActionController::TestCase + tests ForceSSLControllerLevel + + def setup + Rails.env.stubs(:development?).returns(false) + end + + def test_development_environment_not_redirects_to_https + Rails.env.stubs(:development?).returns(true) + get :banana + assert_response 200 + end +end
\ No newline at end of file diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb index 2a478c214f..e453dd11ce 100644 --- a/actionpack/test/dispatch/show_exceptions_test.rb +++ b/actionpack/test/dispatch/show_exceptions_test.rb @@ -7,6 +7,8 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest case req.path when "/not_found" raise ActionController::UnknownAction + when "/runtime_error" + raise RuntimeError when "/method_not_allowed" raise ActionController::MethodNotAllowed when "/not_implemented" @@ -121,4 +123,18 @@ class ShowExceptionsTest < ActionDispatch::IntegrationTest assert_response 404 assert_match(/AbstractController::ActionNotFound/, body) end + + test "show the controller name in the diagnostics template when controller name is present" do + @app = ProductionApp + get("/runtime_error", {}, { + 'action_dispatch.show_exceptions' => true, + 'action_dispatch.request.parameters' => { + 'action' => 'show', + 'id' => 'unknown', + 'controller' => 'featured_tiles' + } + }) + assert_response 500 + assert_match(/RuntimeError\n in FeaturedTilesController/, body) + end end diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 359b078466..ff183d097d 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -715,14 +715,31 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_method_as_part_of_html_options + form_for(@post, :url => '/', :html => { :id => 'create-post', :method => :delete }) do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end + + expected = whole_form("/", "create-post", "edit_post", "delete") do + "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[secret]' type='hidden' value='0' />" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + end + + assert_dom_equal expected, output_buffer + end + def test_form_for_with_method - form_for(@post, :url => '/', :html => { :id => 'create-post', :method => :put }) do |f| + form_for(@post, :url => '/', :method => :delete, :html => { :id => 'create-post' }) do |f| concat f.text_field(:title) concat f.text_area(:body) concat f.check_box(:secret) end - expected = whole_form("/", "create-post", "edit_post", "put") do + expected = whole_form("/", "create-post", "edit_post", "delete") do "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + "<input name='post[secret]' type='hidden' value='0' />" + diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb index 2e7484afaf..8aa2730da1 100644 --- a/actionpack/test/template/javascript_helper_test.rb +++ b/actionpack/test/template/javascript_helper_test.rb @@ -27,6 +27,7 @@ class JavaScriptHelperTest < ActionView::TestCase assert_equal %(This \\"thing\\" is really\\n netos\\'), escape_javascript(%(This "thing" is really\n netos')) assert_equal %(backslash\\\\test), escape_javascript( %(backslash\\test) ) assert_equal %(dont <\\/close> tags), escape_javascript(%(dont </close> tags)) + assert_equal %(dont <\\/close> tags), j(%(dont </close> tags)) end def test_button_to_function |