mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	upload: Create function to delete avatar image.
This commit is contained in:
		@@ -126,7 +126,7 @@ from zerver.lib.narrow import check_supported_events_narrow_filter
 | 
				
			|||||||
from zerver.lib.exceptions import JsonableError, ErrorCode, BugdownRenderingException
 | 
					from zerver.lib.exceptions import JsonableError, ErrorCode, BugdownRenderingException
 | 
				
			||||||
from zerver.lib.sessions import delete_user_sessions
 | 
					from zerver.lib.sessions import delete_user_sessions
 | 
				
			||||||
from zerver.lib.upload import attachment_url_re, attachment_url_to_path_id, \
 | 
					from zerver.lib.upload import attachment_url_re, attachment_url_to_path_id, \
 | 
				
			||||||
    claim_attachment, delete_message_image, upload_emoji_image
 | 
					    claim_attachment, delete_message_image, upload_emoji_image, delete_avatar_image
 | 
				
			||||||
from zerver.lib.str_utils import NonBinaryStr
 | 
					from zerver.lib.str_utils import NonBinaryStr
 | 
				
			||||||
from zerver.tornado.event_queue import request_event_queue, send_event
 | 
					from zerver.tornado.event_queue import request_event_queue, send_event
 | 
				
			||||||
from zerver.lib.types import ProfileFieldData
 | 
					from zerver.lib.types import ProfileFieldData
 | 
				
			||||||
@@ -3021,6 +3021,9 @@ def do_change_avatar_fields(user_profile: UserProfile, avatar_source: str) -> No
 | 
				
			|||||||
                    person=payload),
 | 
					                    person=payload),
 | 
				
			||||||
               active_user_ids(user_profile.realm_id))
 | 
					               active_user_ids(user_profile.realm_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def do_delete_avatar_image(user: UserProfile) -> None:
 | 
				
			||||||
 | 
					    do_change_avatar_fields(user, UserProfile.AVATAR_FROM_GRAVATAR)
 | 
				
			||||||
 | 
					    delete_avatar_image(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def do_change_icon_source(realm: Realm, icon_source: str, log: bool=True) -> None:
 | 
					def do_change_icon_source(realm: Realm, icon_source: str, log: bool=True) -> None:
 | 
				
			||||||
    realm.icon_source = icon_source
 | 
					    realm.icon_source = icon_source
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -167,6 +167,9 @@ class ZulipUploadBackend:
 | 
				
			|||||||
                            target_user_profile: UserProfile) -> None:
 | 
					                            target_user_profile: UserProfile) -> None:
 | 
				
			||||||
        raise NotImplementedError()
 | 
					        raise NotImplementedError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete_avatar_image(self, user: UserProfile) -> None:
 | 
				
			||||||
 | 
					        raise NotImplementedError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def delete_message_image(self, path_id: str) -> bool:
 | 
					    def delete_message_image(self, path_id: str) -> bool:
 | 
				
			||||||
        raise NotImplementedError()
 | 
					        raise NotImplementedError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -359,6 +362,14 @@ class S3UploadBackend(ZulipUploadBackend):
 | 
				
			|||||||
        self.write_avatar_images(s3_file_name, target_user_profile,
 | 
					        self.write_avatar_images(s3_file_name, target_user_profile,
 | 
				
			||||||
                                 image_data, content_type)
 | 
					                                 image_data, content_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_avatar_key(self, file_name: str) -> Key:
 | 
					    def get_avatar_key(self, file_name: str) -> Key:
 | 
				
			||||||
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
 | 
					        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
 | 
				
			||||||
        bucket_name = settings.S3_AVATAR_BUCKET
 | 
					        bucket_name = settings.S3_AVATAR_BUCKET
 | 
				
			||||||
@@ -531,6 +542,13 @@ class LocalUploadBackend(ZulipUploadBackend):
 | 
				
			|||||||
        image_data = user_file.read()
 | 
					        image_data = user_file.read()
 | 
				
			||||||
        self.write_avatar_images(file_path, image_data)
 | 
					        self.write_avatar_images(file_path, image_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_avatar_url(self, hash_key: str, medium: bool=False) -> str:
 | 
					    def get_avatar_url(self, hash_key: str, medium: bool=False) -> str:
 | 
				
			||||||
        # ?x=x allows templates to append additional parameters with &s
 | 
					        # ?x=x allows templates to append additional parameters with &s
 | 
				
			||||||
        medium_suffix = "-medium" if medium else ""
 | 
					        medium_suffix = "-medium" if medium else ""
 | 
				
			||||||
@@ -607,6 +625,9 @@ def upload_avatar_image(user_file: File, acting_user_profile: UserProfile,
 | 
				
			|||||||
                        target_user_profile: UserProfile) -> None:
 | 
					                        target_user_profile: UserProfile) -> None:
 | 
				
			||||||
    upload_backend.upload_avatar_image(user_file, acting_user_profile, target_user_profile)
 | 
					    upload_backend.upload_avatar_image(user_file, acting_user_profile, target_user_profile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def delete_avatar_image(user_profile: UserProfile):
 | 
				
			||||||
 | 
					    upload_backend.delete_avatar_image(user_profile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def copy_avatar(source_profile: UserProfile, target_profile: UserProfile) -> None:
 | 
					def copy_avatar(source_profile: UserProfile, target_profile: UserProfile) -> None:
 | 
				
			||||||
    upload_backend.copy_avatar(source_profile, target_profile)
 | 
					    upload_backend.copy_avatar(source_profile, target_profile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -970,6 +970,29 @@ class AvatarTest(UploadSerializeMixin, ZulipTestCase):
 | 
				
			|||||||
        target_medium_path_id = avatar_disk_path(target_user_profile, medium=True)
 | 
					        target_medium_path_id = avatar_disk_path(target_user_profile, medium=True)
 | 
				
			||||||
        self.assertEqual(open(source_medium_path_id, "rb").read(), open(target_medium_path_id, "rb").read())
 | 
					        self.assertEqual(open(source_medium_path_id, "rb").read(), open(target_medium_path_id, "rb").read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_delete_avatar_image(self) -> None:
 | 
				
			||||||
 | 
					        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')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        avatar_path_id = avatar_disk_path(user)
 | 
				
			||||||
 | 
					        avatar_original_path_id = avatar_disk_path(user, original=True)
 | 
				
			||||||
 | 
					        avatar_medium_path_id = avatar_disk_path(user, medium=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(user.avatar_source, UserProfile.AVATAR_FROM_USER)
 | 
				
			||||||
 | 
					        self.assertTrue(os.path.isfile(avatar_path_id))
 | 
				
			||||||
 | 
					        self.assertTrue(os.path.isfile(avatar_original_path_id))
 | 
				
			||||||
 | 
					        self.assertTrue(os.path.isfile(avatar_medium_path_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        zerver.lib.actions.do_delete_avatar_image(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(user.avatar_source, UserProfile.AVATAR_FROM_GRAVATAR)
 | 
				
			||||||
 | 
					        self.assertFalse(os.path.isfile(avatar_path_id))
 | 
				
			||||||
 | 
					        self.assertFalse(os.path.isfile(avatar_original_path_id))
 | 
				
			||||||
 | 
					        self.assertFalse(os.path.isfile(avatar_medium_path_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_invalid_avatars(self) -> None:
 | 
					    def test_invalid_avatars(self) -> None:
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        A PUT request to /json/users/me/avatar with an invalid file should fail.
 | 
					        A PUT request to /json/users/me/avatar with an invalid file should fail.
 | 
				
			||||||
@@ -1392,6 +1415,33 @@ class S3Test(ZulipTestCase):
 | 
				
			|||||||
        target_medium_image_data = target_medium_image_key.get_contents_as_string()
 | 
					        target_medium_image_data = target_medium_image_key.get_contents_as_string()
 | 
				
			||||||
        self.assertEqual(source_medium_image_data, target_medium_image_data)
 | 
					        self.assertEqual(source_medium_image_data, target_medium_image_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @use_s3_backend
 | 
				
			||||||
 | 
					    def test_delete_avatar_image(self) -> None:
 | 
				
			||||||
 | 
					        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
 | 
				
			||||||
 | 
					        bucket = conn.create_bucket(settings.S3_AVATAR_BUCKET)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        avatar_path_id = user_avatar_path(user)
 | 
				
			||||||
 | 
					        avatar_original_image_path_id = avatar_path_id + ".original"
 | 
				
			||||||
 | 
					        avatar_medium_path_id = avatar_path_id + "-medium.png"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(user.avatar_source, UserProfile.AVATAR_FROM_USER)
 | 
				
			||||||
 | 
					        self.assertIsNotNone(bucket.get_key(avatar_path_id))
 | 
				
			||||||
 | 
					        self.assertIsNotNone(bucket.get_key(avatar_original_image_path_id))
 | 
				
			||||||
 | 
					        self.assertIsNotNone(bucket.get_key(avatar_medium_path_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        zerver.lib.actions.do_delete_avatar_image(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.assertEqual(user.avatar_source, UserProfile.AVATAR_FROM_GRAVATAR)
 | 
				
			||||||
 | 
					        self.assertIsNone(bucket.get_key(avatar_path_id))
 | 
				
			||||||
 | 
					        self.assertIsNone(bucket.get_key(avatar_original_image_path_id))
 | 
				
			||||||
 | 
					        self.assertIsNone(bucket.get_key(avatar_medium_path_id))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @use_s3_backend
 | 
					    @use_s3_backend
 | 
				
			||||||
    def test_get_realm_for_filename(self) -> None:
 | 
					    def test_get_realm_for_filename(self) -> None:
 | 
				
			||||||
        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
 | 
					        conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user