diff --git a/.github/stale.yml b/.github/stale.yml
index 21d9d792b025d..cf2bd96c759cf 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -18,7 +18,7 @@ markComment: >
The resources of the Rails team are limited, and so we are asking for your help.
- If you can still reproduce this error on the `5-2-stable` branch or on `master`,
+ If you can still reproduce this error on the `5-2-stable` branch or on `main`,
please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7e34cecb2e902..216c329e3215e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -10,9 +10,9 @@
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/rails/rails/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
* If possible, use the relevant bug report templates to create the issue. Simply copy the content of the appropriate template into a .rb file, make the necessary changes to demonstrate the issue, and **paste the content into the issue description**:
- * [**Active Record** (models, database) issues](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_master.rb)
- * [**Action Pack** (controllers, routing) issues](https://github.com/rails/rails/blob/master/guides/bug_report_templates/action_controller_master.rb)
- * [**Generic template** for other issues](https://github.com/rails/rails/blob/master/guides/bug_report_templates/generic_master.rb)
+ * [**Active Record** (models, database) issues](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_main.rb)
+ * [**Action Pack** (controllers, routing) issues](https://github.com/rails/rails/blob/main/guides/bug_report_templates/action_controller_main.rb)
+ * [**Generic template** for other issues](https://github.com/rails/rails/blob/main/guides/bug_report_templates/generic_main.rb)
* For more detailed information on submitting a bug report and creating an issue, visit our [reporting guidelines](https://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html#reporting-an-issue).
diff --git a/Gemfile b/Gemfile
index 60766bd39126a..f5113a0a74d18 100644
--- a/Gemfile
+++ b/Gemfile
@@ -10,7 +10,7 @@ gemspec
gem "rake", ">= 11.1"
gem "capybara", ">= 2.15"
-gem "selenium-webdriver", ">= 3.141.592"
+gem "selenium-webdriver", ">= 4.0.0.alpha7"
gem "rack-cache", "~> 1.2"
gem "sass-rails"
@@ -28,6 +28,9 @@ gem "uglifier", ">= 1.3.0", require: false
# Explicitly avoid 1.x that doesn't support Ruby 2.4+
gem "json", ">= 2.0.0"
+# Lock rack-test to v1 until #45467 is fixed
+gem "rack-test", "< 2"
+
gem "rubocop", ">= 0.47", require: false
gem "rubocop-performance", require: false
gem "rubocop-rails", require: false
@@ -35,19 +38,20 @@ gem "rubocop-rails", require: false
group :doc do
gem "sdoc", "~> 1.1"
gem "redcarpet", "~> 3.2.3", platforms: :ruby
- gem "w3c_validators"
+ gem "w3c_validators", "~> 1.3.6"
gem "kindlerb", "~> 1.2.0"
end
# Active Support
gem "dalli"
-gem "listen", "~> 3.2", require: false
+gem "listen", "~> 3.2", require: false, github: "guard/listen"
gem "libxml-ruby", platforms: :ruby
gem "connection_pool", require: false
gem "rexml", require: false
-# for railties app_generator_test
+# for railties
gem "bootsnap", ">= 1.4.2", require: false
+gem "webrick", require: false
# Active Job
group :job do
@@ -58,7 +62,7 @@ group :job do
gem "delayed_job", require: false
gem "queue_classic", github: "QueueClassic/queue_classic", require: false, platforms: :ruby
gem "sneakers", require: false
- gem "que", require: false
+ gem "que", "<= 0.14.3", require: false
gem "backburner", require: false
gem "delayed_job_active_record", require: false
gem "sequel", require: false
@@ -71,7 +75,7 @@ group :cable do
gem "hiredis", require: false
gem "redis", "~> 4.0", require: false
- gem "redis-namespace"
+ gem "redis-namespace", github: "resque/redis-namespace"
gem "websocket-client-simple", github: "matthewd/websocket-client-simple", branch: "close-race", require: false
@@ -103,6 +107,7 @@ local_gemfile = File.expand_path(".Gemfile", __dir__)
instance_eval File.read local_gemfile if File.exist? local_gemfile
group :test do
+ gem "minitest", "< 5.15.0"
gem "minitest-bisect"
gem "minitest-retry"
gem "minitest-reporters"
@@ -164,3 +169,15 @@ end
gem "ibm_db" if ENV["IBM_DB"]
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
gem "wdm", ">= 0.1.0", platforms: [:mingw, :mswin, :x64_mingw, :mswin64]
+
+if RUBY_VERSION >= "3.1"
+ # net-smtp, net-imap and net-pop were removed from default gems in Ruby 3.1, but is used by the `mail` gem.
+ # So we need to add them as dependencies until `mail` is fixed: https://github.com/mikel/mail/pull/1439
+ gem "net-smtp", require: false
+ gem "net-imap", require: false
+ gem "net-pop", require: false
+
+ # matrix was removed from default gems in Ruby 3.1, but is used by the `capybara` gem.
+ # So we need to add it as a dependency until `capybara` is fixed: https://github.com/teamcapybara/capybara/pull/2468
+ gem "matrix", require: false
+end
diff --git a/Gemfile.lock b/Gemfile.lock
index afd5189bc874a..f8fd74d66dc58 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,10 +1,18 @@
GIT
remote: https://github.com/QueueClassic/queue_classic.git
- revision: 655143b7952fa011346a00f94d628407aa4e0056
+ revision: 1e40ddd810c416619ead88316b2b251936ee2495
specs:
queue_classic (4.0.0.pre.alpha1)
pg (>= 0.17, < 2.0)
+GIT
+ remote: https://github.com/guard/listen.git
+ revision: 96c9476af3ab383c150e7f533718a2b37d1ede66
+ specs:
+ listen (3.5.1)
+ rb-fsevent (~> 0.10, >= 0.10.3)
+ rb-inotify (~> 0.9, >= 0.9.10)
+
GIT
remote: https://github.com/matthewd/websocket-client-simple.git
revision: e161305f1a466b9398d86df3b1731b03362da91b
@@ -14,82 +22,89 @@ GIT
event_emitter
websocket
+GIT
+ remote: https://github.com/resque/redis-namespace.git
+ revision: 6f1bb31bbddd2efc9e16c53759d986b29206a12e
+ specs:
+ redis-namespace (1.8.1)
+ redis (>= 3.0.4)
+
PATH
remote: .
specs:
- actioncable (6.0.3.3)
- actionpack (= 6.0.3.3)
+ actioncable (6.0.6.1)
+ actionpack (= 6.0.6.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailbox (6.0.3.3)
- actionpack (= 6.0.3.3)
- activejob (= 6.0.3.3)
- activerecord (= 6.0.3.3)
- activestorage (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ actionmailbox (6.0.6.1)
+ actionpack (= 6.0.6.1)
+ activejob (= 6.0.6.1)
+ activerecord (= 6.0.6.1)
+ activestorage (= 6.0.6.1)
+ activesupport (= 6.0.6.1)
mail (>= 2.7.1)
- actionmailer (6.0.3.3)
- actionpack (= 6.0.3.3)
- actionview (= 6.0.3.3)
- activejob (= 6.0.3.3)
+ actionmailer (6.0.6.1)
+ actionpack (= 6.0.6.1)
+ actionview (= 6.0.6.1)
+ activejob (= 6.0.6.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (6.0.3.3)
- actionview (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ actionpack (6.0.6.1)
+ actionview (= 6.0.6.1)
+ activesupport (= 6.0.6.1)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
- actiontext (6.0.3.3)
- actionpack (= 6.0.3.3)
- activerecord (= 6.0.3.3)
- activestorage (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ actiontext (6.0.6.1)
+ actionpack (= 6.0.6.1)
+ activerecord (= 6.0.6.1)
+ activestorage (= 6.0.6.1)
+ activesupport (= 6.0.6.1)
nokogiri (>= 1.8.5)
- actionview (6.0.3.3)
- activesupport (= 6.0.3.3)
+ actionview (6.0.6.1)
+ activesupport (= 6.0.6.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
- activejob (6.0.3.3)
- activesupport (= 6.0.3.3)
+ activejob (6.0.6.1)
+ activesupport (= 6.0.6.1)
globalid (>= 0.3.6)
- activemodel (6.0.3.3)
- activesupport (= 6.0.3.3)
- activerecord (6.0.3.3)
- activemodel (= 6.0.3.3)
- activesupport (= 6.0.3.3)
- activestorage (6.0.3.3)
- actionpack (= 6.0.3.3)
- activejob (= 6.0.3.3)
- activerecord (= 6.0.3.3)
- marcel (~> 0.3.1)
- activesupport (6.0.3.3)
+ activemodel (6.0.6.1)
+ activesupport (= 6.0.6.1)
+ activerecord (6.0.6.1)
+ activemodel (= 6.0.6.1)
+ activesupport (= 6.0.6.1)
+ activestorage (6.0.6.1)
+ actionpack (= 6.0.6.1)
+ activejob (= 6.0.6.1)
+ activerecord (= 6.0.6.1)
+ marcel (~> 1.0)
+ activesupport (6.0.6.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
- rails (6.0.3.3)
- actioncable (= 6.0.3.3)
- actionmailbox (= 6.0.3.3)
- actionmailer (= 6.0.3.3)
- actionpack (= 6.0.3.3)
- actiontext (= 6.0.3.3)
- actionview (= 6.0.3.3)
- activejob (= 6.0.3.3)
- activemodel (= 6.0.3.3)
- activerecord (= 6.0.3.3)
- activestorage (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ rails (6.0.6.1)
+ actioncable (= 6.0.6.1)
+ actionmailbox (= 6.0.6.1)
+ actionmailer (= 6.0.6.1)
+ actionpack (= 6.0.6.1)
+ actiontext (= 6.0.6.1)
+ actionview (= 6.0.6.1)
+ activejob (= 6.0.6.1)
+ activemodel (= 6.0.6.1)
+ activerecord (= 6.0.6.1)
+ activestorage (= 6.0.6.1)
+ activesupport (= 6.0.6.1)
bundler (>= 1.3.0)
- railties (= 6.0.3.3)
+ railties (= 6.0.6.1)
sprockets-rails (>= 2.0.0)
- railties (6.0.3.3)
- actionpack (= 6.0.3.3)
- activesupport (= 6.0.3.3)
+ railties (6.0.6.1)
+ actionpack (= 6.0.6.1)
+ activesupport (= 6.0.6.1)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
@@ -97,41 +112,30 @@ PATH
GEM
remote: https://rubygems.org/
specs:
- activerecord-jdbc-adapter (60.1-java)
- activerecord (~> 6.0.0)
- activerecord-jdbcmysql-adapter (60.1-java)
- activerecord-jdbc-adapter (= 60.1)
- jdbc-mysql (~> 5.1.36, < 9)
- activerecord-jdbcpostgresql-adapter (60.1-java)
- activerecord-jdbc-adapter (= 60.1)
- jdbc-postgres (>= 9.4, < 43)
- activerecord-jdbcsqlite3-adapter (60.1-java)
- activerecord-jdbc-adapter (= 60.1)
- jdbc-sqlite3 (~> 3.8, < 3.30)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
- amq-protocol (2.3.0)
+ amq-protocol (2.3.2)
ansi (1.5.0)
- ast (2.4.0)
- aws-eventstream (1.0.3)
- aws-partitions (1.260.0)
- aws-sdk-core (3.86.0)
- aws-eventstream (~> 1.0, >= 1.0.2)
+ ast (2.4.2)
+ aws-eventstream (1.1.1)
+ aws-partitions (1.451.0)
+ aws-sdk-core (3.114.0)
+ aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.239.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
- aws-sdk-kms (1.27.0)
- aws-sdk-core (~> 3, >= 3.71.0)
+ aws-sdk-kms (1.43.0)
+ aws-sdk-core (~> 3, >= 3.112.0)
aws-sigv4 (~> 1.1)
- aws-sdk-s3 (1.60.1)
- aws-sdk-core (~> 3, >= 3.83.0)
+ aws-sdk-s3 (1.94.1)
+ aws-sdk-core (~> 3, >= 3.112.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.1)
- aws-sdk-sns (1.21.0)
- aws-sdk-core (~> 3, >= 3.71.0)
+ aws-sdk-sns (1.40.0)
+ aws-sdk-core (~> 3, >= 3.112.0)
aws-sigv4 (~> 1.1)
- aws-sigv4 (1.1.0)
- aws-eventstream (~> 1.0, >= 1.0.2)
+ aws-sigv4 (1.2.3)
+ aws-eventstream (~> 1, >= 1.0.2)
azure-core (0.1.15)
faraday (~> 0.9)
faraday_middleware (~> 0.10)
@@ -145,67 +149,65 @@ GEM
beaneater (~> 1.0)
concurrent-ruby (~> 1.0, >= 1.0.1)
dante (> 0.1.5)
- bcrypt (3.1.13)
- bcrypt (3.1.13-java)
- beaneater (1.0.0)
- benchmark-ips (2.7.2)
- blade (0.7.1)
+ bcrypt (3.1.16)
+ beaneater (1.1.1)
+ benchmark-ips (2.8.4)
+ blade (0.7.2)
activesupport (>= 3.0.0)
- blade-qunit_adapter (~> 2.0.1)
+ blade-qunit_adapter (>= 2.0.1)
coffee-script
coffee-script-source
- curses (~> 1.0.0)
+ curses (>= 1.4.0)
eventmachine
faye
sprockets (>= 3.0)
thin (>= 1.6.0)
thor (>= 0.19.1)
- useragent (~> 0.16.7)
+ useragent (>= 0.16.7)
blade-qunit_adapter (2.0.1)
blade-sauce_labs_plugin (0.7.3)
childprocess
faraday
selenium-webdriver
- bootsnap (1.4.5)
- msgpack (~> 1.0)
- bootsnap (1.4.5-java)
- msgpack (~> 1.0)
+ bootsnap (1.12.0)
+ msgpack (~> 1.2)
builder (3.2.4)
- bunny (2.14.3)
- amq-protocol (~> 2.3, >= 2.3.0)
- byebug (11.0.1)
- capybara (3.30.0)
+ bunny (2.17.0)
+ amq-protocol (~> 2.3, >= 2.3.1)
+ byebug (11.1.3)
+ capybara (3.35.3)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
- regexp_parser (~> 1.5)
+ regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
- childprocess (3.0.0)
+ childprocess (4.0.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
- concurrent-ruby (1.1.5)
- connection_pool (2.2.2)
+ concurrent-ruby (1.1.8)
+ connection_pool (2.2.5)
cookiejar (0.3.3)
- crack (0.4.3)
- safe_yaml (~> 1.0.0)
+ crack (0.4.5)
+ rexml
crass (1.0.6)
- curses (1.0.2)
- daemons (1.3.1)
- dalli (2.7.10)
+ curses (1.4.0)
+ daemons (1.4.0)
+ dalli (2.7.11)
dante (0.2.0)
- declarative (0.0.10)
- declarative-option (0.1.0)
- delayed_job (4.1.8)
- activesupport (>= 3.0, < 6.1)
- delayed_job_active_record (4.1.4)
- activerecord (>= 3.0, < 6.1)
+ declarative (0.0.20)
+ delayed_job (4.1.9)
+ activesupport (>= 3.0, < 6.2)
+ delayed_job_active_record (4.1.6)
+ activerecord (>= 3.0, < 6.2)
delayed_job (>= 3.0, < 5)
- digest-crc (0.4.1)
- em-http-request (1.1.5)
+ digest (3.1.0)
+ digest-crc (0.6.3)
+ rake (>= 12.0.0, < 14.0.0)
+ em-http-request (1.1.7)
addressable (>= 2.3.4)
cookiejar (!= 0.3.1)
em-socksify (>= 0.3)
@@ -213,159 +215,157 @@ GEM
http_parser.rb (>= 0.6.0)
em-socksify (0.3.2)
eventmachine (>= 1.0.0.beta.4)
- erubi (1.9.0)
- et-orbi (1.2.2)
+ erubi (1.12.0)
+ et-orbi (1.2.4)
tzinfo
event_emitter (0.2.6)
eventmachine (1.2.7)
execjs (2.7.0)
- faraday (0.17.1)
+ faraday (0.17.4)
multipart-post (>= 1.2, < 3)
- faraday_middleware (0.13.1)
+ faraday_middleware (0.14.0)
faraday (>= 0.7.4, < 1.0)
- faye (1.2.4)
+ faye (1.4.0)
cookiejar (>= 0.3.0)
- em-http-request (>= 0.3.0)
+ em-http-request (>= 1.1.6)
eventmachine (>= 0.12.0)
- faye-websocket (>= 0.9.1)
+ faye-websocket (>= 0.11.0)
multi_json (>= 1.0.0)
rack (>= 1.0.0)
websocket-driver (>= 0.5.1)
- faye-websocket (0.10.9)
+ faye-websocket (0.11.0)
eventmachine (>= 0.12.0)
websocket-driver (>= 0.5.1)
- ffi (1.11.3)
- ffi (1.11.3-java)
- ffi (1.11.3-x64-mingw32)
- ffi (1.11.3-x86-mingw32)
- fugit (1.3.3)
+ ffi (1.15.0)
+ fugit (1.4.5)
et-orbi (~> 1.1, >= 1.1.8)
- raabro (~> 1.1)
- globalid (0.4.2)
- activesupport (>= 4.2.0)
- google-api-client (0.36.2)
+ raabro (~> 1.4)
+ globalid (1.0.0)
+ activesupport (>= 5.0)
+ google-apis-core (0.3.0)
addressable (~> 2.5, >= 2.5.1)
- googleauth (~> 0.9)
+ googleauth (~> 0.14)
httpclient (>= 2.8.1, < 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
- signet (~> 0.12)
- google-cloud-core (1.4.1)
+ rexml
+ signet (~> 0.14)
+ webrick
+ google-apis-iamcredentials_v1 (0.3.0)
+ google-apis-core (~> 0.1)
+ google-apis-storage_v1 (0.3.0)
+ google-apis-core (~> 0.1)
+ google-cloud-core (1.6.0)
google-cloud-env (~> 1.0)
- google-cloud-env (1.3.0)
- faraday (~> 0.11)
- google-cloud-storage (1.25.0)
+ google-cloud-errors (~> 1.0)
+ google-cloud-env (1.5.0)
+ faraday (>= 0.17.3, < 2.0)
+ google-cloud-errors (1.1.0)
+ google-cloud-storage (1.31.0)
addressable (~> 2.5)
digest-crc (~> 0.4)
- google-api-client (~> 0.33)
+ google-apis-iamcredentials_v1 (~> 0.1)
+ google-apis-storage_v1 (~> 0.1)
google-cloud-core (~> 1.2)
googleauth (~> 0.9)
mini_mime (~> 1.0)
- googleauth (0.10.0)
- faraday (~> 0.12)
+ googleauth (0.16.2)
+ faraday (>= 0.17.3, < 2.0)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
- signet (~> 0.12)
- hashdiff (1.0.0)
+ signet (~> 0.14)
+ hashdiff (1.0.1)
hiredis (0.6.3)
- hiredis (0.6.3-java)
http_parser.rb (0.6.0)
httpclient (2.8.3)
- i18n (1.8.5)
+ i18n (1.12.0)
concurrent-ruby (~> 1.0)
- image_processing (1.10.0)
+ image_processing (1.12.1)
mini_magick (>= 4.9.5, < 5)
- ruby-vips (>= 2.0.13, < 3)
- jaro_winkler (1.5.4)
- jaro_winkler (1.5.4-java)
- jdbc-mysql (5.1.47)
- jdbc-postgres (42.2.6)
- jdbc-sqlite3 (3.28.0)
+ ruby-vips (>= 2.0.17, < 3)
jmespath (1.4.0)
- json (2.3.0)
- json (2.3.0-java)
- jwt (2.2.1)
+ json (2.5.1)
+ jwt (2.2.3)
kindlerb (1.2.0)
mustache
nokogiri
- libxml-ruby (3.1.0)
- listen (3.2.0)
- rb-fsevent (~> 0.10, >= 0.10.3)
- rb-inotify (~> 0.9, >= 0.9.10)
- loofah (2.7.0)
+ libxml-ruby (3.2.1)
+ loofah (2.19.1)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
- mail (2.7.1)
+ mail (2.8.0)
mini_mime (>= 0.1.1)
- marcel (0.3.3)
- mimemagic (~> 0.3.2)
+ net-imap
+ net-pop
+ net-smtp
+ marcel (1.0.2)
+ matrix (0.4.2)
memoist (0.16.2)
method_source (1.0.0)
- mimemagic (0.3.5)
- mini_magick (4.9.5)
- mini_mime (1.0.2)
- mini_portile2 (2.4.0)
- minitest (5.14.0)
+ mini_magick (4.11.0)
+ mini_mime (1.1.0)
+ mini_portile2 (2.5.3)
+ minitest (5.14.4)
minitest-bisect (1.5.1)
minitest-server (~> 1.0)
path_expander (~> 1.1)
- minitest-reporters (1.4.2)
+ minitest-reporters (1.4.3)
ansi
builder
minitest (>= 5.0)
ruby-progressbar
- minitest-retry (0.1.9)
+ minitest-retry (0.2.2)
minitest (>= 5.0)
minitest-server (1.0.6)
minitest (~> 5.0)
- mono_logger (1.1.0)
- msgpack (1.3.1)
- msgpack (1.3.1-java)
- msgpack (1.3.1-x64-mingw32)
- msgpack (1.3.1-x86-mingw32)
- multi_json (1.14.1)
+ mono_logger (1.1.1)
+ msgpack (1.5.3)
+ multi_json (1.15.0)
multipart-post (2.1.1)
mustache (1.1.1)
- mustermann (1.0.3)
+ mustermann (1.1.1)
+ ruby2_keywords (~> 0.0.1)
mysql2 (0.5.3)
- mysql2 (0.5.3-x64-mingw32)
- mysql2 (0.5.3-x86-mingw32)
- nio4r (2.5.2)
- nio4r (2.5.2-java)
- nokogiri (1.10.7)
- mini_portile2 (~> 2.4.0)
- nokogiri (1.10.7-java)
- nokogiri (1.10.7-x64-mingw32)
- mini_portile2 (~> 2.4.0)
- nokogiri (1.10.7-x86-mingw32)
- mini_portile2 (~> 2.4.0)
- os (1.0.1)
- parallel (1.19.1)
- parser (2.6.5.0)
- ast (~> 2.4.0)
+ net-imap (0.2.3)
+ digest
+ net-protocol
+ strscan
+ net-pop (0.1.1)
+ digest
+ net-protocol
+ timeout
+ net-protocol (0.1.3)
+ timeout
+ net-smtp (0.3.1)
+ digest
+ net-protocol
+ timeout
+ nio4r (2.5.7)
+ nokogiri (1.11.3)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.4)
+ os (1.1.1)
+ parallel (1.20.1)
+ parser (3.0.1.1)
+ ast (~> 2.4.1)
path_expander (1.1.0)
- pg (1.2.0)
- pg (1.2.0-x64-mingw32)
- pg (1.2.0-x86-mingw32)
- psych (3.1.0)
- public_suffix (4.0.2)
- puma (4.3.1)
- nio4r (~> 2.0)
- puma (4.3.1-java)
+ pg (1.2.3)
+ public_suffix (4.0.6)
+ puma (5.2.2)
nio4r (~> 2.0)
que (0.14.3)
qunit-selenium (0.0.4)
selenium-webdriver
thor
- raabro (1.1.6)
- racc (1.4.16)
- rack (2.2.1)
- rack-cache (1.10.0)
+ raabro (1.4.0)
+ racc (1.5.2)
+ rack (2.2.3)
+ rack-cache (1.12.1)
rack (>= 0.4)
- rack-protection (2.0.7)
+ rack-protection (2.1.0)
rack
rack-proxy (0.6.5)
rack
@@ -374,22 +374,20 @@ GEM
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
- rails-html-sanitizer (1.3.0)
- loofah (~> 2.3)
+ rails-html-sanitizer (1.4.4)
+ loofah (~> 2.19, >= 2.19.1)
rainbow (3.0.0)
- rake (13.0.1)
- rb-fsevent (0.10.3)
+ rake (13.0.3)
+ rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
- rdoc (6.2.1)
+ rdoc (6.3.1)
redcarpet (3.2.3)
- redis (4.1.3)
- redis-namespace (1.7.0)
- redis (>= 3.0.4)
- regexp_parser (1.6.0)
- representable (3.0.4)
+ redis (4.2.5)
+ regexp_parser (2.1.1)
+ representable (3.1.1)
declarative (< 0.1.0)
- declarative-option (< 0.2.0)
+ trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
resque (2.0.0)
mono_logger (~> 1.0)
@@ -403,33 +401,35 @@ GEM
resque (>= 1.26)
rufus-scheduler (~> 3.2)
retriable (3.1.2)
- rexml (3.2.3)
- rubocop (0.78.0)
- jaro_winkler (~> 1.5.1)
+ rexml (3.2.5)
+ rubocop (1.14.0)
parallel (~> 1.10)
- parser (>= 2.6)
+ parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 1.8, < 3.0)
+ rexml
+ rubocop-ast (>= 1.5.0, < 2.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (>= 1.4.0, < 1.7)
- rubocop-performance (1.5.2)
- rubocop (>= 0.71.0)
- rubocop-rails (2.4.1)
+ unicode-display_width (>= 1.4.0, < 3.0)
+ rubocop-ast (1.5.0)
+ parser (>= 3.0.1.1)
+ rubocop-performance (1.11.2)
+ rubocop (>= 1.7.0, < 2.0)
+ rubocop-ast (>= 0.4.0)
+ rubocop-rails (2.10.0)
+ activesupport (>= 4.2.0)
rack (>= 1.1)
- rubocop (>= 0.72.0)
- ruby-progressbar (1.10.1)
- ruby-vips (2.0.16)
- ffi (~> 1.9)
- rubyzip (2.0.0)
- rufus-scheduler (3.6.0)
+ rubocop (>= 1.7.0, < 2.0)
+ ruby-progressbar (1.11.0)
+ ruby-vips (2.1.0)
+ ffi (~> 1.12)
+ ruby2_keywords (0.0.4)
+ rubyzip (2.3.0)
+ rufus-scheduler (3.7.0)
fugit (~> 1.1, >= 1.1.6)
- safe_yaml (1.0.5)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
- sassc (2.2.1)
- ffi (~> 1.9)
- sassc (2.2.1-x64-mingw32)
- ffi (~> 1.9)
- sassc (2.2.1-x86-mingw32)
+ sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
@@ -439,27 +439,28 @@ GEM
tilt
sdoc (1.1.0)
rdoc (>= 5.0)
- selenium-webdriver (3.142.7)
- childprocess (>= 0.5, < 4.0)
+ selenium-webdriver (4.0.0.beta3)
+ childprocess (>= 0.5, < 5.0)
+ rexml (~> 3.2)
rubyzip (>= 1.2.2)
- sequel (5.27.0)
+ websocket (~> 1.0)
+ sequel (5.44.0)
serverengine (2.0.7)
sigdump (~> 0.2.2)
- sidekiq (6.0.4)
+ sidekiq (6.2.1)
connection_pool (>= 2.2.2)
- rack (>= 2.0.0)
- rack-protection (>= 2.0.0)
- redis (>= 4.1.0)
+ rack (~> 2.0)
+ redis (>= 4.2.0)
sigdump (0.2.4)
- signet (0.12.0)
+ signet (0.15.0)
addressable (~> 2.3)
- faraday (~> 0.9)
+ faraday (>= 0.17.3, < 2.0)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
- sinatra (2.0.7)
+ sinatra (2.1.0)
mustermann (~> 1.0)
- rack (~> 2.0)
- rack-protection (= 2.0.7)
+ rack (~> 2.2)
+ rack-protection (= 2.1.0)
tilt (~> 2.0)
sneakers (2.11.0)
bunny (~> 2.12)
@@ -467,69 +468,68 @@ GEM
rake
serverengine (~> 2.0.5)
thor
- sprockets (4.0.0)
+ sprockets (4.0.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-export (1.0.0)
- sprockets-rails (3.2.1)
+ sprockets-rails (3.2.2)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.4.2)
- stackprof (0.2.15)
- sucker_punch (2.1.2)
+ stackprof (0.2.17)
+ strscan (3.0.4)
+ sucker_punch (3.0.1)
concurrent-ruby (~> 1.0)
- thin (1.7.2)
+ thin (1.8.0)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
- thor (1.0.1)
+ thor (1.1.0)
thread_safe (0.3.6)
- thread_safe (0.3.6-java)
tilt (2.0.10)
+ timeout (0.3.0)
+ trailblazer-option (0.1.1)
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
- tzinfo (1.2.6)
+ tzinfo (1.2.9)
thread_safe (~> 0.1)
- tzinfo-data (1.2019.3)
- tzinfo (>= 1.0.0)
uber (0.1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
- unicode-display_width (1.6.0)
+ unicode-display_width (2.0.0)
useragent (0.16.10)
vegas (0.1.11)
rack (>= 1.0.0)
- w3c_validators (1.3.4)
+ w3c_validators (1.3.6)
json (>= 1.8)
nokogiri (~> 1.6)
- wdm (0.1.1)
- webdrivers (4.1.3)
+ rexml (~> 3.2)
+ webdrivers (4.6.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
- webmock (3.7.6)
+ webmock (3.12.2)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
- webpacker (4.2.2)
+ webpacker (4.3.0)
activesupport (>= 4.2)
rack-proxy (>= 0.6.1)
railties (>= 4.2)
- websocket (1.2.8)
- websocket-driver (0.7.1)
+ webrick (1.7.0)
+ websocket (1.2.9)
+ websocket-driver (0.7.3)
websocket-extensions (>= 0.1.0)
- websocket-extensions (0.1.4)
+ websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.4.0)
+ zeitwerk (2.6.6)
PLATFORMS
- java
ruby
- x64-mingw32
- x86-mingw32
+ x86_64-darwin-19
DEPENDENCIES
activerecord-jdbcmysql-adapter (>= 1.3.0)
@@ -556,25 +556,31 @@ DEPENDENCIES
json (>= 2.0.0)
kindlerb (~> 1.2.0)
libxml-ruby
- listen (~> 3.2)
+ listen (~> 3.2)!
+ matrix
+ minitest (< 5.15.0)
minitest-bisect
minitest-reporters
minitest-retry
mysql2 (>= 0.4.10)
+ net-imap
+ net-pop
+ net-smtp
nokogiri (>= 1.8.1)
pg (>= 0.18.0)
psych (~> 3.0)
puma
- que
+ que (<= 0.14.3)
queue_classic!
qunit-selenium
racc (>= 1.4.6)
rack-cache (~> 1.2)
+ rack-test (< 2)
rails!
rake (>= 11.1)
redcarpet (~> 3.2.3)
redis (~> 4.0)
- redis-namespace
+ redis-namespace!
resque
resque-scheduler
rexml
@@ -583,7 +589,7 @@ DEPENDENCIES
rubocop-rails
sass-rails
sdoc (~> 1.1)
- selenium-webdriver (>= 3.141.592)
+ selenium-webdriver (>= 4.0.0.alpha7)
sequel
sidekiq
sneakers
@@ -594,12 +600,13 @@ DEPENDENCIES
turbolinks (~> 5)
tzinfo-data
uglifier (>= 1.3.0)
- w3c_validators
+ w3c_validators (~> 1.3.6)
wdm (>= 0.1.0)
webdrivers
webmock
webpacker (~> 4.0)
+ webrick
websocket-client-simple!
BUNDLED WITH
- 2.1.4
+ 2.2.32
diff --git a/RAILS_VERSION b/RAILS_VERSION
index b78e7815ba447..039be6a33fed0 100644
--- a/RAILS_VERSION
+++ b/RAILS_VERSION
@@ -1 +1 @@
-6.0.3.3
+6.0.6.1
diff --git a/README.md b/README.md
index c18a0d782617a..b51feb181c527 100644
--- a/README.md
+++ b/README.md
@@ -96,7 +96,7 @@ Everyone interacting in Rails and its sub-projects' codebases, issue trackers, c
## Code Status
-[](https://buildkite.com/rails/rails)
+[](https://buildkite.com/rails/rails)
## License
diff --git a/RELEASING_RAILS.md b/RELEASING_RAILS.md
index cd850e6ddf104..ecdfd7e3e8c60 100644
--- a/RELEASING_RAILS.md
+++ b/RELEASING_RAILS.md
@@ -93,7 +93,7 @@ You can review the commits for the 3.0.10 release like this:
```
If you're doing a stable branch release, you should also ensure that all of
-the CHANGELOG entries in the stable branch are also synced to the master
+the CHANGELOG entries in the stable branch are also synced to the main
branch.
### Put the new version in the RAILS_VERSION file.
@@ -158,7 +158,7 @@ break existing applications.
If you used Markdown format for your email, you can just paste it into the
blog.
-* https://weblog.rubyonrails.org
+* https://rubyonrails.org/blog
### Post the announcement to the Rails Twitter account.
diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md
index 99ee7ed4c26d5..093c484f8d53d 100644
--- a/actioncable/CHANGELOG.md
+++ b/actioncable/CHANGELOG.md
@@ -1,3 +1,93 @@
+## Rails 6.0.6.1 (January 17, 2023) ##
+
+* No changes.
+
+
+## Rails 6.0.6 (September 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5.1 (July 12, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5 (May 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.8 (April 26, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.7 (March 08, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.6 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.5 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.4 (December 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.3 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.2 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.1 (August 19, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4 (June 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.7 (May 05, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.6 (May 04, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.6 (March 26, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.5 (February 10, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.4 (October 07, 2020) ##
+
+* No changes.
+
+
## Rails 6.0.3.3 (September 09, 2020) ##
* No changes.
diff --git a/actioncable/actioncable.gemspec b/actioncable/actioncable.gemspec
index 60751c3dfee17..ecfcd931c3d59 100644
--- a/actioncable/actioncable.gemspec
+++ b/actioncable/actioncable.gemspec
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
"documentation_uri" => "https://api.rubyonrails.org/v#{version}/",
"mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk",
"source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actioncable",
+ "rubygems_mfa_required" => "true",
}
# NOTE: Please read our dependency guidelines before updating versions:
diff --git a/actioncable/lib/action_cable/gem_version.rb b/actioncable/lib/action_cable/gem_version.rb
index beadc28443866..53b335374b726 100644
--- a/actioncable/lib/action_cable/gem_version.rb
+++ b/actioncable/lib/action_cable/gem_version.rb
@@ -9,8 +9,8 @@ def self.gem_version
module VERSION
MAJOR = 6
MINOR = 0
- TINY = 3
- PRE = "3"
+ TINY = 6
+ PRE = "1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/actioncable/package.json b/actioncable/package.json
index 358ea3aebfa51..e99aaa65b6b8f 100644
--- a/actioncable/package.json
+++ b/actioncable/package.json
@@ -1,6 +1,6 @@
{
"name": "@rails/actioncable",
- "version": "6.0.3-3",
+ "version": "6.0.6-1",
"description": "WebSocket framework for Ruby on Rails.",
"main": "app/assets/javascripts/action_cable.js",
"files": [
diff --git a/actionmailbox/CHANGELOG.md b/actionmailbox/CHANGELOG.md
index 3797bd89a297f..2b7a12dbd5501 100644
--- a/actionmailbox/CHANGELOG.md
+++ b/actionmailbox/CHANGELOG.md
@@ -1,3 +1,88 @@
+## Rails 6.0.6.1 (January 17, 2023) ##
+
+* No changes.
+
+
+## Rails 6.0.6 (September 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5.1 (July 12, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5 (May 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.8 (April 26, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.7 (March 08, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.6 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.5 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.4 (December 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.3 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.2 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.1 (August 19, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4 (June 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.7 (May 05, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.6 (March 26, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.5 (February 10, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.4 (October 07, 2020) ##
+
+* No changes.
+
+
## Rails 6.0.3.3 (September 09, 2020) ##
* No changes.
diff --git a/actionmailbox/actionmailbox.gemspec b/actionmailbox/actionmailbox.gemspec
index 47501b1cd19e9..18786628578b6 100644
--- a/actionmailbox/actionmailbox.gemspec
+++ b/actionmailbox/actionmailbox.gemspec
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
"documentation_uri" => "https://api.rubyonrails.org/v#{version}/",
"mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk",
"source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionmailbox",
+ "rubygems_mfa_required" => "true",
}
# NOTE: Please read our dependency guidelines before updating versions:
diff --git a/actionmailbox/lib/action_mailbox/gem_version.rb b/actionmailbox/lib/action_mailbox/gem_version.rb
index 8e03f9ce978a7..d8fdfcfe661bc 100644
--- a/actionmailbox/lib/action_mailbox/gem_version.rb
+++ b/actionmailbox/lib/action_mailbox/gem_version.rb
@@ -9,8 +9,8 @@ def self.gem_version
module VERSION
MAJOR = 6
MINOR = 0
- TINY = 3
- PRE = "3"
+ TINY = 6
+ PRE = "1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index 382c9c4bf2767..0b2396e0d87df 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1,3 +1,88 @@
+## Rails 6.0.6.1 (January 17, 2023) ##
+
+* No changes.
+
+
+## Rails 6.0.6 (September 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5.1 (July 12, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5 (May 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.8 (April 26, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.7 (March 08, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.6 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.5 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.4 (December 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.3 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.2 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.1 (August 19, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4 (June 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.7 (May 05, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.6 (March 26, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.5 (February 10, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.4 (October 07, 2020) ##
+
+* No changes.
+
+
## Rails 6.0.3.3 (September 09, 2020) ##
* No changes.
diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc
index f9c84b4232c8f..d55459de86fc3 100644
--- a/actionmailer/README.rdoc
+++ b/actionmailer/README.rdoc
@@ -116,7 +116,7 @@ The latest version of Action Mailer can be installed with RubyGems:
Source code can be downloaded as part of the Rails project on GitHub:
-* https://github.com/rails/rails/tree/master/actionmailer
+* https://github.com/rails/rails/tree/main/actionmailer
== License
diff --git a/actionmailer/actionmailer.gemspec b/actionmailer/actionmailer.gemspec
index 5cce629dbe8f8..dd550ec11159b 100644
--- a/actionmailer/actionmailer.gemspec
+++ b/actionmailer/actionmailer.gemspec
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
"documentation_uri" => "https://api.rubyonrails.org/v#{version}/",
"mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk",
"source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionmailer",
+ "rubygems_mfa_required" => "true",
}
# NOTE: Please read our dependency guidelines before updating versions:
diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb
index 5ef8dadcb5676..20c1929b53144 100644
--- a/actionmailer/lib/action_mailer/gem_version.rb
+++ b/actionmailer/lib/action_mailer/gem_version.rb
@@ -9,8 +9,8 @@ def self.gem_version
module VERSION
MAJOR = 6
MINOR = 0
- TINY = 3
- PRE = "3"
+ TINY = 6
+ PRE = "1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 8afc64bd2c185..49ce2936a76db 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,138 @@
+## Rails 6.0.6.1 (January 17, 2023) ##
+
+* No changes.
+
+
+## Rails 6.0.6 (September 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5.1 (July 12, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5 (May 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.8 (April 26, 2022) ##
+
+* Allow Content Security Policy DSL to generate for API responses.
+
+ *Tim Wade*
+
+## Rails 6.0.4.7 (March 08, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.6 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.5 (February 11, 2022) ##
+
+* Under certain circumstances, the middleware isn't informed that the
+ response body has been fully closed which result in request state not
+ being fully reset before the next request
+
+ [CVE-2022-23633]
+
+
+## Rails 6.0.4.4 (December 15, 2021) ##
+
+* Fix issue with host protection not allowing host with port in development.
+
+
+## Rails 6.0.4.3 (December 14, 2021) ##
+
+* Fix issue with host protection not allowing localhost in development.
+
+
+## Rails 6.0.4.2 (December 14, 2021) ##
+
+* Fix X_FORWARDED_HOST protection. [CVE-2021-44528]
+
+## Rails 6.1.4.1 (August 19, 2021) ##
+
+* [CVE-2021-22942] Fix possible open redirect in Host Authorization middleware.
+
+ Specially crafted "X-Forwarded-Host" headers in combination with certain
+ "allowed host" formats can cause the Host Authorization middleware in Action
+ Pack to redirect users to a malicious website.
+
+## Rails 6.0.4 (June 15, 2021) ##
+
+* Accept base64_urlsafe CSRF tokens to make forward compatible.
+
+ Base64 strict-encoded CSRF tokens are not inherently websafe, which makes
+ them difficult to deal with. For example, the common practice of sending
+ the CSRF token to a browser in a client-readable cookie does not work properly
+ out of the box: the value has to be url-encoded and decoded to survive transport.
+
+ In Rails 6.1, we generate Base64 urlsafe-encoded CSRF tokens, which are inherently
+ safe to transport. Validation accepts both urlsafe tokens, and strict-encoded
+ tokens for backwards compatibility.
+
+ In Rails 5.2.5, the CSRF token format is accidentally changed to urlsafe-encoded.
+ If you upgrade apps from 5.2.5, set the config `urlsafe_csrf_tokens = true`.
+
+ ```ruby
+ Rails.application.config.action_controller.urlsafe_csrf_tokens = true
+ ```
+
+ *Scott Blum*, *Étienne Barrié*
+
+* Signed and encrypted cookies can now store `false` as their value when
+ `action_dispatch.use_cookies_with_metadata` is enabled.
+
+ *Rolandas Barysas*
+
+
+## Rails 6.0.3.7 (May 05, 2021) ##
+
+* Prevent catastrophic backtracking during mime parsing
+ CVE-2021-22902
+
+* Prevent regex DoS in HTTP token authentication
+ CVE-2021-22904
+
+* Prevent string polymorphic route arguments.
+
+ `url_for` supports building polymorphic URLs via an array
+ of arguments (usually symbols and records). If a developer passes a
+ user input array, strings can result in unwanted route helper calls.
+
+ CVE-2021-22885
+
+ *Gannon McGibbon*
+
+## Rails 6.0.3.6 (March 26, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.5 (February 10, 2021) ##
+
+* Prevent open redirect when allowed host starts with a dot
+
+ [CVE-2021-22881]
+
+ Thanks to @tktech (https://hackerone.com/tktech) for reporting this
+ issue and the patch!
+
+ *Aaron Patterson*
+
+
+## Rails 6.0.3.4 (October 07, 2020) ##
+
+* [CVE-2020-8264] Prevent XSS in Actionable Exceptions
+
+
## Rails 6.0.3.3 (September 09, 2020) ##
* No changes.
@@ -13,6 +148,7 @@
* [CVE-2020-8164] Return self when calling #each, #each_pair, and #each_value instead of the raw @parameters hash
+
## Rails 6.0.3 (May 06, 2020) ##
* Include child session assertion count in ActionDispatch::IntegrationTest
diff --git a/actionpack/README.rdoc b/actionpack/README.rdoc
index 67d0c62a84815..30b52efb37c52 100644
--- a/actionpack/README.rdoc
+++ b/actionpack/README.rdoc
@@ -33,7 +33,7 @@ The latest version of Action Pack can be installed with RubyGems:
Source code can be downloaded as part of the Rails project on GitHub:
-* https://github.com/rails/rails/tree/master/actionpack
+* https://github.com/rails/rails/tree/main/actionpack
== License
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index 332f861acda1b..1dcbc5b67f61b 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
"documentation_uri" => "https://api.rubyonrails.org/v#{version}/",
"mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk",
"source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actionpack",
+ "rubygems_mfa_required" => "true",
}
# NOTE: Please read our dependency guidelines before updating versions:
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 6a274d35cb64d..97cafbe46fa47 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -405,7 +405,7 @@ def opaque(secret_key)
module Token
TOKEN_KEY = "token="
TOKEN_REGEX = /^(Token|Bearer)\s+/
- AUTHN_PAIR_DELIMITERS = /(?:,|;|\t+)/
+ AUTHN_PAIR_DELIMITERS = /(?:,|;|\t)/
extend self
module ControllerMethods
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index ba10dfd6baae2..5cf2e7fee285c 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -275,7 +275,10 @@ def _wrapper_enabled?
return false unless request.has_content_type?
ref = request.content_mime_type.ref
+
_wrapper_formats.include?(ref) && _wrapper_key && !request.parameters.key?(_wrapper_key)
+ rescue ActionDispatch::Http::Parameters::ParseError
+ false
end
def _perform_parameter_wrapping
@@ -289,8 +292,6 @@ def _perform_parameter_wrapping
# This will display the wrapped hash in the log file.
request.filtered_parameters.merge! wrapped_filtered_hash
- rescue ActionDispatch::Http::Parameters::ParseError
- # swallow parse error exception
end
end
end
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index c9ec3c051f014..3c7faaf1d1c94 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -32,29 +32,21 @@ class InvalidCrossOriginRequest < ActionControllerError #:nodoc:
# response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or
# Ajax) requests are allowed to make requests for JavaScript responses.
#
- # It's important to remember that XML or JSON requests are also checked by default. If
- # you're building an API or an SPA you could change forgery protection method in
- # ApplicationController (by default: :exception):
+ # Subclasses of ActionController::Base are protected by default with the
+ # :exception strategy, which raises an
+ # ActionController::InvalidAuthenticityToken error on unverified requests.
+ #
+ # APIs may want to disable this behavior since they are typically designed to be
+ # state-less: that is, the request API client handles the session instead of Rails.
+ # One way to achieve this is to use the :null_session strategy instead,
+ # which allows unverified requests to be handled, but with an empty session:
#
# class ApplicationController < ActionController::Base
- # protect_from_forgery unless: -> { request.format.json? }
+ # protect_from_forgery with: :null_session
# end
#
- # It is generally safe to exclude XHR requests from CSRF protection
- # (like the code snippet above does), because XHR requests can only be made from
- # the same origin. Note however that any cross-origin third party domain
- # allowed via {CORS}[https://en.wikipedia.org/wiki/Cross-origin_resource_sharing]
- # will also be able to create XHR requests. Be sure to check your
- # CORS configuration before disabling forgery protection for XHR.
- #
- # CSRF protection is turned on with the protect_from_forgery method.
- # By default protect_from_forgery protects your session with
- # :null_session method, which provides an empty session
- # during request.
- #
- # We may want to disable CSRF protection for APIs since they are typically
- # designed to be state-less. That is, the request API client will handle
- # the session for you instead of Rails.
+ # Note that API only applications don't include this module or a session middleware
+ # by default, and so don't require CSRF protection to be configured.
#
# The token parameter is named authenticity_token by default. The name and
# value of this token must be added to every layout that renders forms by including
@@ -98,6 +90,10 @@ module RequestForgeryProtection
config_accessor :default_protect_from_forgery
self.default_protect_from_forgery = false
+ # Controls whether URL-safe CSRF tokens are generated.
+ config_accessor :urlsafe_csrf_tokens, instance_writer: false
+ self.urlsafe_csrf_tokens = false
+
helper_method :form_authenticity_token
helper_method :protect_against_forgery?
end
@@ -337,7 +333,7 @@ def valid_authenticity_token?(session, encoded_masked_token) # :doc:
end
begin
- masked_token = Base64.strict_decode64(encoded_masked_token)
+ masked_token = decode_csrf_token(encoded_masked_token)
rescue ArgumentError # encoded_masked_token is invalid Base64
return false
end
@@ -375,7 +371,7 @@ def mask_token(raw_token) # :doc:
one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
masked_token = one_time_pad + encrypted_csrf_token
- Base64.strict_encode64(masked_token)
+ encode_csrf_token(masked_token)
end
def compare_with_real_token(token, session) # :doc:
@@ -401,8 +397,8 @@ def valid_per_form_csrf_token?(token, session) # :doc:
end
def real_csrf_token(session) # :doc:
- session[:_csrf_token] ||= SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH)
- Base64.strict_decode64(session[:_csrf_token])
+ session[:_csrf_token] ||= generate_csrf_token
+ decode_csrf_token(session[:_csrf_token])
end
def per_form_csrf_token(session, action_path, method) # :doc:
@@ -470,5 +466,33 @@ def normalize_action_path(action_path) # :doc:
uri = URI.parse(action_path)
uri.path.chomp("/")
end
+
+ def generate_csrf_token # :nodoc:
+ if urlsafe_csrf_tokens
+ SecureRandom.urlsafe_base64(AUTHENTICITY_TOKEN_LENGTH, padding: false)
+ else
+ SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH)
+ end
+ end
+
+ def encode_csrf_token(csrf_token) # :nodoc:
+ if urlsafe_csrf_tokens
+ Base64.urlsafe_encode64(csrf_token, padding: false)
+ else
+ Base64.strict_encode64(csrf_token)
+ end
+ end
+
+ def decode_csrf_token(encoded_csrf_token) # :nodoc:
+ if urlsafe_csrf_tokens
+ Base64.urlsafe_decode64(encoded_csrf_token)
+ else
+ begin
+ Base64.strict_decode64(encoded_csrf_token)
+ rescue ArgumentError
+ Base64.urlsafe_decode64(encoded_csrf_token)
+ end
+ end
+ end
end
end
diff --git a/actionpack/lib/action_controller/renderer.rb b/actionpack/lib/action_controller/renderer.rb
index dadf6d3445ea8..43762cdcbd4b5 100644
--- a/actionpack/lib/action_controller/renderer.rb
+++ b/actionpack/lib/action_controller/renderer.rb
@@ -95,6 +95,7 @@ def render(*args)
instance.set_response! controller.make_response!(request)
instance.render_to_string(*args)
end
+ alias_method :render_to_string, :render # :nodoc:
private
def normalize_keys(env)
diff --git a/actionpack/lib/action_dispatch/http/content_disposition.rb b/actionpack/lib/action_dispatch/http/content_disposition.rb
index 58164c15225d8..89b5bb2fa6a00 100644
--- a/actionpack/lib/action_dispatch/http/content_disposition.rb
+++ b/actionpack/lib/action_dispatch/http/content_disposition.rb
@@ -14,13 +14,13 @@ def initialize(disposition:, filename:)
@filename = filename
end
- TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!#$+.^_`|~-]/
+ TRADITIONAL_ESCAPED_CHAR = /[^ A-Za-z0-9!\#$+.^_`|~-]/
def ascii_filename
'filename="' + percent_escape(I18n.transliterate(filename), TRADITIONAL_ESCAPED_CHAR) + '"'
end
- RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!#$&+.^_`|~-]/
+ RFC_5987_ESCAPED_CHAR = /[^A-Za-z0-9!\#$&+.^_`|~-]/
def utf8_filename
"filename*=UTF-8''" + percent_escape(filename, RFC_5987_ESCAPED_CHAR)
diff --git a/actionpack/lib/action_dispatch/http/content_security_policy.rb b/actionpack/lib/action_dispatch/http/content_security_policy.rb
index 7dedecef34c9d..50a3ec4bd11c7 100644
--- a/actionpack/lib/action_dispatch/http/content_security_policy.rb
+++ b/actionpack/lib/action_dispatch/http/content_security_policy.rb
@@ -17,7 +17,6 @@ def call(env)
request = ActionDispatch::Request.new env
_, headers, _ = response = @app.call(env)
- return response unless html_response?(headers)
return response if policy_present?(headers)
if policy = request.content_security_policy
@@ -31,12 +30,6 @@ def call(env)
end
private
- def html_response?(headers)
- if content_type = headers[CONTENT_TYPE]
- content_type =~ /html/
- end
- end
-
def header_name(request)
if request.content_security_policy_report_only
POLICY_REPORT_ONLY
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index a2cac49082c75..653542febc3c7 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -7,6 +7,8 @@ module Http
module MimeNegotiation
extend ActiveSupport::Concern
+ class InvalidType < ::Mime::Type::InvalidMimeType; end
+
RESCUABLE_MIME_FORMAT_ERRORS = [
ActionController::BadRequest,
ActionDispatch::Http::Parameters::ParseError,
@@ -25,6 +27,8 @@ def content_mime_type
nil
end
set_header k, v
+ rescue ::Mime::Type::InvalidMimeType => e
+ raise InvalidType, e.message
end
end
@@ -47,6 +51,8 @@ def accepts
Mime::Type.parse(header)
end
set_header k, v
+ rescue ::Mime::Type::InvalidMimeType => e
+ raise InvalidType, e.message
end
end
diff --git a/actionpack/lib/action_dispatch/http/mime_type.rb b/actionpack/lib/action_dispatch/http/mime_type.rb
index 6719f0c3d9351..a5816924de36b 100644
--- a/actionpack/lib/action_dispatch/http/mime_type.rb
+++ b/actionpack/lib/action_dispatch/http/mime_type.rb
@@ -226,7 +226,7 @@ def unregister(symbol)
MIME_PARAMETER_KEY = "[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
MIME_PARAMETER_VALUE = "#{Regexp.escape('"')}?[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}#{Regexp.escape('"')}?"
MIME_PARAMETER = "\s*\;\s*#{MIME_PARAMETER_KEY}(?:\=#{MIME_PARAMETER_VALUE})?"
- MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?:\s*#{MIME_PARAMETER}\s*)*)\z/
+ MIME_REGEXP = /\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>\s*#{MIME_PARAMETER}\s*)*)\z/
class InvalidMimeType < StandardError; end
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index deb499a6a0de3..909132a05b01f 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -89,7 +89,7 @@ def set_binary_encoding(params, controller, action)
return params unless controller && controller.valid_encoding?
if binary_params_for?(controller, action)
- ActionDispatch::Request::Utils.each_param_value(params) do |param|
+ ActionDispatch::Request::Utils.each_param_value(params.except(:controller, :action)) do |param|
param.force_encoding ::Encoding::ASCII_8BIT
end
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 79058ce6a70cf..6f1430fab866c 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -133,6 +133,8 @@ def key?(key)
HTTP_METHOD_LOOKUP[method] = method.underscore.to_sym
}
+ alias raw_request_method request_method # :nodoc:
+
# Returns the HTTP \method that the application should see.
# In the case where the \method was overridden by a middleware
# (for instance, if a HEAD request was converted to a GET,
diff --git a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb
index 266fd92ce9856..a5ae54296aeec 100644
--- a/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/actionable_exceptions.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "erb"
+require "uri"
require "action_dispatch/http/request"
require "active_support/actionable_error"
@@ -27,7 +28,13 @@ def actionable_request?(request)
end
def redirect_to(location)
- body = "
You are being redirected."
+ uri = URI.parse location
+
+ if uri.relative? || uri.scheme == "http" || uri.scheme == "https"
+ body = "You are being redirected."
+ else
+ return [400, { "Content-Type" => "text/plain" }, ["Invalid redirection URI"]]
+ end
[302, {
"Content-Type" => "text/html; charset=#{Response.default_charset}",
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 41b913af67857..66ffb71abd649 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -458,7 +458,13 @@ def initialize(parent_jar)
def [](name)
if data = @parent_jar[name.to_s]
- parse(name, data, purpose: "cookie.#{name}") || parse(name, data)
+ result = parse(name, data, purpose: "cookie.#{name}")
+
+ if result.nil?
+ parse(name, data)
+ else
+ result
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index ac5131f7b999c..119c9f37cb855 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -63,8 +63,8 @@ def render_exception(request, exception)
if request.get_header("action_dispatch.show_detailed_exceptions")
begin
content_type = request.formats.first
- rescue Mime::Type::InvalidMimeType
- render_for_api_request(Mime[:text], wrapper)
+ rescue ActionDispatch::Http::MimeNegotiation::InvalidType
+ content_type = Mime[:text]
end
if api_request?(content_type)
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index 2da0ef9600a91..b82565847b8f8 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -12,7 +12,7 @@ class ExceptionWrapper
"ActionController::UnknownHttpMethod" => :method_not_allowed,
"ActionController::NotImplemented" => :not_implemented,
"ActionController::UnknownFormat" => :not_acceptable,
- "Mime::Type::InvalidMimeType" => :not_acceptable,
+ "ActionDispatch::Http::MimeNegotiation::InvalidType" => :not_acceptable,
"ActionController::MissingExactTemplate" => :not_acceptable,
"ActionController::InvalidAuthenticityToken" => :unprocessable_entity,
"ActionController::InvalidCrossOriginRequest" => :unprocessable_entity,
diff --git a/actionpack/lib/action_dispatch/middleware/executor.rb b/actionpack/lib/action_dispatch/middleware/executor.rb
index 129b18d3d946a..a32f9162609ba 100644
--- a/actionpack/lib/action_dispatch/middleware/executor.rb
+++ b/actionpack/lib/action_dispatch/middleware/executor.rb
@@ -9,7 +9,7 @@ def initialize(app, executor)
end
def call(env)
- state = @executor.run!
+ state = @executor.run!(reset: true)
begin
response = @app.call(env)
returned = response << ::Rack::BodyProxy.new(response.pop) { state.complete! }
diff --git a/actionpack/lib/action_dispatch/middleware/host_authorization.rb b/actionpack/lib/action_dispatch/middleware/host_authorization.rb
index de7739b9b6807..ca68b0241a769 100644
--- a/actionpack/lib/action_dispatch/middleware/host_authorization.rb
+++ b/actionpack/lib/action_dispatch/middleware/host_authorization.rb
@@ -10,6 +10,17 @@ module ActionDispatch
# application will be executed and rendered. If no +response_app+ is given, a
# default one will run, which responds with +403 Forbidden+.
class HostAuthorization
+ ALLOWED_HOSTS_IN_DEVELOPMENT = [".localhost", IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")]
+ PORT_REGEX = /(?::\d+)/ # :nodoc:
+ IPV4_HOSTNAME = /(?\d+\.\d+\.\d+\.\d+)#{PORT_REGEX}?/ # :nodoc:
+ IPV6_HOSTNAME = /(?[a-f0-9]*:[a-f0-9.:]+)/i # :nodoc:
+ IPV6_HOSTNAME_WITH_PORT = /\[#{IPV6_HOSTNAME}\]#{PORT_REGEX}/i # :nodoc:
+ VALID_IP_HOSTNAME = Regexp.union( # :nodoc:
+ /\A#{IPV4_HOSTNAME}\z/,
+ /\A#{IPV6_HOSTNAME}\z/,
+ /\A#{IPV6_HOSTNAME_WITH_PORT}\z/,
+ )
+
class Permissions # :nodoc:
def initialize(hosts)
@hosts = sanitize_hosts(hosts)
@@ -21,11 +32,17 @@ def empty?
def allows?(host)
@hosts.any? do |allowed|
- allowed === host
- rescue
- # IPAddr#=== raises an error if you give it a hostname instead of
- # IP. Treat similar errors as blocked access.
- false
+ if allowed.is_a?(IPAddr)
+ begin
+ allowed === extract_hostname(host)
+ rescue
+ # IPAddr#=== raises an error if you give it a hostname instead of
+ # IP. Treat similar errors as blocked access.
+ false
+ end
+ else
+ allowed === host
+ end
end
end
@@ -41,16 +58,20 @@ def sanitize_hosts(hosts)
end
def sanitize_regexp(host)
- /\A#{host}\z/
+ /\A#{host}#{PORT_REGEX}?\z/
end
def sanitize_string(host)
if host.start_with?(".")
- /\A(.+\.)?#{Regexp.escape(host[1..-1])}\z/
+ /\A([a-z0-9-]+\.)?#{Regexp.escape(host[1..-1])}#{PORT_REGEX}?\z/i
else
- host
+ /\A#{Regexp.escape host}#{PORT_REGEX}?\z/i
end
end
+
+ def extract_hostname(host)
+ host.slice(VALID_IP_HOSTNAME, "host") || host
+ end
end
DEFAULT_RESPONSE_APP = -> env do
@@ -87,11 +108,10 @@ def call(env)
private
def authorized?(request)
- origin_host = request.get_header("HTTP_HOST").to_s.sub(/:\d+\z/, "")
- forwarded_host = request.x_forwarded_host.to_s.split(/,\s?/).last.to_s.sub(/:\d+\z/, "")
+ origin_host = request.get_header("HTTP_HOST")
+ forwarded_host = request.x_forwarded_host&.split(/,\s?/)&.last
- @permissions.allows?(origin_host) &&
- (forwarded_host.blank? || @permissions.allows?(forwarded_host))
+ @permissions.allows?(origin_host) && (forwarded_host.blank? || @permissions.allows?(forwarded_host))
end
def mark_as_authorized(request)
diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
index 3a2a1d73346ad..4404dbe874bd3 100644
--- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
@@ -23,7 +23,7 @@ def call(env)
status = request.path_info[1..-1].to_i
begin
content_type = request.formats.first
- rescue Mime::Type::InvalidMimeType
+ rescue ActionDispatch::Http::MimeNegotiation::InvalidType
content_type = Mime[:text]
end
body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb
index 1fbc107e288bf..0eed0f9749238 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb
@@ -2,6 +2,6 @@
Blocked host: <%= @host %>
-
To allow requests to <%= @host %>, add the following to your environment configuration:
+
To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:
config.hosts << "<%= @host %>"
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb
index a94dd982a7078..75483ac8c829c 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb
@@ -1,5 +1,5 @@
Blocked host: <%= @host %>
-To allow requests to <%= @host %>, add the following to your environment configuration:
+To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:
config.hosts << "<%= @host %>"
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
index 16c3ecc331d04..99260e54a7497 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb
@@ -6,6 +6,7 @@
<%= @exception.message %>
<% if defined?(ActiveStorage) && @exception.message.match?(%r{#{ActiveStorage::Blob.table_name}|#{ActiveStorage::Attachment.table_name}}) %>
To resolve this issue run: rails active_storage:install
+<% end %>
<% if defined?(ActionMailbox) && @exception.message.match?(%r{#{ActionMailbox::InboundEmail.table_name}}) %>
To resolve this issue run: rails action_mailbox:install
<% end %>
diff --git a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
index e3322e99ab8fb..6f0f5c45110a4 100644
--- a/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
+++ b/actionpack/lib/action_dispatch/routing/polymorphic_routes.rb
@@ -286,10 +286,12 @@ def handle_list(list)
args = []
- route = record_list.map { |parent|
+ route = record_list.map do |parent|
case parent
- when Symbol, String
+ when Symbol
parent.to_s
+ when String
+ raise(ArgumentError, "Please use symbols for polymorphic route arguments.")
when Class
args << parent
parent.model_name.singular_route_key
@@ -297,12 +299,14 @@ def handle_list(list)
args << parent.to_model
parent.to_model.model_name.singular_route_key
end
- }
+ end
route <<
case record
- when Symbol, String
+ when Symbol
record.to_s
+ when String
+ raise(ArgumentError, "Please use symbols for polymorphic route arguments.")
when Class
@key_strategy.call record.model_name
else
diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb
index e02a6541c159c..3160fb117cacd 100644
--- a/actionpack/lib/action_dispatch/routing/url_for.rb
+++ b/actionpack/lib/action_dispatch/routing/url_for.rb
@@ -107,6 +107,7 @@ def initialize(*)
@_routes = nil
super
end
+ ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
# Hook overridden in controller to add request information
# with +default_url_options+. Application logic should not
diff --git a/actionpack/lib/action_dispatch/system_testing/browser.rb b/actionpack/lib/action_dispatch/system_testing/browser.rb
index e861e52f0943c..ab416b4600750 100644
--- a/actionpack/lib/action_dispatch/system_testing/browser.rb
+++ b/actionpack/lib/action_dispatch/system_testing/browser.rb
@@ -64,14 +64,14 @@ def preload
private
def headless_chrome_browser_options
- capabilities.args << "--headless"
- capabilities.args << "--disable-gpu" if Gem.win_platform?
+ capabilities.add_argument("--headless")
+ capabilities.add_argument("--disable-gpu") if Gem.win_platform?
capabilities
end
def headless_firefox_browser_options
- capabilities.args << "-headless"
+ capabilities.add_argument("-headless")
capabilities
end
diff --git a/actionpack/lib/action_pack/gem_version.rb b/actionpack/lib/action_pack/gem_version.rb
index 0e333ee7341ab..7f2440fe41a3e 100644
--- a/actionpack/lib/action_pack/gem_version.rb
+++ b/actionpack/lib/action_pack/gem_version.rb
@@ -9,8 +9,8 @@ def self.gem_version
module VERSION
MAJOR = 6
MINOR = 0
- TINY = 3
- PRE = "3"
+ TINY = 6
+ PRE = "1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb
index 57b78154bc54e..23d83609b92ad 100644
--- a/actionpack/test/controller/http_token_authentication_test.rb
+++ b/actionpack/test/controller/http_token_authentication_test.rb
@@ -88,6 +88,16 @@ def authenticate_long_credentials
assert_equal "HTTP Token: Access denied.\n", @response.body, "Authentication header was not properly parsed"
end
+ test "authentication request with evil header" do
+ @request.env["HTTP_AUTHORIZATION"] = "Token ." + " " * (1024*80-8) + "."
+ Timeout.timeout(1) do
+ get :index
+ end
+
+ assert_response :unauthorized
+ assert_equal "HTTP Token: Access denied.\n", @response.body, "Authentication header was not properly parsed"
+ end
+
test "successful authentication request with Bearer instead of Token" do
@request.env["HTTP_AUTHORIZATION"] = "Bearer lifo"
get :index
diff --git a/actionpack/test/controller/parameter_encoding_test.rb b/actionpack/test/controller/parameter_encoding_test.rb
index e2194e8974dbb..179c643922691 100644
--- a/actionpack/test/controller/parameter_encoding_test.rb
+++ b/actionpack/test/controller/parameter_encoding_test.rb
@@ -15,7 +15,7 @@ def test_bar
end
def test_all_values_encoding
- render body: ::JSON.dump(params.values.map(&:encoding).map(&:name))
+ render body: ::JSON.dump(params.except(:action, :controller).values.map(&:encoding).map(&:name))
end
end
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 7f1c41787ab94..e218ef35e483b 100644
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -116,6 +116,14 @@ def redirect_to_nil
redirect_to nil
end
+ def redirect_to_polymorphic
+ redirect_to [:internal, Workshop.new(5)]
+ end
+
+ def redirect_to_polymorphic_string_args
+ redirect_to ["internal", Workshop.new(5)]
+ end
+
def redirect_to_params
redirect_to ActionController::Parameters.new(status: 200, protocol: "javascript", f: "%0Aeval(name)")
end
@@ -346,6 +354,43 @@ def test_redirect_to_record
end
end
+ def test_polymorphic_redirect
+ with_routing do |set|
+ set.draw do
+ namespace :internal do
+ resources :workshops
+ end
+
+ ActiveSupport::Deprecation.silence do
+ get ":controller/:action"
+ end
+ end
+
+ get :redirect_to_polymorphic
+ assert_equal "http://test.host/internal/workshops/5", redirect_to_url
+ assert_redirected_to [:internal, Workshop.new(5)]
+ end
+ end
+
+ def test_polymorphic_redirect_with_string_args
+ with_routing do |set|
+ set.draw do
+ namespace :internal do
+ resources :workshops
+ end
+
+ ActiveSupport::Deprecation.silence do
+ get ":controller/:action"
+ end
+ end
+
+ error = assert_raises(ArgumentError) do
+ get :redirect_to_polymorphic_string_args
+ end
+ assert_equal("Please use symbols for polymorphic route arguments.", error.message)
+ end
+ end
+
def test_redirect_to_nil
error = assert_raise(ActionController::ActionControllerError) do
get :redirect_to_nil
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 10de9bcc3e533..1ad48b5cf69f3 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -175,12 +175,15 @@ class SkipProtectionController < ActionController::Base
# common test methods
module RequestForgeryProtectionTests
def setup
- @token = Base64.strict_encode64("railstestrailstestrailstestrails")
+ @old_urlsafe_csrf_tokens = ActionController::Base.urlsafe_csrf_tokens
+ ActionController::Base.urlsafe_csrf_tokens = true
+ @token = Base64.urlsafe_encode64("railstestrailstestrailstestrails")
@old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token
ActionController::Base.request_forgery_protection_token = :custom_authenticity_token
end
def teardown
+ ActionController::Base.urlsafe_csrf_tokens = @old_urlsafe_csrf_tokens
ActionController::Base.request_forgery_protection_token = @old_request_forgery_protection_token
end
@@ -377,6 +380,28 @@ def test_should_allow_post_with_token
end
end
+ def test_should_allow_post_with_strict_encoded_token
+ token_length = (ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH * 4.0 / 3).ceil
+ token_including_url_unsafe_chars = "+/".ljust(token_length, "A")
+ session[:_csrf_token] = token_including_url_unsafe_chars
+ @controller.stub :form_authenticity_token, token_including_url_unsafe_chars do
+ assert_not_blocked { post :index, params: { custom_authenticity_token: token_including_url_unsafe_chars } }
+ end
+ end
+
+ def test_should_allow_post_with_urlsafe_token_when_migrating
+ config_before = ActionController::Base.urlsafe_csrf_tokens
+ ActionController::Base.urlsafe_csrf_tokens = false
+ token_length = (ActionController::RequestForgeryProtection::AUTHENTICITY_TOKEN_LENGTH * 4.0 / 3).ceil
+ token_including_url_safe_chars = "-_".ljust(token_length, "A")
+ session[:_csrf_token] = token_including_url_safe_chars
+ @controller.stub :form_authenticity_token, token_including_url_safe_chars do
+ assert_not_blocked { post :index, params: { custom_authenticity_token: token_including_url_safe_chars } }
+ end
+ ensure
+ ActionController::Base.urlsafe_csrf_tokens = config_before
+ end
+
def test_should_allow_patch_with_token
session[:_csrf_token] = @token
@controller.stub :form_authenticity_token, @token do
@@ -735,21 +760,21 @@ def setup
end
def test_should_not_render_form_with_token_tag
- SecureRandom.stub :base64, @token do
+ SecureRandom.stub :urlsafe_base64, @token do
get :index
assert_select "form>div>input[name=?][value=?]", "authenticity_token", @token, false
end
end
def test_should_not_render_button_to_with_token_tag
- SecureRandom.stub :base64, @token do
+ SecureRandom.stub :urlsafe_base64, @token do
get :show_button
assert_select "form>div>input[name=?][value=?]", "authenticity_token", @token, false
end
end
def test_should_allow_all_methods_without_token
- SecureRandom.stub :base64, @token do
+ SecureRandom.stub :urlsafe_base64, @token do
[:post, :patch, :put, :delete].each do |method|
assert_nothing_raised { send(method, :index) }
end
@@ -757,7 +782,7 @@ def test_should_allow_all_methods_without_token
end
test "should not emit a csrf-token meta tag" do
- SecureRandom.stub :base64, @token do
+ SecureRandom.stub :urlsafe_base64, @token do
get :meta
assert_predicate @response.body, :blank?
end
@@ -769,7 +794,7 @@ def setup
super
@old_logger = ActionController::Base.logger
@logger = ActiveSupport::LogSubscriber::TestHelper::MockLogger.new
- @token = Base64.strict_encode64(SecureRandom.random_bytes(32))
+ @token = Base64.urlsafe_encode64(SecureRandom.random_bytes(32))
@old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token
ActionController::Base.request_forgery_protection_token = @token
end
@@ -1029,7 +1054,7 @@ def assert_presence_and_fetch_form_csrf_token
end
def assert_matches_session_token_on_server(form_token, method = "post")
- actual = @controller.send(:unmask_token, Base64.strict_decode64(form_token))
+ actual = @controller.send(:unmask_token, Base64.urlsafe_decode64(form_token))
expected = @controller.send(:per_form_csrf_token, session, "/per_form_tokens/post_one", method)
assert_equal expected, actual
end
diff --git a/actionpack/test/controller/rescue_test.rb b/actionpack/test/controller/rescue_test.rb
index 538bc15fc9ea9..fe691af2aedef 100644
--- a/actionpack/test/controller/rescue_test.rb
+++ b/actionpack/test/controller/rescue_test.rb
@@ -33,6 +33,8 @@ class ResourceUnavailable < StandardError
class ResourceUnavailableToRescueAsString < StandardError
end
+ wrap_parameters format: :json
+
# We use a fully qualified name in some strings, and a relative constant
# name in some other to test correct handling of both cases.
diff --git a/actionpack/test/dispatch/content_disposition_test.rb b/actionpack/test/dispatch/content_disposition_test.rb
index 3f5959da6e31b..6e1aae24fef95 100644
--- a/actionpack/test/dispatch/content_disposition_test.rb
+++ b/actionpack/test/dispatch/content_disposition_test.rb
@@ -28,6 +28,14 @@ class ContentDispositionTest < ActiveSupport::TestCase
assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
end
+ test "encoding a filename with permitted chars" do
+ disposition = Http::ContentDisposition.new(disposition: :inline, filename: "argh+!#$-123_|&^`~.jpg")
+
+ assert_equal %(filename="argh+!\#$-123_|%26^`~.jpg"), disposition.ascii_filename
+ assert_equal "filename*=UTF-8''argh+!\#$-123_|&^`~.jpg", disposition.utf8_filename
+ assert_equal "inline; #{disposition.ascii_filename}; #{disposition.utf8_filename}", disposition.to_s
+ end
+
test "without filename" do
disposition = Http::ContentDisposition.new(disposition: :inline, filename: nil)
diff --git a/actionpack/test/dispatch/content_security_policy_test.rb b/actionpack/test/dispatch/content_security_policy_test.rb
index a4634626bb6b8..9fd49ead241b4 100644
--- a/actionpack/test/dispatch/content_security_policy_test.rb
+++ b/actionpack/test/dispatch/content_security_policy_test.rb
@@ -353,6 +353,11 @@ class PolicyController < ActionController::Base
content_security_policy_report_only only: :report_only
+ content_security_policy only: :api do |p|
+ p.default_src :none
+ p.frame_ancestors :none
+ end
+
def index
head :ok
end
@@ -381,6 +386,10 @@ def no_policy
head :ok
end
+ def api
+ render json: {}
+ end
+
private
def condition?
params[:condition] == "true"
@@ -397,6 +406,7 @@ def condition?
get "/script-src", to: "policy#script_src"
get "/style-src", to: "policy#style_src"
get "/no-policy", to: "policy#no_policy"
+ get "/api", to: "policy#api"
end
end
@@ -468,6 +478,11 @@ def test_generates_no_content_security_policy
assert_nil response.headers["Content-Security-Policy-Report-Only"]
end
+ def test_generates_api_security_policy
+ get "/api"
+ assert_policy "default-src 'none'; frame-ancestors 'none'"
+ end
+
private
def assert_policy(expected, report_only: false)
assert_response :success
diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb
index 446aa8e37dc78..16b21103b83ae 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -1185,6 +1185,20 @@ def test_vanilla_cookie_with_expires_set_relatively
end
end
+ def test_signed_cookie_with_false_value_and_metadata
+ request.env["action_dispatch.use_cookies_with_metadata"] = true
+
+ cookies.signed[:foo] = false
+ assert_equal false, cookies.signed[:foo]
+ end
+
+ def test_encrypted_cookie_with_false_value_and_metadata
+ request.env["action_dispatch.use_cookies_with_metadata"] = true
+
+ cookies.encrypted[:foo] = false
+ assert_equal false, cookies.encrypted[:foo]
+ end
+
def test_purpose_metadata_for_encrypted_cookies
get :encrypted_discount_and_user_id_cookie
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index 9911690f2bf35..8ad20fc1a43d1 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -81,7 +81,7 @@ def call(env)
when "/unprocessable_entity"
raise ActionController::InvalidAuthenticityToken
when "/invalid_mimetype"
- raise Mime::Type::InvalidMimeType
+ raise ActionDispatch::Http::MimeNegotiation::InvalidType
when "/not_found_original_exception"
begin
raise AbstractController::ActionNotFound.new
@@ -137,6 +137,7 @@ def call(env)
DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp)
InterceptedApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :default, [Interceptor])
BadInterceptedApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :default, [BadInterceptor])
+ ApiApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
test "skip diagnosis if not showing detailed exceptions" do
@app = ProductionApp
@@ -215,7 +216,7 @@ def call(env)
get "/invalid_mimetype", headers: { "Accept" => "text/html,*", "action_dispatch.show_exceptions" => true }
assert_response 406
- assert_match(/Mime::Type::InvalidMimeType/, body)
+ assert_match(/ActionDispatch::Http::MimeNegotiation::InvalidType/, body)
end
test "rescue with text error for xhr request" do
@@ -269,7 +270,7 @@ def call(env)
end
test "rescue with JSON error for JSON API request" do
- @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
+ @app = ApiApp
get "/", headers: { "action_dispatch.show_exceptions" => true }, as: :json
assert_response 500
@@ -307,10 +308,16 @@ def call(env)
assert_no_match(//, body)
assert_equal "application/json", response.media_type
assert_match(/ActionController::ParameterMissing/, body)
+
+ get "/invalid_mimetype", headers: { "Accept" => "text/html,*", "action_dispatch.show_exceptions" => true }, as: :json
+ assert_response 406
+ assert_no_match(//, body)
+ assert_equal "application/json", response.media_type
+ assert_match(/ActionDispatch::Http::MimeNegotiation::InvalidType/, body)
end
test "rescue with HTML format for HTML API request" do
- @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
+ @app = ApiApp
get "/index.html", headers: { "action_dispatch.show_exceptions" => true }
assert_response 500
@@ -321,7 +328,7 @@ def call(env)
end
test "rescue with XML format for XML API requests" do
- @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
+ @app = ApiApp
get "/index.xml", headers: { "action_dispatch.show_exceptions" => true }
assert_response 500
@@ -335,7 +342,7 @@ def call(env)
ActionDispatch::IntegrationTest.register_encoder(:wibble,
param_encoder: -> params { params })
- @app = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp, :api)
+ @app = ApiApp
get "/index", headers: { "action_dispatch.show_exceptions" => true }, as: :wibble
assert_response 500
diff --git a/actionpack/test/dispatch/executor_test.rb b/actionpack/test/dispatch/executor_test.rb
index 5b8be39b6d106..5e95193205025 100644
--- a/actionpack/test/dispatch/executor_test.rb
+++ b/actionpack/test/dispatch/executor_test.rb
@@ -119,6 +119,27 @@ def test_callbacks_execute_in_shared_context
assert_not defined?(@in_shared_context) # it's not in the test itself
end
+ def test_body_abandonned
+ total = 0
+ ran = 0
+ completed = 0
+
+ executor.to_run { total += 1; ran += 1 }
+ executor.to_complete { total += 1; completed += 1 }
+
+ stack = middleware(proc { [200, {}, "response"] })
+
+ requests_count = 5
+
+ requests_count.times do
+ stack.call({})
+ end
+
+ assert_equal (requests_count * 2) - 1, total
+ assert_equal requests_count, ran
+ assert_equal requests_count - 1, completed
+ end
+
private
def call_and_return_body(&block)
app = middleware(block || proc { [200, {}, "response"] })
diff --git a/actionpack/test/dispatch/host_authorization_test.rb b/actionpack/test/dispatch/host_authorization_test.rb
index 5263dd2597f28..57125078c7be0 100644
--- a/actionpack/test/dispatch/host_authorization_test.rb
+++ b/actionpack/test/dispatch/host_authorization_test.rb
@@ -42,6 +42,50 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest
assert_equal "Success", body
end
+ test "hosts are matched case insensitive" do
+ @app = ActionDispatch::HostAuthorization.new(App, "Example.local")
+
+ get "/", env: {
+ "HOST" => "example.local",
+ }
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "hosts are matched case insensitive with titlecased host" do
+ @app = ActionDispatch::HostAuthorization.new(App, "example.local")
+
+ get "/", env: {
+ "HOST" => "Example.local",
+ }
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "hosts are matched case insensitive with hosts array" do
+ @app = ActionDispatch::HostAuthorization.new(App, ["Example.local"])
+
+ get "/", env: {
+ "HOST" => "example.local",
+ }
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "regex matches are not title cased" do
+ @app = ActionDispatch::HostAuthorization.new(App, [/www.Example.local/])
+
+ get "/", env: {
+ "HOST" => "www.example.local",
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: www.example.local", response.body
+ end
+
test "passes requests to allowed hosts with domain name notation" do
@app = ActionDispatch::HostAuthorization.new(App, ".example.com")
@@ -99,6 +143,126 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest
assert_equal "Custom", body
end
+ test "localhost works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "localhost:3000",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV4 works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "127.0.0.1",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV4 with port works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "127.0.0.1:3000",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV4 binding in all addresses works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "0.0.0.0",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV4 with port binding in all addresses works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "0.0.0.0:3000",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV6 works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "::1",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV6 with port works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "[::1]:3000",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV6 binding in all addresses works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "::",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "localhost using IPV6 with port binding in all addresses works in dev" do
+ @app = ActionDispatch::HostAuthorization.new(App, ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT)
+
+ get "/", env: {
+ "HOST" => "[::]:3000",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
+ test "hosts with port works" do
+ @app = ActionDispatch::HostAuthorization.new(App, ["host.test"])
+
+ get "/", env: {
+ "HOST" => "host.test:3000",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :ok
+ assert_match "Success", response.body
+ end
+
test "blocks requests with spoofed X-FORWARDED-HOST" do
@app = ActionDispatch::HostAuthorization.new(App, [IPAddr.new("127.0.0.1")])
@@ -111,6 +275,44 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest
assert_match "Blocked host: 127.0.0.1", response.body
end
+ test "blocks requests with spoofed relative X-FORWARDED-HOST" do
+ @app = ActionDispatch::HostAuthorization.new(App, ["www.example.com"])
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "//randomhost.com",
+ "HOST" => "www.example.com",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: //randomhost.com", response.body
+ end
+
+ test "forwarded secondary hosts are allowed when permitted" do
+ @app = ActionDispatch::HostAuthorization.new(App, ".domain.com")
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "example.com, my-sub.domain.com",
+ "HOST" => "domain.com",
+ }
+
+ assert_response :ok
+ assert_equal "Success", body
+ end
+
+ test "forwarded secondary hosts are blocked when mismatch" do
+ @app = ActionDispatch::HostAuthorization.new(App, "domain.com")
+
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => "domain.com, evil.com",
+ "HOST" => "domain.com",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: evil.com", response.body
+ end
+
test "does not consider IP addresses in X-FORWARDED-HOST spoofed when disabled" do
@app = ActionDispatch::HostAuthorization.new(App, nil)
@@ -147,15 +349,86 @@ class HostAuthorizationTest < ActionDispatch::IntegrationTest
assert_match "Blocked host: sub.domain.com", response.body
end
+ test "sub-sub domains should not be permitted" do
+ @app = ActionDispatch::HostAuthorization.new(App, ".domain.com")
+
+ get "/", env: {
+ "HOST" => "secondary.sub.domain.com",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: secondary.sub.domain.com", response.body
+ end
+
test "forwarded hosts are allowed when permitted" do
@app = ActionDispatch::HostAuthorization.new(App, ".domain.com")
get "/", env: {
- "HTTP_X_FORWARDED_HOST" => "sub.domain.com",
+ "HTTP_X_FORWARDED_HOST" => "my-sub.domain.com",
"HOST" => "domain.com",
}
assert_response :ok
assert_equal "Success", body
end
+
+ test "only compare to valid hostnames" do
+ @app = ActionDispatch::HostAuthorization.new(App, ".example.com")
+
+ get "/", env: {
+ "HOST" => "attacker.com#x.example.com",
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: attacker.com#x.example.com", response.body
+ end
+
+ test "blocks requests to similar host" do
+ @app = ActionDispatch::HostAuthorization.new(App, "sub.example.com")
+
+ get "/", env: {
+ "HOST" => "sub-example.com",
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: sub-example.com", response.body
+ end
+
+ test "lots of NG hosts" do
+ ng_hosts = [
+ "hacker%E3%80%82com",
+ "hacker%00.com",
+ "www.theirsite.com@yoursite.com",
+ "hacker.com/test/",
+ "hacker%252ecom",
+ ".hacker.com",
+ "/\/\/hacker.com/",
+ "/hacker.com",
+ "../hacker.com",
+ ".hacker.com",
+ "@hacker.com",
+ "hacker.com",
+ "hacker.com%23@example.com",
+ "hacker.com/.jpg",
+ "hacker.com\texample.com/",
+ "hacker.com/example.com",
+ "hacker.com\@example.com",
+ "hacker.com/example.com",
+ "hacker.com/"
+ ]
+
+ @app = ActionDispatch::HostAuthorization.new(App, "example.com")
+
+ ng_hosts.each do |host|
+ get "/", env: {
+ "HTTP_X_FORWARDED_HOST" => host,
+ "HOST" => "example.com",
+ "action_dispatch.show_detailed_exceptions" => true
+ }
+
+ assert_response :forbidden
+ assert_match "Blocked host: #{host}", response.body
+ end
+ end
end
diff --git a/actionpack/test/dispatch/mime_type_test.rb b/actionpack/test/dispatch/mime_type_test.rb
index 2df973e44d59a..23a5b7f338ed6 100644
--- a/actionpack/test/dispatch/mime_type_test.rb
+++ b/actionpack/test/dispatch/mime_type_test.rb
@@ -225,5 +225,11 @@ class MimeTypeTest < ActiveSupport::TestCase
assert_raises Mime::Type::InvalidMimeType do
Mime::Type.new(nil)
end
+
+ assert_raises Mime::Type::InvalidMimeType do
+ Timeout.timeout(1) do # Shouldn't take more than 1s
+ Mime::Type.new("text/html ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0 ;0;")
+ end
+ end
end
end
diff --git a/actionpack/test/dispatch/prefix_generation_test.rb b/actionpack/test/dispatch/prefix_generation_test.rb
index f20043b9ac671..e6106766ee118 100644
--- a/actionpack/test/dispatch/prefix_generation_test.rb
+++ b/actionpack/test/dispatch/prefix_generation_test.rb
@@ -126,12 +126,19 @@ def ivar_usage
end
end
+ module KwObject
+ def initialize(kw:)
+ end
+ end
+
class EngineObject
+ include KwObject
include ActionDispatch::Routing::UrlFor
include BlogEngine.routes.url_helpers
end
class AppObject
+ include KwObject
include ActionDispatch::Routing::UrlFor
include RailsApplication.routes.url_helpers
end
@@ -144,8 +151,8 @@ def app
def setup
RailsApplication.routes.default_url_options = {}
- @engine_object = EngineObject.new
- @app_object = AppObject.new
+ @engine_object = EngineObject.new(kw: 1)
+ @app_object = AppObject.new(kw: 2)
end
include BlogEngine.routes.mounted_helpers
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index d514c9316bb47..bb4c34ba6dc19 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -4538,10 +4538,14 @@ def show
with_routing do |set|
set.draw do
get "/foo/show(/:id)", to: "test_invalid_urls/foo#show"
+ get "/bar/show(/:id)", controller: "test_invalid_urls/foo", action: "show"
end
get "/foo/show/%E2%EF%BF%BD%A6"
assert_response :ok
+
+ get "/bar/show/%E2%EF%BF%BD%A6"
+ assert_response :ok
end
end
end
diff --git a/actionpack/test/dispatch/show_exceptions_test.rb b/actionpack/test/dispatch/show_exceptions_test.rb
index 6fafa4e426710..a370076af52ed 100644
--- a/actionpack/test/dispatch/show_exceptions_test.rb
+++ b/actionpack/test/dispatch/show_exceptions_test.rb
@@ -10,7 +10,7 @@ def call(env)
when "/not_found"
raise AbstractController::ActionNotFound
when "/invalid_mimetype"
- raise Mime::Type::InvalidMimeType
+ raise ActionDispatch::Http::MimeNegotiation::InvalidType
when "/bad_params", "/bad_params.json"
begin
raise StandardError.new
diff --git a/actionpack/test/dispatch/system_testing/driver_test.rb b/actionpack/test/dispatch/system_testing/driver_test.rb
index 7877215110ae6..affe091d8f3ad 100644
--- a/actionpack/test/dispatch/system_testing/driver_test.rb
+++ b/actionpack/test/dispatch/system_testing/driver_test.rb
@@ -71,7 +71,8 @@ class DriverTest < ActiveSupport::TestCase
"args" => ["start-maximized"],
"mobileEmulation" => { "deviceName" => "iphone 6" },
"prefs" => { "detach" => true }
- }
+ },
+ "browserName" => "chrome"
}
assert_equal expected, driver_option.as_json
end
@@ -92,7 +93,8 @@ class DriverTest < ActiveSupport::TestCase
"args" => ["start-maximized"],
"mobileEmulation" => { "deviceName" => "iphone 6" },
"prefs" => { "detach" => true }
- }
+ },
+ "browserName" => "chrome"
}
assert_equal expected, driver_option.as_json
end
@@ -111,7 +113,8 @@ class DriverTest < ActiveSupport::TestCase
"moz:firefoxOptions" => {
"args" => ["--host=127.0.0.1"],
"prefs" => { "browser.startup.homepage" => "http://www.seleniumhq.com/" }
- }
+ },
+ "browserName" => "firefox"
}
assert_equal expected, driver_option.as_json
end
@@ -130,7 +133,8 @@ class DriverTest < ActiveSupport::TestCase
"moz:firefoxOptions" => {
"args" => ["--host=127.0.0.1"],
"prefs" => { "browser.startup.homepage" => "http://www.seleniumhq.com/" }
- }
+ },
+ "browserName" => "firefox"
}
assert_equal expected, driver_option.as_json
end
diff --git a/actiontext/CHANGELOG.md b/actiontext/CHANGELOG.md
index b7c2763b87683..576978dce24ca 100644
--- a/actiontext/CHANGELOG.md
+++ b/actiontext/CHANGELOG.md
@@ -1,3 +1,96 @@
+## Rails 6.0.6.1 (January 17, 2023) ##
+
+* No changes.
+
+
+## Rails 6.0.6 (September 09, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5.1 (July 12, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.5 (May 09, 2022) ##
+
+* Disentangle Action Text from ApplicationController
+
+ Allow Action Text to be used without having an ApplicationController
+ defined.
+ This makes sure:
+ * Action Text attachments render the correct URL host in mailers.
+ * an ActionController::Renderer isn't allocated per request.
+ * Sidekiq doesn't hang with the "classic" autoloader.
+
+ *Jonathan Hefner*
+
+## Rails 6.0.4.8 (April 26, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.7 (March 08, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.6 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.5 (February 11, 2022) ##
+
+* No changes.
+
+
+## Rails 6.0.4.4 (December 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.3 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.2 (December 14, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4.1 (August 19, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.4 (June 15, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.7 (May 05, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.6 (March 26, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.5 (February 10, 2021) ##
+
+* No changes.
+
+
+## Rails 6.0.3.4 (October 07, 2020) ##
+
+* No changes.
+
+
## Rails 6.0.3.3 (September 09, 2020) ##
* No changes.
diff --git a/actiontext/actiontext.gemspec b/actiontext/actiontext.gemspec
index 8c5e6564e3ec1..f639ce5f9452a 100644
--- a/actiontext/actiontext.gemspec
+++ b/actiontext/actiontext.gemspec
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
"documentation_uri" => "https://api.rubyonrails.org/v#{version}/",
"mailing_list_uri" => "https://discuss.rubyonrails.org/c/rubyonrails-talk",
"source_code_uri" => "https://github.com/rails/rails/tree/v#{version}/actiontext",
+ "rubygems_mfa_required" => "true",
}
# NOTE: Please read our dependency guidelines before updating versions:
diff --git a/actiontext/app/helpers/action_text/content_helper.rb b/actiontext/app/helpers/action_text/content_helper.rb
index 1e05f572f7262..7040fe4e48d6d 100644
--- a/actiontext/app/helpers/action_text/content_helper.rb
+++ b/actiontext/app/helpers/action_text/content_helper.rb
@@ -10,6 +10,7 @@ module ContentHelper
mattr_accessor(:scrubber)
def render_action_text_content(content)
+ self.prefix_partial_path_with_controller_namespace = false
sanitize_action_text_content(render_action_text_attachments(content))
end
diff --git a/actiontext/lib/action_text.rb b/actiontext/lib/action_text.rb
index 0dd6318f89e02..15fdf70b3bae2 100644
--- a/actiontext/lib/action_text.rb
+++ b/actiontext/lib/action_text.rb
@@ -16,6 +16,7 @@ module ActionText
autoload :Fragment
autoload :HtmlConversion
autoload :PlainTextConversion
+ autoload :Rendering
autoload :Serialization
autoload :TrixAttachment
diff --git a/actiontext/lib/action_text/attachments/trix_conversion.rb b/actiontext/lib/action_text/attachments/trix_conversion.rb
index 24937d6c2276d..a95843a641228 100644
--- a/actiontext/lib/action_text/attachments/trix_conversion.rb
+++ b/actiontext/lib/action_text/attachments/trix_conversion.rb
@@ -26,7 +26,7 @@ def to_trix_attachment(content = trix_attachment_content)
private
def trix_attachment_content
if partial_path = attachable.try(:to_trix_content_attachment_partial_path)
- ActionText::Content.renderer.render(partial: partial_path, object: self, as: model_name.element)
+ ActionText::Content.render(partial: partial_path, object: self, as: model_name.element)
end
end
end
diff --git a/actiontext/lib/action_text/content.rb b/actiontext/lib/action_text/content.rb
index 16bc6fe03102c..6126a4de49d50 100644
--- a/actiontext/lib/action_text/content.rb
+++ b/actiontext/lib/action_text/content.rb
@@ -1,12 +1,8 @@
# frozen_string_literal: true
-require "active_support/core_ext/module/attribute_accessors_per_thread"
-
module ActionText
class Content
- include Serialization
-
- thread_cattr_accessor :renderer
+ include Rendering, Serialization
attr_reader :fragment
@@ -88,7 +84,7 @@ def to_html
end
def to_rendered_html_with_layout
- renderer.render(partial: "action_text/content/layout", locals: { content: self })
+ render partial: "action_text/content/layout", locals: { content: self }
end
def to_s
diff --git a/actiontext/lib/action_text/engine.rb b/actiontext/lib/action_text/engine.rb
index 7ac953e6ec28f..4c8a65c6a5bec 100644
--- a/actiontext/lib/action_text/engine.rb
+++ b/actiontext/lib/action_text/engine.rb
@@ -37,21 +37,24 @@ def to_trix_content_attachment_partial_path
end
initializer "action_text.helper" do
- ActiveSupport.on_load(:action_controller_base) do
- helper ActionText::Engine.helpers
+ %i[action_controller_base action_mailer].each do |abstract_controller|
+ ActiveSupport.on_load(abstract_controller) do
+ helper ActionText::Engine.helpers
+ end
end
end
- initializer "action_text.renderer" do |app|
- app.executor.to_run { ActionText::Content.renderer = ApplicationController.renderer }
- app.executor.to_complete { ActionText::Content.renderer = ApplicationController.renderer }
-
+ initializer "action_text.renderer" do
ActiveSupport.on_load(:action_text_content) do
- self.renderer = ApplicationController.renderer
+ self.renderer = Class.new(ActionController::Base).renderer
end
- ActiveSupport.on_load(:action_controller_base) do
- before_action { ActionText::Content.renderer = ApplicationController.renderer.new(request.env) }
+ %i[action_controller_base action_mailer].each do |abstract_controller|
+ ActiveSupport.on_load(abstract_controller) do
+ around_action do |controller, action|
+ ActionText::Content.with_renderer(controller, &action)
+ end
+ end
end
end
end
diff --git a/actiontext/lib/action_text/gem_version.rb b/actiontext/lib/action_text/gem_version.rb
index 9032ec529515d..bab98a89785ff 100644
--- a/actiontext/lib/action_text/gem_version.rb
+++ b/actiontext/lib/action_text/gem_version.rb
@@ -9,8 +9,8 @@ def self.gem_version
module VERSION
MAJOR = 6
MINOR = 0
- TINY = 3
- PRE = "3"
+ TINY = 6
+ PRE = "1"
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
end
diff --git a/actiontext/lib/action_text/rendering.rb b/actiontext/lib/action_text/rendering.rb
new file mode 100644
index 0000000000000..caef71c6b4838
--- /dev/null
+++ b/actiontext/lib/action_text/rendering.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require "active_support/concern"
+require "active_support/core_ext/module/attribute_accessors_per_thread"
+
+module ActionText
+ module Rendering #:nodoc:
+ extend ActiveSupport::Concern
+
+ included do
+ thread_cattr_accessor :renderer, instance_accessor: false
+ delegate :render, to: :class
+ end
+
+ class_methods do
+ def with_renderer(renderer)
+ previous_renderer = self.renderer
+ self.renderer = renderer
+ yield
+ ensure
+ self.renderer = previous_renderer
+ end
+
+ def render(*args, &block)
+ renderer.render_to_string(*args, &block)
+ end
+ end
+ end
+end
diff --git a/actiontext/package.json b/actiontext/package.json
index e8f7bef71d027..575aa217b9d5f 100644
--- a/actiontext/package.json
+++ b/actiontext/package.json
@@ -1,6 +1,6 @@
{
"name": "@rails/actiontext",
- "version": "6.0.3-3",
+ "version": "6.0.6-1",
"description": "Edit and display rich text in Rails applications",
"main": "app/javascript/actiontext/index.js",
"files": [
@@ -21,7 +21,7 @@
],
"license": "MIT",
"dependencies": {
- "@rails/activestorage": "^6.0.0-alpha"
+ "@rails/activestorage": "^6.0.0"
},
"peerDependencies": {
"trix": "^1.2.0"
diff --git a/actiontext/test/dummy/app/controllers/admin/messages_controller.rb b/actiontext/test/dummy/app/controllers/admin/messages_controller.rb
new file mode 100644
index 0000000000000..7c3316324b514
--- /dev/null
+++ b/actiontext/test/dummy/app/controllers/admin/messages_controller.rb
@@ -0,0 +1,5 @@
+class Admin::MessagesController < ActionController::Base
+ def show
+ @message = Message.find(params[:id])
+ end
+end
diff --git a/actiontext/test/dummy/app/controllers/application_controller.rb b/actiontext/test/dummy/app/controllers/application_controller.rb
deleted file mode 100644
index 09705d12ab4df..0000000000000
--- a/actiontext/test/dummy/app/controllers/application_controller.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-class ApplicationController < ActionController::Base
-end
diff --git a/actiontext/test/dummy/app/controllers/messages_controller.rb b/actiontext/test/dummy/app/controllers/messages_controller.rb
index 81c79a2d1e304..539468a3599b0 100644
--- a/actiontext/test/dummy/app/controllers/messages_controller.rb
+++ b/actiontext/test/dummy/app/controllers/messages_controller.rb
@@ -1,4 +1,4 @@
-class MessagesController < ApplicationController
+class MessagesController < ActionController::Base
before_action :set_message, only: [:show, :edit, :update, :destroy]
# GET /messages
diff --git a/actiontext/test/dummy/app/mailers/messages_mailer.rb b/actiontext/test/dummy/app/mailers/messages_mailer.rb
new file mode 100644
index 0000000000000..ce0af3b3cac45
--- /dev/null
+++ b/actiontext/test/dummy/app/mailers/messages_mailer.rb
@@ -0,0 +1,6 @@
+class MessagesMailer < ApplicationMailer
+ def notification
+ @message = params[:message]
+ mail to: params[:recipient], subject: "NEW MESSAGE: #{@message.subject}"
+ end
+end
diff --git a/actiontext/test/dummy/app/views/admin/messages/show.html.erb b/actiontext/test/dummy/app/views/admin/messages/show.html.erb
new file mode 100644
index 0000000000000..ba9067f2018dc
--- /dev/null
+++ b/actiontext/test/dummy/app/views/admin/messages/show.html.erb
@@ -0,0 +1,16 @@
+
If you are looking for the ones for the stable version, please check
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 9f4a567f96f88..8aaffb5d11a4a 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -579,7 +579,7 @@ URL helper.
<%= user_url(@user, host: 'example.com') %>
```
-NOTE: non-`GET` links require [rails-ujs](https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts) or
+NOTE: non-`GET` links require [rails-ujs](https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts) or
[jQuery UJS](https://github.com/rails/jquery-ujs), and won't work in mailer templates.
They will result in normal `GET` requests.
diff --git a/guides/source/active_record_callbacks.md b/guides/source/active_record_callbacks.md
index 31521bb90b305..80e73faca2145 100644
--- a/guides/source/active_record_callbacks.md
+++ b/guides/source/active_record_callbacks.md
@@ -247,10 +247,17 @@ Just as with validations, it is also possible to skip callbacks by using the fol
* `delete_all`
* `increment!`
* `increment_counter`
+* `insert`
+* `insert!`
+* `insert_all`
+* `insert_all!`
+* `touch_all`
* `update_column`
* `update_columns`
* `update_all`
* `update_counters`
+* `upsert`
+* `upsert_all`
These methods should be used with caution, however, because important business rules and application logic may be kept in callbacks. Bypassing them without understanding the potential implications may lead to invalid data.
diff --git a/guides/source/active_record_multiple_databases.md b/guides/source/active_record_multiple_databases.md
index fc86d7696da2a..99ac6fa8f0208 100644
--- a/guides/source/active_record_multiple_databases.md
+++ b/guides/source/active_record_multiple_databases.md
@@ -265,9 +265,9 @@ handles outside of Rails.
### Joining Across Databases
-Applications cannot join across databases. Rails 6.1 will support using `has_many`
-relationships and creating 2 queries instead of joining, but Rails 6.0 will require
-you to split the joins into 2 selects manually.
+Applications cannot join across databases. At the moment applications will need to
+manually write two selects and split the joins themselves. In a future version Rails
+will split the joins for you.
### Schema Cache
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index e68f34dd5df66..7a04de98329ea 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -134,13 +134,20 @@ database regardless of its validity. They should be used with caution.
* `decrement_counter`
* `increment!`
* `increment_counter`
+* `insert`
+* `insert!`
+* `insert_all`
+* `insert_all!`
* `toggle!`
* `touch`
+* `touch_all`
* `update_all`
* `update_attribute`
* `update_column`
* `update_columns`
* `update_counters`
+* `upsert`
+* `upsert_all`
Note that `save` also has the ability to skip validations if passed `validate:
false` as an argument. This technique should be used with caution.
diff --git a/guides/source/active_storage_overview.md b/guides/source/active_storage_overview.md
index 37fc6d6cfa027..6755f3d9c11b7 100644
--- a/guides/source/active_storage_overview.md
+++ b/guides/source/active_storage_overview.md
@@ -76,7 +76,7 @@ development environment, you would add the following to
config.active_storage.service = :local
```
-To use the Amazon S3 service in production, you add the following to
+To use the S3 service in production, you add the following to
`config/environments/production.rb`:
```ruby
@@ -105,9 +105,9 @@ local:
root: <%= Rails.root.join("storage") %>
```
-### Amazon S3 Service
+### S3 Service (Amazon S3 and S3-compatible APIs)
-Declare an S3 service in `config/storage.yml`:
+To connect to Amazon S3, declare an S3 service in `config/storage.yml`:
```yaml
amazon:
@@ -128,10 +128,20 @@ NOTE: The core features of Active Storage require the following permissions: `s3
NOTE: If you want to use environment variables, standard SDK configuration files, profiles,
IAM instance profiles or task roles, you can omit the `access_key_id`, `secret_access_key`,
-and `region` keys in the example above. The Amazon S3 Service supports all of the
+and `region` keys in the example above. The S3 Service supports all of the
authentication options described in the [AWS SDK documentation]
(https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html).
+To connect to an S3-compatible object storage API such as Digital Ocean Spaces, provide the `endpoint`:
+
+```yaml
+digitalocean:
+ service: S3
+ endpoint: https://nyc3.digitaloceanspaces.com
+ access_key_id: ...
+ secret_access_key: ...
+ # ...and other options
+```
### Microsoft Azure Storage Service
@@ -843,5 +853,5 @@ Implementing Support for Other Cloud Services
If you need to support a cloud service other than these, you will need to
implement the Service. Each service extends
-[`ActiveStorage::Service`](https://github.com/rails/rails/blob/master/activestorage/lib/active_storage/service.rb)
+[`ActiveStorage::Service`](https://github.com/rails/rails/blob/main/activestorage/lib/active_storage/service.rb)
by implementing the methods necessary to upload and download files to the cloud.
diff --git a/guides/source/autoloading_and_reloading_constants.md b/guides/source/autoloading_and_reloading_constants.md
index cc2a08d05467e..59188d741ee64 100644
--- a/guides/source/autoloading_and_reloading_constants.md
+++ b/guides/source/autoloading_and_reloading_constants.md
@@ -81,7 +81,7 @@ The section _Customizing Inflections_ below documents ways to override this defa
Please, check the [Zeitwerk documentation](https://github.com/fxn/zeitwerk#file-structure) for further details.
-Autoload paths
+Autoload Paths
--------------
We call _autoload paths_ to the list of application directories whose contents are to be autoloaded. For example, `app/models`. Such directories represent the root namespace: `Object`.
@@ -356,6 +356,60 @@ You can check if `zeitwerk` mode is enabled with
Rails.autoloaders.zeitwerk_enabled?
```
+Differences with Classic Mode
+-----------------------------
+
+### Ruby Constant Lookup Compliance
+
+`classic` mode cannot match constant lookup semantics due to fundamental limitations of the technique it is based on, whereas `zeitwerk` mode works like Ruby.
+
+For example, in `classic` mode defining classes or modules in namespaces with qualified constants this way
+
+```ruby
+class Admin::UsersController < ApplicationController
+end
+```
+
+was not recommended because the resolution of constants inside their body was britle. You'd better write them in this style:
+
+```ruby
+module Admin
+ class UsersController < ApplicationController
+ end
+end
+```
+
+In `zeitwerk` mode that does not matter anymore, you can pick either style.
+
+The resolution of a constant could depend on load order, the definition of a class or module object could depend on load order, there was edge cases with singleton classes, oftentimes you had to use `require_dependency` as a workaround, .... The guide for `classic` mode documents [these issues](autoloading_and_reloading_constants_classic_mode.html#common-gotchas).
+
+All these problems are solved in `zeitwerk` mode, it just works as expected, and `require_dependency` should not be used anymore, it is no longer needed.
+
+### Less File Lookups
+
+In `classic` mode, every single missing constant triggers a file lookup that walks the autoload paths.
+
+In `zeitwerk` mode there is only one pass. That pass is done once, not per missing constant, and so it is generally more performant. Subdirectories are visited only if their namespace is used.
+
+### Underscore vs Camelize
+
+Inflections go the other way around.
+
+In `classic` mode, given a missing constant Rails _underscores_ its name and performs a file lookup. On the other hand, `zeitwerk` mode checks first the file system, and _camelizes_ file names to know the constant those files are expected to define.
+
+While in common names these operations match, if acronyms or custom inflection rules are configured, they may not. For example, by default `"HTMLParser".underscore` is `"html_parser"`, and `"html_parser".camelize` is `"HtmlParser"`.
+
+### More Differences
+
+There are some other subtle differences, please check [this section of _Upgrading Ruby on Rails_](upgrading_ruby_on_rails.html#autoloading) guide for details.
+
+Classic Mode is Deprecated
+--------------------------
+
+By now, it is still possible to use `classic` mode. However, `classic` is deprecated and will be eventually removed.
+
+New applications should use `zeitwerk` mode (which is the default), and applications being upgrade are strongly encouraged to migrate to `zeitwerk` mode. Please check the [_Upgrading Ruby on Rails_](upgrading_ruby_on_rails.html#autoloading) guide for details.
+
Opting Out
----------
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 2f679e74498a8..29750bc97701d 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -112,6 +112,8 @@ numbers. It also filters out sensitive values of database columns when call `#in
* `config.force_ssl` forces all requests to be served over HTTPS by using the `ActionDispatch::SSL` middleware, and sets `config.action_mailer.default_url_options` to be `{ protocol: 'https' }`. This can be configured by setting `config.ssl_options` - see the [ActionDispatch::SSL documentation](https://api.rubyonrails.org/classes/ActionDispatch/SSL.html) for details.
+* `config.javascript_path` sets the path where your app's JavaScript lives relative to the `app` directory. The default is `javascript`, used by [webpacker](https://github.com/rails/webpacker). An app's configured `javascript_path` will be excluded from `autoload_paths`.
+
* `config.log_formatter` defines the formatter of the Rails logger. This option defaults to an instance of `ActiveSupport::Logger::SimpleFormatter` for all modes. If you are setting a value for `config.logger` you must manually pass the value of your formatter to your logger before it is wrapped in an `ActiveSupport::TaggedLogging` instance, Rails will not do it for you.
* `config.log_level` defines the verbosity of the Rails logger. This option
@@ -259,6 +261,10 @@ Every Rails application comes with a standard set of middleware which it uses in
# `beta1.product.com`.
Rails.application.config.hosts << /.*\.product\.com/
```
+
+ The provided regexp will be wrapped with both anchors (`\A` and `\z`) so it
+ must match the entire hostname. `/product.com/`, for example, once anchored,
+ would fail to match `www.product.com`.
A special case is supported that allows you to permit all sub-domains:
@@ -480,6 +486,8 @@ The schema dumper adds two additional configuration options:
* `config.action_controller.default_protect_from_forgery` determines whether forgery protection is added on `ActionController:Base`. This is false by default.
+* `config.action_controller.urlsafe_csrf_tokens` configures whether generated CSRF tokens are URL-safe. Defaults to `false`.
+
* `config.action_controller.relative_url_root` can be used to tell Rails that you are [deploying to a subdirectory](configuring.html#deploy-to-a-subdirectory-relative-url-root). The default is `ENV['RAILS_RELATIVE_URL_ROOT']`.
* `config.action_controller.permit_all_parameters` sets all the parameters for mass assignment to be permitted by default. The default value is `false`.
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index eeb301e684408..a43f49afbdd2f 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -8,7 +8,7 @@ This guide covers ways in which _you_ can become a part of the ongoing developme
After reading this guide, you will know:
* How to use GitHub to report issues.
-* How to clone master and run the test suite.
+* How to clone main and run the test suite.
* How to help resolve existing issues.
* How to contribute to the Ruby on Rails documentation.
* How to contribute to the Ruby on Rails code.
@@ -16,7 +16,7 @@ After reading this guide, you will know:
Ruby on Rails is not "someone else's framework." Over the years, thousands of people have contributed to Ruby on Rails ranging from a single character to massive architectural changes or significant documentation - all with the goal of making Ruby on Rails better for everyone. Even if you don't feel up to writing code or documentation yet, there are a variety of other ways that you can contribute, from reporting issues to testing patches.
As mentioned in [Rails'
-README](https://github.com/rails/rails/blob/master/README.md), everyone interacting in Rails and its sub-projects' codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Rails [code of conduct](https://rubyonrails.org/conduct/).
+README](https://github.com/rails/rails/blob/main/README.md), everyone interacting in Rails and its sub-projects' codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Rails [code of conduct](https://rubyonrails.org/conduct/).
--------------------------------------------------------------------------------
@@ -39,13 +39,13 @@ Then, don't get your hopes up! Unless you have a "Code Red, Mission Critical, th
Having a way to reproduce your issue will be very helpful for others to help confirm, investigate, and ultimately fix your issue. You can do this by providing an executable test case. To make this process easier, we have prepared several bug report templates for you to use as a starting point:
-* Template for Active Record (models, database) issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_master.rb)
-* Template for testing Active Record (migration) issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_migrations_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_record_migrations_master.rb)
-* Template for Action Pack (controllers, routing) issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/action_controller_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/action_controller_master.rb)
-* Template for Active Job issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_job_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/active_job_master.rb)
-* Generic template for other issues: [gem](https://github.com/rails/rails/blob/master/guides/bug_report_templates/generic_gem.rb) / [master](https://github.com/rails/rails/blob/master/guides/bug_report_templates/generic_master.rb)
+* Template for Active Record (models, database) issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_main.rb)
+* Template for testing Active Record (migration) issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_migrations_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_record_migrations_main.rb)
+* Template for Action Pack (controllers, routing) issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/action_controller_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/action_controller_main.rb)
+* Template for Active Job issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_job_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/active_job_main.rb)
+* Generic template for other issues: [gem](https://github.com/rails/rails/blob/main/guides/bug_report_templates/generic_gem.rb) / [main](https://github.com/rails/rails/blob/main/guides/bug_report_templates/generic_main.rb)
-These templates include the boilerplate code to set up a test case against either a released version of Rails (`*_gem.rb`) or edge Rails (`*_master.rb`).
+These templates include the boilerplate code to set up a test case against either a released version of Rails (`*_gem.rb`) or edge Rails (`*_main.rb`).
Simply copy the content of the appropriate template into a `.rb` file and make the necessary changes to demonstrate the issue. You can execute it by running `ruby the_file.rb` in your terminal. If all goes well, you should see your test case failing.
@@ -134,8 +134,7 @@ learn about Ruby on Rails, and the API, which serves as a reference.
You can help improve the Rails guides by making them more coherent, consistent, or readable, adding missing information, correcting factual errors, fixing typos, or bringing them up to date with the latest edge Rails.
-To do so, make changes to Rails guides source files (located [here](https://github.com/rails/rails/tree/master/guides/source) on GitHub). Then open a pull request to apply your
-changes to the master branch.
+To do so, make changes to Rails guides source files (located [here](https://github.com/rails/rails/tree/main/guides/source) on GitHub). Then open a pull request to apply your changes to the main branch.
When working with documentation, please take into account the [API Documentation Guidelines](api_documentation_guidelines.html) and the [Ruby on Rails Guides Guidelines](ruby_on_rails_guides_guidelines.html).
@@ -286,7 +285,7 @@ Therefore, you should test your change against a list of representative
scenarios. Ideally, they should be based on real-world scenarios extracted
from production applications.
-You can use the [benchmark template](https://github.com/rails/rails/blob/master/guides/bug_report_templates/benchmark.rb)
+You can use the [benchmark template](https://github.com/rails/rails/blob/main/guides/bug_report_templates/benchmark.rb)
as a starting point. It includes the boilerplate code to setup a benchmark
using the [benchmark-ips](https://github.com/evanphx/benchmark-ips) gem. The
template is designed for testing relatively self-contained changes that can be
@@ -504,10 +503,10 @@ simplifies future cherry picks and keeps the git log clean.
### Update Your Branch
-It's pretty likely that other changes to master have happened while you were working. Go get them:
+It's pretty likely that other changes to main have happened while you were working. Go get them:
```bash
-$ git checkout master
+$ git checkout main
$ git pull --rebase
```
@@ -515,7 +514,7 @@ Now reapply your patch on top of the latest changes:
```bash
$ git checkout my_new_branch
-$ git rebase master
+$ git rebase main
```
No conflicts? Tests still pass? Change still seems reasonable to you? Then move on.
@@ -545,16 +544,16 @@ $ git fetch rails
Merge the new content:
```bash
-$ git checkout master
-$ git rebase rails/master
+$ git checkout main
+$ git rebase rails/main
$ git checkout my_new_branch
-$ git rebase rails/master
+$ git rebase rails/main
```
Update your fork:
```bash
-$ git push fork master
+$ git push fork main
$ git push fork my_new_branch
```
@@ -566,7 +565,7 @@ the right panel. On the next page, press "New pull request" in the upper right
hand corner.
Click on "Edit", if you need to change the branches being compared (it compares
-"master" by default) and press "Click to create a pull request for this
+"main" by default) and press "Click to create a pull request for this
comparison".
Ensure the changesets you introduced are included. Fill in some details about
@@ -610,7 +609,7 @@ extraneous commits can add a lot of noise.
```bash
$ git fetch rails
$ git checkout my_new_branch
-$ git rebase -i rails/master
+$ git rebase -i rails/main
< Choose 'squash' for all of your commits except the first one. >
< Edit the commit message to make sense, and describe all your changes. >
@@ -652,20 +651,20 @@ TIP: You may want to [put your Git branch name in your shell prompt](http://qugs
#### Backporting
-Changes that are merged into master are intended for the next major release of Rails. Sometimes, it might be beneficial for your changes to propagate back to the maintenance releases for older stable branches. Generally, security fixes and bug fixes are good candidates for a backport, while new features and patches that introduce a change in behavior will not be accepted. When in doubt, it is best to consult a Rails team member before backporting your changes to avoid wasted effort.
+Changes that are merged into main are intended for the next major release of Rails. Sometimes, it might be beneficial for your changes to propagate back to the maintenance releases for older stable branches. Generally, security fixes and bug fixes are good candidates for a backport, while new features and patches that introduce a change in behavior will not be accepted. When in doubt, it is best to consult a Rails team member before backporting your changes to avoid wasted effort.
-For simple fixes, the easiest way to backport your changes is to [extract a diff from your changes in master and apply them to the target branch](http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git).
+For simple fixes, the easiest way to backport your changes is to [extract a diff from your changes in main and apply them to the target branch](http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git).
-First, make sure your changes are the only difference between your current branch and master:
+First, make sure your changes are the only difference between your current branch and main:
```bash
-$ git log master..HEAD
+$ git log main..HEAD
```
Then extract the diff:
```bash
-$ git format-patch master --stdout > ~/my_changes.patch
+$ git format-patch main --stdout > ~/my_changes.patch
```
Switch over to the target branch and apply your changes:
@@ -675,9 +674,9 @@ $ git checkout -b my_backport_branch 4-2-stable
$ git apply ~/my_changes.patch
```
-This works well for simple changes. However, if your changes are complicated or if the code in master has deviated significantly from your target branch, it might require more work on your part. The difficulty of a backport varies greatly from case to case, and sometimes it is simply not worth the effort.
+This works well for simple changes. However, if your changes are complicated or if the code in main has deviated significantly from your target branch, it might require more work on your part. The difficulty of a backport varies greatly from case to case, and sometimes it is simply not worth the effort.
-Once you have resolved all conflicts and made sure all the tests are passing, push your changes and open a separate pull request for your backport. It is also worth noting that older branches might have a different set of build targets than master. When possible, it is best to first test your backport locally against the oldest Ruby version permitted by the target branch's `rails.gemspec` before submitting your pull request.
+Once you have resolved all conflicts and made sure all the tests are passing, push your changes and open a separate pull request for your backport. It is also worth noting that older branches might have a different set of build targets than main. When possible, it is best to first test your backport locally against the oldest Ruby version permitted by the target branch's `rails.gemspec` before submitting your pull request.
And then... think about your next contribution!
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 40da25354c36e..34abd8044275d 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -80,7 +80,7 @@ your prompt will look something like `c:\source_code>`
Before you install Rails, you should check to make sure that your system has the
proper prerequisites installed. These include:
-* Ruby
+* Ruby
* SQLite3
* Node.js
* Yarn
@@ -100,21 +100,18 @@ ruby 2.5.0
Rails requires Ruby version 2.5.0 or later. If the version number returned is
less than that number, you'll need to install a fresh copy of Ruby.
-TIP: To quickly install Ruby and Ruby on Rails on your system in Windows, you can use
-[Rails Installer](http://railsinstaller.org). For more installation methods for most
-Operating Systems take a look at [ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/).
+To install Rails on Windows, you'll first need to install [Ruby Installer](https://rubyinstaller.org/).
-If you are working on Windows, you should also install the
-[Ruby Installer Development Kit](https://rubyinstaller.org/downloads/).
+For more installation methods for most Operating Systems take a look at
+[ruby-lang.org](https://www.ruby-lang.org/en/documentation/installation/).
#### Installing SQLite3
You will also need an installation of the SQLite3 database.
Many popular UNIX-like OSes ship with an acceptable version of SQLite3.
-On Windows, if you installed Rails through Rails Installer, you
-already have SQLite installed. Others can find installation instructions
-at the [SQLite3 website](https://www.sqlite.org).
-Verify that it is correctly installed and in your PATH:
+Others can find installation instructions at the [SQLite3 website](https://www.sqlite.org).
+
+Verify that it is correctly installed and in your load `PATH`:
```bash
$ sqlite3 --version
@@ -126,10 +123,10 @@ The program should report its version.
Finally, you'll need Node.js and Yarn installed to manage your application's JavaScript.
-Find the installation instructions at the [Node.js website](https://nodejs.org/en/download/) and
+Find the installation instructions at the [Node.js website](https://nodejs.org/en/download/) and
verify it's installed correctly with the following command:
-```bash
+```bash
$ node --version
```
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index 0518da9fc26e0..6dc19bc299822 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -103,7 +103,7 @@ en:
hello: "Hello world"
```
-This means, that in the `:en` locale, the key _hello_ will map to the _Hello world_ string. Every string inside Rails is internationalized in this way, see for instance Active Model validation messages in the [`activemodel/lib/active_model/locale/en.yml`](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml) file or time and date formats in the [`activesupport/lib/active_support/locale/en.yml`](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml) file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend.
+This means, that in the `:en` locale, the key _hello_ will map to the _Hello world_ string. Every string inside Rails is internationalized in this way, see for instance Active Model validation messages in the [`activemodel/lib/active_model/locale/en.yml`](https://github.com/rails/rails/blob/main/activemodel/lib/active_model/locale/en.yml) file or time and date formats in the [`activesupport/lib/active_support/locale/en.yml`](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml) file. You can use YAML or standard Ruby Hashes to store translations in the default (Simple) backend.
The I18n library will use **English** as a **default locale**, i.e. if a different locale is not set, `:en` will be used for looking up translations.
@@ -1059,23 +1059,23 @@ Rails uses fixed strings and other localizations, such as format strings and oth
#### Action View Helper Methods
-* `distance_of_time_in_words` translates and pluralizes its result and interpolates the number of seconds, minutes, hours, and so on. See [datetime.distance_in_words](https://github.com/rails/rails/blob/master/actionview/lib/action_view/locale/en.yml#L4) translations.
+* `distance_of_time_in_words` translates and pluralizes its result and interpolates the number of seconds, minutes, hours, and so on. See [datetime.distance_in_words](https://github.com/rails/rails/blob/main/actionview/lib/action_view/locale/en.yml#L4) translations.
-* `datetime_select` and `select_month` use translated month names for populating the resulting select tag. See [date.month_names](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L15) for translations. `datetime_select` also looks up the order option from [date.order](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L18) (unless you pass the option explicitly). All date selection helpers translate the prompt using the translations in the [datetime.prompts](https://github.com/rails/rails/blob/master/actionview/lib/action_view/locale/en.yml#L39) scope if applicable.
+* `datetime_select` and `select_month` use translated month names for populating the resulting select tag. See [date.month_names](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L15) for translations. `datetime_select` also looks up the order option from [date.order](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L18) (unless you pass the option explicitly). All date selection helpers translate the prompt using the translations in the [datetime.prompts](https://github.com/rails/rails/blob/main/actionview/lib/action_view/locale/en.yml#L39) scope if applicable.
-* The `number_to_currency`, `number_with_precision`, `number_to_percentage`, `number_with_delimiter`, and `number_to_human_size` helpers use the number format settings located in the [number](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L37) scope.
+* The `number_to_currency`, `number_with_precision`, `number_to_percentage`, `number_with_delimiter`, and `number_to_human_size` helpers use the number format settings located in the [number](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L37) scope.
#### Active Model Methods
-* `model_name.human` and `human_attribute_name` use translations for model names and attribute names if available in the [activerecord.models](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/locale/en.yml#L36) scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
+* `model_name.human` and `human_attribute_name` use translations for model names and attribute names if available in the [activerecord.models](https://github.com/rails/rails/blob/main/activerecord/lib/active_record/locale/en.yml#L36) scope. They also support translations for inherited class names (e.g. for use with STI) as explained above in "Error message scopes".
* `ActiveModel::Errors#generate_message` (which is used by Active Model validations but may also be used manually) uses `model_name.human` and `human_attribute_name` (see above). It also translates the error message and supports translations for inherited class names as explained above in "Error message scopes".
-* `ActiveModel::Errors#full_messages` prepends the attribute name to the error message using a separator that will be looked up from [errors.format](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/locale/en.yml#L4) (and which defaults to `"%{attribute} %{message}"`).
+* `ActiveModel::Errors#full_messages` prepends the attribute name to the error message using a separator that will be looked up from [errors.format](https://github.com/rails/rails/blob/main/activemodel/lib/active_model/locale/en.yml#L4) (and which defaults to `"%{attribute} %{message}"`).
#### Active Support Methods
-* `Array#to_sentence` uses format settings as given in the [support.array](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.yml#L33) scope.
+* `Array#to_sentence` uses format settings as given in the [support.array](https://github.com/rails/rails/blob/main/activesupport/lib/active_support/locale/en.yml#L33) scope.
How to Store your Custom Translations
-------------------------------------
diff --git a/guides/source/kindle/rails_guides.opf.erb b/guides/source/kindle/rails_guides.opf.erb
index 1882ec100538b..83d00cfc2eef4 100644
--- a/guides/source/kindle/rails_guides.opf.erb
+++ b/guides/source/kindle/rails_guides.opf.erb
@@ -5,7 +5,7 @@
- Ruby on Rails Guides (<%= @version || "master@#{@edge[0, 7]}" %>)
+ Ruby on Rails Guides (<%= @version || "main@#{@edge[0, 7]}" %>)en-usRuby on Rails
diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb
index 72c676202e216..7a646bde6ca28 100644
--- a/guides/source/layout.html.erb
+++ b/guides/source/layout.html.erb
@@ -35,10 +35,10 @@
More Ruby on Rails
You may also find incomplete content or stuff that is not up to date.
- Please do add any missing documentation for master. Make sure to check
+ Please do add any missing documentation for main. Make sure to check
<%= link_to 'Edge Guides', 'https://edgeguides.rubyonrails.org' %> first to verify
- if the issues are already fixed or not on the master branch.
+ if the issues are already fixed or not on the main branch.
Check the <%= link_to 'Ruby on Rails Guides Guidelines', 'ruby_on_rails_guides_guidelines.html' %>
for style and conventions.