about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThibG <thib@sitedethib.com>2020-12-04 02:23:51 +0100
committerGitHub <noreply@github.com>2020-12-04 02:23:51 +0100
commitfbe75192436e81b778319c597e0461d0415b5c6f (patch)
treefbe6309fd013c67d3cd38639149bf2c1bd9e5afb
parentd849aad85206bff2058fbbd9e187b0048c793cb9 (diff)
Fix account merging in maintenance script (#15264)
Also include AccountNote and AccountDeletionRequest to the list of classes
needing to be reassigned the merged account.
-rw-r--r--app/models/concerns/account_merging.rb7
-rw-r--r--lib/mastodon/maintenance_cli.rb45
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