# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-02-27 17:03 import os from typing import Text from boto.s3.connection import S3Connection from django.conf import settings from django.db import migrations from django.db.backends.postgresql_psycopg2.schema import DatabaseSchemaEditor from django.db.migrations.state import StateApps from zerver.lib.avatar_hash import user_avatar_hash, user_avatar_path def mkdirs(path: Text) -> None: dirname = os.path.dirname(path) if not os.path.isdir(dirname): os.makedirs(dirname) class MissingAvatarException(Exception): pass def move_local_file(type: Text, path_src: Text, path_dst: Text) -> None: src_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, type, path_src) dst_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, type, path_dst) if os.path.exists(dst_file_path): return if not os.path.exists(src_file_path): # This is likely caused by a user having previously changed their email raise MissingAvatarException() mkdirs(dst_file_path) os.rename(src_file_path, dst_file_path) def move_avatars_to_be_uid_based(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None: user_profile_model = apps.get_model('zerver', 'UserProfile') if settings.LOCAL_UPLOADS_DIR is not None: for user_profile in user_profile_model.objects.filter(avatar_source="U"): src_file_name = user_avatar_hash(user_profile.email) dst_file_name = user_avatar_path(user_profile) try: move_local_file('avatars', src_file_name + '.original', dst_file_name + '.original') move_local_file('avatars', src_file_name + '-medium.png', dst_file_name + '-medium.png') move_local_file('avatars', src_file_name + '.png', dst_file_name + '.png') except MissingAvatarException: # If the user's avatar is missing, it's probably # because they previously changed their email address. # So set them to have a gravatar instead. user_profile.avatar_source = "G" user_profile.save(update_fields=["avatar_source"]) else: conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY) bucket_name = settings.S3_AVATAR_BUCKET bucket = conn.get_bucket(bucket_name, validate=False) for user_profile in user_profile_model.objects.filter(avatar_source="U"): uid_hash_path = user_avatar_path(user_profile) email_hash_path = user_avatar_hash(user_profile.email) if bucket.get_key(uid_hash_path): continue if not bucket.get_key(email_hash_path): # This is likely caused by a user having previously changed their email # If the user's avatar is missing, it's probably # because they previously changed their email address. # So set them to have a gravatar instead. user_profile.avatar_source = "G" user_profile.save(update_fields=["avatar_source"]) continue bucket.copy_key(uid_hash_path + ".original", bucket_name, email_hash_path + ".original") bucket.copy_key(uid_hash_path + "-medium.png", bucket_name, email_hash_path + "-medium.png") bucket.copy_key(uid_hash_path, bucket_name, email_hash_path) # From an error handling sanity perspective, it's best to # start deleting after everything is copied, so that recovery # from failures is easy (just rerun one loop or the other). for user_profile in user_profile_model.objects.filter(avatar_source="U"): bucket.delete_key(user_avatar_hash(user_profile.email) + ".original") bucket.delete_key(user_avatar_hash(user_profile.email) + "-medium.png") bucket.delete_key(user_avatar_hash(user_profile.email)) class Migration(migrations.Migration): dependencies = [ ('zerver', '0059_userprofile_quota'), ] operations = [ migrations.RunPython(move_avatars_to_be_uid_based) ]