Unverified Commit 8680b24a authored by cmrd Senya's avatar cmrd Senya Committed by Benjamin Neff
Browse files

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
parent 211e5cd1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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

+49 −0
Original line number Diff line number Diff line
@@ -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

+61 −0
Original line number Diff line number Diff line
@@ -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