@ -14,7 +14,7 @@ module Mastodon
end
end
MIN_SUPPORTED_VERSION = 2019_10_01_213028
MIN_SUPPORTED_VERSION = 2019_10_01_213028
MAX_SUPPORTED_VERSION = 202 1_05_26_193025
MAX_SUPPORTED_VERSION = 202 2_01_18_183123
# Stubs to enjoy ActiveRecord queries while not depending on a particular
# Stubs to enjoy ActiveRecord queries while not depending on a particular
# version of the code/database
# version of the code/database
@ -84,13 +84,14 @@ module Mastodon
owned_classes = [
owned_classes = [
Status , StatusPin , MediaAttachment , Poll , Report , Tombstone , Favourite ,
Status , StatusPin , MediaAttachment , Poll , Report , Tombstone , Favourite ,
Follow , FollowRequest , Block , Mute , AccountIdentityProof ,
Follow , FollowRequest , Block , Mute ,
AccountModerationNote , AccountPin , AccountStat , ListAccount ,
AccountModerationNote , AccountPin , AccountStat , ListAccount ,
PollVote , Mention
PollVote , Mention
]
]
owned_classes << AccountDeletionRequest if ActiveRecord :: Base . connection . table_exists? ( :account_deletion_requests )
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 << AccountNote if ActiveRecord :: Base . connection . table_exists? ( :account_notes )
owned_classes << FollowRecommendationSuppression if ActiveRecord :: Base . connection . table_exists? ( :follow_recommendation_suppressions )
owned_classes << FollowRecommendationSuppression if ActiveRecord :: Base . connection . table_exists? ( :follow_recommendation_suppressions )
owned_classes << AccountIdentityProof if ActiveRecord :: Base . connection . table_exists? ( :account_identity_proofs )
owned_classes . each do | klass |
owned_classes . each do | klass |
klass . where ( account_id : other_account . id ) . find_each do | record |
klass . where ( account_id : other_account . id ) . find_each do | record |
@ -139,17 +140,22 @@ module Mastodon
@prompt = TTY :: Prompt . new
@prompt = TTY :: Prompt . new
if ActiveRecord :: Migrator . current_version < MIN_SUPPORTED_VERSION
if ActiveRecord :: Migrator . current_version < MIN_SUPPORTED_VERSION
@prompt . warn 'Your version of the database schema is too old and is not supported by this script.'
@prompt . error 'Your version of the database schema is too old and is not supported by this script.'
@prompt . warn 'Please update to at least Mastodon 3.0.0 before running this script.'
@prompt . error 'Please update to at least Mastodon 3.0.0 before running this script.'
exit ( 1 )
exit ( 1 )
elsif ActiveRecord :: Migrator . current_version > MAX_SUPPORTED_VERSION
elsif ActiveRecord :: Migrator . current_version > MAX_SUPPORTED_VERSION
@prompt . warn 'Your version of the database schema is more recent than this script, this may cause unexpected errors.'
@prompt . warn 'Your version of the database schema is more recent than this script, this may cause unexpected errors.'
exit ( 1 ) unless @prompt . yes? ( 'Continue anyway?' )
exit ( 1 ) unless @prompt . yes? ( 'Continue anyway? (Yes/No)' )
end
if Sidekiq :: ProcessSet . new . any?
@prompt . error 'It seems Sidekiq is running. All Mastodon processes need to be stopped when using this script.'
exit ( 1 )
end
end
@prompt . warn 'This task will take a long time to run and is potentially destructive.'
@prompt . warn 'This task will take a long time to run and is potentially destructive.'
@prompt . warn 'Please make sure to stop Mastodon and have a backup.'
@prompt . warn 'Please make sure to stop Mastodon and have a backup.'
exit ( 1 ) unless @prompt . yes? ( 'Continue?' )
exit ( 1 ) unless @prompt . yes? ( 'Continue? (Yes/No) ')
deduplicate_users!
deduplicate_users!
deduplicate_account_domain_blocks!
deduplicate_account_domain_blocks!
@ -236,12 +242,14 @@ module Mastodon
end
end
end
end
ActiveRecord :: Base . connection . select_all ( " SELECT string_agg(id::text, ',') AS ids FROM users WHERE remember_token IS NOT NULL GROUP BY remember_token HAVING count(*) > 1 " ) . each do | row |
if ActiveRecord :: Migrator . current_version < 20220118183010
users = User . where ( id : row [ 'ids' ] . split ( ',' ) ) . sort_by ( & :updated_at ) . reverse . drop ( 1 )
ActiveRecord :: Base . connection . select_all ( " SELECT string_agg(id::text, ',') AS ids FROM users WHERE remember_token IS NOT NULL GROUP BY remember_token HAVING count(*) > 1 " ) . each do | row |
@prompt . warn " Unsetting remember token for those accounts: #{ users . map ( & :account ) . map ( & :acct ) . join ( ', ' ) } "
users = User . where ( id : row [ 'ids' ] . split ( ',' ) ) . sort_by ( & :updated_at ) . reverse . drop ( 1 )
@prompt . warn " Unsetting remember token for those accounts: #{ users . map ( & :account ) . map ( & :acct ) . join ( ', ' ) } "
users . each do | user |
users . each do | user |
user . update! ( remember_token : nil )
user . update! ( remember_token : nil )
end
end
end
end
end
@ -257,7 +265,7 @@ module Mastodon
@prompt . say 'Restoring users indexes…'
@prompt . say 'Restoring users indexes…'
ActiveRecord :: Base . connection . add_index :users , [ 'confirmation_token' ] , name : 'index_users_on_confirmation_token' , unique : true
ActiveRecord :: Base . connection . add_index :users , [ 'confirmation_token' ] , name : 'index_users_on_confirmation_token' , unique : true
ActiveRecord :: Base . connection . add_index :users , [ 'email' ] , name : 'index_users_on_email' , unique : true
ActiveRecord :: Base . connection . add_index :users , [ 'email' ] , name : 'index_users_on_email' , unique : true
ActiveRecord :: Base . connection . add_index :users , [ 'remember_token' ] , name : 'index_users_on_remember_token' , unique : true
ActiveRecord :: Base . connection . add_index :users , [ 'remember_token' ] , name : 'index_users_on_remember_token' , unique : true if ActiveRecord :: Migrator . current_version < 20220118183010
ActiveRecord :: Base . connection . add_index :users , [ 'reset_password_token' ] , name : 'index_users_on_reset_password_token' , unique : true
ActiveRecord :: Base . connection . add_index :users , [ 'reset_password_token' ] , name : 'index_users_on_reset_password_token' , unique : true
end
end
@ -274,6 +282,8 @@ module Mastodon
end
end
def deduplicate_account_identity_proofs!
def deduplicate_account_identity_proofs!
return unless ActiveRecord :: Base . connection . table_exists? ( :account_identity_proofs )
remove_index_if_exists! ( :account_identity_proofs , 'index_account_proofs_on_account_and_provider_and_username' )
remove_index_if_exists! ( :account_identity_proofs , 'index_account_proofs_on_account_and_provider_and_username' )
@prompt . say 'Removing duplicate account identity proofs…'
@prompt . say 'Removing duplicate account identity proofs…'