AccountMigration: support chained migration case
This commit is contained in:
parent
dd9ac758e8
commit
597d9e0275
2 changed files with 122 additions and 36 deletions
|
|
@ -81,6 +81,10 @@ class AccountMigration < ApplicationRecord
|
|||
new_person.owner
|
||||
end
|
||||
|
||||
def newest_user
|
||||
newest_person.owner
|
||||
end
|
||||
|
||||
def lock_old_user!
|
||||
old_user&.lock_access!
|
||||
end
|
||||
|
|
@ -106,7 +110,7 @@ class AccountMigration < ApplicationRecord
|
|||
# We need to resend contacts of users of our pod for the remote new person so that the remote pod received this
|
||||
# contact information from the authoritative source.
|
||||
def dispatch_contacts
|
||||
new_person.contacts.sharing.each do |contact|
|
||||
newest_person.contacts.sharing.each do |contact|
|
||||
Diaspora::Federation::Dispatcher.defer_dispatch(contact.user, contact)
|
||||
end
|
||||
end
|
||||
|
|
@ -179,7 +183,7 @@ class AccountMigration < ApplicationRecord
|
|||
def duplicate_person_contacts
|
||||
Contact
|
||||
.joins("INNER JOIN contacts as c2 ON (contacts.user_id = c2.user_id AND contacts.person_id=#{old_person.id} AND"\
|
||||
" c2.person_id=#{new_person.id})")
|
||||
" c2.person_id=#{newest_person.id})")
|
||||
end
|
||||
|
||||
def duplicate_person_likes
|
||||
|
|
@ -187,7 +191,7 @@ class AccountMigration < ApplicationRecord
|
|||
.joins("INNER JOIN likes as l2 ON (likes.target_id = l2.target_id "\
|
||||
"AND likes.target_type = l2.target_type "\
|
||||
"AND likes.author_id=#{old_person.id} AND"\
|
||||
" l2.author_id=#{new_person.id})")
|
||||
" l2.author_id=#{newest_person.id})")
|
||||
end
|
||||
|
||||
def duplicate_person_participations
|
||||
|
|
@ -195,41 +199,41 @@ class AccountMigration < ApplicationRecord
|
|||
.joins("INNER JOIN participations as p2 ON (participations.target_id = p2.target_id "\
|
||||
"AND participations.target_type = p2.target_type "\
|
||||
"AND participations.author_id=#{old_person.id} AND"\
|
||||
" p2.author_id=#{new_person.id})")
|
||||
" p2.author_id=#{newest_person.id})")
|
||||
end
|
||||
|
||||
def duplicate_person_poll_participations
|
||||
PollParticipation
|
||||
.joins("INNER JOIN poll_participations as p2 ON (poll_participations.poll_id = p2.poll_id "\
|
||||
"AND poll_participations.author_id=#{old_person.id} AND"\
|
||||
" p2.author_id=#{new_person.id})")
|
||||
" p2.author_id=#{newest_person.id})")
|
||||
end
|
||||
|
||||
def eliminate_user_duplicates
|
||||
Aspect
|
||||
.joins("INNER JOIN aspects as a2 ON (aspects.name = a2.name AND aspects.user_id=#{old_user.id}
|
||||
AND a2.user_id=#{new_user.id})")
|
||||
AND a2.user_id=#{newest_user.id})")
|
||||
.destroy_all
|
||||
Contact
|
||||
.joins("INNER JOIN contacts as c2 ON (contacts.person_id = c2.person_id AND contacts.user_id=#{old_user.id} AND"\
|
||||
" c2.user_id=#{new_user.id})")
|
||||
" c2.user_id=#{newest_user.id})")
|
||||
.destroy_all
|
||||
TagFollowing
|
||||
.joins("INNER JOIN tag_followings as t2 ON (tag_followings.tag_id = t2.tag_id AND"\
|
||||
" tag_followings.user_id=#{old_user.id} AND t2.user_id=#{new_user.id})")
|
||||
" tag_followings.user_id=#{old_user.id} AND t2.user_id=#{newest_user.id})")
|
||||
.destroy_all
|
||||
end
|
||||
|
||||
def update_person_references
|
||||
logger.debug "Updating references from person id=#{old_person.id} to person id=#{new_person.id}"
|
||||
logger.debug "Updating references from person id=#{old_person.id} to person id=#{newest_person.id}"
|
||||
eliminate_person_duplicates
|
||||
update_references(person_references, old_person, new_person.id)
|
||||
update_references(person_references, old_person, newest_person.id)
|
||||
end
|
||||
|
||||
def update_user_references
|
||||
logger.debug "Updating references from user id=#{old_user.id} to user id=#{new_user.id}"
|
||||
logger.debug "Updating references from user id=#{old_user.id} to user id=#{newest_user.id}"
|
||||
eliminate_user_duplicates
|
||||
update_references(user_references, old_user, new_user.id)
|
||||
update_references(user_references, old_user, newest_user.id)
|
||||
end
|
||||
|
||||
def update_references(references, object, new_id)
|
||||
|
|
|
|||
|
|
@ -149,6 +149,36 @@ shared_examples_for "migration scenarios initiated locally" do
|
|||
end
|
||||
end
|
||||
|
||||
shared_examples_for "migration scenarios with local user rename" do
|
||||
it "updates user references" do
|
||||
invited_user = FactoryGirl.create(:user, invited_by: old_user)
|
||||
aspect = FactoryGirl.create(:aspect, user: old_user, name: r_str)
|
||||
contact = FactoryGirl.create(:contact, user: old_user)
|
||||
service = FactoryGirl.create(:service, user: old_user)
|
||||
pref = UserPreference.create!(user: old_user, email_type: "also_commented")
|
||||
tag_following = FactoryGirl.create(:tag_following, user: old_user)
|
||||
block = FactoryGirl.create(:block, user: old_user)
|
||||
notification = FactoryGirl.create(:notification, recipient: old_user)
|
||||
report = FactoryGirl.create(:report, user: old_user)
|
||||
authorization = FactoryGirl.create(:auth_with_read, user: old_user)
|
||||
share_visibility = FactoryGirl.create(:share_visibility, user: old_user)
|
||||
|
||||
run_migration
|
||||
|
||||
expect(invited_user.reload.invited_by).to eq(new_user)
|
||||
expect(aspect.reload.user).to eq(new_user)
|
||||
expect(contact.reload.user).to eq(new_user)
|
||||
expect(service.reload.user).to eq(new_user)
|
||||
expect(pref.reload.user).to eq(new_user)
|
||||
expect(tag_following.reload.user).to eq(new_user)
|
||||
expect(block.reload.user).to eq(new_user)
|
||||
expect(notification.reload.recipient).to eq(new_user)
|
||||
expect(report.reload.user).to eq(new_user)
|
||||
expect(authorization.reload.user).to eq(new_user)
|
||||
expect(share_visibility.reload.user).to eq(new_user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "account migration" do
|
||||
# this is the case when we receive account migration message from the federation
|
||||
context "remotely initiated" do
|
||||
|
|
@ -173,6 +203,22 @@ describe "account migration" do
|
|||
include_examples "every migration scenario"
|
||||
|
||||
include_examples "migration scenarios initiated remotely"
|
||||
|
||||
context "when new person has been migrated before" do
|
||||
let(:intermidiate_person) { create_remote_user("remote-d.net").person }
|
||||
|
||||
before do
|
||||
AccountMigration.create!(old_person: intermidiate_person, new_person: new_person).perform!
|
||||
end
|
||||
|
||||
def run_migration
|
||||
AccountMigration.create!(old_person: old_person, new_person: intermidiate_person).perform!
|
||||
end
|
||||
|
||||
include_examples "every migration scenario"
|
||||
|
||||
include_examples "migration scenarios initiated remotely"
|
||||
end
|
||||
end
|
||||
|
||||
# this is the case when we're a pod, which was left by a person in favor of remote one
|
||||
|
|
@ -200,6 +246,24 @@ describe "account migration" do
|
|||
user.reload
|
||||
end
|
||||
end
|
||||
|
||||
context "when new person has been migrated before" do
|
||||
let(:intermidiate_person) { create_remote_user("remote-d.net").person }
|
||||
|
||||
before do
|
||||
AccountMigration.create!(old_person: intermidiate_person, new_person: new_person).perform!
|
||||
end
|
||||
|
||||
def run_migration
|
||||
AccountMigration.create!(old_person: old_user.person, new_person: intermidiate_person).perform!
|
||||
end
|
||||
|
||||
include_examples "every migration scenario"
|
||||
|
||||
include_examples "migration scenarios initiated remotely"
|
||||
|
||||
it_behaves_like "migration scenarios with local old user"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -228,6 +292,24 @@ describe "account migration" do
|
|||
it_behaves_like "migration scenarios initiated locally" do
|
||||
let!(:remote_contact) { create_remote_contact(new_user, "remote-friend.org") }
|
||||
end
|
||||
|
||||
context "when new person has been migrated before" do
|
||||
let(:intermidiate_person) { FactoryGirl.create(:user).person }
|
||||
|
||||
before do
|
||||
AccountMigration.create!(old_person: intermidiate_person, new_person: new_person).perform!
|
||||
end
|
||||
|
||||
def run_migration
|
||||
AccountMigration.create!(
|
||||
old_person: old_person,
|
||||
new_person: intermidiate_person,
|
||||
old_private_key: old_user.serialized_private_key
|
||||
).perform!
|
||||
end
|
||||
|
||||
include_examples "every migration scenario"
|
||||
end
|
||||
end
|
||||
|
||||
# this is the case when a user changes diaspora id but stays on the same pod
|
||||
|
|
@ -254,32 +336,32 @@ describe "account migration" do
|
|||
expect(old_user.reload).to be_a_clear_account
|
||||
end
|
||||
|
||||
it "updates user references" do
|
||||
invited_user = FactoryGirl.create(:user, invited_by: old_user)
|
||||
aspect = FactoryGirl.create(:aspect, user: old_user, name: r_str)
|
||||
contact = FactoryGirl.create(:contact, user: old_user)
|
||||
service = FactoryGirl.create(:service, user: old_user)
|
||||
pref = UserPreference.create!(user: old_user, email_type: "also_commented")
|
||||
tag_following = FactoryGirl.create(:tag_following, user: old_user)
|
||||
block = FactoryGirl.create(:block, user: old_user)
|
||||
notification = FactoryGirl.create(:notification, recipient: old_user)
|
||||
report = FactoryGirl.create(:report, user: old_user)
|
||||
authorization = FactoryGirl.create(:auth_with_read, user: old_user)
|
||||
share_visibility = FactoryGirl.create(:share_visibility, user: old_user)
|
||||
include_examples "migration scenarios with local user rename"
|
||||
|
||||
run_migration
|
||||
context "when new user has been migrated before" do
|
||||
let(:intermidiate_person) { FactoryGirl.create(:user).person }
|
||||
|
||||
expect(invited_user.reload.invited_by).to eq(new_user)
|
||||
expect(aspect.reload.user).to eq(new_user)
|
||||
expect(contact.reload.user).to eq(new_user)
|
||||
expect(service.reload.user).to eq(new_user)
|
||||
expect(pref.reload.user).to eq(new_user)
|
||||
expect(tag_following.reload.user).to eq(new_user)
|
||||
expect(block.reload.user).to eq(new_user)
|
||||
expect(notification.reload.recipient).to eq(new_user)
|
||||
expect(report.reload.user).to eq(new_user)
|
||||
expect(authorization.reload.user).to eq(new_user)
|
||||
expect(share_visibility.reload.user).to eq(new_user)
|
||||
before do
|
||||
AccountMigration.create!(old_person: intermidiate_person, new_person: new_person).perform!
|
||||
end
|
||||
|
||||
def run_migration
|
||||
AccountMigration.create!(
|
||||
old_person: old_person,
|
||||
new_person: intermidiate_person
|
||||
).perform!
|
||||
end
|
||||
|
||||
include_examples "every migration scenario"
|
||||
|
||||
it_behaves_like "migration scenarios with local old user"
|
||||
|
||||
it "clears the old user account" do
|
||||
run_migration
|
||||
expect(old_user.reload).to be_a_clear_account
|
||||
end
|
||||
|
||||
include_examples "migration scenarios with local user rename"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue