Merge remote-tracking branch 'parent/main' into upstream-20231225

This commit is contained in:
KMY 2023-12-25 09:59:33 +09:00
commit 4355dfc64f
151 changed files with 1711 additions and 644 deletions

View file

@ -1208,15 +1208,21 @@ RSpec.describe ActivityPub::Activity::Create do
mediaType: 'image/png',
url: 'http://example.com/attachment.png',
},
{
type: 'Document',
mediaType: 'image/png',
url: 'http://example.com/emoji.png',
},
],
}
end
it 'creates status' do
it 'creates status with correctly-ordered media attachments' do
status = sender.statuses.first
expect(status).to_not be_nil
expect(status.media_attachments.map(&:remote_url)).to include('http://example.com/attachment.png')
expect(status.ordered_media_attachments.map(&:remote_url)).to eq ['http://example.com/attachment.png', 'http://example.com/emoji.png']
expect(status.ordered_media_attachment_ids).to be_present
end
end

View file

@ -50,6 +50,10 @@ RSpec.describe ActivityPub::Activity::Delete do
it 'sends delete activity to followers of rebloggers' do
expect(a_request(:post, 'http://example.com/inbox')).to have_been_made.once
end
it 'deletes the reblog' do
expect { reblog.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end

View file

@ -62,6 +62,7 @@ describe Mastodon::CLI::Maintenance do
context 'with duplicate accounts' do
before do
prepare_duplicate_data
choose_local_account_to_keep
end
let(:duplicate_account_username) { 'username' }
@ -71,21 +72,37 @@ describe Mastodon::CLI::Maintenance do
expect { subject }
.to output_results(
'Deduplicating accounts',
'Multiple local accounts were found for',
'Restoring index_accounts_on_username_and_domain_lower',
'Reindexing textual indexes on accounts…',
'Finished!'
)
.and change(duplicate_accounts, :count).from(2).to(1)
.and change(duplicate_remote_accounts, :count).from(2).to(1)
.and change(duplicate_local_accounts, :count).from(2).to(1)
end
def duplicate_accounts
def duplicate_remote_accounts
Account.where(username: duplicate_account_username, domain: duplicate_account_domain)
end
def duplicate_local_accounts
Account.where(username: duplicate_account_username, domain: nil)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :accounts, name: :index_accounts_on_username_and_domain_lower
Fabricate(:account, username: duplicate_account_username, domain: duplicate_account_domain)
Fabricate.build(:account, username: duplicate_account_username, domain: duplicate_account_domain).save(validate: false)
_remote_account = Fabricate(:account, username: duplicate_account_username, domain: duplicate_account_domain)
_remote_account_dupe = Fabricate.build(:account, username: duplicate_account_username, domain: duplicate_account_domain).save(validate: false)
_local_account = Fabricate(:account, username: duplicate_account_username, domain: nil)
_local_account_dupe = Fabricate.build(:account, username: duplicate_account_username, domain: nil).save(validate: false)
end
def choose_local_account_to_keep
allow(cli.shell)
.to receive(:ask)
.with(/Account to keep unchanged/, anything)
.and_return('0')
.once
end
end
@ -175,6 +192,407 @@ describe Mastodon::CLI::Maintenance do
end
end
context 'with duplicate account_domain_blocks' do
before do
prepare_duplicate_data
end
let(:duplicate_domain) { 'example.host' }
let(:account) { Fabricate(:account) }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Removing duplicate account domain blocks',
'Restoring account domain blocks indexes',
'Finished!'
)
.and change(duplicate_account_domain_blocks, :count).from(2).to(1)
end
def duplicate_account_domain_blocks
AccountDomainBlock.where(account: account, domain: duplicate_domain)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :account_domain_blocks, [:account_id, :domain]
Fabricate(:account_domain_block, account: account, domain: duplicate_domain)
Fabricate.build(:account_domain_block, account: account, domain: duplicate_domain).save(validate: false)
end
end
context 'with duplicate announcement_reactions' do
before do
prepare_duplicate_data
end
let(:account) { Fabricate(:account) }
let(:announcement) { Fabricate(:announcement) }
let(:name) { Fabricate(:custom_emoji).shortcode }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Removing duplicate announcement reactions',
'Restoring announcement_reactions indexes',
'Finished!'
)
.and change(duplicate_announcement_reactions, :count).from(2).to(1)
end
def duplicate_announcement_reactions
AnnouncementReaction.where(account: account, announcement: announcement, name: name)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :announcement_reactions, [:account_id, :announcement_id, :name]
Fabricate(:announcement_reaction, account: account, announcement: announcement, name: name)
Fabricate.build(:announcement_reaction, account: account, announcement: announcement, name: name).save(validate: false)
end
end
context 'with duplicate conversations' do
before do
prepare_duplicate_data
end
let(:uri) { 'https://example.host/path' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating conversations',
'Restoring conversations indexes',
'Finished!'
)
.and change(duplicate_conversations, :count).from(2).to(1)
end
def duplicate_conversations
Conversation.where(uri: uri)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :conversations, :uri
Fabricate(:conversation, uri: uri)
Fabricate.build(:conversation, uri: uri).save(validate: false)
end
end
context 'with duplicate custom_emojis' do
before do
prepare_duplicate_data
end
let(:duplicate_shortcode) { 'wowzers' }
let(:duplicate_domain) { 'example.host' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating custom_emojis',
'Restoring custom_emojis indexes',
'Finished!'
)
.and change(duplicate_custom_emojis, :count).from(2).to(1)
end
def duplicate_custom_emojis
CustomEmoji.where(shortcode: duplicate_shortcode, domain: duplicate_domain)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :custom_emojis, [:shortcode, :domain]
Fabricate(:custom_emoji, shortcode: duplicate_shortcode, domain: duplicate_domain)
Fabricate.build(:custom_emoji, shortcode: duplicate_shortcode, domain: duplicate_domain).save(validate: false)
end
end
context 'with duplicate custom_emoji_categories' do
before do
prepare_duplicate_data
end
let(:duplicate_name) { 'name_value' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating custom_emoji_categories',
'Restoring custom_emoji_categories indexes',
'Finished!'
)
.and change(duplicate_custom_emoji_categories, :count).from(2).to(1)
end
def duplicate_custom_emoji_categories
CustomEmojiCategory.where(name: duplicate_name)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :custom_emoji_categories, :name
Fabricate(:custom_emoji_category, name: duplicate_name)
Fabricate.build(:custom_emoji_category, name: duplicate_name).save(validate: false)
end
end
context 'with duplicate domain_allows' do
before do
prepare_duplicate_data
end
let(:domain) { 'example.host' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating domain_allows',
'Restoring domain_allows indexes',
'Finished!'
)
.and change(duplicate_domain_allows, :count).from(2).to(1)
end
def duplicate_domain_allows
DomainAllow.where(domain: domain)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :domain_allows, :domain
Fabricate(:domain_allow, domain: domain)
Fabricate.build(:domain_allow, domain: domain).save(validate: false)
end
end
context 'with duplicate domain_blocks' do
before do
prepare_duplicate_data
end
let(:domain) { 'example.host' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating domain_blocks',
'Restoring domain_blocks indexes',
'Finished!'
)
.and change(duplicate_domain_blocks, :count).from(2).to(1)
end
def duplicate_domain_blocks
DomainBlock.where(domain: domain)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :domain_blocks, :domain
Fabricate(:domain_block, domain: domain)
Fabricate.build(:domain_block, domain: domain).save(validate: false)
end
end
context 'with duplicate email_domain_blocks' do
before do
prepare_duplicate_data
end
let(:domain) { 'example.host' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating email_domain_blocks',
'Restoring email_domain_blocks indexes',
'Finished!'
)
.and change(duplicate_email_domain_blocks, :count).from(2).to(1)
end
def duplicate_email_domain_blocks
EmailDomainBlock.where(domain: domain)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :email_domain_blocks, :domain
Fabricate(:email_domain_block, domain: domain)
Fabricate.build(:email_domain_block, domain: domain).save(validate: false)
end
end
context 'with duplicate media_attachments' do
before do
prepare_duplicate_data
end
let(:shortcode) { 'codenam' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating media_attachments',
'Restoring media_attachments indexes',
'Finished!'
)
.and change(duplicate_media_attachments, :count).from(2).to(1)
end
def duplicate_media_attachments
MediaAttachment.where(shortcode: shortcode)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :media_attachments, :shortcode
Fabricate(:media_attachment, shortcode: shortcode)
Fabricate.build(:media_attachment, shortcode: shortcode).save(validate: false)
end
end
context 'with duplicate preview_cards' do
before do
prepare_duplicate_data
end
let(:url) { 'https://example.host/path' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating preview_cards',
'Restoring preview_cards indexes',
'Finished!'
)
.and change(duplicate_preview_cards, :count).from(2).to(1)
end
def duplicate_preview_cards
PreviewCard.where(url: url)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :preview_cards, :url
Fabricate(:preview_card, url: url)
Fabricate.build(:preview_card, url: url).save(validate: false)
end
end
context 'with duplicate statuses' do
before do
prepare_duplicate_data
end
let(:uri) { 'https://example.host/path' }
let(:account) { Fabricate(:account) }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating statuses',
'Restoring statuses indexes',
'Finished!'
)
.and change(duplicate_statuses, :count).from(2).to(1)
end
def duplicate_statuses
Status.where(uri: uri)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :statuses, :uri
Fabricate(:status, account: account, uri: uri)
duplicate = Fabricate.build(:status, account: account, uri: uri)
duplicate.save(validate: false)
Fabricate(:status_pin, account: account, status: duplicate)
Fabricate(:status, in_reply_to_id: duplicate.id)
Fabricate(:status, reblog_of_id: duplicate.id)
end
end
context 'with duplicate tags' do
before do
prepare_duplicate_data
end
let(:name) { 'tagname' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating tags',
'Restoring tags indexes',
'Finished!'
)
.and change(duplicate_tags, :count).from(2).to(1)
end
def duplicate_tags
Tag.where(name: name)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :tags, name: 'index_tags_on_name_lower_btree'
Fabricate(:tag, name: name)
Fabricate.build(:tag, name: name).save(validate: false)
end
end
context 'with duplicate webauthn_credentials' do
before do
prepare_duplicate_data
end
let(:external_id) { '123_123_123' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating webauthn_credentials',
'Restoring webauthn_credentials indexes',
'Finished!'
)
.and change(duplicate_webauthn_credentials, :count).from(2).to(1)
end
def duplicate_webauthn_credentials
WebauthnCredential.where(external_id: external_id)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :webauthn_credentials, :external_id
Fabricate(:webauthn_credential, external_id: external_id)
Fabricate.build(:webauthn_credential, external_id: external_id).save(validate: false)
end
end
context 'with duplicate webhooks' do
before do
prepare_duplicate_data
end
let(:url) { 'https://example.host/path' }
it 'runs the deduplication process' do
expect { subject }
.to output_results(
'Deduplicating webhooks',
'Restoring webhooks indexes',
'Finished!'
)
.and change(duplicate_webhooks, :count).from(2).to(1)
end
def duplicate_webhooks
Webhook.where(url: url)
end
def prepare_duplicate_data
ActiveRecord::Base.connection.remove_index :webhooks, :url
Fabricate(:webhook, url: url)
Fabricate.build(:webhook, url: url).save(validate: false)
end
end
def agree_to_backup_warning
allow(cli.shell)
.to receive(:yes?)

View file

@ -13,11 +13,11 @@ RSpec.describe Vacuum::ApplicationsVacuum do
let!(:unused_app) { Fabricate(:application, created_at: 1.month.ago) }
let!(:recent_app) { Fabricate(:application, created_at: 1.hour.ago) }
let!(:active_access_token) { Fabricate(:access_token, application: app_with_token) }
let!(:active_access_grant) { Fabricate(:access_grant, application: app_with_grant) }
let!(:user) { Fabricate(:user, created_by_application: app_with_signup) }
before do
Fabricate(:access_token, application: app_with_token)
Fabricate(:access_grant, application: app_with_grant)
Fabricate(:user, created_by_application: app_with_signup)
subject.perform
end

View file

@ -30,5 +30,9 @@ RSpec.describe Vacuum::PreviewCardsVacuum do
it 'does not delete attached preview cards' do
expect(new_preview_card.reload).to be_persisted
end
it 'does not delete orphaned preview cards in the retention period' do
expect(orphaned_preview_card.reload).to be_persisted
end
end
end