Skip to content

Commit

Permalink
[Fixes #12341] Asset download handler and link generator (#12343)
Browse files Browse the repository at this point in the history
* [Fixes #12341] Download handler fix
* [Fixes #12341] Assets: link generation (#12342)
---------

Co-authored-by: Emanuele Tajariol <etj@geo-solutions.it>
  • Loading branch information
mattiagiupponi and etj authored Jun 20, 2024
1 parent d008bad commit 51458d5
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ geonode/local_settings.py

# Uploaded files
geonode/uploaded
geonode/assets_data

#Testing output
.coverage
Expand Down
4 changes: 2 additions & 2 deletions geonode/assets/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ def clone(self, asset: Asset) -> Asset:
def create_link_url(self, asset: Asset) -> str:
raise NotImplementedError()

Check warning on line 39 in geonode/assets/handlers.py

View check run for this annotation

Codecov / codecov/patch

geonode/assets/handlers.py#L39

Added line #L39 was not covered by tests

def get_download_handler(self, asset: Asset) -> AssetDownloadHandlerInterface:
def get_download_handler(self, asset: Asset = None) -> AssetDownloadHandlerInterface:
raise NotImplementedError()

Check warning on line 42 in geonode/assets/handlers.py

View check run for this annotation

Codecov / codecov/patch

geonode/assets/handlers.py#L42

Added line #L42 was not covered by tests

def get_storage_manager(self, asset):
def get_storage_manager(self, asset=None):
raise NotImplementedError()

Check warning on line 45 in geonode/assets/handlers.py

View check run for this annotation

Codecov / codecov/patch

geonode/assets/handlers.py#L45

Added line #L45 was not covered by tests


Expand Down
24 changes: 22 additions & 2 deletions geonode/assets/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,33 @@
)


class DefaultLocalLinkUrlHandler:
def get_link_url(self, asset: LocalAsset):
return build_absolute_uri(reverse("assets-link", args=(asset.pk,)))


class IndexLocalLinkUrlHandler:
def get_link_url(self, asset: LocalAsset):
return build_absolute_uri(reverse("assets-link", args=(asset.pk,))) + f"/{os.path.basename(asset.location[0])}"

Check warning on line 30 in geonode/assets/local.py

View check run for this annotation

Codecov / codecov/patch

geonode/assets/local.py#L30

Added line #L30 was not covered by tests


class LocalAssetHandler(AssetHandlerInterface):

link_url_handlers = {"gpkg": IndexLocalLinkUrlHandler()}

@staticmethod
def handled_asset_class():
return LocalAsset

def get_download_handler(self, asset):
def get_download_handler(self, asset=None):
return LocalAssetDownloadHandler()

def get_storage_manager(self, asset):
return _asset_storage_manager

def get_link_url_handler(self, asset):
return self.link_url_handlers.get(asset.type, None) or DefaultLocalLinkUrlHandler()

def _create_asset_dir(self):
return os.path.normpath(
mkdtemp(dir=settings.ASSETS_ROOT, prefix=datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
Expand Down Expand Up @@ -126,7 +142,7 @@ def create_download_url(self, asset) -> str:
return build_absolute_uri(reverse("assets-download", args=(asset.pk,)))

def create_link_url(self, asset) -> str:
return build_absolute_uri(reverse("assets-link", args=(asset.pk,))) + f"/{os.path.basename(asset.location[0])}"
return self.get_link_url_handler(asset).get_link_url(asset)

@classmethod
def _is_file_managed(cls, file) -> bool:
Expand Down Expand Up @@ -175,6 +191,10 @@ def _get_managed_dir(cls, asset):
base_common = base

managed_dir = os.path.join(assets_root, base_common)

if not os.path.exists(managed_dir):
raise ValueError(f"Common dir '{managed_dir}' does not exist - Asset {asset.pk}")

Check warning on line 196 in geonode/assets/local.py

View check run for this annotation

Codecov / codecov/patch

geonode/assets/local.py#L196

Added line #L196 was not covered by tests

if not os.path.isdir(managed_dir):
raise ValueError(f"Common dir '{managed_dir}' does not seem to be a directory - Asset {asset.pk}")

Check warning on line 199 in geonode/assets/local.py

View check run for this annotation

Codecov / codecov/patch

geonode/assets/local.py#L199

Added line #L199 was not covered by tests

Expand Down
2 changes: 1 addition & 1 deletion geonode/assets/tests/data/one.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"one": 1
"one": 1
}
2 changes: 1 addition & 1 deletion geonode/assets/tests/data/three.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"three": 3
"three": 3
}
2 changes: 1 addition & 1 deletion geonode/assets/tests/data/two.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"two": 2
"two": 2
}
24 changes: 19 additions & 5 deletions geonode/base/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +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.people import Roles
from django.http import QueryDict
from deprecated import deprecated
Expand Down Expand Up @@ -62,7 +63,8 @@
from geonode.geoapps.models import GeoApp
from geonode.groups.models import GroupCategory, GroupProfile
from geonode.base.api.fields import ComplexDynamicRelationField
from geonode.layers.utils import get_dataset_download_handlers, get_default_dataset_download_handler
from geonode.layers.utils import get_download_handlers, get_default_dataset_download_handler
from geonode.assets.handlers import asset_handler_registry
from geonode.utils import build_absolute_uri
from geonode.security.utils import get_resources_with_perms, get_geoapp_subtypes
from geonode.resource.models import ExecutionRequest
Expand Down Expand Up @@ -298,15 +300,24 @@ def get_attribute(self, instance):
except Exception as e:
logger.exception(e)
raise e

asset = get_default_asset(_instance)
if asset is not None:
asset_url = asset_handler_registry.get_handler(asset).create_download_url(asset)

if _instance.resource_type in ["map"] + get_geoapp_subtypes():
return []
elif _instance.resource_type in ["document"]:
return [
payload = [
{
"url": _instance.download_url,
"ajax_safe": _instance.download_is_ajax_safe,
}
},
]
if asset:
payload.append({"url": asset_url, "ajax_safe": False, "default": False})
return payload

elif _instance.resource_type in ["dataset"]:
download_urls = []
# lets get only the default one first to set it
Expand All @@ -315,11 +326,14 @@ def get_attribute(self, instance):
if obj.download_url:
download_urls.append({"url": obj.download_url, "ajax_safe": obj.is_ajax_safe, "default": True})
# then let's prepare the payload with everything
handler_list = get_dataset_download_handlers()
for handler in handler_list:
for handler in get_download_handlers():
obj = handler(self.context.get("request"), _instance.alternate)
if obj.download_url:
download_urls.append({"url": obj.download_url, "ajax_safe": obj.is_ajax_safe, "default": False})

if asset:
download_urls.append({"url": asset_url, "ajax_safe": True, "default": False if download_urls else True})

Check warning on line 335 in geonode/base/api/serializers.py

View check run for this annotation

Codecov / codecov/patch

geonode/base/api/serializers.py#L335

Added line #L335 was not covered by tests

return download_urls
else:
return []
Expand Down
9 changes: 8 additions & 1 deletion geonode/base/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
from geonode.assets.utils import create_asset_and_link
from geonode.maps.models import Map, MapLayer
from geonode.tests.base import GeoNodeBaseTestSupport
from geonode.assets.utils import get_default_asset
from geonode.assets.handlers import asset_handler_registry

from geonode.base import enumerations
from geonode.base.api.serializers import ResourceBaseSerializer
Expand Down Expand Up @@ -2477,7 +2479,12 @@ def test_base_resources_return_download_links_for_documents(self):
Ensure we can access the Resource Base list.
"""
doc = Document.objects.first()
expected_payload = [{"url": build_absolute_uri(doc.download_url), "ajax_safe": doc.download_is_ajax_safe}]
asset = get_default_asset(doc)
handler = asset_handler_registry.get_handler(asset)
expected_payload = [
{"url": build_absolute_uri(doc.download_url), "ajax_safe": doc.download_is_ajax_safe},
{"ajax_safe": False, "default": False, "url": handler.create_download_url(asset)},
]
# From resource base API
json = self._get_for_object(doc, "base-resources-detail")
download_url = json.get("resource").get("download_urls")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def get_ext(filename):
# no existing "uploaded" links exist, so create them right away
# otherwise we create the link with the assigned asset
if dataset_hm := Dataset_hm.objects.filter(pk=res_hm.id).first():
url = build_absolute_uri(reverse("assets-download", args=(asset.pk,)))
url = build_absolute_uri(reverse("assets-link", args=(asset.pk,)))

Check warning on line 53 in geonode/base/migrations/0092_migrate and_remove_resourcebase_files.py

View check run for this annotation

Codecov / codecov/patch

geonode/base/migrations/0092_migrate and_remove_resourcebase_files.py#L53

Added line #L53 was not covered by tests
elif doc_hm := Document_hm.objects.filter(pk=res_hm.id).first():
url = build_absolute_uri(reverse("assets-link", args=(asset.pk,)))

Check warning on line 55 in geonode/base/migrations/0092_migrate and_remove_resourcebase_files.py

View check run for this annotation

Codecov / codecov/patch

geonode/base/migrations/0092_migrate and_remove_resourcebase_files.py#L55

Added line #L55 was not covered by tests
else:
Expand Down
2 changes: 1 addition & 1 deletion geonode/layers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ def get_uuid_handler():
dataset_download_handler_list = []


def get_dataset_download_handlers():
def get_download_handlers():
if not dataset_download_handler_list and getattr(settings, "DATASET_DOWNLOAD_HANDLERS", None):
dataset_download_handler_list.append(import_string(settings.DATASET_DOWNLOAD_HANDLERS[0]))

Expand Down
2 changes: 1 addition & 1 deletion geonode/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@
# Absolute path to the directory that hold assets files
# This dir should not be made publicly accessible by nginx, since its content may be private
# Using a sibling of MEDIA_ROOT as default
ASSETS_ROOT = os.getenv("ASSETS_ROOT", os.path.join(os.path.dirname(MEDIA_ROOT.rstrip("/")), "assets"))
ASSETS_ROOT = os.getenv("ASSETS_ROOT", os.path.join(os.path.dirname(MEDIA_ROOT.rstrip("/")), "assets_data"))

# Cache Bustin Settings: enable WhiteNoise compression and caching support
# ref: http://whitenoise.evans.io/en/stable/django.html#add-compression-and-caching-support
Expand Down

0 comments on commit 51458d5

Please sign in to comment.