Example #1
0
    def copy_avatar(self, source_profile: UserProfile, target_profile: UserProfile) -> None:
        s3_source_file_name = user_avatar_path(source_profile)
        s3_target_file_name = user_avatar_path(target_profile)

        key = self.get_avatar_key(s3_source_file_name + ".original")
        image_data = key.get_contents_as_string()  # type: ignore # https://github.com/python/typeshed/issues/1552
        content_type = key.content_type

        self.write_avatar_images(s3_target_file_name, target_profile, image_data, content_type)  # type: ignore # image_data is `bytes`, boto subs are wrong
def move_avatars_to_be_uid_based(apps, schema_editor):
    # type: (StateApps, 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"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 = u"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"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 = u"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"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))
Example #3
0
    def test_import_files_from_local(self) -> None:

        realm = Realm.objects.get(string_id='zulip')
        self._setup_export_files()
        self._export_realm(realm)

        with patch('logging.info'):
            do_import_realm('var/test-export', 'test-zulip')
        imported_realm = Realm.objects.get(string_id='test-zulip')

        # Test attachments
        uploaded_file = Attachment.objects.get(realm=imported_realm)
        self.assertEqual(len(b'zulip!'), uploaded_file.size)

        attachment_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, 'files', uploaded_file.path_id)
        self.assertTrue(os.path.isfile(attachment_file_path))

        # Test emojis
        realm_emoji = RealmEmoji.objects.get(realm=imported_realm)
        emoji_path = RealmEmoji.PATH_ID_TEMPLATE.format(
            realm_id=imported_realm.id,
            emoji_file_name=realm_emoji.file_name,
        )
        emoji_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", emoji_path)
        self.assertTrue(os.path.isfile(emoji_file_path))

        # Test avatars
        user_email = Message.objects.all()[0].sender.email
        user_profile = UserProfile.objects.get(email=user_email, realm=imported_realm)
        avatar_path_id = user_avatar_path(user_profile) + ".original"
        avatar_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", avatar_path_id)
        self.assertTrue(os.path.isfile(avatar_file_path))
Example #4
0
    def test_upload_avatar_image(self) -> None:
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket = conn.create_bucket(settings.S3_AVATAR_BUCKET)

        user_profile = self.example_user('hamlet')
        path_id = user_avatar_path(user_profile)
        original_image_path_id = path_id + ".original"
        medium_path_id = path_id + "-medium.png"

        with get_test_image_file('img.png') as image_file:
            zerver.lib.upload.upload_backend.upload_avatar_image(image_file, user_profile, user_profile)
        test_image_data = open(get_test_image_file('img.png').name, 'rb').read()
        test_medium_image_data = resize_avatar(test_image_data, MEDIUM_AVATAR_SIZE)

        original_image_key = bucket.get_key(original_image_path_id)
        self.assertEqual(original_image_key.key, original_image_path_id)
        image_data = original_image_key.get_contents_as_string()
        self.assertEqual(image_data, test_image_data)

        medium_image_key = bucket.get_key(medium_path_id)
        self.assertEqual(medium_image_key.key, medium_path_id)
        medium_image_data = medium_image_key.get_contents_as_string()
        self.assertEqual(medium_image_data, test_medium_image_data)
        bucket.delete_key(medium_image_key)

        zerver.lib.upload.upload_backend.ensure_medium_avatar_image(user_profile)
        medium_image_key = bucket.get_key(medium_path_id)
        self.assertEqual(medium_image_key.key, medium_path_id)
Example #5
0
    def delete_avatar_image(self, user: UserProfile) -> None:
        path_id = user_avatar_path(user)
        bucket_name = settings.S3_AVATAR_BUCKET

        self.delete_file_from_s3(path_id + ".original", bucket_name)
        self.delete_file_from_s3(path_id + "-medium.png", bucket_name)
        self.delete_file_from_s3(path_id, bucket_name)
Example #6
0
    def upload_avatar_image(self, user_file: File,
                            acting_user_profile: UserProfile,
                            target_user_profile: UserProfile) -> None:
        file_path = user_avatar_path(target_user_profile)

        image_data = user_file.read()
        self.write_avatar_images(file_path, image_data)
Example #7
0
    def upload_avatar_image(self, user_file, acting_user_profile, target_user_profile):
        # type: (File, UserProfile, UserProfile) -> None
        content_type = guess_type(user_file.name)[0]
        bucket_name = settings.S3_AVATAR_BUCKET
        s3_file_name = user_avatar_path(target_user_profile)

        image_data = user_file.read()
        upload_image_to_s3(
            bucket_name,
            s3_file_name + ".original",
            content_type,
            target_user_profile,
            image_data,
        )

        # custom 500px wide version
        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        upload_image_to_s3(
            bucket_name,
            s3_file_name + "-medium.png",
            "image/png",
            target_user_profile,
            resized_medium
        )

        resized_data = resize_avatar(image_data)
        upload_image_to_s3(
            bucket_name,
            s3_file_name,
            'image/png',
            target_user_profile,
            resized_data,
        )
Example #8
0
    def _setup_export_files(self) -> Tuple[str, str, str, bytes]:
        realm = Realm.objects.get(string_id='zulip')
        message = Message.objects.all()[0]
        user_profile = message.sender
        url = upload_message_file(u'dummy.txt', len(b'zulip!'), u'text/plain', b'zulip!', user_profile)
        attachment_path_id = url.replace('/user_uploads/', '')
        claim_attachment(
            user_profile=user_profile,
            path_id=attachment_path_id,
            message=message,
            is_message_realm_public=True
        )
        avatar_path_id = user_avatar_path(user_profile)
        original_avatar_path_id = avatar_path_id + ".original"

        emoji_path = RealmEmoji.PATH_ID_TEMPLATE.format(
            realm_id=realm.id,
            emoji_file_name='1.png',
        )

        with get_test_image_file('img.png') as img_file:
            upload_emoji_image(img_file, '1.png', user_profile)
        with get_test_image_file('img.png') as img_file:
            upload_avatar_image(img_file, user_profile, user_profile)
        test_image = open(get_test_image_file('img.png').name, 'rb').read()
        message.sender.avatar_source = 'U'
        message.sender.save()

        return attachment_path_id, emoji_path, original_avatar_path_id, test_image
Example #9
0
    def upload_avatar_image(self, user_file: File,
                            acting_user_profile: UserProfile,
                            target_user_profile: UserProfile) -> None:
        content_type = guess_type(user_file.name)[0]
        s3_file_name = user_avatar_path(target_user_profile)

        image_data = user_file.read()
        self.write_avatar_images(s3_file_name, target_user_profile,
                                 image_data, content_type)
Example #10
0
 def _transfer_avatar_to_s3(user: UserProfile) -> int:
     avatar_path = user_avatar_path(user)
     file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", avatar_path) + ".original"
     try:
         with open(file_path, 'rb') as f:
             s3backend.upload_avatar_image(f, user, user)
             logging.info("Uploaded avatar for {} in realm {}".format(user.email, user.realm.name))
     except FileNotFoundError:
         pass
     return 0
Example #11
0
    def test_export_files_from_s3(self) -> None:
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        conn.create_bucket(settings.S3_AUTH_UPLOADS_BUCKET)
        conn.create_bucket(settings.S3_AVATAR_BUCKET)

        realm = Realm.objects.get(string_id='zulip')
        message = Message.objects.all()[0]
        user_profile = message.sender

        url = upload_message_file(u'dummy.txt', len(b'zulip!'), u'text/plain', b'zulip!', user_profile)
        attachment_path_id = url.replace('/user_uploads/', '')
        claim_attachment(
            user_profile=user_profile,
            path_id=attachment_path_id,
            message=message,
            is_message_realm_public=True
        )

        avatar_path_id = user_avatar_path(user_profile)
        original_avatar_path_id = avatar_path_id + ".original"

        emoji_path = RealmEmoji.PATH_ID_TEMPLATE.format(
            realm_id=realm.id,
            emoji_file_name='1.png',
        )

        with get_test_image_file('img.png') as img_file:
            upload_emoji_image(img_file, '1.png', user_profile)
        with get_test_image_file('img.png') as img_file:
            upload_avatar_image(img_file, user_profile, user_profile)
        test_image = open(get_test_image_file('img.png').name, 'rb').read()

        full_data = self._export_realm(realm)

        data = full_data['attachment']
        self.assertEqual(len(data['zerver_attachment']), 1)
        record = data['zerver_attachment'][0]
        self.assertEqual(record['path_id'], attachment_path_id)

        # Test uploads
        fields = attachment_path_id.split('/')
        fn = os.path.join(full_data['uploads_dir'], os.path.join(fields[1], fields[2]))
        with open(fn) as f:
            self.assertEqual(f.read(), 'zulip!')

        # Test emojis
        fn = os.path.join(full_data['emoji_dir'], emoji_path)
        fn = fn.replace('1.png', '')
        self.assertIn('1.png', os.listdir(fn))

        # Test avatars
        fn = os.path.join(full_data['avatar_dir'], original_avatar_path_id)
        fn_data = open(fn, 'rb').read()
        self.assertEqual(fn_data, test_image)
Example #12
0
    def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
        file_path = user_avatar_path(user_profile)

        output_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + "-medium.png")
        if os.path.isfile(output_path):
            return

        image_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + ".original")
        image_data = open(image_path, "rb").read()
        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        write_local_file('avatars', file_path + '-medium.png', resized_medium)
Example #13
0
    def ensure_basic_avatar_image(self, user_profile: UserProfile) -> None:  # nocoverage
        # TODO: Refactor this to share code with ensure_medium_avatar_image
        file_path = user_avatar_path(user_profile)

        output_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + ".png")
        if os.path.isfile(output_path):
            return

        image_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + ".original")
        image_data = open(image_path, "rb").read()
        resized_avatar = resize_avatar(image_data)
        write_local_file('avatars', file_path + '.png', resized_avatar)
Example #14
0
    def ensure_medium_avatar_image(self, user_profile):
        # type: (UserProfile) -> None
        file_path = user_avatar_path(user_profile)

        output_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + "-medium.png")
        if os.path.isfile(output_path):
            return

        image_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + ".original")
        image_data = open(image_path, "rb").read()
        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        write_local_file('avatars', file_path + '-medium.png', resized_medium)
Example #15
0
    def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        bucket = get_bucket(self.connection, bucket_name)
        key = bucket.get_key(file_path + ".original")
        image_data = key.get_contents_as_string()

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        upload_image_to_s3(bucket_name, s3_file_name + "-medium.png",
                           "image/png", user_profile, resized_medium)
Example #16
0
    def upload_avatar_image(self,
                            user_file: File,
                            acting_user_profile: UserProfile,
                            target_user_profile: UserProfile,
                            content_type: Optional[str] = None) -> None:
        if content_type is None:
            content_type = guess_type(user_file.name)[0]
        s3_file_name = user_avatar_path(target_user_profile)

        image_data = user_file.read()
        self.write_avatar_images(s3_file_name, target_user_profile, image_data,
                                 content_type)
Example #17
0
    def upload_avatar_image(self, user_file, acting_user_profile, target_user_profile):
        # type: (File, UserProfile, UserProfile) -> None
        file_path = user_avatar_path(target_user_profile)

        image_data = user_file.read()
        write_local_file('avatars', file_path + '.original', image_data)

        resized_data = resize_avatar(image_data)
        write_local_file('avatars', file_path + '.png', resized_data)

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        write_local_file('avatars', file_path + '-medium.png', resized_medium)
Example #18
0
    def ensure_basic_avatar_image(self, user_profile: UserProfile) -> None:  # nocoverage
        # TODO: Refactor this to share code with ensure_medium_avatar_image
        file_path = user_avatar_path(user_profile)

        output_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + ".png")
        if os.path.isfile(output_path):
            return

        image_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + ".original")
        image_data = open(image_path, "rb").read()
        resized_avatar = resize_avatar(image_data)
        write_local_file('avatars', file_path + '.png', resized_avatar)
Example #19
0
    def upload_avatar_image(self, user_file, acting_user_profile, target_user_profile):
        # type: (File, UserProfile, UserProfile) -> None
        file_path = user_avatar_path(target_user_profile)

        image_data = user_file.read()
        write_local_file('avatars', file_path + '.original', image_data)

        resized_data = resize_avatar(image_data)
        write_local_file('avatars', file_path + '.png', resized_data)

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        write_local_file('avatars', file_path + '-medium.png', resized_medium)
Example #20
0
 def _transfer_avatar_to_s3(user: UserProfile) -> int:
     avatar_path = user_avatar_path(user)
     file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars",
                              avatar_path) + ".original"
     try:
         with open(file_path, 'rb') as f:
             s3backend.upload_avatar_image(f, user, user)
             logging.info("Uploaded avatar for %s in realm %s", user.id,
                          user.realm.name)
     except FileNotFoundError:
         pass
     return 0
Example #21
0
    def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket = get_bucket(conn, bucket_name)
        key = bucket.get_key(file_path)
        image_data = force_bytes(key.get_contents_as_string())

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        upload_image_to_s3(bucket_name, s3_file_name + "-medium.png",
                           "image/png", user_profile, resized_medium)
Example #22
0
def _get_unversioned_avatar_url(avatar_source, email, medium=False):
    # type: (Text, Text, bool) -> Text
    if avatar_source == u'U':
        user_profile = get_user_profile_by_email(email)
        hash_key = user_avatar_path(user_profile)
        return upload_backend.get_avatar_url(hash_key, medium=medium)
    elif settings.ENABLE_GRAVATAR:
        gravitar_query_suffix = "&s=%s" % (
            MEDIUM_AVATAR_SIZE, ) if medium else ""
        hash_key = gravatar_hash(email)
        return u"https://secure.gravatar.com/avatar/%s?d=identicon%s" % (
            hash_key, gravitar_query_suffix)
    else:
        return settings.DEFAULT_AVATAR_URI + '?x=x'
Example #23
0
    def ensure_basic_avatar_image(
            self, user_profile: UserProfile) -> None:  # nocoverage
        # TODO: Refactor this to share code with ensure_medium_avatar_image
        file_path = user_avatar_path(user_profile)
        # Also TODO: Migrate to user_avatar_path(user_profile) + ".png".
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        bucket = get_bucket(self.connection, bucket_name)
        key = bucket.get_key(file_path + ".original")
        image_data = key.get_contents_as_string()

        resized_avatar = resize_avatar(image_data)
        upload_image_to_s3(bucket_name, s3_file_name, "image/png",
                           user_profile, resized_avatar)
Example #24
0
    def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket = get_bucket(conn, bucket_name)
        key = bucket.get_key(file_path + ".original")
        image_data = key.get_contents_as_string()

        resized_medium = resize_avatar(
            image_data, MEDIUM_AVATAR_SIZE
        )  # type: ignore # image_data is `bytes`, boto subs are wrong
        upload_image_to_s3(bucket_name, s3_file_name + "-medium.png",
                           "image/png", user_profile, resized_medium)
Example #25
0
    def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        key = self.avatar_bucket.Object(file_path + ".original")
        image_data = key.get()['Body'].read()

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        upload_image_to_s3(
            self.avatar_bucket,
            s3_file_name + "-medium.png",
            "image/png",
            user_profile,
            resized_medium,
        )
Example #26
0
    def test_export_files_from_local(self) -> None:
        message = Message.objects.all()[0]
        user_profile = message.sender
        url = upload_message_file(u'dummy.txt', len(b'zulip!'), u'text/plain',
                                  b'zulip!', user_profile)
        path_id = url.replace('/user_uploads/', '')
        claim_attachment(user_profile=user_profile,
                         path_id=path_id,
                         message=message,
                         is_message_realm_public=True)
        avatar_path_id = user_avatar_path(user_profile)
        original_avatar_path_id = avatar_path_id + ".original"

        realm = Realm.objects.get(string_id='zulip')
        with get_test_image_file('img.png') as img_file:
            upload_emoji_image(img_file, '1.png', user_profile)
        with get_test_image_file('img.png') as img_file:
            upload_avatar_image(img_file, user_profile, user_profile)
        test_image = open(get_test_image_file('img.png').name, 'rb').read()
        message.sender.avatar_source = 'U'
        message.sender.save()

        full_data = self._export_realm(realm)

        data = full_data['attachment']
        self.assertEqual(len(data['zerver_attachment']), 1)
        record = data['zerver_attachment'][0]
        self.assertEqual(record['path_id'], path_id)

        # Test uploads
        fn = os.path.join(full_data['uploads_dir'], path_id)
        with open(fn) as f:
            self.assertEqual(f.read(), 'zulip!')

        # Test emojis
        fn = os.path.join(
            full_data['emoji_dir'],
            RealmEmoji.PATH_ID_TEMPLATE.format(realm_id=realm.id,
                                               emoji_file_name='1.png'))
        fn = fn.replace('1.png', '')
        self.assertEqual('1.png', os.listdir(fn)[0])

        # Test avatars
        fn = os.path.join(full_data['avatar_dir'], original_avatar_path_id)
        fn_data = open(fn, 'rb').read()
        self.assertEqual(fn_data, test_image)
Example #27
0
def _get_unversioned_avatar_url(avatar_source, email=None, realm_id=None,
                                user_profile_id=None, medium=False):
    # type: (Text, Text, Optional[int], Optional[int], bool) -> Text
    if avatar_source == u'U':
        if user_profile_id is not None and realm_id is not None:
            # If we can, avoid doing a database query to fetch user_profile
            hash_key = user_avatar_path_from_ids(user_profile_id, realm_id)
        else:
            user_profile = get_user_profile_by_email(email)
            hash_key = user_avatar_path(user_profile)
        return upload_backend.get_avatar_url(hash_key, medium=medium)
    elif settings.ENABLE_GRAVATAR:
        gravitar_query_suffix = "&s=%s" % (MEDIUM_AVATAR_SIZE,) if medium else ""
        hash_key = gravatar_hash(email)
        return u"https://secure.gravatar.com/avatar/%s?d=identicon%s" % (hash_key, gravitar_query_suffix)
    else:
        return settings.DEFAULT_AVATAR_URI+'?x=x'
Example #28
0
    def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        bucket = get_bucket(self.session, bucket_name)
        key = bucket.Object(file_path + ".original")
        image_data = key.get()['Body'].read()

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        upload_image_to_s3(
            bucket_name,
            s3_file_name + "-medium.png",
            "image/png",
            user_profile,
            resized_medium,
        )
Example #29
0
    def ensure_basic_avatar_image(self, user_profile: UserProfile) -> None:  # nocoverage
        # TODO: Refactor this to share code with ensure_medium_avatar_image
        file_path = user_avatar_path(user_profile)
        # Also TODO: Migrate to user_avatar_path(user_profile) + ".png".
        s3_file_name = file_path

        key = self.avatar_bucket.Object(file_path + ".original")
        image_data = key.get()['Body'].read()

        resized_avatar = resize_avatar(image_data)
        upload_image_to_s3(
            self.avatar_bucket,
            s3_file_name,
            "image/png",
            user_profile,
            resized_avatar,
        )
Example #30
0
    def test_export_files_from_local(self) -> None:
        message = Message.objects.all()[0]
        user_profile = message.sender
        url = upload_message_file(u'dummy.txt', len(b'zulip!'), u'text/plain', b'zulip!', user_profile)
        path_id = url.replace('/user_uploads/', '')
        claim_attachment(
            user_profile=user_profile,
            path_id=path_id,
            message=message,
            is_message_realm_public=True
        )
        avatar_path_id = user_avatar_path(user_profile)
        original_avatar_path_id = avatar_path_id + ".original"

        realm = Realm.objects.get(string_id='zulip')
        with get_test_image_file('img.png') as img_file:
            upload_emoji_image(img_file, '1.png', user_profile)
        with get_test_image_file('img.png') as img_file:
            upload_avatar_image(img_file, user_profile, user_profile)
        test_image = open(get_test_image_file('img.png').name, 'rb').read()
        message.sender.avatar_source = 'U'
        message.sender.save()

        full_data = self._export_realm(realm)

        data = full_data['attachment']
        self.assertEqual(len(data['zerver_attachment']), 1)
        record = data['zerver_attachment'][0]
        self.assertEqual(record['path_id'], path_id)

        # Test uploads
        fn = os.path.join(full_data['uploads_dir'], path_id)
        with open(fn) as f:
            self.assertEqual(f.read(), 'zulip!')

        # Test emojis
        fn = os.path.join(full_data['emoji_dir'],
                          RealmEmoji.PATH_ID_TEMPLATE.format(realm_id=realm.id, emoji_file_name='1.png'))
        fn = fn.replace('1.png', '')
        self.assertEqual('1.png', os.listdir(fn)[0])

        # Test avatars
        fn = os.path.join(full_data['avatar_dir'], original_avatar_path_id)
        fn_data = open(fn, 'rb').read()
        self.assertEqual(fn_data, test_image)
Example #31
0
    def ensure_medium_avatar_image(self, user_profile: UserProfile) -> None:
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket = get_bucket(conn, bucket_name)
        key = bucket.get_key(file_path + ".original")
        image_data = key.get_contents_as_string()

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)  # type: ignore # image_data is `bytes`, boto subs are wrong
        upload_image_to_s3(
            bucket_name,
            s3_file_name + "-medium.png",
            "image/png",
            user_profile,
            resized_medium
        )
Example #32
0
    def ensure_basic_avatar_image(
            self, user_profile: UserProfile) -> None:  # nocoverage
        # TODO: Refactor this to share code with ensure_medium_avatar_image
        file_path = user_avatar_path(user_profile)
        # Also TODO: Migrate to user_avatar_path(user_profile) + ".png".
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket = get_bucket(conn, bucket_name)
        key = bucket.get_key(file_path + ".original")
        image_data = key.get_contents_as_string()

        resized_avatar = resize_avatar(
            image_data
        )  # type: ignore # image_data is `bytes`, boto subs are wrong
        upload_image_to_s3(bucket_name, s3_file_name, "image/png",
                           user_profile, resized_avatar)
Example #33
0
    def ensure_avatar_image(self, user_profile: UserProfile, is_medium: bool = False) -> None:
        file_extension = "-medium.png" if is_medium else ".png"
        file_path = user_avatar_path(user_profile)

        output_path = os.path.join(
            settings.LOCAL_UPLOADS_DIR, "avatars", file_path + file_extension
        )
        if os.path.isfile(output_path):
            return

        image_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars", file_path + ".original")
        with open(image_path, "rb") as f:
            image_data = f.read()
        if is_medium:
            resized_avatar = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        else:
            resized_avatar = resize_avatar(image_data)
        write_local_file("avatars", file_path + file_extension, resized_avatar)
Example #34
0
    def ensure_medium_avatar_image(self, user_profile):
        # type: (UserProfile) -> None
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket = get_bucket(conn, bucket_name)
        key = bucket.get_key(file_path)
        image_data = force_bytes(key.get_contents_as_string())

        resized_medium = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        upload_image_to_s3(
            bucket_name,
            s3_file_name + "-medium.png",
            "image/png",
            user_profile,
            resized_medium
        )
Example #35
0
    def test_import_files_from_s3(self) -> None:
        uploads_bucket, avatar_bucket = create_s3_buckets(
            settings.S3_AUTH_UPLOADS_BUCKET, settings.S3_AVATAR_BUCKET)

        realm = Realm.objects.get(string_id='zulip')
        self._setup_export_files()
        self._export_realm(realm)
        with patch('logging.info'):
            do_import_realm(
                os.path.join(settings.TEST_WORKER_DIR, 'test-export'),
                'test-zulip')
        imported_realm = Realm.objects.get(string_id='test-zulip')
        with open(get_test_image_file('img.png').name, 'rb') as f:
            test_image_data = f.read()

        # Test attachments
        uploaded_file = Attachment.objects.get(realm=imported_realm)
        self.assertEqual(len(b'zulip!'), uploaded_file.size)

        attachment_content = uploads_bucket.get_key(
            uploaded_file.path_id).get_contents_as_string()
        self.assertEqual(b"zulip!", attachment_content)

        # Test emojis
        realm_emoji = RealmEmoji.objects.get(realm=imported_realm)
        emoji_path = RealmEmoji.PATH_ID_TEMPLATE.format(
            realm_id=imported_realm.id,
            emoji_file_name=realm_emoji.file_name,
        )
        emoji_key = avatar_bucket.get_key(emoji_path)
        self.assertIsNotNone(emoji_key)
        self.assertEqual(emoji_key.key, emoji_path)

        # Test avatars
        user_email = Message.objects.all()[0].sender.email
        user_profile = UserProfile.objects.get(email=user_email,
                                               realm=imported_realm)
        avatar_path_id = user_avatar_path(user_profile) + ".original"
        original_image_key = avatar_bucket.get_key(avatar_path_id)
        self.assertEqual(original_image_key.key, avatar_path_id)
        image_data = original_image_key.get_contents_as_string()
        self.assertEqual(image_data, test_image_data)
Example #36
0
    def test_transfer_avatars_to_s3(self) -> None:
        bucket = create_s3_buckets(settings.S3_AVATAR_BUCKET)[0]

        self.login(self.example_email("hamlet"))
        with get_test_image_file('img.png') as image_file:
            self.client_post("/json/users/me/avatar", {'file': image_file})

        user = self.example_user("hamlet")

        transfer_avatars_to_s3(1)

        path_id = user_avatar_path(user)
        image_key = bucket.get_key(path_id)
        original_image_key = bucket.get_key(path_id + ".original")
        medium_image_key = bucket.get_key(path_id + "-medium.png")

        self.assertEqual(len(bucket.get_all_keys()), 3)
        self.assertEqual(image_key.get_contents_as_string(), open(avatar_disk_path(user), "rb").read())
        self.assertEqual(original_image_key.get_contents_as_string(), open(avatar_disk_path(user, original=True), "rb").read())
        self.assertEqual(medium_image_key.get_contents_as_string(), open(avatar_disk_path(user, medium=True), "rb").read())
Example #37
0
    def test_transfer_avatars_to_s3(self) -> None:
        bucket = create_s3_buckets(settings.S3_AVATAR_BUCKET)[0]

        self.login('hamlet')
        with get_test_image_file('img.png') as image_file:
            self.client_post("/json/users/me/avatar", {'file': image_file})

        user = self.example_user("hamlet")

        transfer_avatars_to_s3(1)

        path_id = user_avatar_path(user)
        image_key = bucket.get_key(path_id)
        original_image_key = bucket.get_key(path_id + ".original")
        medium_image_key = bucket.get_key(path_id + "-medium.png")

        self.assertEqual(len(bucket.get_all_keys()), 3)
        self.assertEqual(image_key.get_contents_as_string(), open(avatar_disk_path(user), "rb").read())
        self.assertEqual(original_image_key.get_contents_as_string(), open(avatar_disk_path(user, original=True), "rb").read())
        self.assertEqual(medium_image_key.get_contents_as_string(), open(avatar_disk_path(user, medium=True), "rb").read())
Example #38
0
    def ensure_basic_avatar_image(self, user_profile: UserProfile) -> None:  # nocoverage
        # TODO: Refactor this to share code with ensure_medium_avatar_image
        file_path = user_avatar_path(user_profile)
        # Also TODO: Migrate to user_avatar_path(user_profile) + ".png".
        s3_file_name = file_path

        bucket_name = settings.S3_AVATAR_BUCKET
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        bucket = get_bucket(conn, bucket_name)
        key = bucket.get_key(file_path + ".original")
        image_data = key.get_contents_as_string()

        resized_avatar = resize_avatar(image_data)  # type: ignore # image_data is `bytes`, boto subs are wrong
        upload_image_to_s3(
            bucket_name,
            s3_file_name,
            "image/png",
            user_profile,
            resized_avatar
        )
Example #39
0
    def ensure_avatar_image(self, user_profile: UserProfile, is_medium: bool = False) -> None:
        # BUG: The else case should be user_avatar_path(user_profile) + ".png".
        # See #12852 for details on this bug and how to migrate it.
        file_extension = "-medium.png" if is_medium else ""
        file_path = user_avatar_path(user_profile)
        s3_file_name = file_path

        key = self.avatar_bucket.Object(file_path + ".original")
        image_data = key.get()["Body"].read()

        if is_medium:
            resized_avatar = resize_avatar(image_data, MEDIUM_AVATAR_SIZE)
        else:
            resized_avatar = resize_avatar(image_data)
        upload_image_to_s3(
            self.avatar_bucket,
            s3_file_name + file_extension,
            "image/png",
            user_profile,
            resized_avatar,
        )
Example #40
0
def _get_unversioned_avatar_url(avatar_source,
                                email=None,
                                realm_id=None,
                                user_profile_id=None,
                                medium=False):
    # type: (Text, Text, Optional[int], Optional[int], bool) -> Text
    if avatar_source == u'U':
        if user_profile_id is not None and realm_id is not None:
            # If we can, avoid doing a database query to fetch user_profile
            hash_key = user_avatar_path_from_ids(user_profile_id, realm_id)
        else:
            user_profile = get_user_profile_by_email(email)
            hash_key = user_avatar_path(user_profile)
        return upload_backend.get_avatar_url(hash_key, medium=medium)
    elif settings.ENABLE_GRAVATAR:
        gravitar_query_suffix = "&s=%s" % (
            MEDIUM_AVATAR_SIZE, ) if medium else ""
        hash_key = gravatar_hash(email)
        return u"https://secure.gravatar.com/avatar/%s?d=identicon%s" % (
            hash_key, gravitar_query_suffix)
    else:
        return settings.DEFAULT_AVATAR_URI + '?x=x'
Example #41
0
    def test_import_files_from_local(self) -> None:

        realm = Realm.objects.get(string_id='zulip')
        self._setup_export_files()
        self._export_realm(realm)

        with patch('logging.info'):
            do_import_realm(
                os.path.join(settings.TEST_WORKER_DIR, 'test-export'),
                'test-zulip')
        imported_realm = Realm.objects.get(string_id='test-zulip')

        # Test attachments
        uploaded_file = Attachment.objects.get(realm=imported_realm)
        self.assertEqual(len(b'zulip!'), uploaded_file.size)

        attachment_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR,
                                            'files', uploaded_file.path_id)
        self.assertTrue(os.path.isfile(attachment_file_path))

        # Test emojis
        realm_emoji = RealmEmoji.objects.get(realm=imported_realm)
        emoji_path = RealmEmoji.PATH_ID_TEMPLATE.format(
            realm_id=imported_realm.id,
            emoji_file_name=realm_emoji.file_name,
        )
        emoji_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars",
                                       emoji_path)
        self.assertTrue(os.path.isfile(emoji_file_path))

        # Test avatars
        user_email = Message.objects.all()[0].sender.email
        user_profile = UserProfile.objects.get(email=user_email,
                                               realm=imported_realm)
        avatar_path_id = user_avatar_path(user_profile) + ".original"
        avatar_file_path = os.path.join(settings.LOCAL_UPLOADS_DIR, "avatars",
                                        avatar_path_id)
        self.assertTrue(os.path.isfile(avatar_file_path))
Example #42
0
    def test_import_files_from_s3(self) -> None:
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
        uploads_bucket = conn.create_bucket(settings.S3_AUTH_UPLOADS_BUCKET)
        avatar_bucket = conn.create_bucket(settings.S3_AVATAR_BUCKET)

        realm = Realm.objects.get(string_id='zulip')
        self._setup_export_files()
        self._export_realm(realm)
        with patch('logging.info'):
            do_import_realm('var/test-export', 'test-zulip')
        imported_realm = Realm.objects.get(string_id='test-zulip')
        test_image_data = open(get_test_image_file('img.png').name, 'rb').read()

        # Test attachments
        uploaded_file = Attachment.objects.get(realm=imported_realm)
        self.assertEqual(len(b'zulip!'), uploaded_file.size)

        attachment_content = uploads_bucket.get_key(uploaded_file.path_id).get_contents_as_string()
        self.assertEqual(b"zulip!", attachment_content)

        # Test emojis
        realm_emoji = RealmEmoji.objects.get(realm=imported_realm)
        emoji_path = RealmEmoji.PATH_ID_TEMPLATE.format(
            realm_id=imported_realm.id,
            emoji_file_name=realm_emoji.file_name,
        )
        emoji_key = avatar_bucket.get_key(emoji_path)
        self.assertIsNotNone(emoji_key)
        self.assertEqual(emoji_key.key, emoji_path)

        # Test avatars
        user_email = Message.objects.all()[0].sender.email
        user_profile = UserProfile.objects.get(email=user_email, realm=imported_realm)
        avatar_path_id = user_avatar_path(user_profile) + ".original"
        original_image_key = avatar_bucket.get_key(avatar_path_id)
        self.assertEqual(original_image_key.key, avatar_path_id)
        image_data = original_image_key.get_contents_as_string()
        self.assertEqual(image_data, test_image_data)
Example #43
0
    def test_transfer_avatars_to_s3(self) -> None:
        bucket = create_s3_buckets(settings.S3_AVATAR_BUCKET)[0]

        self.login("hamlet")
        with get_test_image_file("img.png") as image_file:
            self.client_post("/json/users/me/avatar", {"file": image_file})

        user = self.example_user("hamlet")

        with self.assertLogs(level="INFO"):
            transfer_avatars_to_s3(1)

        path_id = user_avatar_path(user)
        image_key = bucket.Object(path_id)
        original_image_key = bucket.Object(path_id + ".original")
        medium_image_key = bucket.Object(path_id + "-medium.png")

        self.assert_length(list(bucket.objects.all()), 3)
        with open(avatar_disk_path(user), "rb") as f:
            self.assertEqual(image_key.get()["Body"].read(), f.read())
        with open(avatar_disk_path(user, original=True), "rb") as f:
            self.assertEqual(original_image_key.get()["Body"].read(), f.read())
        with open(avatar_disk_path(user, medium=True), "rb") as f:
            self.assertEqual(medium_image_key.get()["Body"].read(), f.read())
Example #44
0
    def delete_avatar_image(self, user: UserProfile) -> None:
        path_id = user_avatar_path(user)

        delete_local_file("avatars", path_id + ".original")
        delete_local_file("avatars", path_id + ".png")
        delete_local_file("avatars", path_id + "-medium.png")
Example #45
0
    def delete_avatar_image(self, user: UserProfile) -> None:
        path_id = user_avatar_path(user)

        self.delete_file_from_s3(path_id + ".original", self.avatar_bucket)
        self.delete_file_from_s3(path_id + "-medium.png", self.avatar_bucket)
        self.delete_file_from_s3(path_id, self.avatar_bucket)
Example #46
0
    def copy_avatar(self, source_profile: UserProfile, target_profile: UserProfile) -> None:
        source_file_path = user_avatar_path(source_profile)
        target_file_path = user_avatar_path(target_profile)

        image_data = read_local_file('avatars', source_file_path + '.original')
        self.write_avatar_images(target_file_path, image_data)
Example #47
0
    def delete_avatar_image(self, user: UserProfile) -> None:
        path_id = user_avatar_path(user)

        delete_local_file("avatars", path_id + ".original")
        delete_local_file("avatars", path_id + ".png")
        delete_local_file("avatars", path_id + "-medium.png")
Example #48
0
    def copy_avatar(self, source_profile: UserProfile, target_profile: UserProfile) -> None:
        source_file_path = user_avatar_path(source_profile)
        target_file_path = user_avatar_path(target_profile)

        image_data = read_local_file("avatars", source_file_path + ".original")
        self.write_avatar_images(target_file_path, image_data)