Skip to content

Commit 9bbbf4f

Browse files
mattiagiupponietj
authored andcommitted
[Fixes GeoNode#12341] Asset download handler and link generator (GeoNode#12343)
* [Fixes GeoNode#12341] Download handler fix * [Fixes GeoNode#12341] Assets: link generation (GeoNode#12342) --------- Co-authored-by: Emanuele Tajariol <etj@geo-solutions.it>
1 parent 618a936 commit 9bbbf4f

11 files changed

+58
-16
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ geonode/local_settings.py
2929

3030
# Uploaded files
3131
geonode/uploaded
32+
geonode/assets_data
3233

3334
#Testing output
3435
.coverage

geonode/assets/handlers.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ def clone(self, asset: Asset) -> Asset:
3838
def create_link_url(self, asset: Asset) -> str:
3939
raise NotImplementedError()
4040

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

44-
def get_storage_manager(self, asset):
44+
def get_storage_manager(self, asset=None):
4545
raise NotImplementedError()
4646

4747

geonode/assets/local.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,33 @@
2020
)
2121

2222

23+
class DefaultLocalLinkUrlHandler:
24+
def get_link_url(self, asset: LocalAsset):
25+
return build_absolute_uri(reverse("assets-link", args=(asset.pk,)))
26+
27+
28+
class IndexLocalLinkUrlHandler:
29+
def get_link_url(self, asset: LocalAsset):
30+
return build_absolute_uri(reverse("assets-link", args=(asset.pk,))) + f"/{os.path.basename(asset.location[0])}"
31+
32+
2333
class LocalAssetHandler(AssetHandlerInterface):
34+
35+
link_url_handlers = {"gpkg": IndexLocalLinkUrlHandler()}
36+
2437
@staticmethod
2538
def handled_asset_class():
2639
return LocalAsset
2740

28-
def get_download_handler(self, asset):
41+
def get_download_handler(self, asset=None):
2942
return LocalAssetDownloadHandler()
3043

3144
def get_storage_manager(self, asset):
3245
return _asset_storage_manager
3346

47+
def get_link_url_handler(self, asset):
48+
return self.link_url_handlers.get(asset.type, None) or DefaultLocalLinkUrlHandler()
49+
3450
def _create_asset_dir(self):
3551
return os.path.normpath(
3652
mkdtemp(dir=settings.ASSETS_ROOT, prefix=datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
@@ -126,7 +142,7 @@ def create_download_url(self, asset) -> str:
126142
return build_absolute_uri(reverse("assets-download", args=(asset.pk,)))
127143

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

131147
@classmethod
132148
def _is_file_managed(cls, file) -> bool:
@@ -175,6 +191,10 @@ def _get_managed_dir(cls, asset):
175191
base_common = base
176192

177193
managed_dir = os.path.join(assets_root, base_common)
194+
195+
if not os.path.exists(managed_dir):
196+
raise ValueError(f"Common dir '{managed_dir}' does not exist - Asset {asset.pk}")
197+
178198
if not os.path.isdir(managed_dir):
179199
raise ValueError(f"Common dir '{managed_dir}' does not seem to be a directory - Asset {asset.pk}")
180200

geonode/assets/tests/data/one.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"one": 1
2+
"one": 1
33
}

geonode/assets/tests/data/three.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"three": 3
2+
"three": 3
33
}

geonode/assets/tests/data/two.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"two": 2
2+
"two": 2
33
}

geonode/base/api/serializers.py

+19-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from django.forms.models import model_to_dict
2929
from django.contrib.auth import get_user_model
3030
from django.db.models.query import QuerySet
31+
from geonode.assets.utils import get_default_asset
3132
from geonode.people import Roles
3233
from django.http import QueryDict
3334
from deprecated import deprecated
@@ -62,7 +63,8 @@
6263
from geonode.geoapps.models import GeoApp
6364
from geonode.groups.models import GroupCategory, GroupProfile
6465
from geonode.base.api.fields import ComplexDynamicRelationField
65-
from geonode.layers.utils import get_dataset_download_handlers, get_default_dataset_download_handler
66+
from geonode.layers.utils import get_download_handlers, get_default_dataset_download_handler
67+
from geonode.assets.handlers import asset_handler_registry
6668
from geonode.utils import build_absolute_uri
6769
from geonode.security.utils import get_resources_with_perms, get_geoapp_subtypes
6870
from geonode.resource.models import ExecutionRequest
@@ -298,15 +300,24 @@ def get_attribute(self, instance):
298300
except Exception as e:
299301
logger.exception(e)
300302
raise e
303+
304+
asset = get_default_asset(_instance)
305+
if asset is not None:
306+
asset_url = asset_handler_registry.get_handler(asset).create_download_url(asset)
307+
301308
if _instance.resource_type in ["map"] + get_geoapp_subtypes():
302309
return []
303310
elif _instance.resource_type in ["document"]:
304-
return [
311+
payload = [
305312
{
306313
"url": _instance.download_url,
307314
"ajax_safe": _instance.download_is_ajax_safe,
308-
}
315+
},
309316
]
317+
if asset:
318+
payload.append({"url": asset_url, "ajax_safe": False, "default": False})
319+
return payload
320+
310321
elif _instance.resource_type in ["dataset"]:
311322
download_urls = []
312323
# lets get only the default one first to set it
@@ -315,11 +326,14 @@ def get_attribute(self, instance):
315326
if obj.download_url:
316327
download_urls.append({"url": obj.download_url, "ajax_safe": obj.is_ajax_safe, "default": True})
317328
# then let's prepare the payload with everything
318-
handler_list = get_dataset_download_handlers()
319-
for handler in handler_list:
329+
for handler in get_download_handlers():
320330
obj = handler(self.context.get("request"), _instance.alternate)
321331
if obj.download_url:
322332
download_urls.append({"url": obj.download_url, "ajax_safe": obj.is_ajax_safe, "default": False})
333+
334+
if asset:
335+
download_urls.append({"url": asset_url, "ajax_safe": True, "default": False if download_urls else True})
336+
323337
return download_urls
324338
else:
325339
return []

geonode/base/api/tests.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
from geonode.assets.utils import create_asset_and_link
5050
from geonode.maps.models import Map, MapLayer
5151
from geonode.tests.base import GeoNodeBaseTestSupport
52+
from geonode.assets.utils import get_default_asset
53+
from geonode.assets.handlers import asset_handler_registry
5254

5355
from geonode.base import enumerations
5456
from geonode.base.api.serializers import ResourceBaseSerializer
@@ -2477,7 +2479,12 @@ def test_base_resources_return_download_links_for_documents(self):
24772479
Ensure we can access the Resource Base list.
24782480
"""
24792481
doc = Document.objects.first()
2480-
expected_payload = [{"url": build_absolute_uri(doc.download_url), "ajax_safe": doc.download_is_ajax_safe}]
2482+
asset = get_default_asset(doc)
2483+
handler = asset_handler_registry.get_handler(asset)
2484+
expected_payload = [
2485+
{"url": build_absolute_uri(doc.download_url), "ajax_safe": doc.download_is_ajax_safe},
2486+
{"ajax_safe": False, "default": False, "url": handler.create_download_url(asset)},
2487+
]
24812488
# From resource base API
24822489
json = self._get_for_object(doc, "base-resources-detail")
24832490
download_url = json.get("resource").get("download_urls")

geonode/base/migrations/0092_migrate and_remove_resourcebase_files.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def get_ext(filename):
5050
# no existing "uploaded" links exist, so create them right away
5151
# otherwise we create the link with the assigned asset
5252
if dataset_hm := Dataset_hm.objects.filter(pk=res_hm.id).first():
53-
url = build_absolute_uri(reverse("assets-download", args=(asset.pk,)))
53+
url = build_absolute_uri(reverse("assets-link", args=(asset.pk,)))
5454
elif doc_hm := Document_hm.objects.filter(pk=res_hm.id).first():
5555
url = build_absolute_uri(reverse("assets-link", args=(asset.pk,)))
5656
else:

geonode/layers/utils.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ def get_uuid_handler():
507507
dataset_download_handler_list = []
508508

509509

510-
def get_dataset_download_handlers():
510+
def get_download_handlers():
511511
if not dataset_download_handler_list and getattr(settings, "DATASET_DOWNLOAD_HANDLERS", None):
512512
dataset_download_handler_list.append(import_string(settings.DATASET_DOWNLOAD_HANDLERS[0]))
513513

geonode/settings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@
303303
# Absolute path to the directory that hold assets files
304304
# This dir should not be made publicly accessible by nginx, since its content may be private
305305
# Using a sibling of MEDIA_ROOT as default
306-
ASSETS_ROOT = os.getenv("ASSETS_ROOT", os.path.join(os.path.dirname(MEDIA_ROOT.rstrip("/")), "assets"))
306+
ASSETS_ROOT = os.getenv("ASSETS_ROOT", os.path.join(os.path.dirname(MEDIA_ROOT.rstrip("/")), "assets_data"))
307307

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

0 commit comments

Comments
 (0)