From fbe75192436e81b778319c597e0461d0415b5c6f Mon Sep 17 00:00:00 2001 From: ThibG Date: Fri, 4 Dec 2020 02:23:51 +0100 Subject: [PATCH] Fix account merging in maintenance script (#15264) Also include AccountNote and AccountDeletionRequest to the list of classes needing to be reassigned the merged account. --- app/models/concerns/account_merging.rb | 7 ++-- lib/mastodon/maintenance_cli.rb | 45 +++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/app/models/concerns/account_merging.rb b/app/models/concerns/account_merging.rb index 45050c269..c3b7018f2 100644 --- a/app/models/concerns/account_merging.rb +++ b/app/models/concerns/account_merging.rb @@ -15,7 +15,7 @@ module AccountMerging Status, StatusPin, MediaAttachment, Poll, Report, Tombstone, Favourite, Follow, FollowRequest, Block, Mute, AccountIdentityProof, AccountModerationNote, AccountPin, AccountStat, ListAccount, - PollVote, Mention + PollVote, Mention, AccountDeletionRequest, AccountNote ] owned_classes.each do |klass| @@ -28,7 +28,10 @@ module AccountMerging end end - target_classes = [Follow, FollowRequest, Block, Mute, AccountModerationNote, AccountPin] + target_classes = [ + Follow, FollowRequest, Block, Mute, AccountModerationNote, AccountPin, + AccountNote + ] target_classes.each do |klass| klass.where(target_account_id: other_account.id).find_each do |record| 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