From fbe75192436e81b778319c597e0461d0415b5c6f Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 4 Dec 2020 02:23:51 +0100 Subject: Fix account merging in maintenance script (#15264) Also include AccountNote and AccountDeletionRequest to the list of classes needing to be reassigned the merged account. --- lib/mastodon/maintenance_cli.rb | 45 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/mastodon/maintenance_cli.rb b/lib/mastodon/maintenance_cli.rb index 547238ec6..99d13f43d 100644 --- a/lib/mastodon/maintenance_cli.rb +++ b/lib/mastodon/maintenance_cli.rb @@ -55,8 +55,8 @@ module Mastodon belongs_to :account, inverse_of: :account_stat end + # Dummy class, to make migration possible across version changes class Account < ApplicationRecord - # Dummy class, to make migration possible across version changes has_one :user, inverse_of: :account has_one :account_stat, inverse_of: :account @@ -69,6 +69,49 @@ module Mastodon def acct local? ? username : "#{username}@#{domain}" end + + # This is a duplicate of the AccountMerging concern because we need it to + # be independent from code version. + def merge_with!(other_account) + # Since it's the same remote resource, the remote resource likely + # already believes we are following/blocking, so it's safe to + # re-attribute the relationships too. However, during the presence + # of the index bug users could have *also* followed the reference + # account already, therefore mass update will not work and we need + # to check for (and skip past) uniqueness errors + + owned_classes = [ + Status, StatusPin, MediaAttachment, Poll, Report, Tombstone, Favourite, + Follow, FollowRequest, Block, Mute, AccountIdentityProof, + AccountModerationNote, AccountPin, AccountStat, ListAccount, + PollVote, Mention + ] + owned_classes << AccountDeletionRequest if ActiveRecord::Base.connection.table_exists?(:account_deletion_requests) + owned_classes << AccountNote if ActiveRecord::Base.connection.table_exists?(:account_notes) + + owned_classes.each do |klass| + klass.where(account_id: other_account.id).find_each do |record| + begin + record.update_attribute(:account_id, id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + + target_classes = [Follow, FollowRequest, Block, Mute, AccountModerationNote, AccountPin] + target_classes << AccountNote if ActiveRecord::Base.connection.table_exists?(:account_notes) + + target_classes.each do |klass| + klass.where(target_account_id: other_account.id).find_each do |record| + begin + record.update_attribute(:target_account_id, id) + rescue ActiveRecord::RecordNotUnique + next + end + end + end + end end class User < ApplicationRecord -- cgit