diff --git a/Changelog.md b/Changelog.md index 7a7e25366..45862c627 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ ## Features * Make public stream accessible for logged out users [#7775](https://github.com/diaspora/diaspora/pull/7775) +* Add account-merging support when receiving an account migration [#7803](https://github.com/diaspora/diaspora/pull/7803) # 0.7.4.1 diff --git a/app/models/account_migration.rb b/app/models/account_migration.rb index ced82ace7..1822e947e 100644 --- a/app/models/account_migration.rb +++ b/app/models/account_migration.rb @@ -148,13 +148,62 @@ class AccountMigration < ApplicationRecord } end + def eliminate_person_duplicates + duplicate_person_contacts.destroy_all + duplicate_person_likes.destroy_all + duplicate_person_participations.destroy_all + duplicate_person_poll_participations.destroy_all + end + + 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})") + end + + def duplicate_person_likes + Like + .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})") + end + + def duplicate_person_participations + Participation + .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})") + 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})") + 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})") + .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})") + .destroy_all + end + def update_person_references logger.debug "Updating references from person id=#{old_person.id} to person id=#{new_person.id}" + eliminate_person_duplicates update_references(person_references, old_person, new_person.id) end def update_user_references logger.debug "Updating references from user id=#{old_user.id} to user id=#{new_user.id}" + eliminate_user_duplicates update_references(user_references, old_user, new_user.id) end diff --git a/spec/models/account_migration_spec.rb b/spec/models/account_migration_spec.rb index 2121a5a7a..d0cad3e79 100644 --- a/spec/models/account_migration_spec.rb +++ b/spec/models/account_migration_spec.rb @@ -154,5 +154,66 @@ describe AccountMigration, type: :model do account_migration.perform! end end + + context "with remote account merging (non-empty new person)" do + before do + FactoryGirl.create( + :contact, + person: new_person, + user: FactoryGirl.create(:contact, person: old_person).user + ) + FactoryGirl.create( + :like, + author: new_person, + target: FactoryGirl.create(:like, author: old_person).target + ) + FactoryGirl.create( + :participation, + author: new_person, + target: FactoryGirl.create(:participation, author: old_person).target + ) + FactoryGirl.create( + :poll_participation, + author: new_person, + poll_answer: FactoryGirl.create(:poll_participation, author: old_person).poll_answer + ) + end + + it "runs without errors" do + expect { + account_migration.perform! + }.not_to raise_error + expect(new_person.likes.count).to eq(1) + expect(new_person.participations.count).to eq(1) + expect(new_person.poll_participations.count).to eq(1) + expect(new_person.contacts.count).to eq(1) + end + end + + context "with local account merging (non-empty new user)" do + include_context "with local old user" + include_context "with local new user" + + before do + FactoryGirl.create( + :aspect, + user: new_person.owner, + name: FactoryGirl.create(:aspect, user: old_person.owner).name + ) + FactoryGirl.create( + :contact, + user: new_person.owner, + person: FactoryGirl.create(:contact, user: old_person.owner).person + ) + end + + it "runs without errors" do + expect { + account_migration.perform! + }.not_to raise_error + expect(new_person.owner.contacts.count).to eq(1) + expect(new_person.owner.aspects.count).to eq(1) + end + end end end