about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/well_known/webfinger_controller.rb7
-rw-r--r--app/lib/activitypub/activity/create.rb2
-rw-r--r--app/lib/webfinger_resource.rb4
-rw-r--r--app/services/search_service.rb2
-rwxr-xr-xbin/tootctl8
-rw-r--r--docker-compose.yml2
-rw-r--r--lib/mastodon/media_cli.rb17
-rw-r--r--lib/mastodon/upgrade_cli.rb41
-rw-r--r--lib/paperclip/gif_transcoder.rb2
-rw-r--r--spec/controllers/well_known/webfinger_controller_spec.rb10
-rw-r--r--spec/lib/activitypub/activity/create_spec.rb25
-rw-r--r--spec/lib/webfinger_resource_spec.rb12
-rw-r--r--spec/services/search_service_spec.rb8
13 files changed, 119 insertions, 21 deletions
diff --git a/app/controllers/well_known/webfinger_controller.rb b/app/controllers/well_known/webfinger_controller.rb
index 480e58f3f..9de9db6ba 100644
--- a/app/controllers/well_known/webfinger_controller.rb
+++ b/app/controllers/well_known/webfinger_controller.rb
@@ -8,7 +8,8 @@ module WellKnown
     before_action :set_account
     before_action :check_account_suspension
 
-    rescue_from ActiveRecord::RecordNotFound, ActionController::ParameterMissing, with: :not_found
+    rescue_from ActiveRecord::RecordNotFound, with: :not_found
+    rescue_from ActionController::ParameterMissing, WebfingerResource::InvalidRequest, with: :bad_request
 
     def show
       expires_in 3.days, public: true
@@ -37,6 +38,10 @@ module WellKnown
       expires_in(3.minutes, public: true) && gone if @account.suspended?
     end
 
+    def bad_request
+      head 400
+    end
+
     def not_found
       head 404
     end
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index c55cfe08e..572b8087e 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -201,7 +201,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
 
       begin
         href             = Addressable::URI.parse(attachment['url']).normalize.to_s
-        media_attachment = MediaAttachment.create(account: @account, remote_url: href, description: attachment['name'].presence, focus: attachment['focalPoint'], blurhash: supported_blurhash?(attachment['blurhash']) ? attachment['blurhash'] : nil)
+        media_attachment = MediaAttachment.create(account: @account, remote_url: href, description: attachment['summary'].presence || attachment['name'].presence, focus: attachment['focalPoint'], blurhash: supported_blurhash?(attachment['blurhash']) ? attachment['blurhash'] : nil)
         media_attachments << media_attachment
 
         next if unsupported_media_type?(attachment['mediaType']) || skip_download?
diff --git a/app/lib/webfinger_resource.rb b/app/lib/webfinger_resource.rb
index 22d78874a..420945485 100644
--- a/app/lib/webfinger_resource.rb
+++ b/app/lib/webfinger_resource.rb
@@ -3,6 +3,8 @@
 class WebfingerResource
   attr_reader :resource
 
+  class InvalidRequest < StandardError; end
+
   def initialize(resource)
     @resource = resource
   end
@@ -14,7 +16,7 @@ class WebfingerResource
     when /\@/
       username_from_acct
     else
-      raise(ActiveRecord::RecordNotFound)
+      raise InvalidRequest
     end
   end
 
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 830de4de3..19500a8d4 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -94,7 +94,7 @@ class SearchService < BaseService
   end
 
   def account_searchable?
-    account_search? && !(@query.include?('@') && @query.include?(' '))
+    account_search? && !(@query.start_with?('#') || (@query.include?('@') && @query.include?(' ')))
   end
 
   def hashtag_searchable?
diff --git a/bin/tootctl b/bin/tootctl
index f26e1c7ed..a9ebb22c6 100755
--- a/bin/tootctl
+++ b/bin/tootctl
@@ -1,5 +1,11 @@
 #!/usr/bin/env ruby
 APP_PATH = File.expand_path('../config/application', __dir__)
+
 require_relative '../config/boot'
 require_relative '../lib/cli'
-Mastodon::CLI.start(ARGV)
+
+begin
+  Mastodon::CLI.start(ARGV)
+rescue Interrupt
+  exit(130)
+end
diff --git a/docker-compose.yml b/docker-compose.yml
index b41578274..e190df6d6 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -14,7 +14,7 @@ services:
 
   redis:
     restart: always
-    image: redis:5.0-alpine
+    image: redis:6.0-alpine
     networks:
       - internal_network
     healthcheck:
diff --git a/lib/mastodon/media_cli.rb b/lib/mastodon/media_cli.rb
index 2b1653335..c95f3410a 100644
--- a/lib/mastodon/media_cli.rb
+++ b/lib/mastodon/media_cli.rb
@@ -88,6 +88,11 @@ module Mastodon
             path_segments = object.key.split('/')
             path_segments.delete('cache')
 
+            if path_segments.size != 7
+              progress.log(pastel.yellow("Unrecognized file found: #{object.key}"))
+              next
+            end
+
             model_name      = path_segments.first.classify
             attachment_name = path_segments[1].singularize
             record_id       = path_segments[2..-2].join.to_i
@@ -127,6 +132,11 @@ module Mastodon
           path_segments = key.split(File::SEPARATOR)
           path_segments.delete('cache')
 
+          if path_segments.size != 7
+            progress.log(pastel.yellow("Unrecognized file found: #{key}"))
+            next
+          end
+
           model_name      = path_segments.first.classify
           record_id       = path_segments[2..-2].join.to_i
           attachment_name = path_segments[1].singularize
@@ -246,6 +256,11 @@ module Mastodon
       path_segments = path.split('/')[2..-1]
       path_segments.delete('cache')
 
+      if path_segments.size != 7
+        say('Not a media URL', :red)
+        exit(1)
+      end
+
       model_name = path_segments.first.classify
       record_id  = path_segments[2..-2].join.to_i
 
@@ -294,6 +309,8 @@ module Mastodon
         segments = object.key.split('/')
         segments.delete('cache')
 
+        next if segments.size != 7
+
         model_name = segments.first.classify
         record_id  = segments[2..-2].join.to_i
 
diff --git a/lib/mastodon/upgrade_cli.rb b/lib/mastodon/upgrade_cli.rb
index 779462a4f..570b7e6fa 100644
--- a/lib/mastodon/upgrade_cli.rb
+++ b/lib/mastodon/upgrade_cli.rb
@@ -41,23 +41,32 @@ module Mastodon
         klass.find_each do |record|
           attachment_names.each do |attachment_name|
             attachment = record.public_send(attachment_name)
+            upgraded   = false
 
             next if attachment.blank? || attachment.storage_schema_version >= CURRENT_STORAGE_SCHEMA_VERSION
 
-            attachment.styles.each_key do |style|
-              case Paperclip::Attachment.default_options[:storage]
-              when :s3
-                upgrade_storage_s3(progress, attachment, style)
-              when :fog
-                upgrade_storage_fog(progress, attachment, style)
-              when :filesystem
-                upgrade_storage_filesystem(progress, attachment, style)
+            styles = attachment.styles.keys
+
+            styles << :original unless styles.include?(:original)
+
+            styles.each do |style|
+              success = begin
+                case Paperclip::Attachment.default_options[:storage]
+                when :s3
+                  upgrade_storage_s3(progress, attachment, style)
+                when :fog
+                  upgrade_storage_fog(progress, attachment, style)
+                when :filesystem
+                  upgrade_storage_filesystem(progress, attachment, style)
+                end
               end
 
+              upgraded = true if style == :original && success
+
               progress.increment
             end
 
-            attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION)
+            attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION) if upgraded
           end
 
           if record.changed?
@@ -78,18 +87,20 @@ module Mastodon
     def upgrade_storage_s3(progress, attachment, style)
       previous_storage_schema_version = attachment.storage_schema_version
       object                          = attachment.s3_object(style)
+      success                         = true
 
       attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION)
 
-      upgraded_path = attachment.path(style)
+      new_object = attachment.s3_object(style)
 
-      if upgraded_path != object.key && object.exists?
-        progress.log("Moving #{object.key} to #{upgraded_path}") if options[:verbose]
+      if new_object.key != object.key && object.exists?
+        progress.log("Moving #{object.key} to #{new_object.key}") if options[:verbose]
 
         begin
-          object.move_to(upgraded_path) unless dry_run?
+          object.move_to(new_object, acl: attachment.s3_permissions(style)) unless dry_run?
         rescue => e
           progress.log(pastel.red("Error processing #{object.key}: #{e}"))
+          success = false
         end
       end
 
@@ -97,6 +108,7 @@ module Mastodon
       # previous version at the end. The upgrade will be recorded after
       # all styles are updated
       attachment.instance_write(:storage_schema_version, previous_storage_schema_version)
+      success
     end
 
     def upgrade_storage_fog(_progress, _attachment, _style)
@@ -107,6 +119,7 @@ module Mastodon
     def upgrade_storage_filesystem(progress, attachment, style)
       previous_storage_schema_version = attachment.storage_schema_version
       previous_path                   = attachment.path(style)
+      success                         = true
 
       attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION)
 
@@ -128,6 +141,7 @@ module Mastodon
           end
         rescue => e
           progress.log(pastel.red("Error processing #{previous_path}: #{e}"))
+          success = false
 
           unless dry_run?
             begin
@@ -143,6 +157,7 @@ module Mastodon
       # previous version at the end. The upgrade will be recorded after
       # all styles are updated
       attachment.instance_write(:storage_schema_version, previous_storage_schema_version)
+      success
     end
   end
 end
diff --git a/lib/paperclip/gif_transcoder.rb b/lib/paperclip/gif_transcoder.rb
index 64f12f963..9f3c8e8be 100644
--- a/lib/paperclip/gif_transcoder.rb
+++ b/lib/paperclip/gif_transcoder.rb
@@ -6,7 +6,7 @@ class GifReader
   EXTENSION_LABELS = [0xf9, 0x01, 0xff].freeze
   GIF_HEADERS      = %w(GIF87a GIF89a).freeze
 
-  class GifReaderException; end
+  class GifReaderException < StandardError; end
 
   class UnknownImageType < GifReaderException; end
 
diff --git a/spec/controllers/well_known/webfinger_controller_spec.rb b/spec/controllers/well_known/webfinger_controller_spec.rb
index 20275aa63..46f63185b 100644
--- a/spec/controllers/well_known/webfinger_controller_spec.rb
+++ b/spec/controllers/well_known/webfinger_controller_spec.rb
@@ -84,5 +84,15 @@ PEM
 
       expect(response).to have_http_status(:not_found)
     end
+
+    it 'returns http bad request when not given a resource parameter' do
+      get :show, params: { }, format: :json
+      expect(response).to have_http_status(:bad_request)
+    end
+
+    it 'returns http bad request when given a nonsense parameter' do
+      get :show, params: { resource: 'df/:dfkj' }
+      expect(response).to have_http_status(:bad_request)
+    end
   end
 end
diff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index c4efb5cc9..5220deabb 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -287,6 +287,31 @@ RSpec.describe ActivityPub::Activity::Create do
         end
       end
 
+      context 'with media attachments with long description as summary' do
+        let(:object_json) do
+          {
+            id: [ActivityPub::TagManager.instance.uri_for(sender), '#bar'].join,
+            type: 'Note',
+            content: 'Lorem ipsum',
+            attachment: [
+              {
+                type: 'Document',
+                mediaType: 'image/png',
+                url: 'http://example.com/attachment.png',
+                summary: '*' * 1500,
+              },
+            ],
+          }
+        end
+
+        it 'creates status' do
+          status = sender.statuses.first
+
+          expect(status).to_not be_nil
+          expect(status.media_attachments.map(&:description)).to include('*' * 1500)
+        end
+      end
+
       context 'with media attachments with focal points' do
         let(:object_json) do
           {
diff --git a/spec/lib/webfinger_resource_spec.rb b/spec/lib/webfinger_resource_spec.rb
index 287537a26..236e9f3e2 100644
--- a/spec/lib/webfinger_resource_spec.rb
+++ b/spec/lib/webfinger_resource_spec.rb
@@ -39,7 +39,7 @@ describe WebfingerResource do
 
         expect {
           WebfingerResource.new(resource).username
-        }.to raise_error(ActiveRecord::RecordNotFound)
+        }.to raise_error(WebfingerResource::InvalidRequest)
       end
 
       it 'finds the username in a valid https route' do
@@ -123,5 +123,15 @@ describe WebfingerResource do
         expect(result).to eq 'alice'
       end
     end
+
+    describe 'with a nonsense resource' do
+      it 'raises InvalidRequest' do
+        resource = 'df/:dfkj'
+
+        expect {
+          WebfingerResource.new(resource).username
+        }.to raise_error(WebfingerResource::InvalidRequest)
+      end
+    end
   end
 end
diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb
index 739bb9cf5..5b52662ba 100644
--- a/spec/services/search_service_spec.rb
+++ b/spec/services/search_service_spec.rb
@@ -91,6 +91,14 @@ describe SearchService, type: :service do
           expect(Tag).not_to have_received(:search_for)
           expect(results).to eq empty_results
         end
+        it 'does not include account when starts with # character' do
+          query = '#tag'
+          allow(AccountSearchService).to receive(:new)
+
+          results = subject.call(query, nil, 10)
+          expect(AccountSearchService).to_not have_received(:new)
+          expect(results).to eq empty_results
+        end
       end
     end
   end