diff --git a/taiga/users/api.py b/taiga/users/api.py index 93f42fb1..e9696bfd 100644 --- a/taiga/users/api.py +++ b/taiga/users/api.py @@ -233,6 +233,7 @@ class UsersViewSet(ModelCrudViewSet): except Exception: raise exc.WrongArguments(_("Invalid image format")) + request.user.delete_photo() request.user.photo = avatar request.user.save(update_fields=["photo"]) user_data = self.admin_serializer_class(request.user).data @@ -245,7 +246,7 @@ class UsersViewSet(ModelCrudViewSet): Remove the avatar of current logged user. """ self.check_permissions(request, "remove_avatar", None) - request.user.photo = None + request.user.delete_photo() request.user.save(update_fields=["photo"]) user_data = self.admin_serializer_class(request.user).data return response.Ok(user_data) diff --git a/taiga/users/models.py b/taiga/users/models.py index 345115be..38b34559 100644 --- a/taiga/users/models.py +++ b/taiga/users/models.py @@ -40,6 +40,8 @@ from taiga.base.utils.slug import slugify_uniquely from taiga.base.utils.iterators import split_by_n from taiga.permissions.permissions import MEMBERS_PERMISSIONS +from easy_thumbnails.files import get_thumbnailer + def generate_random_hex_color(): return "#{:06x}".format(random.randint(0,0xFFFFFF)) @@ -174,9 +176,22 @@ class User(AbstractBaseUser, PermissionsMixin): self.colorize_tags = True self.token = None self.set_unusable_password() + self.delete_photo() self.save() self.auth_data.all().delete() + def delete_photo(self): + # Removing thumbnails + thumbnailer = get_thumbnailer(self.photo) + thumbnailer.delete_thumbnails() + + # Removing original photo + if self.photo: + storage, path = self.photo.storage, self.photo.path + storage.delete(path) + + self.photo = None + class Role(models.Model): name = models.CharField(max_length=200, null=False, blank=False, diff --git a/tests/integration/test_users.py b/tests/integration/test_users.py index 8cb28a58..f20049f1 100644 --- a/tests/integration/test_users.py +++ b/tests/integration/test_users.py @@ -3,6 +3,7 @@ from tempfile import NamedTemporaryFile from django.contrib.contenttypes.models import ContentType from django.core.urlresolvers import reverse +from django.core.files import File from .. import factories as f @@ -12,6 +13,10 @@ from taiga.auth.tokens import get_token_for_user from taiga.permissions.permissions import MEMBERS_PERMISSIONS, ANON_PERMISSIONS, USER_PERMISSIONS from taiga.users.services import get_favourites_list +from easy_thumbnails.files import generate_all_aliases, get_thumbnailer + +import os + pytestmark = pytest.mark.django_db @@ -193,6 +198,56 @@ def test_change_avatar(client): assert response.status_code == 200 +def test_change_avatar_removes_the_old_one(client): + url = reverse('users-change-avatar') + user = f.UserFactory() + + with NamedTemporaryFile(delete=False) as avatar: + avatar.write(DUMMY_BMP_DATA) + avatar.seek(0) + user.photo = File(avatar) + user.save() + generate_all_aliases(user.photo, include_global=True) + + with NamedTemporaryFile(delete=False) as avatar: + thumbnailer = get_thumbnailer(user.photo) + original_photo_paths = [user.photo.path] + original_photo_paths += [th.path for th in thumbnailer.get_thumbnails()] + assert list(map(os.path.exists, original_photo_paths)) == [True, True, True, True] + + client.login(user) + avatar.write(DUMMY_BMP_DATA) + avatar.seek(0) + post_data = {'avatar': avatar} + response = client.post(url, post_data) + + assert response.status_code == 200 + assert list(map(os.path.exists, original_photo_paths)) == [False, False, False, False] + + +def test_remove_avatar(client): + url = reverse('users-remove-avatar') + user = f.UserFactory() + + with NamedTemporaryFile(delete=False) as avatar: + avatar.write(DUMMY_BMP_DATA) + avatar.seek(0) + user.photo = File(avatar) + user.save() + generate_all_aliases(user.photo, include_global=True) + + thumbnailer = get_thumbnailer(user.photo) + original_photo_paths = [user.photo.path] + original_photo_paths += [th.path for th in thumbnailer.get_thumbnails()] + assert list(map(os.path.exists, original_photo_paths)) == [True, True, True, True] + + client.login(user) + response = client.post(url) + + assert response.status_code == 200 + assert list(map(os.path.exists, original_photo_paths)) == [False, False, False, False] + + def test_list_contacts_private_projects(client): project = f.ProjectFactory.create() user_1 = f.UserFactory.create()