def testMergeAvatars(self): self._createDummies() avatar_links.init_links(self._avatar1, client=self._redis, assumeEvents=True) keys = frozenset(self._redis.keys()) avatar_links.init_links(self._avatar2, client=self._redis, assumeEvents=True) avatar_links.merge_avatars(self._avatar1, self._avatar2, client=self._redis) self.assertEqual(keys, frozenset(self._redis.keys())) self.assertEqual(avatar_links.get_links(self._avatar2, client=self._redis), OrderedDict()) self.assertEqual(avatar_links.get_links(self._avatar1, client=self._redis), OrderedDict([('2', set(['conference_participant'])), ('1', set(['conference_manager', 'conference_participant'])), ('4', set(['conference_manager', 'conference_participant'])), ('3', set(['conference_manager']))]))
def merge_users(source, target, force=False): """Merge two users together, unifying all related data :param source: source user (will be set as deleted) :param target: target user (final) """ if source.is_deleted and not force: raise ValueError('Source user {} has been deleted. Merge aborted.'.format(source)) if target.is_deleted: raise ValueError('Target user {} has been deleted. Merge aborted.'.format(target)) # Merge links for link in source.linked_objects: if link.object is None: # remove link if object does no longer exist db.session.delete(link) else: link.user = target # De-duplicate links unique_links = {(link.object, link.role): link for link in target.linked_objects} to_delete = set(target.linked_objects) - set(unique_links.viewvalues()) for link in to_delete: db.session.delete(link) # Move emails to the target user primary_source_email = source.email logger.info("Target %s initial emails: %s", target, ', '.join(target.all_emails)) logger.info("Source %s emails to be linked to target %s: %s", source, target, ', '.join(source.all_emails)) UserEmail.find(user_id=source.id).update({ UserEmail.user_id: target.id, UserEmail.is_primary: False }) # Make sure we don't have stale data after the bulk update we just performed db.session.expire_all() # Update favorites target.favorite_users |= source.favorite_users target.favorite_of |= source.favorite_of target.favorite_categories |= source.favorite_categories # Merge identities for identity in set(source.identities): identity.user = target # Merge avatars in redis if redis_write_client: avatar_links.merge_avatars(target, source) suggestions.merge_avatars(target, source) # Notify signal listeners about the merge signals.users.merged.send(target, source=source) db.session.flush() # Mark source as merged source.merged_into_user = target source.is_deleted = True db.session.flush() # Restore the source user's primary email source.email = primary_source_email db.session.flush() logger.info("Successfully merged %s into %s", source, target)