Account merging support

Adds support for merging accounts with account migration by eliminating
duplicate data in favor of the target user's data.

closes #7803
This commit is contained in:
cmrd Senya 2018-04-29 13:31:11 +03:00 committed by Benjamin Neff
parent 211e5cd1bc
commit 8680b24a2e
No known key found for this signature in database
GPG key ID: 971464C3F1A90194
3 changed files with 111 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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