diff options
Diffstat (limited to 'railties')
-rw-r--r-- | railties/CHANGELOG.md | 28 | ||||
-rw-r--r-- | railties/lib/rails/application.rb | 39 | ||||
-rw-r--r-- | railties/lib/rails/generators/app_base.rb | 26 | ||||
-rw-r--r-- | railties/lib/rails/generators/rails/app/app_generator.rb | 1 | ||||
-rw-r--r-- | railties/test/application/configuration_test.rb | 35 | ||||
-rw-r--r-- | railties/test/application/initializers/i18n_test.rb | 11 | ||||
-rw-r--r-- | railties/test/generators/app_generator_test.rb | 28 | ||||
-rw-r--r-- | railties/test/generators/shared_generator_tests.rb | 16 |
8 files changed, 169 insertions, 15 deletions
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 6169f3ebee..3813ef7909 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,27 @@ +* Add `Application#message_verifier` method to return a message verifier. + + This verifier can be used to generate and verify signed messages in the application. + + message = Rails.application.message_verifier('salt').generate('my sensible data') + Rails.application.message_verifier('salt').verify(message) + # => 'my sensible data' + + It is recommended not to use the same verifier for different things, so you can get different + verifiers passing the name argument. + + message = Rails.application.message_verifier('cookies').generate('my sensible cookie data') + + See the `ActiveSupport::MessageVerifier` documentation for more information. + + *Rafael Mendonça França* + +* The [Spring application + preloader](https://github.com/jonleighton/spring) is now installed + by default for new applications. It uses the development group of + the Gemfile, so will not be installed in production. + + *Jon Leighton* + * Uses .railsrc while creating new plugin if it is available. Fixes #10700. @@ -153,11 +177,11 @@ *Paul Nikitochkin* * Remove deprecated `ActiveRecord::Generators::ActiveModel#update_attributes` in - favor of `ActiveRecord::Generators::ActiveModel#update` + favor of `ActiveRecord::Generators::ActiveModel#update`. *Vipul A M* -* Remove deprecated `config.whiny_nils` option +* Remove deprecated `config.whiny_nils` option. *Vipul A M* diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb index d1e88cfafd..e45bfaf6fc 100644 --- a/railties/lib/rails/application.rb +++ b/railties/lib/rails/application.rb @@ -1,6 +1,7 @@ require 'fileutils' require 'active_support/core_ext/object/blank' require 'active_support/key_generator' +require 'active_support/message_verifier' require 'rails/engine' module Rails @@ -107,12 +108,13 @@ module Rails def initialize(initial_variable_values = {}, &block) super() - @initialized = false - @reloaders = [] - @routes_reloader = nil - @app_env_config = nil - @ordered_railties = nil - @railties = nil + @initialized = false + @reloaders = [] + @routes_reloader = nil + @app_env_config = nil + @ordered_railties = nil + @railties = nil + @message_verifiers = {} add_lib_to_load_path! ActiveSupport.run_load_hooks(:before_configuration, self) @@ -158,6 +160,31 @@ module Rails end end + # Returns a message verifier object. + # + # This verifier can be used to generate and verify signed messages in the application. + # + # It is recommended not to use the same verifier for different things, so you can get different + # verifiers passing the +verifier_name+ argument. + # + # ==== Parameters + # + # * +salt+ - the salt that will be used to generate the secret key of the verifier. + # + # ==== Examples + # + # message = Rails.application.message_verifier('salt').generate('my sensible data') + # Rails.application.message_verifier('salt').verify(message) + # # => 'my sensible data' + # + # See the +ActiveSupport::MessageVerifier+ documentation for more information. + def message_verifier(salt) + @message_verifiers[salt] ||= begin + secret = key_generator.generate_key(salt) + ActiveSupport::MessageVerifier.new(secret) + end + end + # Stores some of the Rails initial environment parameters which # will be used by middlewares and engines to configure themselves. def env_config diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 2022b4ed3d..5d4682f6e3 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -47,6 +47,9 @@ module Rails class_option :skip_sprockets, type: :boolean, aliases: '-S', default: false, desc: 'Skip Sprockets files' + class_option :skip_spring, type: :boolean, default: false, + desc: "Don't install Spring application preloader" + class_option :database, type: :string, aliases: '-d', default: 'sqlite3', desc: "Preconfigure for selected database (options: #{DATABASES.join('/')})" @@ -109,6 +112,7 @@ module Rails jbuilder_gemfile_entry, sdoc_gemfile_entry, platform_dependent_gemfile_entry, + spring_gemfile_entry, @extra_entries].flatten.find_all(&@gem_filter) end @@ -365,6 +369,12 @@ module Rails end end + def spring_gemfile_entry + return [] unless spring_install? + comment = 'Spring speeds up development by keeping your application running in the background. Read more: https://github.com/jonleighton/spring' + GemfileEntry.new('spring', nil, comment, group: :development) + end + def bundle_command(command) say_status :run, "bundle #{command}" @@ -388,8 +398,22 @@ module Rails end end + def bundle_install? + !(options[:skip_gemfile] || options[:skip_bundle] || options[:pretend]) + end + + def spring_install? + !options[:skip_spring] && Process.respond_to?(:fork) + end + def run_bundle - bundle_command('install') unless options[:skip_gemfile] || options[:skip_bundle] || options[:pretend] + bundle_command('install') if bundle_install? + end + + def generate_spring_binstubs + if bundle_install? && spring_install? + bundle_command("exec spring binstub --all") + end end def empty_directory_with_keep_file(destination, config = {}) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index a2023886cd..87556bd609 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -237,6 +237,7 @@ module Rails public_task :run_bundle public_task :replay_template + public_task :generate_spring_binstubs protected diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 03a735b1c1..722c940d8e 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -268,6 +268,41 @@ module ApplicationTests assert_equal 'some_value', verifier.verify(last_response.body) end + test "application verifier can be used in the entire application" do + make_basic_app do |app| + app.config.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33' + app.config.session_store :disabled + end + + message = app.message_verifier('salt').generate("some_value") + + assert_equal 'some_value', Rails.application.message_verifier('salt').verify(message) + + secret = app.key_generator.generate_key('salt') + verifier = ActiveSupport::MessageVerifier.new(secret) + assert_equal 'some_value', verifier.verify(message) + end + + test "application verifier can build different verifiers" do + make_basic_app do |app| + app.config.secret_key_base = 'b3c631c314c0bbca50c1b2843150fe33' + app.config.session_store :disabled + end + + default_verifier = app.message_verifier('salt') + text_verifier = app.message_verifier('text') + + message = text_verifier.generate('some_value') + + assert_equal 'some_value', text_verifier.verify(message) + assert_raises ActiveSupport::MessageVerifier::InvalidSignature do + default_verifier.verify(message) + end + + assert_equal default_verifier.object_id, app.message_verifier('salt').object_id + assert_not_equal default_verifier.object_id, text_verifier.object_id + end + test "protect from forgery is the default in a new app" do make_basic_app diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb index 97df073ec7..2a64cd8ba7 100644 --- a/railties/test/application/initializers/i18n_test.rb +++ b/railties/test/application/initializers/i18n_test.rb @@ -183,5 +183,16 @@ en: load_app assert_fallbacks ca: [:ca, :"es-ES", :es, :'en-US', :en] end + + test "config.i18n.enforce_available_locales is set before config.i18n.default_locale is" do + add_to_config <<-RUBY + config.i18n.default_locale = :it + config.i18n.enforce_available_locales = true + RUBY + + assert_raises(I18n::InvalidLocale) do + load_app + end + end end end diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 257d07f514..7c2040470f 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -437,6 +437,34 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "foo bar/config/initializers/session_store.rb", /key: '_foo_bar/ end + def test_spring + run_generator + assert_file "Gemfile", /gem 'spring'/ + end + + def test_spring_binstubs + generator.stubs(:bundle_command).with('install') + generator.expects(:bundle_command).with('exec spring binstub --all').once + quietly { generator.invoke_all } + end + + def test_spring_no_fork + Process.stubs(:respond_to?).with(:fork).returns(false) + run_generator + + assert_file "Gemfile" do |content| + assert_no_match(/spring/, content) + end + end + + def test_skip_spring + run_generator [destination_root, "--skip-spring"] + + assert_file "Gemfile" do |content| + assert_no_match(/spring/, content) + end + end + protected def action(*args, &block) diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index 7184639d23..8e198d5fe1 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -26,11 +26,17 @@ module SharedGeneratorTests default_files.each { |path| assert_file path } end - def test_generation_runs_bundle_install - generator([destination_root]).expects(:bundle_command).with('install').once + def assert_generates_with_bundler(options = {}) + generator([destination_root], options) + generator.expects(:bundle_command).with('install').once + generator.stubs(:bundle_command).with('exec spring binstub --all') quietly { generator.invoke_all } end + def test_generation_runs_bundle_install + assert_generates_with_bundler + end + def test_plugin_new_generate_pretend run_generator ["testapp", "--pretend"] default_files.each{ |path| assert_no_file File.join("testapp",path) } @@ -96,15 +102,13 @@ module SharedGeneratorTests end def test_dev_option - generator([destination_root], dev: true).expects(:bundle_command).with('install').once - quietly { generator.invoke_all } + assert_generates_with_bundler dev: true rails_path = File.expand_path('../../..', Rails.root) assert_file 'Gemfile', /^gem\s+["']rails["'],\s+path:\s+["']#{Regexp.escape(rails_path)}["']$/ end def test_edge_option - generator([destination_root], edge: true).expects(:bundle_command).with('install').once - quietly { generator.invoke_all } + assert_generates_with_bundler edge: true assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+github:\s+["']#{Regexp.escape("rails/rails")}["']$} end |