Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
14 changes: 12 additions & 2 deletions geonode/assets/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ def rollback_asset_and_link(asset, link):
logger.error(f"Could not rollback asset[{asset}] and link[{link}]", exc_info=e)


def is_asset_deletable(asset: Asset):
"""
Checks if an asset can be deleted.
currently Assets with titles "Original" or "Files" are protected and cannot be deleted.
Further logics can be added here.
"""
if asset.title in ["Original", "Files"]:
return False
return True


def unlink_asset(resource: ResourceBase, asset: Asset, remove_asset: bool = True):
"""
Unlinks an asset from a resource. By default, the asset is deleted.
Expand All @@ -214,8 +225,7 @@ def unlink_asset(resource: ResourceBase, asset: Asset, remove_asset: bool = True
* If the asset is only linked to the provided resource, the asset itself is deleted,
which in turn triggers the deletion of the associated files.
"""
if asset.title in ["Original", "Files"]:
logger.info(f"Asset '{asset.title}' is protected and will not be unlinked or deleted.")
if not is_asset_deletable(asset):
return False, "Asset is protected and will not be unlinked or deleted."

link = Link.objects.filter(resource=resource, asset=asset).first()
Expand Down
4 changes: 3 additions & 1 deletion geonode/base/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from django.forms.models import model_to_dict
from django.contrib.auth import get_user_model
from django.db.models.query import QuerySet
from geonode.assets.utils import get_default_asset
from geonode.assets.utils import get_default_asset, is_asset_deletable
from geonode.people import Roles
from django.http import QueryDict
from deprecated import deprecated
Expand Down Expand Up @@ -580,8 +580,10 @@ def to_representation(self, instance):
formatted_link = model_to_dict(lnk, fields=link_fields)
ret.append(formatted_link)
if lnk.asset:
deletable = is_asset_deletable(lnk.asset)
extras = {
"type": "asset",
"deletable": deletable,
"content": model_to_dict(lnk.asset, ["title", "description", "type", "created"]),
}
if request and permissions_registry.user_has_perm(
Expand Down
37 changes: 37 additions & 0 deletions geonode/base/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@
Thesaurus,
ThesaurusKeyword,
generate_thesaurus_reference,
Link,
)
from geonode.assets.tests import ONE_JSON
from geonode.assets.utils import create_asset
from geonode.base.middleware import ReadOnlyMiddleware, MaintenanceMiddleware
from geonode.base.templatetags.base_tags import get_visibile_resources, facets
from geonode.base.templatetags.thesaurus import (
Expand All @@ -80,6 +83,7 @@
from geonode import geoserver
from geonode.decorators import on_ogc_backend
from geonode.resource.manager import resource_manager
from geonode.base.api.serializers import ResourceBaseSerializer

test_image = Image.new("RGBA", size=(50, 50), color=(155, 0, 0))

Expand Down Expand Up @@ -1324,3 +1328,36 @@ def test_fix_otherrestrictions_codetype(self):
fixed_obj = RestrictionCodeType.objects.get(identifier="otherRestrictions")
self.assertEqual(fixed_obj.description, "limitation not listed")
self.assertEqual(fixed_obj.gn_description, "limitation not listed")


class TestDeletableAssetKey(GeoNodeBaseTestSupport):
def setUp(self):
super().setUp()
self.user = get_user_model().objects.get(username="admin")
self.resource = create_single_dataset("test_resource")
self.asset1 = create_asset(self.user, asset_type="document", title="Test Asset for Deletion", files=[ONE_JSON])
self.asset2 = create_asset(self.user, asset_type="document", title="Original", files=[ONE_JSON])
self.link = Link.objects.create(resource=self.resource, asset=self.asset1, name="test_link")
self.link2 = Link.objects.create(resource=self.resource, asset=self.asset2, name="test_link_2")

def test_deletable_extra_property(self):
serializer = ResourceBaseSerializer(instance=self.resource)
data = serializer.data
links = data.get("links", []) # get value from LinksSerializer

# Check each link that has extras with content and deletable properties
for link in links:
extras = link.get("extras", {})
if extras and "deletable" in extras and "content" in extras:
content = extras["content"]
title = content.get("title", "")
deletable = extras["deletable"]
if title == "Original":
self.assertFalse(
deletable, f"Link with title 'Original' should have deletable=False, but got {deletable}"
)
elif title == "Test Asset for Deletion":
self.assertTrue(
deletable,
f"Link with title 'Test Asset for Deletion' should have deletable=True, but got {deletable}",
)
Loading