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