Exemple #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.query.filter_by(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)
Exemple #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)
Exemple #3
0
def category_suggestions():
    users = (User.query.filter(
        ~User.is_deleted,
        User._all_settings.any(
            db.and_(UserSetting.module == 'users',
                    UserSetting.name == 'suggest_categories',
                    db.cast(UserSetting.value, db.String) == 'true'))))
    for user in users:
        existing = {x.category: x for x in user.suggested_categories}
        related = set(get_related_categories(user, detailed=False))
        for category, score in get_category_scores(user).iteritems():
            if score < SUGGESTION_MIN_SCORE:
                continue
            if (category in related or category.is_deleted
                    or category.suggestions_disabled
                    or any(p.suggestions_disabled
                           for p in category.parent_chain_query)):
                continue
            logger.debug('Suggesting %s with score %.03f for %s', category,
                         score, user)
            suggestion = existing.get(category) or SuggestedCategory(
                category=category, user=user)
            suggestion.score = score
        user.settings.set('suggest_categories', False)
        db.session.commit()
Exemple #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

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

    # 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)

    # 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)
Exemple #5
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

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

    # 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)

    # 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)