Esempio n. 1
0
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))

    # 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

    # Update category suggestions
    SuggestedCategory.merge_users(target, source)

    # Merge identities
    for identity in set(source.identities):
        identity.user = target

    # 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)
Esempio n. 2
0
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))

    # 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

    # Update category suggestions
    SuggestedCategory.merge_users(target, source)

    # Merge identities
    for identity in set(source.identities):
        identity.user = target

    # 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)
Esempio n. 3
0
 def validate_email(self, field):
     if UserEmail.find(~User.is_pending,
                       is_user_deleted=False,
                       email=field.data,
                       _join=User).count():
         raise ValidationError(_('This email address is already in use.'))
Esempio n. 4
0
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)
Esempio n. 5
0
 def validate_email(self, field):
     if UserEmail.find(~User.is_pending, is_user_deleted=False, email=field.data, _join=User).count():
         raise ValidationError(_('This email address is already in use.'))