From 2c0c4d754e34b13379dfc53121a970c25fab5dae Mon Sep 17 00:00:00 2001
From: Prem Sichanugrist <s@sikachu.com>
Date: Sun, 27 Mar 2011 23:55:46 +0700
Subject: Add `config.force_ssl` configuration which will load `Rack::SSL`
 middleware if set to true

This will allow user to be able to force all requests to be under HTTPS protocol.

This commit was a request from DHH. Special thanks to Josh Peek as well for making `Rack::SSL`.
---
 railties/CHANGELOG                                     |  2 ++
 railties/guides/source/configuring.textile             |  3 +++
 railties/guides/source/security.textile                |  6 +++++-
 railties/lib/rails/application.rb                      | 17 +++++++++++++----
 railties/lib/rails/application/configuration.rb        |  3 ++-
 .../templates/config/environments/development.rb.tt    |  2 +-
 .../app/templates/config/environments/production.rb.tt | 18 +++++++-----------
 railties/railties.gemspec                              |  1 +
 railties/test/application/middleware_test.rb           |  6 ++++++
 9 files changed, 40 insertions(+), 18 deletions(-)

(limited to 'railties')

diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 75f1df44e7..c1e0a214d2 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
 *Rails 3.1.0 (unreleased)*
 
+* Added `config.force_ssl` configuration which loads Rack::SSL middleware and force all requests to be under HTTPS protocol [DHH, Prem Sichanugrist, and Josh Peek]
+
 * Added `rails plugin new` command which generates rails plugin with gemspec, tests and dummy application for testing [Piotr Sarnacki]
 
 * Added -j parameter with jquery/prototype as options. Now you can create your apps with jQuery using `rails new myapp -j jquery`. The default is still Prototype. [siong1987]
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 62b846e871..04e2d6daed 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -81,6 +81,8 @@ end
 
 * +config.filter_parameters+ used for filtering out the parameters that you don't want shown in the logs, such as passwords or credit card numbers.
 
+* +config.force_ssl+ forcing all requests to be under HTTPS protocol by using +Rack::SSL+ middleware. This will secure your application from a session hijack attempt.
+
 * +config.helper_paths+ configures where Rails can find helpers for this application.
 
 * +config.log_level+ defines the verbosity of the Rails logger. In production mode, this defaults to +:info+. In development mode, it defaults to +:debug+.
@@ -147,6 +149,7 @@ h4. Configuring Middleware
 
 Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
 
+* +Rack::SSL+ Will force every requests to be under HTTPS protocal. Will be available if +config.force_ssl+ is set to _true_.
 * +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_.
 * +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default.
 * +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile
index 182f3631ef..893f65856c 100644
--- a/railties/guides/source/security.textile
+++ b/railties/guides/source/security.textile
@@ -57,7 +57,11 @@ Many web applications have an authentication system: a user provides a user name
 
 Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user – with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:
 
-* Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_.
+* Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _(highlight)provide a secure connection over SSL_. In Rails 3.1 and later, this could be accomplished by always forcing SSL connection in your application config file:
+
+<ruby>
+config.force_ssl = true
+</ruby>
 
 * Most people don't clear out the cookies after working at a public terminal. So if the last user didn't log out of a web application, you would be able to use it as this user. Provide the user with a _(highlight)log-out button_ in the web application, and _(highlight)make it prominent_.
 
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 94819820bc..1b834275a7 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -145,15 +145,21 @@ module Rails
 
     def default_middleware_stack
       ActionDispatch::MiddlewareStack.new.tap do |middleware|
-        rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache
+        if rack_cache = config.action_controller.perform_caching && config.action_dispatch.rack_cache
+          require "action_dispatch/http/rack_cache"
+          middleware.use ::Rack::Cache, rack_cache
+        end
 
-        require "action_dispatch/http/rack_cache" if rack_cache
-        middleware.use ::Rack::Cache, rack_cache  if rack_cache
+        if config.force_ssl
+          require "rack/ssl"
+          middleware.use ::Rack::SSL
+        end
 
         if config.serve_static_assets
           asset_paths = ActiveSupport::OrderedHash[config.static_asset_paths.to_a.reverse]
           middleware.use ::ActionDispatch::Static, asset_paths
         end
+
         middleware.use ::Rack::Lock unless config.allow_concurrency
         middleware.use ::Rack::Runtime
         middleware.use ::Rails::Rack::Logger
@@ -174,7 +180,10 @@ module Rails
         middleware.use ::ActionDispatch::Head
         middleware.use ::Rack::ConditionalGet
         middleware.use ::Rack::ETag, "no-cache"
-        middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support if config.action_dispatch.best_standards_support
+
+        if config.action_dispatch.best_standards_support
+          middleware.use ::ActionDispatch::BestStandardsSupport, config.action_dispatch.best_standards_support
+        end
       end
     end
 
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index c74bcbedf2..23b0e765ae 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -9,7 +9,7 @@ module Rails
                     :filter_parameters, :helpers_paths, :logger,
                     :preload_frameworks, :reload_plugins,
                     :secret_token, :serve_static_assets, :session_options,
-                    :time_zone, :whiny_nils
+                    :time_zone, :whiny_nils, :force_ssl
 
       attr_writer :log_level
 
@@ -22,6 +22,7 @@ module Rails
         @helpers_paths               = []
         @dependency_loading          = true
         @serve_static_assets         = true
+        @force_ssl                   = false
         @session_store               = :cookie_store
         @session_options             = {}
         @time_zone                   = "UTC"
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
index 91d3133ea4..bdb897ad33 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt
@@ -3,7 +3,7 @@
 
   # In the development environment your application's code is reloaded on
   # every request.  This slows down response time but is perfect for development
-  # since you don't have to restart the webserver when you make code changes.
+  # since you don't have to restart the web server when you make code changes.
   config.cache_classes = false
 
   # Log error messages when you accidentally call methods on nil.
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
index 89bb891ddd..874cc403ba 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -1,7 +1,6 @@
 <%= app_const %>.configure do
   # Settings specified here will take precedence over those in config/application.rb
 
-  # The production environment is meant for finished, "live" apps.
   # Code is not reloaded between requests
   config.cache_classes = true
 
@@ -9,14 +8,15 @@
   config.consider_all_requests_local       = false
   config.action_controller.perform_caching = true
 
-  # Specifies the header that your server uses for sending files
-  config.action_dispatch.x_sendfile_header = "X-Sendfile"
+  # Disable Rails's static asset server (Apache or nginx will already do this)
+  config.serve_static_assets = false
 
-  # For nginx:
-  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
+  # Specifies the header that your server uses for sending files
+  # (comment out if your front-end server doesn't support this)
+  config.action_dispatch.x_sendfile_header = "X-Sendfile" # Use 'X-Accel-Redirect' for nginx
 
-  # If you have no front-end server that supports something like X-Sendfile,
-  # just comment this out and Rails will serve the files
+  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+  # config.force_ssl = true
 
   # See everything in the log (default is :info)
   # config.log_level = :debug
@@ -27,10 +27,6 @@
   # Use a different cache store in production
   # config.cache_store = :mem_cache_store
 
-  # Disable Rails's static asset server
-  # In production, Apache or nginx will already do this
-  config.serve_static_assets = false
-
   # Enable serving of images, stylesheets, and javascripts from an asset server
   # config.action_controller.asset_host = "http://assets.example.com"
 
diff --git a/railties/railties.gemspec b/railties/railties.gemspec
index c3793d3ac3..c51fe856be 100644
--- a/railties/railties.gemspec
+++ b/railties/railties.gemspec
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
 
   s.add_dependency('rake',          '>= 0.8.7')
   s.add_dependency('thor',          '~> 0.14.4')
+  s.add_dependency('rack-ssl',      '~> 1.3.2')
   s.add_dependency('activesupport', version)
   s.add_dependency('actionpack',    version)
 end
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index b314832685..0df6f33e8c 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -52,6 +52,12 @@ module ApplicationTests
       assert_equal "Rack::Cache", middleware.first
     end
 
+    test "Rack::SSL is present with force_ssl is set" do
+      add_to_config "config.force_ssl = true"
+      boot!
+      assert middleware.include?("Rack::SSL")
+    end
+
     test "removing Active Record omits its middleware" do
       use_frameworks []
       boot!
-- 
cgit v1.2.3


From 84aab7aa53e0ec4430df89807aa8220353b2d0c9 Mon Sep 17 00:00:00 2001
From: Xavier Noria <fxn@hashref.com>
Date: Sun, 27 Mar 2011 22:31:42 +0200
Subject: s/with/when/

---
 railties/test/application/middleware_test.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'railties')

diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index 0df6f33e8c..01e6c49d9c 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -52,7 +52,7 @@ module ApplicationTests
       assert_equal "Rack::Cache", middleware.first
     end
 
-    test "Rack::SSL is present with force_ssl is set" do
+    test "Rack::SSL is present when force_ssl is set" do
       add_to_config "config.force_ssl = true"
       boot!
       assert middleware.include?("Rack::SSL")
-- 
cgit v1.2.3


From 7cbdfa83035aacb0d4dbfa84525b54e9122efb75 Mon Sep 17 00:00:00 2001
From: Prem Sichanugrist <s@sikachu.com>
Date: Mon, 28 Mar 2011 03:05:14 +0800
Subject: Add controller-specific `force_ssl` method to force web browser to
 use HTTPS protocol

This would become useful for site which sometime transferring sensitive information such as account information on particular controller or action.

This featured was requested by DHH.
---
 .../source/action_controller_overview.textile      | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

(limited to 'railties')

diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile
index ecb03a48e4..178d98c2d6 100644
--- a/railties/guides/source/action_controller_overview.textile
+++ b/railties/guides/source/action_controller_overview.textile
@@ -816,6 +816,28 @@ end
 
 NOTE: Certain exceptions are only rescuable from the +ApplicationController+ class, as they are raised before the controller gets initialized and the action gets executed. See Pratik Naik's "article":http://m.onkey.org/2008/7/20/rescue-from-dispatching on the subject for more information.
 
+h3. Force HTTPS protocol
+
+Sometime you might want to force a particular controller to only be accessible via an HTTPS protocol for security reason. Since Rails 3.1 you can now use +force_ssl+ method in your controller to enforce that:
+
+<ruby>
+class DinnerController
+  force_ssl
+end
+</ruby>
+
+Just like the filter, you could also passing +:only+ and +:except+ to enforce the secure connection only to specific actions
+
+<ruby>
+class DinnerController
+  force_ssl :only => :cheeseburger
+  # or
+  force_ssl :except => :cheeseburger
+end
+</ruby>
+
+Please note that if you found yourself adding +force_ssl+ to many controllers, you may found yourself wanting to force the whole application to use HTTPS instead. In that case, you can set the +config.force_ssl+ in your environment file.
+
 h3. Changelog
 
 * February 17, 2009: Yet another proofread by Xavier Noria.
-- 
cgit v1.2.3


From 884e39f69eb8012b7ce455747d1b8aa7b34d83d3 Mon Sep 17 00:00:00 2001
From: Prem Sichanugrist <s@sikachu.com>
Date: Mon, 28 Mar 2011 04:31:19 +0800
Subject: Fix documentation typo

---
 railties/guides/source/configuring.textile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'railties')

diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 04e2d6daed..298335d484 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -149,7 +149,7 @@ h4. Configuring Middleware
 
 Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
 
-* +Rack::SSL+ Will force every requests to be under HTTPS protocal. Will be available if +config.force_ssl+ is set to _true_.
+* +Rack::SSL+ Will force every requests to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_.
 * +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_.
 * +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default.
 * +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
-- 
cgit v1.2.3


From 6194c6d13b1349228baa85bf19b4f502011365a4 Mon Sep 17 00:00:00 2001
From: Xavier Noria <fxn@hashref.com>
Date: Sun, 27 Mar 2011 23:49:11 +0200
Subject: AR validations and callbacks guide: put update_attribute back

---
 railties/guides/source/active_record_validations_callbacks.textile | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'railties')

diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile
index 6c80ec39f2..514d0322b9 100644
--- a/railties/guides/source/active_record_validations_callbacks.textile
+++ b/railties/guides/source/active_record_validations_callbacks.textile
@@ -83,6 +83,7 @@ The following methods skip validations, and will save the object to the database
 * +increment_counter+
 * +toggle!+
 * +update_all+
+* +update_attribute+
 * +update_column+
 * +update_counters+
 
@@ -964,6 +965,7 @@ The following methods trigger callbacks:
 * +save(false)+
 * +toggle!+
 * +update+
+* +update_attribute+
 * +update_attributes+
 * +update_attributes!+
 * +valid?+
-- 
cgit v1.2.3


From 62dd3458e326b1f2927d43401e7b10004410fdf0 Mon Sep 17 00:00:00 2001
From: mhutchin <mike@mhutchinson.com>
Date: Sun, 27 Mar 2011 23:50:51 -0700
Subject: Minor typo correction.

---
 railties/guides/source/configuring.textile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'railties')

diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 298335d484..9ca567129b 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -149,7 +149,7 @@ h4. Configuring Middleware
 
 Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
 
-* +Rack::SSL+ Will force every requests to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_.
+* +Rack::SSL+ Will force every request to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_.
 * +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_.
 * +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default.
 * +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
-- 
cgit v1.2.3