Prepare Mastodon for Rails 6 (#15911)
* Fix misuse of foreign_type * Fix use of removed "add_template_helper" * Use response.media_type instead of response.content_type in tests * Fix CSV export controller test on Rails 6 Rails 6 sets a "filename*" field in the Content-Disposition header to explicitly encode the filename as UTF-8. This changes checks the first part of the Content-Disposition header so it matches in both Rails 5 and Rails 6. * Fix emoji formatting with Rails 6 * Make emoji output more idiomatic and robust * Switch from redis-rails gem to built-in Rails redis cache storage
This commit is contained in:
		
							parent
							
								
									9cb6bc56fa
								
							
						
					
					
						commit
						43eff898a0
					
				
							
								
								
									
										1
									
								
								Gemfile
								
								
								
								
							
							
						
						
									
										1
									
								
								Gemfile
								
								
								
								
							|  | @ -153,7 +153,6 @@ end | |||
| 
 | ||||
| group :production do | ||||
|   gem 'lograge', '~> 0.11' | ||||
|   gem 'redis-rails', '~> 5.0' | ||||
| end | ||||
| 
 | ||||
| gem 'concurrent-ruby', require: false | ||||
|  |  | |||
							
								
								
									
										17
									
								
								Gemfile.lock
								
								
								
								
							
							
						
						
									
										17
									
								
								Gemfile.lock
								
								
								
								
							|  | @ -491,24 +491,8 @@ GEM | |||
|     rdf-normalize (0.4.0) | ||||
|       rdf (~> 3.1) | ||||
|     redis (4.2.5) | ||||
|     redis-actionpack (5.2.0) | ||||
|       actionpack (>= 5, < 7) | ||||
|       redis-rack (>= 2.1.0, < 3) | ||||
|       redis-store (>= 1.1.0, < 2) | ||||
|     redis-activesupport (5.2.0) | ||||
|       activesupport (>= 3, < 7) | ||||
|       redis-store (>= 1.3, < 2) | ||||
|     redis-namespace (1.8.1) | ||||
|       redis (>= 3.0.4) | ||||
|     redis-rack (2.1.3) | ||||
|       rack (>= 2.0.8, < 3) | ||||
|       redis-store (>= 1.2, < 2) | ||||
|     redis-rails (5.0.2) | ||||
|       redis-actionpack (>= 5.0, < 6) | ||||
|       redis-activesupport (>= 5.0, < 6) | ||||
|       redis-store (>= 1.2, < 2) | ||||
|     redis-store (1.9.0) | ||||
|       redis (>= 4, < 5) | ||||
|     regexp_parser (2.1.1) | ||||
|     request_store (1.5.0) | ||||
|       rack (>= 1.4) | ||||
|  | @ -790,7 +774,6 @@ DEPENDENCIES | |||
|   rdf-normalize (~> 0.4) | ||||
|   redis (~> 4.2) | ||||
|   redis-namespace (~> 1.8) | ||||
|   redis-rails (~> 5.0) | ||||
|   rqrcode (~> 1.2) | ||||
|   rspec-rails (~> 5.0) | ||||
|   rspec-sidekiq (~> 3.1) | ||||
|  |  | |||
|  | @ -158,9 +158,9 @@ class Formatter | |||
|           original_url, static_url = emoji | ||||
|           replacement = begin | ||||
|             if animate | ||||
|               "<img draggable=\"false\" class=\"emojione\" alt=\":#{encode(shortcode)}:\" title=\":#{encode(shortcode)}:\" src=\"#{encode(original_url)}\" />" | ||||
|               image_tag(original_url, draggable: false, class: 'emojione', alt: ":#{shortcode}:", title: ":#{shortcode}:") | ||||
|             else | ||||
|               "<img draggable=\"false\" class=\"emojione custom-emoji\" alt=\":#{encode(shortcode)}:\" title=\":#{encode(shortcode)}:\" src=\"#{encode(static_url)}\" data-original=\"#{original_url}\" data-static=\"#{static_url}\" />" | ||||
|               image_tag(original_url, draggable: false, class: 'emojione custom-emoji', alt: ":#{shortcode}:", title: ":#{shortcode}:", data: { original: original_url, static: static_url }) | ||||
|             end | ||||
|           end | ||||
|           before_html = shortname_start_index.positive? ? html[0..shortname_start_index - 1] : '' | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ class NotificationMailer < ApplicationMailer | |||
|   helper :accounts | ||||
|   helper :statuses | ||||
| 
 | ||||
|   add_template_helper RoutingHelper | ||||
|   helper RoutingHelper | ||||
| 
 | ||||
|   def mention(recipient, notification) | ||||
|     @me     = recipient | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ class UserMailer < Devise::Mailer | |||
|   helper :instance | ||||
|   helper :statuses | ||||
| 
 | ||||
|   add_template_helper RoutingHelper | ||||
|   helper RoutingHelper | ||||
| 
 | ||||
|   def confirmation_instructions(user, token, **) | ||||
|     @resource = user | ||||
|  |  | |||
|  | @ -49,12 +49,12 @@ class Notification < ApplicationRecord | |||
|   belongs_to :from_account, class_name: 'Account', optional: true | ||||
|   belongs_to :activity, polymorphic: true, optional: true | ||||
| 
 | ||||
|   belongs_to :mention,        foreign_type: 'Mention',       foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :status,         foreign_type: 'Status',        foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :follow,         foreign_type: 'Follow',        foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :follow_request, foreign_type: 'FollowRequest', foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :favourite,      foreign_type: 'Favourite',     foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :poll,           foreign_type: 'Poll',          foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :mention,        foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :status,         foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :follow,         foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :follow_request, foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :favourite,      foreign_key: 'activity_id', optional: true | ||||
|   belongs_to :poll,           foreign_key: 'activity_id', optional: true | ||||
| 
 | ||||
|   validates :type, inclusion: { in: TYPES } | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ Rails.application.configure do | |||
|   if Rails.root.join('tmp/caching-dev.txt').exist? | ||||
|     config.action_controller.perform_caching = true | ||||
| 
 | ||||
|     config.cache_store = :redis_store, ENV['REDIS_URL'], REDIS_CACHE_PARAMS | ||||
|     config.cache_store = :redis_cache_store, REDIS_CACHE_PARAMS | ||||
| 
 | ||||
|     config.public_file_server.headers = { | ||||
|       'Cache-Control' => "public, max-age=#{2.days.to_i}", | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ Rails.application.configure do | |||
|   config.log_tags = [:request_id] | ||||
| 
 | ||||
|   # Use a different cache store in production. | ||||
|   config.cache_store = :redis_store, ENV['CACHE_REDIS_URL'], REDIS_CACHE_PARAMS | ||||
|   config.cache_store = :redis_cache_store, REDIS_CACHE_PARAMS | ||||
| 
 | ||||
|   # Ignore bad email addresses and do not raise email delivery errors. | ||||
|   # Set this to true and configure the email server for immediate delivery to raise delivery errors. | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| # frozen_string_literal: true | ||||
| 
 | ||||
| namespace    = ENV.fetch('REDIS_NAMESPACE') { nil } | ||||
| redis_params = { url: ENV['REDIS_URL'] } | ||||
| redis_params = { url: ENV['REDIS_URL'], driver: :hiredis } | ||||
| 
 | ||||
| if namespace | ||||
|   redis_params[:namespace] = namespace | ||||
|  |  | |||
|  | @ -27,6 +27,8 @@ namespace       = ENV.fetch('REDIS_NAMESPACE', nil) | |||
| cache_namespace = namespace ? namespace + '_cache' : 'cache' | ||||
| 
 | ||||
| REDIS_CACHE_PARAMS = { | ||||
|   driver: :hiredis, | ||||
|   url: ENV['REDIS_URL'], | ||||
|   expires_in: 10.minutes, | ||||
|   namespace: cache_namespace, | ||||
| }.freeze | ||||
|  |  | |||
|  | @ -370,7 +370,7 @@ RSpec.describe AccountsController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it_behaves_like 'cachable response' | ||||
|  | @ -402,7 +402,7 @@ RSpec.describe AccountsController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it 'returns public Cache-Control header' do | ||||
|  | @ -428,7 +428,7 @@ RSpec.describe AccountsController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it_behaves_like 'cachable response' | ||||
|  | @ -446,7 +446,7 @@ RSpec.describe AccountsController, type: :controller do | |||
|           end | ||||
| 
 | ||||
|           it 'returns application/activity+json' do | ||||
|             expect(response.content_type).to eq 'application/activity+json' | ||||
|             expect(response.media_type).to eq 'application/activity+json' | ||||
|           end | ||||
| 
 | ||||
|           it 'returns private Cache-Control header' do | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it_behaves_like 'cachable response' | ||||
|  | @ -88,7 +88,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do | |||
|           end | ||||
| 
 | ||||
|           it 'returns application/activity+json' do | ||||
|             expect(response.content_type).to eq 'application/activity+json' | ||||
|             expect(response.media_type).to eq 'application/activity+json' | ||||
|           end | ||||
| 
 | ||||
|           it_behaves_like 'cachable response' | ||||
|  | @ -116,7 +116,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do | |||
|             end | ||||
| 
 | ||||
|             it 'returns application/activity+json' do | ||||
|               expect(response.content_type).to eq 'application/activity+json' | ||||
|               expect(response.media_type).to eq 'application/activity+json' | ||||
|             end | ||||
| 
 | ||||
|             it 'returns private Cache-Control header' do | ||||
|  | @ -141,7 +141,7 @@ RSpec.describe ActivityPub::CollectionsController, type: :controller do | |||
|             end | ||||
| 
 | ||||
|             it 'returns application/activity+json' do | ||||
|               expect(response.content_type).to eq 'application/activity+json' | ||||
|               expect(response.media_type).to eq 'application/activity+json' | ||||
|             end | ||||
| 
 | ||||
|             it 'returns private Cache-Control header' do | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ RSpec.describe ActivityPub::FollowersSynchronizationsController, type: :controll | |||
|       end | ||||
| 
 | ||||
|       it 'returns application/activity+json' do | ||||
|         expect(response.content_type).to eq 'application/activity+json' | ||||
|         expect(response.media_type).to eq 'application/activity+json' | ||||
|       end | ||||
| 
 | ||||
|       it 'returns orderedItems with followers from example.com' do | ||||
|  |  | |||
|  | @ -46,7 +46,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it 'returns totalItems' do | ||||
|  | @ -85,7 +85,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it 'returns orderedItems with public or unlisted statuses' do | ||||
|  | @ -133,7 +133,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it 'returns orderedItems with public or unlisted statuses' do | ||||
|  | @ -159,7 +159,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it 'returns orderedItems with private statuses' do | ||||
|  | @ -185,7 +185,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it 'returns empty orderedItems' do | ||||
|  | @ -210,7 +210,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it 'returns empty orderedItems' do | ||||
|  |  | |||
|  | @ -73,7 +73,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do | |||
|         end | ||||
| 
 | ||||
|         it 'returns application/activity+json' do | ||||
|           expect(response.content_type).to eq 'application/activity+json' | ||||
|           expect(response.media_type).to eq 'application/activity+json' | ||||
|         end | ||||
| 
 | ||||
|         it_behaves_like 'cachable response' | ||||
|  | @ -120,7 +120,7 @@ RSpec.describe ActivityPub::RepliesController, type: :controller do | |||
|           end | ||||
| 
 | ||||
|           it 'returns application/activity+json' do | ||||
|             expect(response.content_type).to eq 'application/activity+json' | ||||
|             expect(response.media_type).to eq 'application/activity+json' | ||||
|           end | ||||
| 
 | ||||
|           it_behaves_like 'cachable response' | ||||
|  |  | |||
|  | @ -22,8 +22,8 @@ describe ApplicationController, type: :controller do | |||
|       get :index, format: :csv | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'text/csv' | ||||
|       expect(response.headers['Content-Disposition']).to eq 'attachment; filename="anonymous.csv"' | ||||
|       expect(response.media_type).to eq 'text/csv' | ||||
|       expect(response.headers['Content-Disposition']).to start_with 'attachment; filename="anonymous.csv"' | ||||
|       expect(response.body).to eq user.account.username | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ describe WellKnown::HostMetaController, type: :controller do | |||
|       get :show, format: :xml | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'application/xrd+xml' | ||||
|       expect(response.media_type).to eq 'application/xrd+xml' | ||||
|       expect(response.body).to eq <<XML | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"> | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ describe WellKnown::KeybaseProofConfigController, type: :controller do | |||
|       get :show | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'application/json' | ||||
|       expect(response.media_type).to eq 'application/json' | ||||
|       expect { JSON.parse(response.body) }.not_to raise_exception | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ describe WellKnown::NodeInfoController, type: :controller do | |||
|       get :index | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'application/json' | ||||
|       expect(response.media_type).to eq 'application/json' | ||||
| 
 | ||||
|       json = body_as_json | ||||
| 
 | ||||
|  | @ -23,7 +23,7 @@ describe WellKnown::NodeInfoController, type: :controller do | |||
|       get :show | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'application/json' | ||||
|       expect(response.media_type).to eq 'application/json' | ||||
| 
 | ||||
|       json = body_as_json | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ describe WellKnown::WebfingerController, type: :controller do | |||
|       end | ||||
| 
 | ||||
|       it 'returns application/jrd+json' do | ||||
|         expect(response.content_type).to eq 'application/jrd+json' | ||||
|         expect(response.media_type).to eq 'application/jrd+json' | ||||
|       end | ||||
| 
 | ||||
|       it 'returns links for the account' do | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ describe "The catch all route" do | |||
|       get "/test" | ||||
| 
 | ||||
|       expect(response.status).to eq 404 | ||||
|       expect(response.content_type).to eq "text/html" | ||||
|       expect(response.media_type).to eq "text/html" | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | @ -15,7 +15,7 @@ describe "The catch all route" do | |||
|       get "/test.test" | ||||
| 
 | ||||
|       expect(response.status).to eq 404 | ||||
|       expect(response.content_type).to eq "text/html" | ||||
|       expect(response.media_type).to eq "text/html" | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ describe "The host_meta route" do | |||
|       get host_meta_url | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq "application/xrd+xml" | ||||
|       expect(response.media_type).to eq "application/xrd+xml" | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ describe 'The webfinger route' do | |||
|       get webfinger_url(resource: alice.to_webfinger_s) | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'application/jrd+json' | ||||
|       expect(response.media_type).to eq 'application/jrd+json' | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | @ -17,7 +17,7 @@ describe 'The webfinger route' do | |||
|       get webfinger_url(resource: alice.to_webfinger_s, format: :json) | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'application/jrd+json' | ||||
|       expect(response.media_type).to eq 'application/jrd+json' | ||||
|     end | ||||
| 
 | ||||
|     it 'returns a json response for json accept header' do | ||||
|  | @ -25,7 +25,7 @@ describe 'The webfinger route' do | |||
|       get webfinger_url(resource: alice.to_webfinger_s), headers: headers | ||||
| 
 | ||||
|       expect(response).to have_http_status(200) | ||||
|       expect(response.content_type).to eq 'application/jrd+json' | ||||
|       expect(response.media_type).to eq 'application/jrd+json' | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue