diff options
-rw-r--r-- | actionpack/CHANGELOG.md | 5 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/force_ssl.rb | 69 | ||||
-rw-r--r-- | actionpack/test/controller/api/force_ssl_test.rb | 4 | ||||
-rw-r--r-- | actionpack/test/controller/force_ssl_test.rb | 40 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/preloader/association.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/callbacks.rb | 16 | ||||
-rw-r--r-- | activerecord/lib/active_record/database_configurations.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/spawn_methods.rb | 1 | ||||
-rw-r--r-- | activerecord/test/cases/associations/eager_test.rb | 2 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_many_associations_test.rb | 4 | ||||
-rw-r--r-- | activesupport/lib/active_support/message_encryptor.rb | 1 | ||||
-rw-r--r-- | guides/source/action_controller_overview.md | 22 | ||||
-rw-r--r-- | guides/source/api_app.md | 1 | ||||
-rw-r--r-- | guides/source/upgrading_ruby_on_rails.md | 11 | ||||
-rw-r--r-- | railties/lib/rails/generators.rb | 4 |
15 files changed, 73 insertions, 115 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 61451dd673..9835733b17 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,8 @@ +* Controller level `force_ssl` has been deprecated in favor of + `config.force_ssl`. + + *Derek Prior* + * Rails 6 requires Ruby 2.4.1 or newer. *Jeremy Daer* diff --git a/actionpack/lib/action_controller/metal/force_ssl.rb b/actionpack/lib/action_controller/metal/force_ssl.rb index 7de500d119..8d53a30e93 100644 --- a/actionpack/lib/action_controller/metal/force_ssl.rb +++ b/actionpack/lib/action_controller/metal/force_ssl.rb @@ -4,18 +4,10 @@ require "active_support/core_ext/hash/except" require "active_support/core_ext/hash/slice" module ActionController - # This module provides a method which will redirect the browser to use the secured HTTPS - # protocol. This will ensure that users' sensitive information will be - # transferred safely over the internet. You _should_ always force the browser - # to use HTTPS when you're transferring sensitive information such as - # user authentication, account information, or credit card information. - # - # Note that if you are really concerned about your application security, - # you might consider using +config.force_ssl+ in your config file instead. - # That will ensure all the data is transferred via HTTPS, and will - # prevent the user from getting their session hijacked when accessing the - # site over unsecured HTTP protocol. - module ForceSSL + # This module is deprecated in favor of +config.force_ssl+ in your environment + # config file. This will ensure all communication to non-whitelisted endpoints + # served by your application occurs over HTTPS. + module ForceSSL # :nodoc: extend ActiveSupport::Concern include AbstractController::Callbacks @@ -23,45 +15,17 @@ module ActionController URL_OPTIONS = [:protocol, :host, :domain, :subdomain, :port, :path] REDIRECT_OPTIONS = [:status, :flash, :alert, :notice] - module ClassMethods - # Force the request to this particular controller or specified actions to be - # through the HTTPS protocol. - # - # If you need to disable this for any reason (e.g. development) then you can use - # an +:if+ or +:unless+ condition. - # - # class AccountsController < ApplicationController - # force_ssl if: :ssl_configured? - # - # def ssl_configured? - # !Rails.env.development? - # end - # end - # - # ==== URL Options - # You can pass any of the following options to affect the redirect URL - # * <tt>host</tt> - Redirect to a different host name - # * <tt>subdomain</tt> - Redirect to a different subdomain - # * <tt>domain</tt> - Redirect to a different domain - # * <tt>port</tt> - Redirect to a non-standard port - # * <tt>path</tt> - Redirect to a different path - # - # ==== Redirect Options - # You can pass any of the following options to affect the redirect status and response - # * <tt>status</tt> - Redirect with a custom status (default is 301 Moved Permanently) - # * <tt>flash</tt> - Set a flash message when redirecting - # * <tt>alert</tt> - Set an alert message when redirecting - # * <tt>notice</tt> - Set a notice message when redirecting - # - # ==== Action Options - # You can pass any of the following options to affect the before_action callback - # * <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 - # * <tt>if</tt> - A symbol naming an instance method or a proc; the - # callback will be called only when it returns a true value. - # * <tt>unless</tt> - A symbol naming an instance method or a proc; the - # callback will be called only when it returns a false value. + module ClassMethods # :nodoc: def force_ssl(options = {}) + ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) + Controller-level `force_ssl` is deprecated and will be removed from + Rails 6.1. Please enable `config.force_ssl` in your environment + configuration to enable the ActionDispatch::SSL middleware to more + fully enforce that your application communicate over HTTPS. If needed, + you can use `config.ssl_options` to exempt matching endpoints from + being redirected to HTTPS. + MESSAGE + action_options = options.slice(*ACTION_OPTIONS) redirect_options = options.except(*ACTION_OPTIONS) before_action(action_options) do @@ -70,11 +34,6 @@ module ActionController end end - # Redirect the existing request to use the HTTPS protocol. - # - # ==== Parameters - # * <tt>host_or_options</tt> - Either a host name or any of the URL and - # redirect options available to the <tt>force_ssl</tt> method. def force_ssl_redirect(host_or_options = nil) unless request.ssl? options = { diff --git a/actionpack/test/controller/api/force_ssl_test.rb b/actionpack/test/controller/api/force_ssl_test.rb index 07459c3753..8191578eb0 100644 --- a/actionpack/test/controller/api/force_ssl_test.rb +++ b/actionpack/test/controller/api/force_ssl_test.rb @@ -3,7 +3,9 @@ require "abstract_unit" class ForceSSLApiController < ActionController::API - force_ssl + ActiveSupport::Deprecation.silence do + force_ssl + end def one; end def two diff --git a/actionpack/test/controller/force_ssl_test.rb b/actionpack/test/controller/force_ssl_test.rb index 84ac1fda3c..7f59f6acaf 100644 --- a/actionpack/test/controller/force_ssl_test.rb +++ b/actionpack/test/controller/force_ssl_test.rb @@ -13,19 +13,23 @@ class ForceSSLController < ActionController::Base end class ForceSSLControllerLevel < ForceSSLController - force_ssl + ActiveSupport::Deprecation.silence do + force_ssl + end end class ForceSSLCustomOptions < ForceSSLController - force_ssl host: "secure.example.com", only: :redirect_host - force_ssl port: 8443, only: :redirect_port - force_ssl subdomain: "secure", only: :redirect_subdomain - force_ssl domain: "secure.com", only: :redirect_domain - force_ssl path: "/foo", only: :redirect_path - force_ssl status: :found, only: :redirect_status - force_ssl flash: { message: "Foo, Bar!" }, only: :redirect_flash - force_ssl alert: "Foo, Bar!", only: :redirect_alert - force_ssl notice: "Foo, Bar!", only: :redirect_notice + ActiveSupport::Deprecation.silence do + force_ssl host: "secure.example.com", only: :redirect_host + force_ssl port: 8443, only: :redirect_port + force_ssl subdomain: "secure", only: :redirect_subdomain + force_ssl domain: "secure.com", only: :redirect_domain + force_ssl path: "/foo", only: :redirect_path + force_ssl status: :found, only: :redirect_status + force_ssl flash: { message: "Foo, Bar!" }, only: :redirect_flash + force_ssl alert: "Foo, Bar!", only: :redirect_alert + force_ssl notice: "Foo, Bar!", only: :redirect_notice + end def force_ssl_action render plain: action_name @@ -55,15 +59,21 @@ class ForceSSLCustomOptions < ForceSSLController end class ForceSSLOnlyAction < ForceSSLController - force_ssl only: :cheeseburger + ActiveSupport::Deprecation.silence do + force_ssl only: :cheeseburger + end end class ForceSSLExceptAction < ForceSSLController - force_ssl except: :banana + ActiveSupport::Deprecation.silence do + force_ssl except: :banana + end end class ForceSSLIfCondition < ForceSSLController - force_ssl if: :use_force_ssl? + ActiveSupport::Deprecation.silence do + force_ssl if: :use_force_ssl? + end def use_force_ssl? action_name == "cheeseburger" @@ -71,7 +81,9 @@ class ForceSSLIfCondition < ForceSSLController end class ForceSSLFlash < ForceSSLController - force_ssl except: [:banana, :set_flash, :use_flash] + ActiveSupport::Deprecation.silence do + force_ssl except: [:banana, :set_flash, :use_flash] + end def set_flash flash["that"] = "hello" diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 0f38d6bbda..d6f7359055 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -42,11 +42,11 @@ module ActiveRecord def associate_records_to_owner(owner, records) association = owner.association(reflection.name) + association.loaded! if reflection.collection? - association.loaded! association.target.concat(records) else - association.target = records.first + association.target = records.first unless records.empty? end end diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 9dbdf845bd..fd6819d08f 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -75,21 +75,7 @@ module ActiveRecord # end # # Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is - # run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation - # where the +before_destroy+ method is overridden: - # - # class Topic < ActiveRecord::Base - # def before_destroy() destroy_author end - # end - # - # class Reply < Topic - # def before_destroy() destroy_readers end - # end - # - # In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+. - # So, use the callback macros when you want to ensure that a certain callback is called for the entire - # hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant - # to decide whether they want to call +super+ and trigger the inherited callbacks. + # run, both +destroy_author+ and +destroy_readers+ are called. # # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the # callbacks before specifying the associations. Otherwise, you might trigger the loading of a diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb index 86624a41c9..1c7a5d1347 100644 --- a/activerecord/lib/active_record/database_configurations.rb +++ b/activerecord/lib/active_record/database_configurations.rb @@ -46,8 +46,8 @@ module ActiveRecord if config["database"] || env_name == "default" DatabaseConfig.new(env_name, spec_name, config) else - config.each_pair.map do |spec_name, sub_config| - walk_configs(env_name, spec_name, sub_config) + config.each_pair.map do |sub_spec_name, sub_config| + walk_configs(env_name, sub_spec_name, sub_config) end end end diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index 562e04194c..b092399657 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -10,6 +10,7 @@ module ActiveRecord def spawn #:nodoc: clone end + alias :all :spawn # Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation. # Returns an array representing the intersection of the resulting records with <tt>other</tt>, if <tt>other</tt> is an array. diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index f18c6177ac..6e0cf30092 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -1218,6 +1218,7 @@ class EagerAssociationTest < ActiveRecord::TestCase client = assert_queries(2) { Client.preload(:firm).find(c.id) } assert_no_queries { assert_nil client.firm } + assert_equal c.client_of, client.client_of end def test_preloading_empty_belongs_to_polymorphic @@ -1225,6 +1226,7 @@ class EagerAssociationTest < ActiveRecord::TestCase tagging = assert_queries(2) { Tagging.preload(:taggable).find(t.id) } assert_no_queries { assert_nil tagging.taggable } + assert_equal t.taggable_id, tagging.taggable_id end def test_preloading_through_empty_belongs_to diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 00821f2319..a64432fae7 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -497,8 +497,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase person = Person.new person.first_name = "Naruto" person.references << Reference.new - person.id = 10 - person.references person.save! assert_equal 1, person.references.update_all(favourite: true) end @@ -507,8 +505,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase person = Person.new person.first_name = "Sasuke" person.references << Reference.new - person.id = 10 - person.references person.save! assert_predicate person.references, :exists? end diff --git a/activesupport/lib/active_support/message_encryptor.rb b/activesupport/lib/active_support/message_encryptor.rb index 5236c776dd..8b73270894 100644 --- a/activesupport/lib/active_support/message_encryptor.rb +++ b/activesupport/lib/active_support/message_encryptor.rb @@ -3,6 +3,7 @@ require "openssl" require "base64" require "active_support/core_ext/array/extract_options" +require "active_support/core_ext/module/attribute_accessors" require "active_support/message_verifier" require "active_support/messages/metadata" diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md index 5b421756e8..e0e85588a0 100644 --- a/guides/source/action_controller_overview.md +++ b/guides/source/action_controller_overview.md @@ -1181,22 +1181,6 @@ NOTE: Certain exceptions are only rescuable from the `ApplicationController` cla Force HTTPS protocol -------------------- -Sometime you might want to force a particular controller to only be accessible via an HTTPS protocol for security reasons. You can use the `force_ssl` method in your controller to enforce that: - -```ruby -class DinnerController - force_ssl -end -``` - -Just like the filter, you could also pass `: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 -``` - -Please note that if you find yourself adding `force_ssl` to many controllers, you may want to force the whole application to use HTTPS instead. In that case, you can set the `config.force_ssl` in your environment file. +If you'd like to ensure that communication to your controller is only possible +via HTTPS, you should do so by enabling the `ActionDispatch::SSL` middleware via +`config.force_ssl` in your environment configuration. diff --git a/guides/source/api_app.md b/guides/source/api_app.md index b4d90d31de..2270eb6584 100644 --- a/guides/source/api_app.md +++ b/guides/source/api_app.md @@ -375,7 +375,6 @@ controller modules by default: - `ActionController::ConditionalGet`: Support for `stale?`. - `ActionController::BasicImplicitRender`: Makes sure to return an empty response, if there isn't an explicit one. - `ActionController::StrongParameters`: Support for parameters white-listing in combination with Active Model mass assignment. -- `ActionController::ForceSSL`: Support for `force_ssl`. - `ActionController::DataStreaming`: Support for `send_file` and `send_data`. - `AbstractController::Callbacks`: Support for `before_action` and similar helpers. diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index d5dfaef591..c2fe012eeb 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -66,6 +66,17 @@ Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh] Don't forget to review the difference, to see if there were any unexpected changes. +Upgrading from Rails 5.2 to Rails 6.0 +------------------------------------- + +### Force SSL + +The `force_ssl` method on controllers has been deprecated and will be removed in +Rails 6.1. You are encouraged to enable `config.force_ssl` to enforce HTTPS +connections throughout your application. If you need to exempt certain endpoints +from redirection, you can use `config.ssl_options` to configure that behavior. + + Upgrading from Rails 5.1 to Rails 5.2 ------------------------------------- diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index f468d82f14..f8460bd4ee 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -278,8 +278,8 @@ module Rails options = sorted_groups.flat_map(&:last) suggestion = Rails::Command::Spellchecker.suggest(namespace.to_s, from: options) puts <<~MSG - Could not find generator '#{namespace}'. Maybe you meant #{suggestion.inspect}?\n" - Run `rails generate --help` for more options." + Could not find generator '#{namespace}'. Maybe you meant #{suggestion.inspect}? + Run `rails generate --help` for more options. MSG end end |