railties 7.0.8.7 → 7.1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +723 -215
- data/MIT-LICENSE +1 -1
- data/RDOC_MAIN.md +99 -0
- data/README.rdoc +4 -4
- data/lib/minitest/rails_plugin.rb +63 -0
- data/lib/rails/api/task.rb +35 -4
- data/lib/rails/app_updater.rb +14 -2
- data/lib/rails/application/bootstrap.rb +23 -4
- data/lib/rails/application/configuration.rb +190 -69
- data/lib/rails/application/default_middleware_stack.rb +8 -2
- data/lib/rails/application/dummy_config.rb +19 -0
- data/lib/rails/application/finisher.rb +43 -33
- data/lib/rails/application.rb +141 -33
- data/lib/rails/backtrace_cleaner.rb +5 -3
- data/lib/rails/cli.rb +5 -2
- data/lib/rails/command/actions.rb +10 -12
- data/lib/rails/command/base.rb +55 -53
- data/lib/rails/command/environment_argument.rb +32 -16
- data/lib/rails/command/helpers/editor.rb +17 -12
- data/lib/rails/command.rb +84 -33
- data/lib/rails/commands/about/about_command.rb +14 -0
- data/lib/rails/commands/application/application_command.rb +2 -0
- data/lib/rails/commands/console/console_command.rb +14 -14
- data/lib/rails/commands/credentials/USAGE +53 -55
- data/lib/rails/commands/credentials/credentials_command/diffing.rb +5 -3
- data/lib/rails/commands/credentials/credentials_command.rb +64 -70
- data/lib/rails/commands/db/system/change/change_command.rb +2 -1
- data/lib/rails/commands/dbconsole/dbconsole_command.rb +25 -115
- data/lib/rails/commands/destroy/destroy_command.rb +3 -2
- data/lib/rails/commands/dev/dev_command.rb +1 -6
- data/lib/rails/commands/encrypted/USAGE +15 -20
- data/lib/rails/commands/encrypted/encrypted_command.rb +46 -35
- data/lib/rails/commands/gem_help/USAGE +16 -0
- data/lib/rails/commands/gem_help/gem_help_command.rb +13 -0
- data/lib/rails/commands/generate/generate_command.rb +2 -2
- data/lib/rails/commands/help/USAGE +13 -13
- data/lib/rails/commands/help/help_command.rb +21 -2
- data/lib/rails/commands/initializers/initializers_command.rb +1 -4
- data/lib/rails/commands/middleware/middleware_command.rb +17 -0
- data/lib/rails/commands/new/new_command.rb +2 -0
- data/lib/rails/commands/notes/notes_command.rb +2 -1
- data/lib/rails/commands/plugin/plugin_command.rb +2 -0
- data/lib/rails/commands/rake/rake_command.rb +25 -22
- data/lib/rails/commands/restart/restart_command.rb +14 -0
- data/lib/rails/commands/routes/routes_command.rb +13 -1
- data/lib/rails/commands/runner/USAGE +14 -12
- data/lib/rails/commands/runner/runner_command.rb +32 -20
- data/lib/rails/commands/secret/secret_command.rb +13 -0
- data/lib/rails/commands/secrets/USAGE +44 -49
- data/lib/rails/commands/secrets/secrets_command.rb +20 -38
- data/lib/rails/commands/server/server_command.rb +33 -32
- data/lib/rails/commands/test/USAGE +14 -0
- data/lib/rails/commands/test/test_command.rb +56 -14
- data/lib/rails/commands/unused_routes/unused_routes_command.rb +75 -0
- data/lib/rails/commands/version/version_command.rb +1 -0
- data/lib/rails/configuration.rb +5 -5
- data/lib/rails/console/app.rb +1 -4
- data/lib/rails/deprecator.rb +7 -0
- data/lib/rails/engine/configuration.rb +50 -6
- data/lib/rails/engine.rb +49 -21
- data/lib/rails/gem_version.rb +4 -4
- data/lib/rails/generators/actions.rb +6 -15
- data/lib/rails/generators/active_model.rb +28 -14
- data/lib/rails/generators/app_base.rb +355 -82
- data/lib/rails/generators/app_name.rb +3 -14
- data/lib/rails/generators/base.rb +17 -9
- data/lib/rails/generators/database.rb +40 -2
- data/lib/rails/generators/erb/mailer/templates/layout.html.erb.tt +1 -1
- data/lib/rails/generators/generated_attribute.rb +12 -0
- data/lib/rails/generators/migration.rb +4 -5
- data/lib/rails/generators/model_helpers.rb +2 -1
- data/lib/rails/generators/rails/app/USAGE +22 -6
- data/lib/rails/generators/rails/app/app_generator.rb +85 -64
- data/lib/rails/generators/rails/app/templates/Dockerfile.tt +103 -0
- data/lib/rails/generators/rails/app/templates/Gemfile.tt +9 -11
- data/lib/rails/generators/rails/app/templates/app/views/layouts/mailer.html.erb.tt +1 -1
- data/lib/rails/generators/rails/app/templates/bin/setup.tt +10 -1
- data/lib/rails/generators/rails/app/templates/config/application.rb.tt +6 -17
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +4 -4
- data/lib/rails/generators/rails/app/templates/config/databases/jdbcsqlite3.yml.tt +3 -3
- data/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +4 -6
- data/lib/rails/generators/rails/app/templates/config/databases/sqlite3.yml.tt +3 -3
- data/lib/rails/generators/rails/app/templates/config/databases/trilogy.yml.tt +59 -0
- data/lib/rails/generators/rails/app/templates/config/environments/development.rb.tt +12 -2
- data/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt +32 -28
- data/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt +13 -9
- data/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +2 -0
- data/lib/rails/generators/rails/app/templates/config/initializers/content_security_policy.rb.tt +2 -2
- data/lib/rails/generators/rails/app/templates/config/initializers/cors.rb.tt +1 -1
- data/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb.tt +3 -3
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_1.rb.tt +280 -0
- data/lib/rails/generators/rails/app/templates/config/initializers/permissions_policy.rb.tt +11 -9
- data/lib/rails/generators/rails/app/templates/config/locales/en.yml +11 -13
- data/lib/rails/generators/rails/app/templates/config/puma.rb.tt +21 -20
- data/lib/rails/generators/rails/app/templates/config/routes.rb.tt +5 -1
- data/lib/rails/generators/rails/app/templates/db/seeds.rb.tt +6 -4
- data/lib/rails/generators/rails/app/templates/docker-entrypoint.tt +10 -0
- data/lib/rails/generators/rails/app/templates/dockerignore.tt +43 -0
- data/lib/rails/generators/rails/app/templates/gitignore.tt +4 -8
- data/lib/rails/generators/rails/app/templates/node-version.tt +1 -0
- data/lib/rails/generators/rails/app/templates/test/channels/application_cable/connection_test.rb.tt +10 -8
- data/lib/rails/generators/rails/app/templates/test/test_helper.rb.tt +9 -7
- data/lib/rails/generators/rails/application_record/application_record_generator.rb +4 -0
- data/lib/rails/generators/rails/benchmark/benchmark_generator.rb +2 -1
- data/lib/rails/generators/rails/controller/USAGE +12 -4
- data/lib/rails/generators/rails/controller/controller_generator.rb +5 -0
- data/lib/rails/generators/rails/controller/templates/controller.rb.tt +1 -1
- data/lib/rails/generators/rails/credentials/credentials_generator.rb +29 -24
- data/lib/rails/generators/rails/credentials/templates/credentials.yml.tt +8 -0
- data/lib/rails/generators/rails/db/system/change/change_generator.rb +30 -0
- data/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator.rb +1 -2
- data/lib/rails/generators/rails/migration/USAGE +21 -11
- data/lib/rails/generators/rails/model/model_generator.rb +4 -0
- data/lib/rails/generators/rails/plugin/USAGE +17 -6
- data/lib/rails/generators/rails/plugin/plugin_generator.rb +5 -15
- data/lib/rails/generators/rails/plugin/templates/Gemfile.tt +2 -2
- data/lib/rails/generators/rails/plugin/templates/MIT-LICENSE.tt +1 -1
- data/lib/rails/generators/rails/plugin/templates/bin/rails.tt +1 -17
- data/lib/rails/generators/rails/plugin/templates/gitignore.tt +0 -2
- data/lib/rails/generators/rails/plugin/templates/test/test_helper.rb.tt +4 -4
- data/lib/rails/generators/rails/resource/resource_generator.rb +6 -0
- data/lib/rails/generators/rails/scaffold/scaffold_generator.rb +2 -1
- data/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +1 -1
- data/lib/rails/generators/test_case.rb +2 -2
- data/lib/rails/generators/test_unit/scaffold/scaffold_generator.rb +1 -1
- data/lib/rails/generators/testing/{behaviour.rb → behavior.rb} +4 -1
- data/lib/rails/generators.rb +6 -14
- data/lib/rails/health_controller.rb +55 -0
- data/lib/rails/info.rb +1 -1
- data/lib/rails/info_controller.rb +33 -11
- data/lib/rails/mailers_controller.rb +15 -5
- data/lib/rails/paths.rb +13 -10
- data/lib/rails/rack/logger.rb +15 -12
- data/lib/rails/rackup/server.rb +15 -0
- data/lib/rails/railtie/configuration.rb +14 -1
- data/lib/rails/railtie.rb +31 -31
- data/lib/rails/ruby_version_check.rb +2 -0
- data/lib/rails/source_annotation_extractor.rb +67 -18
- data/lib/rails/tasks/engine.rake +8 -8
- data/lib/rails/tasks/framework.rake +4 -10
- data/lib/rails/tasks/log.rake +1 -1
- data/lib/rails/tasks/misc.rake +3 -14
- data/lib/rails/tasks/statistics.rake +5 -4
- data/lib/rails/tasks/tmp.rake +5 -5
- data/lib/rails/tasks/zeitwerk.rake +15 -35
- data/lib/rails/tasks.rb +0 -2
- data/lib/rails/templates/rails/mailers/email.html.erb +32 -0
- data/lib/rails/templates/rails/mailers/index.html.erb +14 -7
- data/lib/rails/templates/rails/mailers/mailer.html.erb +11 -5
- data/lib/rails/templates/rails/welcome/index.html.erb +1 -0
- data/lib/rails/test_help.rb +9 -14
- data/lib/rails/test_unit/line_filtering.rb +1 -1
- data/lib/rails/test_unit/reporter.rb +6 -2
- data/lib/rails/test_unit/runner.rb +36 -18
- data/lib/rails/test_unit/test_parser.rb +88 -0
- data/lib/rails/test_unit/testing.rake +13 -33
- data/lib/rails/testing/maintain_test_schema.rb +16 -0
- data/lib/rails/version.rb +1 -1
- data/lib/rails/zeitwerk_checker.rb +15 -0
- data/lib/rails.rb +15 -15
- metadata +64 -27
- data/RDOC_MAIN.rdoc +0 -97
- data/lib/rails/application/dummy_erb_compiler.rb +0 -18
- data/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_7_0.rb.tt +0 -143
- data/lib/rails/generators/rails/model/USAGE +0 -113
- data/lib/rails/tasks/middleware.rake +0 -9
- data/lib/rails/tasks/restart.rake +0 -9
data/lib/rails/command.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "active_support"
|
4
4
|
require "active_support/core_ext/enumerable"
|
5
5
|
require "active_support/core_ext/object/blank"
|
6
|
+
require "rails/deprecator"
|
6
7
|
|
7
8
|
require "thor"
|
8
9
|
|
@@ -13,9 +14,40 @@ module Rails
|
|
13
14
|
autoload :Behavior
|
14
15
|
autoload :Base
|
15
16
|
|
17
|
+
class CorrectableNameError < StandardError # :nodoc:
|
18
|
+
attr_reader :name
|
19
|
+
|
20
|
+
def initialize(message, name, alternatives)
|
21
|
+
@name = name
|
22
|
+
@alternatives = alternatives
|
23
|
+
super(message)
|
24
|
+
end
|
25
|
+
|
26
|
+
if !Exception.method_defined?(:detailed_message)
|
27
|
+
def detailed_message(...)
|
28
|
+
message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
|
33
|
+
include DidYouMean::Correctable
|
34
|
+
|
35
|
+
def corrections
|
36
|
+
@corrections ||= DidYouMean::SpellChecker.new(dictionary: @alternatives).correct(name)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class UnrecognizedCommandError < CorrectableNameError # :nodoc:
|
42
|
+
def initialize(name)
|
43
|
+
super("Unrecognized command #{name.inspect}", name, Command.printing_commands.map(&:first))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
16
47
|
include Behavior
|
17
48
|
|
18
|
-
HELP_MAPPINGS = %w(-h -? --help)
|
49
|
+
HELP_MAPPINGS = %w(-h -? --help).to_set
|
50
|
+
VERSION_MAPPINGS = %w(-v --version).to_set
|
19
51
|
|
20
52
|
class << self
|
21
53
|
def hidden_commands # :nodoc:
|
@@ -28,30 +60,26 @@ module Rails
|
|
28
60
|
|
29
61
|
# Receives a namespace, arguments, and the behavior to invoke the command.
|
30
62
|
def invoke(full_namespace, args = [], **config)
|
31
|
-
|
32
|
-
|
33
|
-
if char = namespace =~ /:(\w+)$/
|
34
|
-
command_name, namespace = $1, namespace.slice(0, char)
|
35
|
-
else
|
36
|
-
command_name = namespace
|
37
|
-
end
|
38
|
-
|
39
|
-
command_name, namespace = "help", "help" if command_name.blank? || HELP_MAPPINGS.include?(command_name)
|
40
|
-
command_name, namespace, args = "application", "application", ["--help"] if rails_new_with_no_path?(args)
|
41
|
-
command_name, namespace = "version", "version" if %w( -v --version ).include?(command_name)
|
42
|
-
|
43
|
-
original_argv = ARGV.dup
|
44
|
-
ARGV.replace(args)
|
63
|
+
args = ["--help"] if rails_new_with_no_path?(args)
|
45
64
|
|
65
|
+
full_namespace = full_namespace.to_s
|
66
|
+
namespace, command_name = split_namespace(full_namespace)
|
46
67
|
command = find_by_namespace(namespace, command_name)
|
47
|
-
|
48
|
-
|
68
|
+
|
69
|
+
with_argv(args) do
|
70
|
+
if command && command.all_commands[command_name]
|
71
|
+
command.perform(command_name, args, config)
|
72
|
+
else
|
73
|
+
invoke_rake(full_namespace, args, config)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
rescue UnrecognizedCommandError => error
|
77
|
+
if error.name == full_namespace && command && command_name == full_namespace
|
78
|
+
command.perform("help", [], config)
|
49
79
|
else
|
50
|
-
|
51
|
-
find_by_namespace("rake").perform(full_namespace, args, config)
|
80
|
+
puts error.detailed_message
|
52
81
|
end
|
53
|
-
|
54
|
-
ARGV.replace(original_argv)
|
82
|
+
exit(1)
|
55
83
|
end
|
56
84
|
|
57
85
|
# Rails finds namespaces similar to Thor, it only adds one rule:
|
@@ -76,33 +104,56 @@ module Rails
|
|
76
104
|
namespaces[(lookups & namespaces.keys).first]
|
77
105
|
end
|
78
106
|
|
79
|
-
# Returns the root of the Rails engine or app running the command.
|
107
|
+
# Returns the root of the \Rails engine or app running the command.
|
80
108
|
def root
|
81
109
|
if defined?(ENGINE_ROOT)
|
82
110
|
Pathname.new(ENGINE_ROOT)
|
83
|
-
|
84
|
-
|
111
|
+
else
|
112
|
+
application_root
|
85
113
|
end
|
86
114
|
end
|
87
115
|
|
88
|
-
def
|
89
|
-
|
116
|
+
def application_root # :nodoc:
|
117
|
+
Pathname.new(File.expand_path("../..", APP_PATH)) if defined?(APP_PATH)
|
90
118
|
end
|
91
119
|
|
92
|
-
|
93
|
-
|
94
|
-
|
120
|
+
def printing_commands # :nodoc:
|
121
|
+
lookup!
|
122
|
+
|
123
|
+
(subclasses - hidden_commands).flat_map(&:printing_commands)
|
124
|
+
end
|
95
125
|
|
126
|
+
private
|
96
127
|
def rails_new_with_no_path?(args)
|
97
128
|
args == ["new"]
|
98
129
|
end
|
99
130
|
|
100
|
-
def
|
101
|
-
|
131
|
+
def split_namespace(namespace)
|
132
|
+
case namespace
|
133
|
+
when /^(.+):(\w+)$/
|
134
|
+
[$1, $2]
|
135
|
+
when ""
|
136
|
+
["help", "help"]
|
137
|
+
when HELP_MAPPINGS, "help"
|
138
|
+
["help", "help_extended"]
|
139
|
+
when VERSION_MAPPINGS
|
140
|
+
["version", "version"]
|
141
|
+
else
|
142
|
+
[namespace, namespace]
|
143
|
+
end
|
144
|
+
end
|
102
145
|
|
103
|
-
|
146
|
+
def with_argv(argv)
|
147
|
+
original_argv = ARGV.dup
|
148
|
+
ARGV.replace(argv)
|
149
|
+
yield
|
150
|
+
ensure
|
151
|
+
ARGV.replace(original_argv)
|
152
|
+
end
|
104
153
|
|
105
|
-
|
154
|
+
def invoke_rake(task, args, config)
|
155
|
+
args = ["--describe", task] if HELP_MAPPINGS.include?(args[0])
|
156
|
+
find_by_namespace("rake").perform(task, args, config)
|
106
157
|
end
|
107
158
|
|
108
159
|
def command_type # :doc:
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module Command
|
5
|
+
class AboutCommand < Base # :nodoc:
|
6
|
+
desc "about", "List versions of all Rails frameworks and the environment"
|
7
|
+
def perform
|
8
|
+
boot_application!
|
9
|
+
|
10
|
+
say Rails::Info
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,8 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "irb"
|
4
|
-
require "irb/completion"
|
5
|
-
|
6
3
|
require "rails/command/environment_argument"
|
7
4
|
|
8
5
|
module Rails
|
@@ -34,19 +31,26 @@ module Rails
|
|
34
31
|
|
35
32
|
app.load_console
|
36
33
|
|
37
|
-
@console = app.config.console ||
|
34
|
+
@console = app.config.console || begin
|
35
|
+
require "irb"
|
36
|
+
require "irb/completion"
|
38
37
|
|
39
|
-
if @console == IRB
|
40
38
|
IRB::WorkSpace.prepend(BacktraceCleaner)
|
41
39
|
|
42
|
-
if Rails.env.
|
40
|
+
if !Rails.env.local?
|
43
41
|
ENV["IRB_USE_AUTOCOMPLETE"] ||= "false"
|
44
42
|
end
|
43
|
+
|
44
|
+
IRB
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
def sandbox?
|
49
|
-
options[:sandbox]
|
49
|
+
return options[:sandbox] if !options[:sandbox].nil?
|
50
|
+
|
51
|
+
return false if Rails.env.local?
|
52
|
+
|
53
|
+
app.config.sandbox_by_default
|
50
54
|
end
|
51
55
|
|
52
56
|
def environment
|
@@ -79,7 +83,7 @@ module Rails
|
|
79
83
|
class ConsoleCommand < Base # :nodoc:
|
80
84
|
include EnvironmentArgument
|
81
85
|
|
82
|
-
class_option :sandbox, aliases: "-s", type: :boolean, default:
|
86
|
+
class_option :sandbox, aliases: "-s", type: :boolean, default: nil,
|
83
87
|
desc: "Rollback database modifications on exit."
|
84
88
|
|
85
89
|
def initialize(args = [], local_options = {}, config = {})
|
@@ -96,13 +100,9 @@ module Rails
|
|
96
100
|
super(args, local_options, config)
|
97
101
|
end
|
98
102
|
|
103
|
+
desc "console", "Start the Rails console"
|
99
104
|
def perform
|
100
|
-
|
101
|
-
|
102
|
-
# RAILS_ENV needs to be set before config/application is required.
|
103
|
-
ENV["RAILS_ENV"] = options[:environment]
|
104
|
-
|
105
|
-
require_application_and_environment!
|
105
|
+
boot_application!
|
106
106
|
Rails::Console.start(Rails.application, options)
|
107
107
|
end
|
108
108
|
end
|
@@ -1,75 +1,73 @@
|
|
1
|
-
|
1
|
+
Description:
|
2
|
+
The Rails `credentials` commands provide access to encrypted credentials,
|
3
|
+
so you can safely store access tokens, database passwords, and the like
|
4
|
+
safely inside the app without relying on a mess of ENVs.
|
2
5
|
|
3
|
-
|
4
|
-
|
5
|
-
safely inside the app without relying on a mess of ENVs.
|
6
|
+
This also allows for atomic deploys: no need to coordinate key changes
|
7
|
+
to get everything working as the keys are shipped with the code.
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
Setup:
|
10
|
+
Applications after Rails 5.2 automatically have a basic credentials file generated
|
11
|
+
that just contains the secret_key_base used by MessageVerifiers/MessageEncryptors, like the ones
|
12
|
+
signing and encrypting cookies.
|
9
13
|
|
10
|
-
|
14
|
+
For applications created prior to Rails 5.2, we'll automatically generate a new
|
15
|
+
credentials file in `config/credentials.yml.enc` the first time you run `<%= executable(:edit) %>`.
|
16
|
+
If you didn't have a master key saved in `config/master.key`, that'll be created too.
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
Don't lose this master key! Put it in a password manager your team can access.
|
19
|
+
Should you lose it no one, including you, will be able to access any encrypted
|
20
|
+
credentials.
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
If you didn't have a master key saved in `config/master.key`, that'll be created too.
|
22
|
+
Don't commit the key! Add `config/master.key` to your source control's
|
23
|
+
ignore file. If you use Git, Rails handles this for you.
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
25
|
+
Rails also looks for the master key in `ENV["RAILS_MASTER_KEY"]`, in case that
|
26
|
+
is easier to manage. You could set `RAILS_MASTER_KEY` in a deployment
|
27
|
+
configuration, or you could prepend it to your server's start command like so:
|
23
28
|
|
24
|
-
|
25
|
-
ignore file. If you use Git, Rails handles this for you.
|
29
|
+
RAILS_MASTER_KEY="very-secret-and-secure" bin/rails server
|
26
30
|
|
27
|
-
|
31
|
+
If `ENV["RAILS_MASTER_KEY"]` is present, it takes precedence over
|
32
|
+
`config/master.key`.
|
28
33
|
|
29
|
-
|
34
|
+
Set up Git to Diff Credentials:
|
35
|
+
Rails provides `<%= executable(:diff) %> --enroll` to instruct Git to call
|
36
|
+
`<%= executable(:diff) %>` when `git diff` is run on a credentials file.
|
30
37
|
|
31
|
-
|
38
|
+
Running the command enrolls the project such that all credentials files use the
|
39
|
+
"rails_credentials" diff driver in .gitattributes.
|
32
40
|
|
33
|
-
|
41
|
+
Additionally since Git requires the driver itself to be set up in a config file
|
42
|
+
that isn't tracked Rails automatically ensures it's configured when running
|
43
|
+
`<%= executable(:edit) %>`.
|
34
44
|
|
35
|
-
|
36
|
-
|
45
|
+
Otherwise each co-worker would have to run enable manually, including on each new
|
46
|
+
repo clone.
|
37
47
|
|
38
|
-
|
39
|
-
"rails_credentials" diff driver in .gitattributes.
|
48
|
+
To disenroll from this feature, run `<%= executable(:diff) %> --disenroll`.
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
50
|
+
Editing Credentials:
|
51
|
+
This will open a temporary file in `$VISUAL` or `$EDITOR` with the decrypted
|
52
|
+
contents to edit the encrypted credentials.
|
44
53
|
|
45
|
-
|
46
|
-
|
54
|
+
When the temporary file is next saved the contents are encrypted and written to
|
55
|
+
`config/credentials.yml.enc` while the file itself is destroyed to prevent credentials
|
56
|
+
from leaking.
|
47
57
|
|
48
|
-
|
58
|
+
Environment Specific Credentials:
|
59
|
+
The `credentials` command supports passing an `--environment` option to create an
|
60
|
+
environment specific override. That override will take precedence over the
|
61
|
+
global `config/credentials.yml.enc` file when running in that environment. So:
|
49
62
|
|
50
|
-
|
63
|
+
<%= executable(:edit) %> --environment development
|
51
64
|
|
52
|
-
|
53
|
-
|
65
|
+
will create `config/credentials/development.yml.enc` with the corresponding
|
66
|
+
encryption key in `config/credentials/development.key` if the credentials file
|
67
|
+
doesn't exist.
|
54
68
|
|
55
|
-
|
56
|
-
`config
|
57
|
-
from leaking.
|
69
|
+
In addition to that, the default credentials lookup paths can be overridden through
|
70
|
+
`config.credentials.content_path` and `config.credentials.key_path`.
|
58
71
|
|
59
|
-
|
60
|
-
|
61
|
-
The `credentials` command supports passing an `--environment` option to create an
|
62
|
-
environment specific override. That override will take precedence over the
|
63
|
-
global `config/credentials.yml.enc` file when running in that environment. So:
|
64
|
-
|
65
|
-
bin/rails credentials:edit --environment development
|
66
|
-
|
67
|
-
will create `config/credentials/development.yml.enc` with the corresponding
|
68
|
-
encryption key in `config/credentials/development.key` if the credentials file
|
69
|
-
doesn't exist.
|
70
|
-
|
71
|
-
The encryption key can also be put in `ENV["RAILS_MASTER_KEY"]`, which takes
|
72
|
-
precedence over the file encryption key.
|
73
|
-
|
74
|
-
In addition to that, the default credentials lookup paths can be overridden through
|
75
|
-
`config.credentials.content_path` and `config.credentials.key_path`.
|
72
|
+
Just as with `config/master.key`, `ENV["RAILS_MASTER_KEY"]` takes precedence
|
73
|
+
over any environment specific or specially configured key files.
|
@@ -13,7 +13,8 @@ module Rails::Command::CredentialsCommand::Diffing # :nodoc:
|
|
13
13
|
gitattributes.write(GITATTRIBUTES_ENTRY, mode: "a")
|
14
14
|
|
15
15
|
say "Enrolled project in credentials file diffing!"
|
16
|
-
say "
|
16
|
+
say ""
|
17
|
+
say "Rails will configure the Git diff driver for credentials when running `#{executable(:edit)}`. See `#{executable(:help)}` for more information."
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
@@ -42,10 +43,11 @@ module Rails::Command::CredentialsCommand::Diffing # :nodoc:
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def configure_diffing_driver
|
45
|
-
system "git config diff.rails_credentials.textconv '
|
46
|
+
system "git config diff.rails_credentials.textconv '#{executable(:diff)}'"
|
47
|
+
say "Configured Git diff driver for credentials."
|
46
48
|
end
|
47
49
|
|
48
50
|
def gitattributes
|
49
|
-
Rails.root.join(".gitattributes")
|
51
|
+
@gitattributes ||= (Rails::Command.root || Pathname.pwd).join(".gitattributes")
|
50
52
|
end
|
51
53
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "pathname"
|
4
|
-
require "shellwords"
|
5
4
|
require "active_support"
|
6
5
|
require "rails/command/helpers/editor"
|
7
6
|
require "rails/command/environment_argument"
|
@@ -15,56 +14,42 @@ module Rails
|
|
15
14
|
require_relative "credentials_command/diffing"
|
16
15
|
include Diffing
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
no_commands do
|
21
|
-
def help
|
22
|
-
say "Usage:\n #{self.class.banner}"
|
23
|
-
say ""
|
24
|
-
say self.class.desc
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
17
|
+
desc "edit", "Open the decrypted credentials in `$VISUAL` or `$EDITOR` for editing"
|
28
18
|
def edit
|
29
|
-
|
30
|
-
|
19
|
+
load_environment_config!
|
20
|
+
load_generators
|
31
21
|
|
32
|
-
|
22
|
+
if environment_specified?
|
23
|
+
@content_path = "config/credentials/#{environment}.yml.enc" unless config.key?(:content_path)
|
24
|
+
@key_path = "config/credentials/#{environment}.key" unless config.key?(:key_path)
|
25
|
+
end
|
33
26
|
|
34
|
-
ensure_encryption_key_has_been_added
|
27
|
+
ensure_encryption_key_has_been_added
|
35
28
|
ensure_credentials_have_been_added
|
36
29
|
ensure_diffing_driver_is_configured
|
37
30
|
|
38
|
-
|
39
|
-
change_credentials_in_system_editor
|
40
|
-
end
|
41
|
-
|
42
|
-
say "File encrypted and saved."
|
43
|
-
rescue ActiveSupport::MessageEncryptor::InvalidMessage
|
44
|
-
say "Couldn't decrypt #{content_path}. Perhaps you passed the wrong key?"
|
31
|
+
change_credentials_in_system_editor
|
45
32
|
end
|
46
33
|
|
34
|
+
desc "show", "Show the decrypted credentials"
|
47
35
|
def show
|
48
|
-
|
49
|
-
require_application!
|
36
|
+
load_environment_config!
|
50
37
|
|
51
38
|
say credentials.read.presence || missing_credentials_message
|
52
39
|
end
|
53
40
|
|
41
|
+
desc "diff", "Enroll/disenroll in decrypted diffs of credentials using git"
|
54
42
|
option :enroll, type: :boolean, default: false,
|
55
|
-
desc: "
|
56
|
-
|
43
|
+
desc: "Enroll project in credentials file diffing with `git diff`"
|
57
44
|
option :disenroll, type: :boolean, default: false,
|
58
|
-
desc: "
|
59
|
-
|
45
|
+
desc: "Disenroll project from credentials file diffing"
|
60
46
|
def diff(content_path = nil)
|
61
47
|
if @content_path = content_path
|
62
|
-
|
63
|
-
|
48
|
+
self.environment = extract_environment_from_path(content_path)
|
49
|
+
load_environment_config!
|
64
50
|
|
65
51
|
say credentials.read.presence || credentials.content_path.read
|
66
52
|
else
|
67
|
-
require_application!
|
68
53
|
disenroll_project_from_credentials_diffing if options[:disenroll]
|
69
54
|
enroll_project_in_credentials_diffing if options[:enroll]
|
70
55
|
end
|
@@ -73,68 +58,77 @@ module Rails
|
|
73
58
|
end
|
74
59
|
|
75
60
|
private
|
61
|
+
def config
|
62
|
+
Rails.application.config.credentials
|
63
|
+
end
|
64
|
+
|
65
|
+
def content_path
|
66
|
+
@content_path ||= relative_path(config.content_path)
|
67
|
+
end
|
68
|
+
|
69
|
+
def key_path
|
70
|
+
@key_path ||= relative_path(config.key_path)
|
71
|
+
end
|
72
|
+
|
76
73
|
def credentials
|
77
|
-
Rails.application.encrypted(content_path, key_path: key_path)
|
74
|
+
@credentials ||= Rails.application.encrypted(content_path, key_path: key_path)
|
78
75
|
end
|
79
76
|
|
80
77
|
def ensure_encryption_key_has_been_added
|
78
|
+
return if credentials.key?
|
79
|
+
|
80
|
+
require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"
|
81
|
+
|
82
|
+
encryption_key_file_generator = Rails::Generators::EncryptionKeyFileGenerator.new
|
81
83
|
encryption_key_file_generator.add_key_file(key_path)
|
82
84
|
encryption_key_file_generator.ignore_key_file(key_path)
|
83
85
|
end
|
84
86
|
|
85
87
|
def ensure_credentials_have_been_added
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
require "rails/generators/rails/credentials/credentials_generator"
|
89
|
+
|
90
|
+
Rails::Generators::CredentialsGenerator.new(
|
91
|
+
[content_path, key_path],
|
92
|
+
skip_secret_key_base: environment_specified? && %w[development test].include?(environment),
|
93
|
+
quiet: true
|
94
|
+
).invoke_all
|
91
95
|
end
|
92
96
|
|
93
97
|
def change_credentials_in_system_editor
|
94
|
-
|
95
|
-
|
98
|
+
using_system_editor do
|
99
|
+
say "Editing #{content_path}..."
|
100
|
+
credentials.change { |tmp_path| system_editor(tmp_path) }
|
101
|
+
say "File encrypted and saved."
|
102
|
+
warn_if_credentials_are_invalid
|
96
103
|
end
|
104
|
+
rescue ActiveSupport::EncryptedFile::MissingKeyError => error
|
105
|
+
say error.message
|
106
|
+
rescue ActiveSupport::MessageEncryptor::InvalidMessage
|
107
|
+
say "Couldn't decrypt #{content_path}. Perhaps you passed the wrong key?"
|
108
|
+
end
|
109
|
+
|
110
|
+
def warn_if_credentials_are_invalid
|
111
|
+
credentials.validate!
|
112
|
+
rescue ActiveSupport::EncryptedConfiguration::InvalidContentError => error
|
113
|
+
say "WARNING: #{error.message}", :red
|
114
|
+
say ""
|
115
|
+
say "Your application will not be able to load '#{content_path}' until the error has been fixed.", :red
|
97
116
|
end
|
98
117
|
|
99
118
|
def missing_credentials_message
|
100
|
-
if credentials.key
|
101
|
-
"Missing '#{key_path}' to decrypt credentials. See
|
119
|
+
if !credentials.key?
|
120
|
+
"Missing '#{key_path}' to decrypt credentials. See `#{executable(:help)}`."
|
102
121
|
else
|
103
|
-
"File '#{content_path}' does not exist. Use
|
122
|
+
"File '#{content_path}' does not exist. Use `#{executable(:edit)}` to change that."
|
104
123
|
end
|
105
124
|
end
|
106
125
|
|
107
|
-
def
|
108
|
-
|
109
|
-
end
|
110
|
-
|
111
|
-
def key_path
|
112
|
-
options[:environment] ? "config/credentials/#{options[:environment]}.key" : "config/master.key"
|
126
|
+
def relative_path(path)
|
127
|
+
Rails.root.join(path).relative_path_from(Rails.root).to_s
|
113
128
|
end
|
114
129
|
|
115
130
|
def extract_environment_from_path(path)
|
116
|
-
available_environments.find { |env| path.
|
117
|
-
end
|
118
|
-
|
119
|
-
def encryption_key_file_generator
|
120
|
-
require "rails/generators"
|
121
|
-
require "rails/generators/rails/encryption_key_file/encryption_key_file_generator"
|
122
|
-
|
123
|
-
Rails::Generators::EncryptionKeyFileGenerator.new
|
124
|
-
end
|
125
|
-
|
126
|
-
def encrypted_file_generator
|
127
|
-
require "rails/generators"
|
128
|
-
require "rails/generators/rails/encrypted_file/encrypted_file_generator"
|
129
|
-
|
130
|
-
Rails::Generators::EncryptedFileGenerator.new
|
131
|
-
end
|
132
|
-
|
133
|
-
def credentials_generator
|
134
|
-
require "rails/generators"
|
135
|
-
require "rails/generators/rails/credentials/credentials_generator"
|
136
|
-
|
137
|
-
Rails::Generators::CredentialsGenerator.new
|
131
|
+
available_environments.find { |env| path.end_with?("#{env}.yml.enc") }
|
138
132
|
end
|
139
133
|
end
|
140
134
|
end
|