commit
4dcabe6f9c
10
Gemfile.lock
10
Gemfile.lock
|
@ -201,13 +201,13 @@ GEM
|
||||||
dotenv (= 2.7.5)
|
dotenv (= 2.7.5)
|
||||||
railties (>= 3.2, < 6.1)
|
railties (>= 3.2, < 6.1)
|
||||||
e2mmap (0.1.0)
|
e2mmap (0.1.0)
|
||||||
elasticsearch (7.6.0)
|
elasticsearch (7.7.0)
|
||||||
elasticsearch-api (= 7.6.0)
|
elasticsearch-api (= 7.7.0)
|
||||||
elasticsearch-transport (= 7.6.0)
|
elasticsearch-transport (= 7.7.0)
|
||||||
elasticsearch-api (7.6.0)
|
elasticsearch-api (7.7.0)
|
||||||
multi_json
|
multi_json
|
||||||
elasticsearch-dsl (0.1.9)
|
elasticsearch-dsl (0.1.9)
|
||||||
elasticsearch-transport (7.6.0)
|
elasticsearch-transport (7.7.0)
|
||||||
faraday (~> 1)
|
faraday (~> 1)
|
||||||
multi_json
|
multi_json
|
||||||
encryptor (3.0.0)
|
encryptor (3.0.0)
|
||||||
|
|
|
@ -8,7 +8,8 @@ module WellKnown
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
before_action :check_account_suspension
|
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
|
def show
|
||||||
expires_in 3.days, public: true
|
expires_in 3.days, public: true
|
||||||
|
@ -37,6 +38,10 @@ module WellKnown
|
||||||
expires_in(3.minutes, public: true) && gone if @account.suspended?
|
expires_in(3.minutes, public: true) && gone if @account.suspended?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def bad_request
|
||||||
|
head 400
|
||||||
|
end
|
||||||
|
|
||||||
def not_found
|
def not_found
|
||||||
head 404
|
head 404
|
||||||
end
|
end
|
||||||
|
|
|
@ -201,7 +201,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
|
||||||
|
|
||||||
begin
|
begin
|
||||||
href = Addressable::URI.parse(attachment['url']).normalize.to_s
|
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
|
media_attachments << media_attachment
|
||||||
|
|
||||||
next if unsupported_media_type?(attachment['mediaType']) || skip_download?
|
next if unsupported_media_type?(attachment['mediaType']) || skip_download?
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
class WebfingerResource
|
class WebfingerResource
|
||||||
attr_reader :resource
|
attr_reader :resource
|
||||||
|
|
||||||
|
class InvalidRequest < StandardError; end
|
||||||
|
|
||||||
def initialize(resource)
|
def initialize(resource)
|
||||||
@resource = resource
|
@resource = resource
|
||||||
end
|
end
|
||||||
|
@ -14,7 +16,7 @@ class WebfingerResource
|
||||||
when /\@/
|
when /\@/
|
||||||
username_from_acct
|
username_from_acct
|
||||||
else
|
else
|
||||||
raise(ActiveRecord::RecordNotFound)
|
raise InvalidRequest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ class SearchService < BaseService
|
||||||
end
|
end
|
||||||
|
|
||||||
def account_searchable?
|
def account_searchable?
|
||||||
account_search? && !(@query.include?('@') && @query.include?(' '))
|
account_search? && !(@query.start_with?('#') || (@query.include?('@') && @query.include?(' ')))
|
||||||
end
|
end
|
||||||
|
|
||||||
def hashtag_searchable?
|
def hashtag_searchable?
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
APP_PATH = File.expand_path('../config/application', __dir__)
|
APP_PATH = File.expand_path('../config/application', __dir__)
|
||||||
|
|
||||||
require_relative '../config/boot'
|
require_relative '../config/boot'
|
||||||
require_relative '../lib/cli'
|
require_relative '../lib/cli'
|
||||||
Mastodon::CLI.start(ARGV)
|
|
||||||
|
begin
|
||||||
|
Mastodon::CLI.start(ARGV)
|
||||||
|
rescue Interrupt
|
||||||
|
exit(130)
|
||||||
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ services:
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
restart: always
|
restart: always
|
||||||
image: redis:5.0-alpine
|
image: redis:6.0-alpine
|
||||||
networks:
|
networks:
|
||||||
- internal_network
|
- internal_network
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
|
@ -88,6 +88,11 @@ module Mastodon
|
||||||
path_segments = object.key.split('/')
|
path_segments = object.key.split('/')
|
||||||
path_segments.delete('cache')
|
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
|
model_name = path_segments.first.classify
|
||||||
attachment_name = path_segments[1].singularize
|
attachment_name = path_segments[1].singularize
|
||||||
record_id = path_segments[2..-2].join.to_i
|
record_id = path_segments[2..-2].join.to_i
|
||||||
|
@ -127,6 +132,11 @@ module Mastodon
|
||||||
path_segments = key.split(File::SEPARATOR)
|
path_segments = key.split(File::SEPARATOR)
|
||||||
path_segments.delete('cache')
|
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
|
model_name = path_segments.first.classify
|
||||||
record_id = path_segments[2..-2].join.to_i
|
record_id = path_segments[2..-2].join.to_i
|
||||||
attachment_name = path_segments[1].singularize
|
attachment_name = path_segments[1].singularize
|
||||||
|
@ -246,6 +256,11 @@ module Mastodon
|
||||||
path_segments = path.split('/')[2..-1]
|
path_segments = path.split('/')[2..-1]
|
||||||
path_segments.delete('cache')
|
path_segments.delete('cache')
|
||||||
|
|
||||||
|
if path_segments.size != 7
|
||||||
|
say('Not a media URL', :red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
model_name = path_segments.first.classify
|
model_name = path_segments.first.classify
|
||||||
record_id = path_segments[2..-2].join.to_i
|
record_id = path_segments[2..-2].join.to_i
|
||||||
|
|
||||||
|
@ -294,6 +309,8 @@ module Mastodon
|
||||||
segments = object.key.split('/')
|
segments = object.key.split('/')
|
||||||
segments.delete('cache')
|
segments.delete('cache')
|
||||||
|
|
||||||
|
next if segments.size != 7
|
||||||
|
|
||||||
model_name = segments.first.classify
|
model_name = segments.first.classify
|
||||||
record_id = segments[2..-2].join.to_i
|
record_id = segments[2..-2].join.to_i
|
||||||
|
|
||||||
|
|
|
@ -41,23 +41,32 @@ module Mastodon
|
||||||
klass.find_each do |record|
|
klass.find_each do |record|
|
||||||
attachment_names.each do |attachment_name|
|
attachment_names.each do |attachment_name|
|
||||||
attachment = record.public_send(attachment_name)
|
attachment = record.public_send(attachment_name)
|
||||||
|
upgraded = false
|
||||||
|
|
||||||
next if attachment.blank? || attachment.storage_schema_version >= CURRENT_STORAGE_SCHEMA_VERSION
|
next if attachment.blank? || attachment.storage_schema_version >= CURRENT_STORAGE_SCHEMA_VERSION
|
||||||
|
|
||||||
attachment.styles.each_key do |style|
|
styles = attachment.styles.keys
|
||||||
case Paperclip::Attachment.default_options[:storage]
|
|
||||||
when :s3
|
styles << :original unless styles.include?(:original)
|
||||||
upgrade_storage_s3(progress, attachment, style)
|
|
||||||
when :fog
|
styles.each do |style|
|
||||||
upgrade_storage_fog(progress, attachment, style)
|
success = begin
|
||||||
when :filesystem
|
case Paperclip::Attachment.default_options[:storage]
|
||||||
upgrade_storage_filesystem(progress, attachment, style)
|
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
|
end
|
||||||
|
|
||||||
|
upgraded = true if style == :original && success
|
||||||
|
|
||||||
progress.increment
|
progress.increment
|
||||||
end
|
end
|
||||||
|
|
||||||
attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION)
|
attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION) if upgraded
|
||||||
end
|
end
|
||||||
|
|
||||||
if record.changed?
|
if record.changed?
|
||||||
|
@ -78,18 +87,20 @@ module Mastodon
|
||||||
def upgrade_storage_s3(progress, attachment, style)
|
def upgrade_storage_s3(progress, attachment, style)
|
||||||
previous_storage_schema_version = attachment.storage_schema_version
|
previous_storage_schema_version = attachment.storage_schema_version
|
||||||
object = attachment.s3_object(style)
|
object = attachment.s3_object(style)
|
||||||
|
success = true
|
||||||
|
|
||||||
attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION)
|
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?
|
if new_object.key != object.key && object.exists?
|
||||||
progress.log("Moving #{object.key} to #{upgraded_path}") if options[:verbose]
|
progress.log("Moving #{object.key} to #{new_object.key}") if options[:verbose]
|
||||||
|
|
||||||
begin
|
begin
|
||||||
object.move_to(upgraded_path) unless dry_run?
|
object.move_to(new_object, acl: attachment.s3_permissions(style)) unless dry_run?
|
||||||
rescue => e
|
rescue => e
|
||||||
progress.log(pastel.red("Error processing #{object.key}: #{e}"))
|
progress.log(pastel.red("Error processing #{object.key}: #{e}"))
|
||||||
|
success = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -97,6 +108,7 @@ module Mastodon
|
||||||
# previous version at the end. The upgrade will be recorded after
|
# previous version at the end. The upgrade will be recorded after
|
||||||
# all styles are updated
|
# all styles are updated
|
||||||
attachment.instance_write(:storage_schema_version, previous_storage_schema_version)
|
attachment.instance_write(:storage_schema_version, previous_storage_schema_version)
|
||||||
|
success
|
||||||
end
|
end
|
||||||
|
|
||||||
def upgrade_storage_fog(_progress, _attachment, _style)
|
def upgrade_storage_fog(_progress, _attachment, _style)
|
||||||
|
@ -107,6 +119,7 @@ module Mastodon
|
||||||
def upgrade_storage_filesystem(progress, attachment, style)
|
def upgrade_storage_filesystem(progress, attachment, style)
|
||||||
previous_storage_schema_version = attachment.storage_schema_version
|
previous_storage_schema_version = attachment.storage_schema_version
|
||||||
previous_path = attachment.path(style)
|
previous_path = attachment.path(style)
|
||||||
|
success = true
|
||||||
|
|
||||||
attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION)
|
attachment.instance_write(:storage_schema_version, CURRENT_STORAGE_SCHEMA_VERSION)
|
||||||
|
|
||||||
|
@ -128,6 +141,7 @@ module Mastodon
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
progress.log(pastel.red("Error processing #{previous_path}: #{e}"))
|
progress.log(pastel.red("Error processing #{previous_path}: #{e}"))
|
||||||
|
success = false
|
||||||
|
|
||||||
unless dry_run?
|
unless dry_run?
|
||||||
begin
|
begin
|
||||||
|
@ -143,6 +157,7 @@ module Mastodon
|
||||||
# previous version at the end. The upgrade will be recorded after
|
# previous version at the end. The upgrade will be recorded after
|
||||||
# all styles are updated
|
# all styles are updated
|
||||||
attachment.instance_write(:storage_schema_version, previous_storage_schema_version)
|
attachment.instance_write(:storage_schema_version, previous_storage_schema_version)
|
||||||
|
success
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ class GifReader
|
||||||
EXTENSION_LABELS = [0xf9, 0x01, 0xff].freeze
|
EXTENSION_LABELS = [0xf9, 0x01, 0xff].freeze
|
||||||
GIF_HEADERS = %w(GIF87a GIF89a).freeze
|
GIF_HEADERS = %w(GIF87a GIF89a).freeze
|
||||||
|
|
||||||
class GifReaderException; end
|
class GifReaderException < StandardError; end
|
||||||
|
|
||||||
class UnknownImageType < GifReaderException; end
|
class UnknownImageType < GifReaderException; end
|
||||||
|
|
||||||
|
|
|
@ -84,5 +84,15 @@ PEM
|
||||||
|
|
||||||
expect(response).to have_http_status(:not_found)
|
expect(response).to have_http_status(:not_found)
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -287,6 +287,31 @@ RSpec.describe ActivityPub::Activity::Create do
|
||||||
end
|
end
|
||||||
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
|
context 'with media attachments with focal points' do
|
||||||
let(:object_json) do
|
let(:object_json) do
|
||||||
{
|
{
|
||||||
|
|
|
@ -39,7 +39,7 @@ describe WebfingerResource do
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
WebfingerResource.new(resource).username
|
WebfingerResource.new(resource).username
|
||||||
}.to raise_error(ActiveRecord::RecordNotFound)
|
}.to raise_error(WebfingerResource::InvalidRequest)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'finds the username in a valid https route' do
|
it 'finds the username in a valid https route' do
|
||||||
|
@ -123,5 +123,15 @@ describe WebfingerResource do
|
||||||
expect(result).to eq 'alice'
|
expect(result).to eq 'alice'
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -91,6 +91,14 @@ describe SearchService, type: :service do
|
||||||
expect(Tag).not_to have_received(:search_for)
|
expect(Tag).not_to have_received(:search_for)
|
||||||
expect(results).to eq empty_results
|
expect(results).to eq empty_results
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue