aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib')
-rw-r--r--railties/lib/rails/application.rb11
-rw-r--r--railties/lib/rails/application/configuration.rb26
-rw-r--r--railties/lib/rails/commands/credentials/USAGE9
-rw-r--r--railties/lib/rails/commands/credentials/credentials_command.rb63
-rw-r--r--railties/lib/rails/commands/dbconsole/dbconsole_command.rb2
-rw-r--r--railties/lib/rails/engine.rb16
-rw-r--r--railties/lib/rails/engine/configuration.rb2
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/lib/rails/generators/generated_attribute.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt3
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt3
-rw-r--r--railties/lib/rails/info.rb2
-rw-r--r--railties/lib/rails/mailers_controller.rb2
-rw-r--r--railties/lib/rails/source_annotation_extractor.rb2
-rw-r--r--railties/lib/rails/tasks/yarn.rake2
-rw-r--r--railties/lib/rails/test_unit/runner.rb8
17 files changed, 113 insertions, 44 deletions
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 99e42ebefb..656786246d 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -232,7 +232,10 @@ module Rails
if yaml.exist?
require "erb"
- (YAML.load(ERB.new(yaml.read).result) || {})[env] || {}
+ require "active_support/ordered_options"
+
+ config = (YAML.load(ERB.new(yaml.read).result) || {})[env] || {}
+ ActiveSupport::InheritableOptions.new(config.deep_symbolize_keys)
else
raise "Could not load configuration. No such file - #{yaml}"
end
@@ -435,8 +438,12 @@ module Rails
# Decrypts the credentials hash as kept in +config/credentials.yml.enc+. This file is encrypted with
# the Rails master key, which is either taken from <tt>ENV["RAILS_MASTER_KEY"]</tt> or from loading
# +config/master.key+.
+ # If specific credentials file exists for current environment, it takes precedence, thus for +production+
+ # environment look first for +config/credentials/production.yml.enc+ with master key taken
+ # from <tt>ENV["RAILS_MASTER_KEY"]</tt> or from loading +config/credentials/production.key+.
+ # Default behavior can be overwritten by setting +config.credentials.content_path+ and +config.credentials.key_path+.
def credentials
- @credentials ||= encrypted("config/credentials.yml.enc")
+ @credentials ||= encrypted(config.credentials.content_path, key_path: config.credentials.key_path)
end
# Shorthand to decrypt any encrypted configurations or files.
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index f4cbd2b9d0..eae902a938 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -17,7 +17,7 @@ module Rails
:session_options, :time_zone, :reload_classes_only_on_change,
:beginning_of_week, :filter_redirect, :x, :enable_dependency_loading,
:read_encrypted_secrets, :log_level, :content_security_policy_report_only,
- :content_security_policy_nonce_generator, :require_master_key
+ :content_security_policy_nonce_generator, :require_master_key, :credentials
attr_reader :encoding, :api_only, :loaded_config_version
@@ -60,6 +60,9 @@ module Rails
@content_security_policy_nonce_generator = nil
@require_master_key = false
@loaded_config_version = nil
+ @credentials = ActiveSupport::OrderedOptions.new
+ @credentials.content_path = default_credentials_content_path
+ @credentials.key_path = default_credentials_key_path
end
def load_defaults(target_version)
@@ -273,6 +276,27 @@ module Rails
true
end
end
+
+ private
+ def credentials_available_for_current_env?
+ File.exist?("#{root}/config/credentials/#{Rails.env}.yml.enc")
+ end
+
+ def default_credentials_content_path
+ if credentials_available_for_current_env?
+ File.join(root, "config", "credentials", "#{Rails.env}.yml.enc")
+ else
+ File.join(root, "config", "credentials.yml.enc")
+ end
+ end
+
+ def default_credentials_key_path
+ if credentials_available_for_current_env?
+ File.join(root, "config", "credentials", "#{Rails.env}.key")
+ else
+ File.join(root, "config", "master.key")
+ end
+ end
end
end
end
diff --git a/railties/lib/rails/commands/credentials/USAGE b/railties/lib/rails/commands/credentials/USAGE
index ea429f58d8..6b33d1ab74 100644
--- a/railties/lib/rails/commands/credentials/USAGE
+++ b/railties/lib/rails/commands/credentials/USAGE
@@ -38,3 +38,12 @@ the encrypted credentials.
When the temporary file is next saved the contents are encrypted and written to
`config/credentials.yml.enc` while the file itself is destroyed to prevent credentials
from leaking.
+
+=== Environment Specific Credentials
+
+It is possible to have credentials for each environment. If the file for current environment exists it will take
+precedence over `config/credentials.yml.enc`, thus for `production` environment first look for
+`config/credentials/production.yml.enc` that can be decrypted using master key taken from `ENV["RAILS_MASTER_KEY"]`
+or stored in `config/credentials/production.key`.
+To edit given file use command `rails credentials:edit --environment production`
+Default paths can be overwritten by setting `config.credentials.content_path` and `config.credentials.key_path`.
diff --git a/railties/lib/rails/commands/credentials/credentials_command.rb b/railties/lib/rails/commands/credentials/credentials_command.rb
index 65c5218fc8..4b30d208e0 100644
--- a/railties/lib/rails/commands/credentials/credentials_command.rb
+++ b/railties/lib/rails/commands/credentials/credentials_command.rb
@@ -8,6 +8,9 @@ module Rails
class CredentialsCommand < Rails::Command::Base # :nodoc:
include Helpers::Editor
+ class_option :environment, aliases: "-e", type: :string,
+ desc: "Uses credentials from config/credentials/:environment.yml.enc encrypted by config/credentials/:environment.key key"
+
no_commands do
def help
say "Usage:\n #{self.class.banner}"
@@ -20,58 +23,74 @@ module Rails
require_application_and_environment!
ensure_editor_available(command: "bin/rails credentials:edit") || (return)
- ensure_master_key_has_been_added if Rails.application.credentials.key.nil?
- ensure_credentials_have_been_added
+
+ encrypted = Rails.application.encrypted(content_path, key_path: key_path)
+
+ ensure_encryption_key_has_been_added(key_path) if encrypted.key.nil?
+ ensure_encrypted_file_has_been_added(content_path, key_path)
catch_editing_exceptions do
- change_credentials_in_system_editor
+ change_encrypted_file_in_system_editor(content_path, key_path)
end
- say "New credentials encrypted and saved."
+ say "File encrypted and saved."
+ rescue ActiveSupport::MessageEncryptor::InvalidMessage
+ say "Couldn't decrypt #{content_path}. Perhaps you passed the wrong key?"
end
def show
require_application_and_environment!
- say Rails.application.credentials.read.presence || missing_credentials_message
+ encrypted = Rails.application.encrypted(content_path, key_path: key_path)
+
+ say encrypted.read.presence || missing_encrypted_message(key: encrypted.key, key_path: key_path, file_path: content_path)
end
private
- def ensure_master_key_has_been_added
- master_key_generator.add_master_key_file
- master_key_generator.ignore_master_key_file
+ def content_path
+ options[:environment] ? "config/credentials/#{options[:environment]}.yml.enc" : "config/credentials.yml.enc"
+ end
+
+ def key_path
+ options[:environment] ? "config/credentials/#{options[:environment]}.key" : "config/master.key"
+ end
+
+
+ def ensure_encryption_key_has_been_added(key_path)
+ encryption_key_file_generator.add_key_file(key_path)
+ encryption_key_file_generator.ignore_key_file(key_path)
end
- def ensure_credentials_have_been_added
- credentials_generator.add_credentials_file_silently
+ def ensure_encrypted_file_has_been_added(file_path, key_path)
+ encrypted_file_generator.add_encrypted_file_silently(file_path, key_path)
end
- def change_credentials_in_system_editor
- Rails.application.credentials.change do |tmp_path|
+ def change_encrypted_file_in_system_editor(file_path, key_path)
+ Rails.application.encrypted(file_path, key_path: key_path).change do |tmp_path|
system("#{ENV["EDITOR"]} #{tmp_path}")
end
end
- def master_key_generator
+ def encryption_key_file_generator
require "rails/generators"
- require "rails/generators/rails/master_key/master_key_generator"
+ require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"
- Rails::Generators::MasterKeyGenerator.new
+ Rails::Generators::EncryptionKeyFileGenerator.new
end
- def credentials_generator
+ def encrypted_file_generator
require "rails/generators"
- require "rails/generators/rails/credentials/credentials_generator"
+ require "rails/generators/rails/encrypted_file/encrypted_file_generator"
- Rails::Generators::CredentialsGenerator.new
+ Rails::Generators::EncryptedFileGenerator.new
end
- def missing_credentials_message
- if Rails.application.credentials.key.nil?
- "Missing master key to decrypt credentials. See `rails credentials:help`"
+ def missing_encrypted_message(key:, key_path:, file_path:)
+ if key.nil?
+ "Missing '#{key_path}' to decrypt credentials. See `rails credentials:help`"
else
- "No credentials have been added yet. Use `rails credentials:edit` to change that."
+ "File '#{file_path}' does not exist. Use `rails credentials:edit` to change that."
end
end
end
diff --git a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
index 806b7de6d6..0fac7d34a0 100644
--- a/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
+++ b/railties/lib/rails/commands/dbconsole/dbconsole_command.rb
@@ -75,7 +75,7 @@ module Rails
args += ["-P", "#{config['password']}"] if config["password"]
if config["host"]
- host_arg = "#{config['host']}".dup
+ host_arg = +"#{config['host']}"
host_arg << ":#{config['port']}" if config["port"]
args += ["-S", host_arg]
end
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 6a13a84108..901934826b 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -403,6 +403,12 @@ module Rails
define_method(:railtie_helpers_paths) { railtie.helpers_paths }
end
+ unless mod.respond_to?(:railtie_include_helpers)
+ define_method(:railtie_include_helpers) { |klass, include_path_helpers|
+ railtie.routes.include_helpers(klass, include_path_helpers)
+ }
+ end
+
unless mod.respond_to?(:railtie_routes_url_helpers)
define_method(:railtie_routes_url_helpers) { |include_path_helpers = true| railtie.routes.url_helpers(include_path_helpers) }
end
@@ -473,9 +479,13 @@ module Rails
# files inside eager_load paths.
def eager_load!
config.eager_load_paths.each do |load_path|
- matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/
- Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
- require_dependency file.sub(matcher, '\1')
+ if File.file?(load_path)
+ require_dependency load_path
+ else
+ matcher = /\A#{Regexp.escape(load_path.to_s)}\/(.*)\.rb\Z/
+ Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
+ require_dependency file.sub(matcher, '\1')
+ end
end
end
end
diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb
index 6bf0406b21..7595272c03 100644
--- a/railties/lib/rails/engine/configuration.rb
+++ b/railties/lib/rails/engine/configuration.rb
@@ -38,6 +38,7 @@ module Rails
@paths ||= begin
paths = Rails::Paths::Root.new(@root)
+ paths.add "config/routes.rb", eager_load: true
paths.add "app", eager_load: true, glob: "{*,*/concerns}"
paths.add "app/assets", glob: "*"
paths.add "app/controllers", eager_load: true
@@ -55,7 +56,6 @@ module Rails
paths.add "config/environments", glob: "#{Rails.env}.rb"
paths.add "config/initializers", glob: "**/*.rb"
paths.add "config/locales", glob: "*.{rb,yml}"
- paths.add "config/routes.rb"
paths.add "db"
paths.add "db/migrate"
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index a6dc60342c..8991c547ca 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -299,7 +299,7 @@ module Rails
def gem_for_database
# %w( mysql postgresql sqlite3 oracle frontbase ibm_db sqlserver jdbcmysql jdbcsqlite3 jdbcpostgresql )
case options[:database]
- when "mysql" then ["mysql2", [">= 0.4.4", "< 0.6.0"]]
+ when "mysql" then ["mysql2", [">= 0.4.4"]]
when "postgresql" then ["pg", [">= 0.18", "< 2.0"]]
when "oracle" then ["activerecord-oracle_enhanced-adapter", nil]
when "frontbase" then ["ruby-frontbase", nil]
diff --git a/railties/lib/rails/generators/generated_attribute.rb b/railties/lib/rails/generators/generated_attribute.rb
index f7fd30a5fb..3f20f5a718 100644
--- a/railties/lib/rails/generators/generated_attribute.rb
+++ b/railties/lib/rails/generators/generated_attribute.rb
@@ -153,7 +153,7 @@ module Rails
end
def inject_options
- "".dup.tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } }
+ (+"").tap { |s| options_for_migration.each { |k, v| s << ", #{k}: #{v.inspect}" } }
end
def inject_index_options
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt
index 97f9a92ff3..f39593372c 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt
@@ -1,4 +1,4 @@
-# MySQL. Versions 5.1.10 and up are supported.
+# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver:
# gem install activerecord-jdbcmysql-adapter
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt
index 1dc508b14f..5860563908 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt
@@ -1,4 +1,4 @@
-# MySQL. Versions 5.1.10 and up are supported.
+# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
@@ -11,7 +11,6 @@
#
default: &default
adapter: mysql2
- encoding: utf8
pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password:
diff --git a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt
index 755d19ef5d..4f7a8d3d6e 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt
+++ b/railties/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt
@@ -10,8 +10,7 @@ ActiveRecord::Migrator.migrations_paths << File.expand_path('../db/migrate', __d
<% end -%>
require "rails/test_help"
-# Filter out Minitest backtrace while allowing backtrace from other libraries
-# to be shown.
+# Filter out the backtrace from minitest while preserving the one from other libraries.
Minitest.backtrace_filter = Minitest::BacktraceFilter.new
<% unless engine? -%>
diff --git a/railties/lib/rails/info.rb b/railties/lib/rails/info.rb
index d5c9973c6b..3df36efc4c 100644
--- a/railties/lib/rails/info.rb
+++ b/railties/lib/rails/info.rb
@@ -41,7 +41,7 @@ module Rails
alias inspect to_s
def to_html
- "<table>".dup.tap do |table|
+ (+"<table>").tap do |table|
properties.each do |(name, value)|
table << %(<tr><td class="name">#{CGI.escapeHTML(name.to_s)}</td>)
formatted_value = if value.kind_of?(Array)
diff --git a/railties/lib/rails/mailers_controller.rb b/railties/lib/rails/mailers_controller.rb
index 0b0e802358..e2d36d7654 100644
--- a/railties/lib/rails/mailers_controller.rb
+++ b/railties/lib/rails/mailers_controller.rb
@@ -10,6 +10,8 @@ class Rails::MailersController < Rails::ApplicationController # :nodoc:
helper_method :part_query, :locale_query
+ content_security_policy(false)
+
def index
@previews = ActionMailer::Preview.all
@page_title = "Mailer Previews"
diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb
index 2d66a4dc7d..d7170e6282 100644
--- a/railties/lib/rails/source_annotation_extractor.rb
+++ b/railties/lib/rails/source_annotation_extractor.rb
@@ -50,7 +50,7 @@ module Rails
# If +options+ has a flag <tt>:tag</tt> the tag is shown as in the example above.
# Otherwise the string contains just line and text.
def to_s(options = {})
- s = "[#{line.to_s.rjust(options[:indent])}] ".dup
+ s = +"[#{line.to_s.rjust(options[:indent])}] "
s << "[#{tag}] " if options[:tag]
s << text
end
diff --git a/railties/lib/rails/tasks/yarn.rake b/railties/lib/rails/tasks/yarn.rake
index cf45a392e8..4fb8586b69 100644
--- a/railties/lib/rails/tasks/yarn.rake
+++ b/railties/lib/rails/tasks/yarn.rake
@@ -9,7 +9,7 @@ namespace :yarn do
rails_env = ENV["RAILS_ENV"]
valid_node_envs.include?(rails_env) ? rails_env : "production"
end
- system({ "NODE_ENV" => node_env }, "./bin/yarn install --no-progress --frozen-lockfile")
+ system({ "NODE_ENV" => node_env }, "#{Rails.root}/bin/yarn install --no-progress --frozen-lockfile")
end
end
diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb
index 2fa7573bdf..d38952bb30 100644
--- a/railties/lib/rails/test_unit/runner.rb
+++ b/railties/lib/rails/test_unit/runner.rb
@@ -12,8 +12,8 @@ module Rails
class << self
def attach_before_load_options(opts)
- opts.on("--warnings", "-w", "Run with Ruby warnings enabled") {}
- opts.on("-e", "--environment ENV", "Run tests in the ENV environment") {}
+ opts.on("--warnings", "-w", "Run with Ruby warnings enabled") { }
+ opts.on("-e", "--environment ENV", "Run tests in the ENV environment") { }
end
def parse_options(argv)
@@ -87,7 +87,7 @@ module Rails
@filters = [ @named_filter, *derive_line_filters(patterns) ].compact
end
- # Minitest uses === to find matching filters.
+ # minitest uses === to find matching filters.
def ===(method)
@filters.any? { |filter| filter === method }
end
@@ -96,7 +96,7 @@ module Rails
def derive_named_filter(filter)
if filter.respond_to?(:named_filter)
filter.named_filter
- elsif filter =~ %r%/(.*)/% # Regexp filtering copied from Minitest.
+ elsif filter =~ %r%/(.*)/% # Regexp filtering copied from minitest.
Regexp.new $1
elsif filter.is_a?(String)
filter