]> cat aescling's git repositories - mastodon.git/commitdiff
Update Mastodon to Rails 6.1 (#15910)
authorClaire <claire.github-309c@sitedethib.com>
Wed, 24 Mar 2021 09:44:31 +0000 (10:44 +0100)
committerGitHub <noreply@github.com>
Wed, 24 Mar 2021 09:44:31 +0000 (10:44 +0100)
* Update devise-two-factor to unreleased fork for Rails 6 support

Update tests to match new `rotp` version.

* Update nsa gem to unreleased fork for Rails 6 support

* Update rails to 6.1.3 and rails-i18n to 6.0

* Update to unreleased fork of pluck_each for Ruby 6 support

* Run "rails app:update"

* Add missing ActiveStorage config file

* Use config.ssl_options instead of removed ApplicationController#force_ssl

Disabled force_ssl-related tests as they do not seem to be easily testable
anymore.

* Fix nonce directives by removing Rails 5 specific monkey-patching

* Fix fixture_file_upload deprecation warning

* Fix yield-based test failing with Rails 6

* Use Rails 6's index_with when possible

* Use ActiveRecord::Cache::Store#delete_multi from Rails 6

This will yield better performances when deleting an account

* Disable Rails 6.1's automatic preload link headers

Since Rails 6.1, ActionView adds preload links for javascript files
in the Links header per default.

In our case, that will bloat headers too much and potentially cause
issues with reverse proxies. Furhermore, we don't need those links,
as we already output them as HTML link tags.

* Switch to Rails 6.0 default config

* Switch to Rails 6.1 default config

* Do not include autoload paths in the load path

29 files changed:
Gemfile
Gemfile.lock
app/controllers/application_controller.rb
app/lib/delivery_failure_tracker.rb
app/lib/feed_manager.rb
app/lib/settings/scoped_settings.rb
app/models/concerns/account_interactions.rb
app/models/report.rb
app/services/delete_account_service.rb
app/services/import_service.rb
bin/setup
bin/yarn
config/application.rb
config/environments/production.rb
config/initializers/application_controller_renderer.rb
config/initializers/backtrace_silencers.rb
config/initializers/content_security_policy.rb
config/initializers/permissions_policy.rb [new file with mode: 0644]
config/initializers/preload_link_headers.rb [new file with mode: 0644]
config/storage.yml [new file with mode: 0644]
lib/tasks/emojis.rake
spec/controllers/api/v1/accounts/credentials_controller_spec.rb
spec/controllers/api/v1/media_controller_spec.rb
spec/controllers/application_controller_spec.rb
spec/controllers/settings/imports_controller_spec.rb
spec/controllers/settings/profiles_controller_spec.rb
spec/controllers/settings/two_factor_authentication/confirmations_controller_spec.rb
spec/models/setting_spec.rb
spec/models/user_spec.rb

diff --git a/Gemfile b/Gemfile
index 98af92deff4190aed0e43cd6a8deccc4922c3813..0b2fdf1560df22948b50ce20b086fc63b3bb5758 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -6,7 +6,7 @@ ruby '>= 2.5.0', '< 3.0.0'
 gem 'pkg-config', '~> 1.4'
 
 gem 'puma', '~> 5.2'
-gem 'rails', '~> 5.2.4.5'
+gem 'rails', '~> 6.1.3'
 gem 'sprockets', '~> 3.7.2'
 gem 'thor', '~> 1.1'
 gem 'rack', '~> 2.2.3'
@@ -34,7 +34,7 @@ gem 'iso-639'
 gem 'chewy', '~> 5.2'
 gem 'cld3', '~> 3.4.1'
 gem 'devise', '~> 4.7'
-gem 'devise-two-factor', '~> 3.1'
+gem 'devise-two-factor', git: 'https://github.com/ClearlyClaire/devise-two-factor', ref: '594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d'
 
 group :pam_authentication, optional: true do
   gem 'devise_pam_authenticatable2', '~> 9.2'
@@ -65,7 +65,7 @@ gem 'link_header', '~> 0.0'
 gem 'mime-types', '~> 3.3.1', require: 'mime/types/columnar'
 gem 'nilsimsa', git: 'https://github.com/witgo/nilsimsa', ref: 'fd184883048b922b176939f851338d0a4971a532'
 gem 'nokogiri', '~> 1.11'
-gem 'nsa', '~> 0.2'
+gem 'nsa', git: 'https://github.com/Gargron/nsa', ref: 'd1079e0cdafdfed7f9f35478d13b9bdaa65965c0'
 gem 'oj', '~> 3.11'
 gem 'ox', '~> 2.14'
 gem 'parslet'
@@ -75,7 +75,7 @@ gem 'pundit', '~> 2.1'
 gem 'premailer-rails'
 gem 'rack-attack', '~> 6.5'
 gem 'rack-cors', '~> 1.1', require: 'rack/cors'
-gem 'rails-i18n', '~> 5.1'
+gem 'rails-i18n', '~> 6.0'
 gem 'rails-settings-cached', '~> 0.6'
 gem 'redis', '~> 4.2', require: ['redis', 'redis/connection/hiredis']
 gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
@@ -159,4 +159,4 @@ gem 'concurrent-ruby', require: false
 gem 'connection_pool', require: false
 
 gem 'xorcist', '~> 1.1'
-gem 'pluck_each', '~> 0.1.3'
+gem 'pluck_each', git: 'https://github.com/nsommer/pluck_each', ref: '73be0947c52fc54bf6d7085378db008358aac5eb'
index 1a67f893d6311111d6c1db836b335682bd3ce1d0..1f7183b9d00d385cd573489e6fdb6e5cfbb818b0 100644 (file)
@@ -1,3 +1,26 @@
+GIT
+  remote: https://github.com/ClearlyClaire/devise-two-factor
+  revision: 594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d
+  ref: 594bb8a32e6f94df7e5ba7c9399eaf9ff25bac0d
+  specs:
+    devise-two-factor (3.1.0)
+      activesupport (< 7.0)
+      attr_encrypted (>= 1.3, < 4, != 2)
+      devise
+      railties (< 7.0)
+      rotp (~> 6)
+
+GIT
+  remote: https://github.com/Gargron/nsa
+  revision: d1079e0cdafdfed7f9f35478d13b9bdaa65965c0
+  ref: d1079e0cdafdfed7f9f35478d13b9bdaa65965c0
+  specs:
+    nsa (0.2.8)
+      activesupport (>= 4.2, < 7)
+      concurrent-ruby (~> 1.0, >= 1.0.2)
+      sidekiq (>= 3.5)
+      statsd-ruby (~> 1.4, >= 1.4.0)
+
 GIT
   remote: https://github.com/ianheggie/health_check
   revision: 0b799ead604f900ed50685e9b2d469cd2befba5b
@@ -6,6 +29,15 @@ GIT
     health_check (4.0.0.pre)
       rails (>= 4.0)
 
+GIT
+  remote: https://github.com/nsommer/pluck_each
+  revision: 73be0947c52fc54bf6d7085378db008358aac5eb
+  ref: 73be0947c52fc54bf6d7085378db008358aac5eb
+  specs:
+    pluck_each (0.1.3)
+      activerecord (>= 6.1.0)
+      activesupport (>= 6.1.0)
+
 GIT
   remote: https://github.com/witgo/nilsimsa
   revision: fd184883048b922b176939f851338d0a4971a532
@@ -16,53 +48,71 @@ GIT
 GEM
   remote: https://rubygems.org/
   specs:
-    actioncable (5.2.4.5)
-      actionpack (= 5.2.4.5)
+    actioncable (6.1.3)
+      actionpack (= 6.1.3)
+      activesupport (= 6.1.3)
       nio4r (~> 2.0)
       websocket-driver (>= 0.6.1)
-    actionmailer (5.2.4.5)
-      actionpack (= 5.2.4.5)
-      actionview (= 5.2.4.5)
-      activejob (= 5.2.4.5)
+    actionmailbox (6.1.3)
+      actionpack (= 6.1.3)
+      activejob (= 6.1.3)
+      activerecord (= 6.1.3)
+      activestorage (= 6.1.3)
+      activesupport (= 6.1.3)
+      mail (>= 2.7.1)
+    actionmailer (6.1.3)
+      actionpack (= 6.1.3)
+      actionview (= 6.1.3)
+      activejob (= 6.1.3)
+      activesupport (= 6.1.3)
       mail (~> 2.5, >= 2.5.4)
       rails-dom-testing (~> 2.0)
-    actionpack (5.2.4.5)
-      actionview (= 5.2.4.5)
-      activesupport (= 5.2.4.5)
-      rack (~> 2.0, >= 2.0.8)
+    actionpack (6.1.3)
+      actionview (= 6.1.3)
+      activesupport (= 6.1.3)
+      rack (~> 2.0, >= 2.0.9)
       rack-test (>= 0.6.3)
       rails-dom-testing (~> 2.0)
-      rails-html-sanitizer (~> 1.0, >= 1.0.2)
-    actionview (5.2.4.5)
-      activesupport (= 5.2.4.5)
+      rails-html-sanitizer (~> 1.0, >= 1.2.0)
+    actiontext (6.1.3)
+      actionpack (= 6.1.3)
+      activerecord (= 6.1.3)
+      activestorage (= 6.1.3)
+      activesupport (= 6.1.3)
+      nokogiri (>= 1.8.5)
+    actionview (6.1.3)
+      activesupport (= 6.1.3)
       builder (~> 3.1)
       erubi (~> 1.4)
       rails-dom-testing (~> 2.0)
-      rails-html-sanitizer (~> 1.0, >= 1.0.3)
+      rails-html-sanitizer (~> 1.1, >= 1.2.0)
     active_model_serializers (0.10.12)
       actionpack (>= 4.1, < 6.2)
       activemodel (>= 4.1, < 6.2)
       case_transform (>= 0.2)
       jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
     active_record_query_trace (1.8)
-    activejob (5.2.4.5)
-      activesupport (= 5.2.4.5)
+    activejob (6.1.3)
+      activesupport (= 6.1.3)
       globalid (>= 0.3.6)
-    activemodel (5.2.4.5)
-      activesupport (= 5.2.4.5)
-    activerecord (5.2.4.5)
-      activemodel (= 5.2.4.5)
-      activesupport (= 5.2.4.5)
-      arel (>= 9.0)
-    activestorage (5.2.4.5)
-      actionpack (= 5.2.4.5)
-      activerecord (= 5.2.4.5)
+    activemodel (6.1.3)
+      activesupport (= 6.1.3)
+    activerecord (6.1.3)
+      activemodel (= 6.1.3)
+      activesupport (= 6.1.3)
+    activestorage (6.1.3)
+      actionpack (= 6.1.3)
+      activejob (= 6.1.3)
+      activerecord (= 6.1.3)
+      activesupport (= 6.1.3)
       marcel (~> 0.3.1)
-    activesupport (5.2.4.5)
+      mimemagic (~> 0.3.2)
+    activesupport (6.1.3)
       concurrent-ruby (~> 1.0, >= 1.0.2)
-      i18n (>= 0.7, < 2)
-      minitest (~> 5.1)
-      tzinfo (~> 1.1)
+      i18n (>= 1.6, < 2)
+      minitest (>= 5.1)
+      tzinfo (~> 2.0)
+      zeitwerk (~> 2.3)
     addressable (2.7.0)
       public_suffix (>= 2.0.2, < 5.0)
     airbrussh (1.4.0)
@@ -71,7 +121,6 @@ GEM
     annotate (3.1.1)
       activerecord (>= 3.2, < 7.0)
       rake (>= 10.4, < 14.0)
-    arel (9.0.0)
     ast (2.4.2)
     attr_encrypted (3.1.0)
       encryptor (~> 3.0.0)
@@ -175,12 +224,6 @@ GEM
       railties (>= 4.1.0)
       responders
       warden (~> 1.2.3)
-    devise-two-factor (3.1.0)
-      activesupport (< 6.1)
-      attr_encrypted (>= 1.3, < 4, != 2)
-      devise (~> 4.0)
-      railties (< 6.1)
-      rotp (~> 2.0)
     devise_pam_authenticatable2 (9.2.0)
       devise (>= 4.0.0)
       rpam2 (~> 4.0)
@@ -370,11 +413,6 @@ GEM
       racc (~> 1.4)
     nokogumbo (2.0.4)
       nokogiri (~> 1.8, >= 1.8.4)
-    nsa (0.2.7)
-      activesupport (>= 4.2, < 6)
-      concurrent-ruby (~> 1.0, >= 1.0.2)
-      sidekiq (>= 3.5)
-      statsd-ruby (~> 1.4, >= 1.4.0)
     oj (3.11.3)
     omniauth (1.9.1)
       hashie (>= 3.4.6)
@@ -414,9 +452,6 @@ GEM
     pghero (2.8.0)
       activerecord (>= 5)
     pkg-config (1.4.5)
-    pluck_each (0.1.3)
-      activerecord (> 3.2.0)
-      activesupport (> 3.0.0)
     posix-spawn (0.3.15)
     premailer (1.14.2)
       addressable
@@ -450,18 +485,20 @@ GEM
       rack
     rack-test (1.1.0)
       rack (>= 1.0, < 3)
-    rails (5.2.4.5)
-      actioncable (= 5.2.4.5)
-      actionmailer (= 5.2.4.5)
-      actionpack (= 5.2.4.5)
-      actionview (= 5.2.4.5)
-      activejob (= 5.2.4.5)
-      activemodel (= 5.2.4.5)
-      activerecord (= 5.2.4.5)
-      activestorage (= 5.2.4.5)
-      activesupport (= 5.2.4.5)
-      bundler (>= 1.3.0)
-      railties (= 5.2.4.5)
+    rails (6.1.3)
+      actioncable (= 6.1.3)
+      actionmailbox (= 6.1.3)
+      actionmailer (= 6.1.3)
+      actionpack (= 6.1.3)
+      actiontext (= 6.1.3)
+      actionview (= 6.1.3)
+      activejob (= 6.1.3)
+      activemodel (= 6.1.3)
+      activerecord (= 6.1.3)
+      activestorage (= 6.1.3)
+      activesupport (= 6.1.3)
+      bundler (>= 1.15.0)
+      railties (= 6.1.3)
       sprockets-rails (>= 2.0.0)
     rails-controller-testing (1.0.5)
       actionpack (>= 5.0.1.rc1)
@@ -472,17 +509,17 @@ GEM
       nokogiri (>= 1.6)
     rails-html-sanitizer (1.3.0)
       loofah (~> 2.3)
-    rails-i18n (5.1.3)
+    rails-i18n (6.0.0)
       i18n (>= 0.7, < 2)
-      railties (>= 5.0, < 6)
+      railties (>= 6.0.0, < 7)
     rails-settings-cached (0.6.6)
       rails (>= 4.2.0)
-    railties (5.2.4.5)
-      actionpack (= 5.2.4.5)
-      activesupport (= 5.2.4.5)
+    railties (6.1.3)
+      actionpack (= 6.1.3)
+      activesupport (= 6.1.3)
       method_source
       rake (>= 0.8.7)
-      thor (>= 0.19.0, < 2.0)
+      thor (~> 1.0)
     rainbow (3.0.0)
     rake (13.0.3)
     rdf (3.1.13)
@@ -500,7 +537,7 @@ GEM
       actionpack (>= 5.0)
       railties (>= 5.0)
     rexml (3.2.4)
-    rotp (2.1.2)
+    rotp (6.2.0)
     rpam2 (4.0.2)
     rqrcode (1.2.0)
       chunky_png (~> 1.0)
@@ -600,7 +637,7 @@ GEM
       net-scp (>= 1.1.2)
       net-ssh (>= 2.8.0)
     stackprof (0.2.16)
-    statsd-ruby (1.4.0)
+    statsd-ruby (1.5.0)
     stoplight (2.2.1)
     streamio-ffmpeg (3.0.2)
       multi_json (~> 1.8)
@@ -612,7 +649,6 @@ GEM
     terrapin (0.6.0)
       climate_control (>= 0.0.3, < 1.0)
     thor (1.1.0)
-    thread_safe (0.3.6)
     thwait (0.2.0)
       e2mmap
     tilt (2.0.10)
@@ -632,8 +668,8 @@ GEM
     twitter-text (3.1.0)
       idn-ruby
       unf (~> 0.1.0)
-    tzinfo (1.2.9)
-      thread_safe (~> 0.1)
+    tzinfo (2.0.4)
+      concurrent-ruby (~> 1.0)
     tzinfo-data (1.2021.1)
       tzinfo (>= 1.0.0)
     unf (0.1.4)
@@ -672,6 +708,7 @@ GEM
     xorcist (1.1.2)
     xpath (3.2.0)
       nokogiri (~> 1.8)
+    zeitwerk (2.4.2)
 
 PLATFORMS
   ruby
@@ -703,7 +740,7 @@ DEPENDENCIES
   concurrent-ruby
   connection_pool
   devise (~> 4.7)
-  devise-two-factor (~> 3.1)
+  devise-two-factor!
   devise_pam_authenticatable2 (~> 9.2)
   discard (~> 1.2)
   doorkeeper (~> 5.5)
@@ -741,7 +778,7 @@ DEPENDENCIES
   net-ldap (~> 0.17)
   nilsimsa!
   nokogiri (~> 1.11)
-  nsa (~> 0.2)
+  nsa!
   oj (~> 3.11)
   omniauth (~> 1.9)
   omniauth-cas (~> 2.0)
@@ -756,7 +793,7 @@ DEPENDENCIES
   pg (~> 1.2)
   pghero (~> 2.8)
   pkg-config (~> 1.4)
-  pluck_each (~> 0.1.3)
+  pluck_each!
   posix-spawn
   premailer-rails
   private_address_check (~> 0.5)
@@ -767,9 +804,9 @@ DEPENDENCIES
   rack (~> 2.2.3)
   rack-attack (~> 6.5)
   rack-cors (~> 1.1)
-  rails (~> 5.2.4.5)
+  rails (~> 6.1.3)
   rails-controller-testing (~> 1.0)
-  rails-i18n (~> 5.1)
+  rails-i18n (~> 6.0)
   rails-settings-cached (~> 0.6)
   rdf-normalize (~> 0.4)
   redis (~> 4.2)
index 5b7eec94f759f22ae455e0bbcfce32682de8081e..6361d4b276fc436f40de9a197c4a0ff8155df690 100644 (file)
@@ -5,8 +5,6 @@ class ApplicationController < ActionController::Base
   # For APIs, you may want to use :null_session instead.
   protect_from_forgery with: :exception
 
-  force_ssl if: :https_enabled?
-
   include Localized
   include UserTrackingConcern
   include SessionTrackingConcern
@@ -42,10 +40,6 @@ class ApplicationController < ActionController::Base
 
   private
 
-  def https_enabled?
-    Rails.env.production? && !request.path.start_with?('/health') && !request.headers["Host"].end_with?(".onion")
-  end
-
   def authorized_fetch_mode?
     ENV['AUTHORIZED_FETCH'] == 'true' || Rails.configuration.x.whitelist_mode
   end
index 25fa694d22fb1969126d8d58faaecadd91b6af7e..2cd6ef7adf8a738c817e58fc3a47f192553cfebd 100644 (file)
@@ -29,7 +29,7 @@ class DeliveryFailureTracker
 
   class << self
     def without_unavailable(urls)
-      unavailable_domains_map = Rails.cache.fetch('unavailable_domains') { UnavailableDomain.pluck(:domain).each_with_object({}) { |domain, hash| hash[domain] = true } }
+      unavailable_domains_map = Rails.cache.fetch('unavailable_domains') { UnavailableDomain.pluck(:domain).index_with(true) }
 
       urls.reject do |url|
         host = Addressable::URI.parse(url).normalized_host
index 165338437bc4fba97b9cabf2d9402c3cb0d21ed1..43aeecb3531c7eace490e9e57cf95d3bebefe1fb 100644 (file)
@@ -533,12 +533,12 @@ class FeedManager
       arr
     end
 
-    crutches[:following]       = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:in_reply_to_account_id).compact).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
-    crutches[:hiding_reblogs]  = Follow.where(account_id: receiver_id, target_account_id: statuses.map { |s| s.account_id if s.reblog? }.compact, show_reblogs: false).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
-    crutches[:blocking]        = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
-    crutches[:muting]          = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
-    crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.map { |s| s.reblog&.account&.domain }.compact).pluck(:domain).each_with_object({}) { |domain, mapping| mapping[domain] = true }
-    crutches[:blocked_by]      = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| s.reblog&.account_id }.compact).pluck(:account_id).each_with_object({}) { |id, mapping| mapping[id] = true }
+    crutches[:following]       = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:in_reply_to_account_id).compact).pluck(:target_account_id).index_with(true)
+    crutches[:hiding_reblogs]  = Follow.where(account_id: receiver_id, target_account_id: statuses.map { |s| s.account_id if s.reblog? }.compact, show_reblogs: false).pluck(:target_account_id).index_with(true)
+    crutches[:blocking]        = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
+    crutches[:muting]          = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
+    crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.map { |s| s.reblog&.account&.domain }.compact).pluck(:domain).index_with(true)
+    crutches[:blocked_by]      = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| s.reblog&.account_id }.compact).pluck(:account_id).index_with(true)
 
     crutches
   end
index acabf0c8e059ec254650a53e24ac3d24f2423b8c..1e18d6d463d8aa347a57c9bfa6d539673dfabf6e 100644 (file)
@@ -63,7 +63,7 @@ module Settings
 
     class << self
       def default_settings
-        defaulting = DEFAULTING_TO_UNSCOPED.each_with_object({}) { |k, h| h[k] = Setting[k] }
+        defaulting = DEFAULTING_TO_UNSCOPED.index_with { |k| Setting[k] }
         Setting.default_settings.merge!(defaulting)
       end
     end
index 974f57820d08332436492d5b0b3bc2cb65fdfa35..51e8e04a80dc3f636f2a133da6fc3c386a9f539d 100644 (file)
@@ -67,7 +67,7 @@ module AccountInteractions
     private
 
     def follow_mapping(query, field)
-      query.pluck(field).each_with_object({}) { |id, mapping| mapping[id] = true }
+      query.pluck(field).index_with(true)
     end
   end
 
index cd08120e4130a9272c89eadd189936405304607e..ef41547d99c61d94aed07a572f159041e23b5d36 100644 (file)
@@ -32,7 +32,7 @@ class Report < ApplicationRecord
 
   scope :unresolved, -> { where(action_taken: false) }
   scope :resolved,   -> { where(action_taken: true) }
-  scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].each_with_object({}) { |k, h| h[k] = { user: [:invite_request, :invite] } }) }
+  scope :with_accounts, -> { includes([:account, :target_account, :action_taken_by_account, :assigned_account].index_with({ user: [:invite_request, :invite] })) }
 
   validates :comment, length: { maximum: 1000 }
 
index 802799ccd9b96389fc644202f3a9e4395acb841f..182f0e1277f808fbf0cf78a7c6aa4b4b82dda4ce 100644 (file)
@@ -188,8 +188,7 @@ class DeleteAccountService < BaseService
       ids = favourites.pluck(:status_id)
       StatusStat.where(status_id: ids).update_all('favourites_count = GREATEST(0, favourites_count - 1)')
       Chewy.strategy.current.update(StatusesIndex::Status, ids) if Chewy.enabled?
-      # Rails.cache.delete_multi would be better, but we don't have it yet
-      ids.each { |id| Rails.cache.delete("statuses/#{id}") }
+      Rails.cache.delete_multi(ids.map { |id| "statuses/#{id}" })
       favourites.delete_all
     end
   end
index b115322831b9d79035a425ecb949545f5c36cfd0..74ad5b79f421c438bd238ffd5e52d6829ad3aa25 100644 (file)
@@ -45,7 +45,7 @@ class ImportService < BaseService
     items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#domain'].strip }
 
     if @import.overwrite?
-      presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true }
+      presence_hash = items.index_with(true)
 
       @account.domain_blocks.find_each do |domain_block|
         if presence_hash[domain_block.domain]
@@ -96,7 +96,7 @@ class ImportService < BaseService
     items = @data.take(ROWS_PROCESSING_LIMIT).map { |row| row['#uri'].strip }
 
     if @import.overwrite?
-      presence_hash = items.each_with_object({}) { |id, mapping| mapping[id] = true }
+      presence_hash = items.index_with(true)
 
       @account.bookmarks.find_each do |bookmark|
         if presence_hash[bookmark.status.uri]
index fc77b080906533e1bd035f6d4c58f9cfdd0fe8c5..90700ac4f9a38d569058bc83f2243a08b4c90eb7 100755 (executable)
--- a/bin/setup
+++ b/bin/setup
@@ -1,6 +1,5 @@
 #!/usr/bin/env ruby
-require 'fileutils'
-include FileUtils
+require "fileutils"
 
 # path to your application root.
 APP_ROOT = File.expand_path('..', __dir__)
@@ -9,22 +8,25 @@ def system!(*args)
   system(*args) || abort("\n== Command #{args} failed ==")
 end
 
-chdir APP_ROOT do
-  # This script is a starting point to setup your application.
+FileUtils.chdir APP_ROOT do
+  # This script is a way to set up or update your development environment automatically.
+  # This script is idempotent, so that you can run it at any time and get an expectable outcome.
   # Add necessary setup steps to this file.
 
   puts '== Installing dependencies =='
   system! 'gem install bundler --conservative'
   system('bundle check') || system!('bundle install')
-  system!('yarn install')
+
+  # Install JavaScript dependencies
+  system! 'bin/yarn'
 
   # puts "\n== Copying sample files =="
   # unless File.exist?('config/database.yml')
-  #   cp 'config/database.yml.sample', 'config/database.yml'
+  #   FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
   # end
 
   puts "\n== Preparing database =="
-  system! 'bin/rails db:setup'
+  system! 'bin/rails db:prepare'
 
   puts "\n== Removing old logs and tempfiles =="
   system! 'bin/rails log:clear tmp:clear'
index 460dd565b4a3dd6c4cb028bc19d78a7c066d3ec8..9fab2c35079e83a3a5fc47d115bc02c21a6a6dd7 100755 (executable)
--- a/bin/yarn
+++ b/bin/yarn
@@ -1,9 +1,15 @@
 #!/usr/bin/env ruby
 APP_ROOT = File.expand_path('..', __dir__)
 Dir.chdir(APP_ROOT) do
-  begin
-    exec "yarnpkg", *ARGV
-  rescue Errno::ENOENT
+  yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
+    select { |dir| File.expand_path(dir) != __dir__ }.
+    product(["yarn", "yarn.cmd", "yarn.ps1"]).
+    map { |dir, file| File.expand_path(file, dir) }.
+    find { |file| File.executable?(file) }
+
+  if yarn
+    exec yarn, *ARGV
+  else
     $stderr.puts "Yarn executable was not detected in the system."
     $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
     exit 1
index 3267fa71be546dd82db90cf16fcb2dc93c3f209a..c911e76dcffa8416355cfc8623a000a4240c05ca 100644 (file)
@@ -39,7 +39,8 @@ require_relative '../lib/mastodon/redis_config'
 module Mastodon
   class Application < Rails::Application
     # Initialize configuration defaults for originally generated Rails version.
-    config.load_defaults 5.2
+    config.load_defaults 6.1
+    config.add_autoload_paths_to_load_path = false
 
     # Settings in config/environments/* take precedence over those specified here.
     # Application configuration should go into files in config/initializers
index 81a67902eadb6214bc56fb1ea397ca817957e202..6df0a336513a383a797d83dc74463d5cdcda62f8 100644 (file)
@@ -44,6 +44,13 @@ Rails.application.configure do
   # Allow to specify public IP of reverse proxy if it's needed
   config.action_dispatch.trusted_proxies = ENV['TRUSTED_PROXY_IP'].split.map { |item| IPAddr.new(item) } if ENV['TRUSTED_PROXY_IP'].present?
 
+  config.force_ssl = true
+  config.ssl_options = {
+    redirect: {
+      exclude: -> request { request.path.start_with?('/health') || request.headers["Host"].end_with?('.onion') }
+    }
+  }
+
   # Use the lowest log level to ensure availability of diagnostic information
   # when problems arise.
   config.log_level = ENV.fetch('RAILS_LOG_LEVEL', 'info').to_sym
index 51639b67a00ddba973a92d59ec277f5d97b63ef6..89d2efab2ba659d7814a7665a99f7f8d7429a072 100644 (file)
@@ -1,6 +1,8 @@
 # Be sure to restart your server when you modify this file.
 
-# ApplicationController.renderer.defaults.merge!(
-#   http_host: 'example.org',
-#   https: false
-# )
+# ActiveSupport::Reloader.to_prepare do
+#   ApplicationController.renderer.defaults.merge!(
+#     http_host: 'example.org',
+#     https: false
+#   )
+# end
index 59385cdf379bd06a8d2326dcd4de6d5cd5d3f5b0..33699c30910b95ab124dc40bb9a244dac0093578 100644 (file)
@@ -1,7 +1,8 @@
 # Be sure to restart your server when you modify this file.
 
 # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
-# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
 
-# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
-# Rails.backtrace_cleaner.remove_silencers!
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
+# by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
+Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
index 98dc711e1b87c943e51d9ee1b18273f7e461a936..92645ff288484ccad22a28850f22a1d198682d3a 100644 (file)
@@ -49,17 +49,7 @@ end
 
 Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
 
-# Monkey-patching Rails 5
-module ActionDispatch
-  class ContentSecurityPolicy
-    def nonce_directive?(directive)
-      directive == 'style-src'
-    end
-  end
-end
-
-# Rails 6 would require the following instead:
-# Rails.application.config.content_security_policy_nonce_directives = %w(style-src)
+Rails.application.config.content_security_policy_nonce_directives = %w(style-src)
 
 PgHero::HomeController.content_security_policy do |p|
   p.script_src :self, :unsafe_inline, assets_host
diff --git a/config/initializers/permissions_policy.rb b/config/initializers/permissions_policy.rb
new file mode 100644 (file)
index 0000000..00f64d7
--- /dev/null
@@ -0,0 +1,11 @@
+# Define an application-wide HTTP permissions policy. For further
+# information see https://developers.google.com/web/updates/2018/06/feature-policy
+#
+# Rails.application.config.permissions_policy do |f|
+#   f.camera      :none
+#   f.gyroscope   :none
+#   f.microphone  :none
+#   f.usb         :none
+#   f.fullscreen  :self
+#   f.payment     :self, "https://secure.example.com"
+# end
diff --git a/config/initializers/preload_link_headers.rb b/config/initializers/preload_link_headers.rb
new file mode 100644 (file)
index 0000000..9f21c45
--- /dev/null
@@ -0,0 +1,8 @@
+# Since Rails 6.1, ActionView adds preload links for javascript files
+# in the Links header per default.
+
+# In our case, that will bloat headers too much and potentially cause
+# issues with reverse proxies. Furhermore, we don't need those links,
+# as we already output them as HTML link tags.
+
+Rails.application.config.action_view.preload_links_header = false
diff --git a/config/storage.yml b/config/storage.yml
new file mode 100644 (file)
index 0000000..e69de29
index 01ae955643bd9937d0a004c508ed2d562122d0f5..c8655cc47850aaec6cb5cfb4067c2e2ee3623456 100644 (file)
@@ -69,7 +69,7 @@ namespace :emojis do
       end
     end
 
-    existence_maps = grouped_codes.map { |c| c.map { |cc| [cc, File.exist?(Rails.root.join('public', 'emoji', codepoints_to_filename(cc) + '.svg'))] }.to_h }
+    existence_maps = grouped_codes.map { |c| c.index_with { |cc| File.exist?(Rails.root.join('public', 'emoji', codepoints_to_filename(cc) + '.svg')) } }
     map = {}
 
     existence_maps.each do |group|
index ebd462a039421c0470b4137593aa6210d4a65980..9fb0d8770045e468b6ad461a45bf4270a61be91b 100644 (file)
@@ -30,8 +30,8 @@ describe Api::V1::Accounts::CredentialsController do
           patch :update, params: {
             display_name: "Alice Isn't Dead",
             note: "Hi!\n\nToot toot!",
-            avatar: fixture_file_upload('files/avatar.gif', 'image/gif'),
-            header: fixture_file_upload('files/attachment.jpg', 'image/jpeg'),
+            avatar: fixture_file_upload('avatar.gif', 'image/gif'),
+            header: fixture_file_upload('attachment.jpg', 'image/jpeg'),
             source: {
               privacy: 'unlisted',
               sensitive: true,
index 4e3037208431268324a19642297ccaa7172ca63f..3eb015a1ca42fdf62f651dfd00ad960cf83a3fdb 100644 (file)
@@ -15,7 +15,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
       context 'when imagemagick cant identify the file type' do
         before do
           expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Errors::NotIdentifiedByImageMagickError)
-          post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
+          post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
         end
 
         it 'returns http 422' do
@@ -26,7 +26,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
       context 'when there is a generic error' do
         before do
           expect_any_instance_of(Account).to receive_message_chain(:media_attachments, :create!).and_raise(Paperclip::Error)
-          post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
+          post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
         end
 
         it 'returns http 422' do
@@ -37,7 +37,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
 
     context 'image/jpeg' do
       before do
-        post :create, params: { file: fixture_file_upload('files/attachment.jpg', 'image/jpeg') }
+        post :create, params: { file: fixture_file_upload('attachment.jpg', 'image/jpeg') }
       end
 
       it 'returns http success' do
@@ -59,7 +59,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
 
     context 'image/gif' do
       before do
-        post :create, params: { file: fixture_file_upload('files/attachment.gif', 'image/gif') }
+        post :create, params: { file: fixture_file_upload('attachment.gif', 'image/gif') }
       end
 
       it 'returns http success' do
@@ -81,7 +81,7 @@ RSpec.describe Api::V1::MediaController, type: :controller do
 
     context 'video/webm' do
       before do
-        post :create, params: { file: fixture_file_upload('files/attachment.webm', 'video/webm') }
+        post :create, params: { file: fixture_file_upload('attachment.webm', 'video/webm') }
       end
 
       it do
index e73a08a0e998d040c74030fdf518689d586e4be0..458298a6b9ec53b9a2c1b9daf1e3d56c8819c78f 100644 (file)
@@ -42,20 +42,6 @@ describe ApplicationController, type: :controller do
     include_examples 'respond_with_error', 422
   end
 
-  it "does not force ssl if Rails.env.production? is not 'true'" do
-    routes.draw { get 'success' => 'anonymous#success' }
-    allow(Rails.env).to receive(:production?).and_return(false)
-    get 'success'
-    expect(response).to have_http_status(200)
-  end
-
-  it "forces ssl if Rails.env.production? is 'true'" do
-    routes.draw { get 'success' => 'anonymous#success' }
-    allow(Rails.env).to receive(:production?).and_return(true)
-    get 'success'
-    expect(response).to redirect_to('https://test.host/success')
-  end
-
   describe 'helper_method :current_account' do
     it 'returns nil if not signed in' do
       expect(controller.view_context.current_account).to be_nil
index 7a9b021957f93bb5c6b1baa9cb2d549ebd0b4786..b8caf59413aa8d52c390c0f385b9512263cc3c19 100644 (file)
@@ -21,7 +21,7 @@ RSpec.describe Settings::ImportsController, type: :controller do
       post :create, params: {
         import: {
           type: 'following',
-          data: fixture_file_upload('files/imports.txt')
+          data: fixture_file_upload('imports.txt')
         }
       }
 
@@ -34,7 +34,7 @@ RSpec.describe Settings::ImportsController, type: :controller do
       post :create, params: {
         import: {
           type: 'blocking',
-          data: fixture_file_upload('files/imports.txt')
+          data: fixture_file_upload('imports.txt')
         }
       }
 
index 5b1fe3acad697e4c8878dd73d82b723de97469cb..1ac286254f3365ddc80405ed0888fd8b9419937f 100644 (file)
@@ -33,7 +33,7 @@ RSpec.describe Settings::ProfilesController, type: :controller do
       account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
       expect(account.avatar.instance.avatar_file_name).to be_nil
 
-      put :update, params: { account: { avatar: fixture_file_upload('files/avatar.gif', 'image/gif') } }
+      put :update, params: { account: { avatar: fixture_file_upload('avatar.gif', 'image/gif') } }
       expect(response).to redirect_to(settings_profile_path)
       expect(account.reload.avatar.instance.avatar_file_name).not_to be_nil
       expect(ActivityPub::UpdateDistributionWorker).to have_received(:perform_async).with(account.id)
@@ -44,7 +44,7 @@ RSpec.describe Settings::ProfilesController, type: :controller do
     it 'gives the user an error message' do
       allow(ActivityPub::UpdateDistributionWorker).to receive(:perform_async)
       account = Fabricate(:account, user: @user, display_name: 'AvatarTest')
-      put :update, params: { account: { avatar: fixture_file_upload('files/4096x4097.png', 'image/png') } }
+      put :update, params: { account: { avatar: fixture_file_upload('4096x4097.png', 'image/png') } }
       expect(response.body).to include('images are not supported')
     end
   end
index cdfeef8d6a7223a7d2a14ac8ee0d20730fb8fd00..7b86513bef6cf9dff6af92710d3cd1789ffccf20 100644 (file)
@@ -11,7 +11,7 @@ describe Settings::TwoFactorAuthentication::ConfirmationsController do
       subject
 
       expect(assigns(:confirmation)).to be_instance_of Form::TwoFactorConfirmation
-      expect(assigns(:provision_url)).to eq 'otpauth://totp/local-part@domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io'
+      expect(assigns(:provision_url)).to eq 'otpauth://totp/cb6e6126.ngrok.io:local-part%40domain?secret=thisisasecretforthespecofnewview&issuer=cb6e6126.ngrok.io'
       expect(assigns(:qrcode)).to be_instance_of RQRCode::QRCode
       expect(response).to have_http_status(200)
       expect(response).to render_template(:new)
index 1cc5286748acd34043f19bd8a8b5b06f44b7b97b..3ccc21d6c41bed1d0386e694d7afad5d36a780e0 100644 (file)
@@ -99,11 +99,12 @@ RSpec.describe Setting, type: :model do
         end
 
         it 'does not query the database' do
-          expect do |callback|
-            ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
-              described_class[key]
-            end
-          end.not_to yield_control
+          callback = double
+          allow(callback).to receive(:call)
+          ActiveSupport::Notifications.subscribed callback, 'sql.active_record' do
+            described_class[key]
+          end
+          expect(callback).not_to have_received(:call)
         end
 
         it 'returns the cached value' do
index 1dae43536087b8cdaf714c04eb26e2b7f3e7e516..5db249be2a9174765d20dad073981897904be5e8 100644 (file)
@@ -175,7 +175,7 @@ RSpec.describe User, type: :model do
       user = Fabricate(:user)
       ActiveJob::Base.queue_adapter = :test
 
-      expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::DeliveryJob)
+      expect { user.send_confirmation_instructions }.to have_enqueued_job(ActionMailer::MailDeliveryJob)
     end
   end