# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-02-27 17:03 import os from typing import Text import requests from boto.s3.bucket import Bucket from boto.s3.connection import S3Connection from boto.s3.key import Key from django.conf import settings from django.core.files.uploadedfile import SimpleUploadedFile 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() return 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) ]