Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions geonode/base/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1998,6 +1998,56 @@ def test_set_resource_thumbnail(self):
)
self.assertEqual(response.status_code, 200)

@patch("geonode.base.api.views.remove_thumb")
def test_delete_thumbnail(self, mock_remove_thumb):

resource = Dataset.objects.first()

# Set a thumbnail url and path
resource.thumbnail_url = "http://example.com/thumb/test.png"
resource.thumbnail_path = "thumb/test.png"
resource.save()

url = reverse("base-resources-delete-thumbnail", kwargs={"resource_id": resource.id})

# Anonymous user
response = self.client.post(url)
self.assertEqual(response.status_code, 403)

# Authenticated user (admin)
self.assertTrue(self.client.login(username="admin", password="admin"))

# Valid thumbnail removal
response = self.client.post(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["message"], "Thumbnail deleted successfully.")
resource.refresh_from_db()
self.assertIsNone(resource.thumbnail_url)
self.assertIsNone(resource.thumbnail_path)
mock_remove_thumb.assert_called_once_with("test.png")

# Thumbnail already deleted
response = self.client.post(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["message"], "The thumbnail URL field is already empty.")
self.assertFalse(response.data["success"])

# Invalid image format
resource.thumbnail_url = "http://example.com/media/thumb/test.txt"
resource.thumbnail_path = "thumb/test.txt"
resource.save()

response = self.client.post(url)
self.assertEqual(response.status_code, 400)
self.assertIn("not a valid image", response.data)

# Resource does not exist
invalid_url = reverse("base-resources-delete-thumbnail", kwargs={"resource_id": 9999})
response = self.client.post(invalid_url)
self.assertEqual(response.status_code, 404)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Gpetrak i guess it could be worth to add a test where a user, tries to delete the thumbnail of a resource which does not belong to it.
like user bobby tries to delete the thumbnail of a resource owner by user norm. I suppose the user should not have the right to do it

self.assertEqual(response.data["message"], "Resource not found.")
self.assertFalse(response.data["success"])

def test_set_thumbnail_from_bbox_from_Anonymous_user_raise_permission_error(self):
"""
Given a request with Anonymous user, should raise an authentication error.
Expand Down
53 changes: 52 additions & 1 deletion geonode/base/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
from geonode.base.models import Configuration, ExtraMetadata, LinkedResource
from geonode.thumbs.exceptions import ThumbnailError
from geonode.thumbs.thumbnails import create_thumbnail
from geonode.thumbs.utils import _decode_base64, BASE64_PATTERN
from geonode.thumbs.utils import _decode_base64, BASE64_PATTERN, remove_thumb
from geonode.groups.conf import settings as groups_settings
from geonode.base.models import HierarchicalKeyword, Region, ResourceBase, TopicCategory, ThesaurusKeyword
from geonode.base.api.filters import (
Expand Down Expand Up @@ -721,6 +721,57 @@
logger.error(e)
return Response(data={"message": e.args[0], "success": False}, status=500, exception=True)

@extend_schema(
methods=["post"],
responses={200},
description="API endpoint allowing to delete a thumbnail for an existing dataset.",
)
@action(
detail=False,
url_path="(?P<resource_id>\d+)/delete_thumbnail", # noqa
url_name="delete-thumbnail",
methods=["post"],
permission_classes=[IsAuthenticated, UserHasPerms(perms_dict={"default": {"POST": ["base.add_resourcebase"]}})],
)
def delete_thumbnail(self, request, resource_id, *args, **kwargs):

try:
resource = ResourceBase.objects.get(id=int(resource_id))

# Check if thumbnail exists
if not resource.thumbnail_url:
return Response(
{"message": "The thumbnail URL field is already empty.", "success": False},
status=status.HTTP_200_OK,
)

thumb_parsed_url = urlparse(resource.thumbnail_url)
thumb_filename = thumb_parsed_url.path.split("/")[-1]
if thumb_filename.rsplit(".")[-1] not in ["png", "jpeg", "jpg"]:
return Response(
"The file name is not a valid image with a format png, jpeg or jpg",
status=status.HTTP_400_BAD_REQUEST,
)

# remove_thumb will call the thumb_path function and then the storage_manager which will delete it
remove_thumb(thumb_filename)

# Clear the related fields in the database
resource.thumbnail_url = None
resource.thumbnail_path = None
resource.save(update_fields=["thumbnail_url", "thumbnail_path"])

return Response({"message": "Thumbnail deleted successfully.", "success": True}, status=status.HTTP_200_OK)

except ResourceBase.DoesNotExist:
return Response({"message": "Resource not found.", "success": False}, status=status.HTTP_404_NOT_FOUND)
except Exception as e:
logger.error(e)
return Response(

Check warning on line 770 in geonode/base/api/views.py

View check run for this annotation

Codecov / codecov/patch

geonode/base/api/views.py#L768-L770

Added lines #L768 - L770 were not covered by tests
{"message": "Unexpected error occurred.", "success": False},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)

@extend_schema(
methods=["post"], responses={200}, description="Instructs the Async dispatcher to execute a 'INGEST' operation."
)
Expand Down
Loading