Files
zulip/zerver/migrations/0060_move_avatars_to_be_uid_based.py
2017-11-15 15:44:00 -08:00

100 lines
4.4 KiB
Python

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