Skip to content

Commit

Permalink
Merge branch 'master' into args_kwargs_api
Browse files Browse the repository at this point in the history
  • Loading branch information
giohappy authored Sep 11, 2023
2 parents d654d9f + cd70285 commit 58600fe
Show file tree
Hide file tree
Showing 16 changed files with 362 additions and 108 deletions.
46 changes: 45 additions & 1 deletion geonode/base/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from django.db.models.query import QuerySet
from django.http import QueryDict

from deprecated import deprecated
from rest_framework import serializers
from rest_framework_gis import fields
from rest_framework.reverse import reverse, NoReverseMatch
Expand All @@ -54,8 +55,9 @@
)
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.utils import build_absolute_uri
from geonode.security.utils import get_resources_with_perms
from geonode.security.utils import get_resources_with_perms, get_geoapp_subtypes
from geonode.resource.models import ExecutionRequest

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -278,15 +280,56 @@ class DownloadLinkField(DynamicComputedField):
def __init__(self, **kwargs):
super().__init__(**kwargs)

@deprecated(version="4.2.0", reason="Will be replaced by download_urls")
def get_attribute(self, instance):
try:
logger.info(
"This field is deprecated, and will be removed in the future GeoNode version. Please refer to download_urls"
)
_instance = instance.get_real_instance()
return _instance.download_url if hasattr(_instance, "download_url") else None
except Exception as e:
logger.exception(e)
return None


class DownloadArrayLinkField(DynamicComputedField):
def __init__(self, **kwargs):
super().__init__(**kwargs)

def get_attribute(self, instance):
try:
_instance = instance.get_real_instance()
except Exception as e:
logger.exception(e)
raise e
if _instance.resource_type in ["map"] + get_geoapp_subtypes():
return []
elif _instance.resource_type in ["document"]:
return [
{
"url": _instance.download_url,
"ajax_safe": _instance.download_is_ajax_safe,
}
]
elif _instance.resource_type in ["dataset"]:
download_urls = []
# lets get only the default one first to set it
default_handler = get_default_dataset_download_handler()
obj = default_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": True})
# then let's prepare the payload with everything
handler_list = get_dataset_download_handlers()
for handler in handler_list:
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})
return download_urls
else:
return []


class FavoriteField(DynamicComputedField):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down Expand Up @@ -479,6 +522,7 @@ def __init__(self, *args, **kwargs):
self.fields["is_copyable"] = serializers.BooleanField(read_only=True)
self.fields["download_url"] = DownloadLinkField(read_only=True)
self.fields["favorite"] = FavoriteField(read_only=True)
self.fields["download_urls"] = DownloadArrayLinkField(read_only=True)

metadata = ComplexDynamicRelationField(ExtraMetadataSerializer, embed=False, many=True, deferred=True)

Expand Down
90 changes: 74 additions & 16 deletions geonode/base/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import json
import logging
from django.contrib.contenttypes.models import ContentType
from django.test import override_settings
from django.test import RequestFactory, override_settings
import gisdata

from PIL import Image
Expand Down Expand Up @@ -751,12 +751,16 @@ def test_resource_serializer_validation(self):
ds = ResourceBase.objects.get(title=title)
ds.keywords.add(HierarchicalKeyword.objects.get(slug="a1"))

serialized = ResourceBaseSerializer(ds)
factory = RequestFactory()
rq = factory.get("test")
rq.user = owner

serialized = ResourceBaseSerializer(ds, context={"request": rq})
json = JSONRenderer().render(serialized.data)
stream = BytesIO(json)
data = JSONParser().parse(stream)
self.assertIsInstance(data, dict)
se = ResourceBaseSerializer(data=data)
se = ResourceBaseSerializer(data=data, context={"request": rq})
self.assertTrue(se.is_valid())

def test_delete_user_with_resource(self):
Expand Down Expand Up @@ -2065,6 +2069,7 @@ def test_manager_can_edit_map(self):
"""
REST API must not forbid saving maps and apps to non-admin and non-owners.
"""
self.maxDiff = None
from geonode.maps.models import Map

_map = Map.objects.filter(uuid__isnull=False, owner__username="admin").first()
Expand Down Expand Up @@ -2120,7 +2125,7 @@ def test_manager_can_edit_map(self):
response = self.client.get(resource_service_permissions_url, format="json")
self.assertEqual(response.status_code, 200)
resource_perm_spec = response.data
self.assertEqual(
self.assertDictEqual(
resource_perm_spec,
{
"users": [
Expand Down Expand Up @@ -2161,7 +2166,7 @@ def test_manager_can_edit_map(self):
response = self.client.get(get_perms_url, format="json")
self.assertEqual(response.status_code, 200)
resource_perm_spec = response.data
self.assertEqual(
self.assertDictEqual(
resource_perm_spec,
{
"users": [
Expand Down Expand Up @@ -2200,20 +2205,10 @@ def test_manager_can_edit_map(self):
response = self.client.get(get_perms_url, format="json")
self.assertEqual(response.status_code, 200)
resource_perm_spec = response.data
self.assertEqual(
self.assertDictEqual(
resource_perm_spec,
{
"users": [
{
"id": 1,
"username": "admin",
"first_name": "admin",
"last_name": "",
"avatar": "https://www.gravatar.com/avatar/7a68c67c8d409ff07e42aa5d5ab7b765/?s=240",
"permissions": "owner",
"is_staff": True,
"is_superuser": True,
},
{
"id": bobby.id,
"username": "bobby",
Expand All @@ -2224,6 +2219,16 @@ def test_manager_can_edit_map(self):
"is_staff": False,
"is_superuser": False,
},
{
"id": 1,
"username": "admin",
"first_name": "admin",
"last_name": "",
"avatar": "https://www.gravatar.com/avatar/7a68c67c8d409ff07e42aa5d5ab7b765/?s=240",
"permissions": "owner",
"is_staff": True,
"is_superuser": True,
},
],
"organizations": [],
"groups": [
Expand Down Expand Up @@ -2445,6 +2450,59 @@ def test_base_resources_dont_return_download_link_if_map(self):
download_url = response.json().get("resource").get("download_url")
self.assertIsNone(download_url)

def test_base_resources_return_not_download_links_for_maps(self):
"""
Ensure we can access the Resource Base list.
"""
_map = Map.objects.first()
# From resource base API
url = reverse("base-resources-detail", args=[_map.id])
response = self.client.get(url, format="json")
download_url = response.json().get("resource").get("download_urls", None)
self.assertListEqual([], download_url)

# from maps api
url = reverse("maps-detail", args=[_map.id])
download_url = response.json().get("resource").get("download_urls")
self.assertListEqual([], download_url)

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}]
# From resource base API
url = reverse("base-resources-detail", args=[doc.id])
response = self.client.get(url, format="json")
download_url = response.json().get("resource").get("download_urls")
self.assertListEqual(expected_payload, download_url)

# from documents api
url = reverse("documents-detail", args=[doc.id])
download_url = response.json().get("resource").get("download_urls")
self.assertListEqual(expected_payload, download_url)

def test_base_resources_return_download_links_for_datasets(self):
"""
Ensure we can access the Resource Base list.
"""
_dataset = Dataset.objects.first()
expected_payload = [
{"url": reverse("dataset_download", args=[_dataset.alternate]), "ajax_safe": True, "default": True}
]

# From resource base API
url = reverse("base-resources-detail", args=[_dataset.id])
response = self.client.get(url, format="json")
download_url = response.json().get("resource").get("download_urls")
self.assertEqual(expected_payload, download_url)

# from dataset api
url = reverse("datasets-detail", args=[_dataset.id])
download_url = response.json().get("resource").get("download_urls")
self.assertEqual(expected_payload, download_url)


class TestExtraMetadataBaseApi(GeoNodeBaseTestSupport):
def setUp(self):
Expand Down
8 changes: 8 additions & 0 deletions geonode/documents/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ def href(self):
elif self.files:
return urljoin(settings.SITEURL, reverse("document_link", args=(self.id,)))

@property
def is_local(self):
return False if self.doc_url else True

@property
def download_is_ajax_safe(self):
return self.is_local

@property
def is_file(self):
return self.files and self.extension
Expand Down
22 changes: 21 additions & 1 deletion geonode/documents/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
from geonode.documents.enumerations import DOCUMENT_TYPE_MAP
from geonode.documents.models import Document, DocumentResourceLink

from geonode.base.populate_test_data import all_public, create_models, remove_models
from geonode.base.populate_test_data import all_public, create_models, create_single_doc, remove_models
from geonode.upload.api.exceptions import FileUploadLimitException

from .forms import DocumentCreateForm
Expand Down Expand Up @@ -153,6 +153,26 @@ def test_remote_document_is_marked_remote(self):
d = Document.objects.get(title="A remote document through form is remote")
self.assertEqual(d.sourcetype, SOURCE_TYPE_REMOTE)

def test_download_is_not_ajax_safe(self):
"""Remote document is mark as not safe."""
self.client.login(username="admin", password="admin")
form_data = {
"title": "A remote document through form is remote",
"doc_url": "https://development.demo.geonode.org/static/mapstore/img/geonode-logo.svg",
}

response = self.client.post(reverse("document_upload"), data=form_data)

self.assertEqual(response.status_code, 302)

d = Document.objects.get(title="A remote document through form is remote")
self.assertFalse(d.download_is_ajax_safe)

def test_download_is_ajax_safe(self):
"""Remote document is mark as not safe."""
d = create_single_doc("example_doc_name")
self.assertTrue(d.download_is_ajax_safe)

def test_create_document_url(self):
"""Tests creating an external document instead of a file."""

Expand Down
29 changes: 28 additions & 1 deletion geonode/geoserver/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from geonode.layers.populate_datasets_data import create_dataset_data
from geonode.base.populate_test_data import all_public, create_models, remove_models, create_single_dataset
from geonode.geoserver.helpers import gs_catalog, get_sld_for, extract_name_from_sld
from geonode.catalogue.models import catalogue_post_save

import logging

Expand Down Expand Up @@ -1192,8 +1193,19 @@ def test_set_resources_links(self):
with self.settings(UPDATE_RESOURCE_LINKS_AT_MIGRATE=True, ASYNC_SIGNALS=False):
# Links
_def_link_types = ["original", "metadata"]
_links = Link.objects.filter(link_type__in=_def_link_types)
# Check 'original' and 'metadata' links exist
Link.objects.update_or_create(
resource=Dataset.objects.first(),
url="https://custom_dowonload_url.com",
defaults=dict(
extension="zip",
name="Original Dataset",
mime="application/octet-stream",
link_type="original",
),
)
_links = Link.objects.filter(link_type__in=_def_link_types)

self.assertIsNotNone(_links, "No 'original' and 'metadata' links have been found")

# Delete all 'original' and 'metadata' links
Expand Down Expand Up @@ -1233,13 +1245,28 @@ def test_set_resources_links(self):

for _lyr in _post_migrate_datasets:
# Check original links in csw_anytext
# by default is not created anymore, we need to create one
Link.objects.update_or_create(
resource=_lyr,
url="https://custom_dowonload_url.com",
defaults=dict(
extension="zip",
name="Original Dataset",
mime="application/octet-stream",
link_type="original",
),
)

_post_migrate_links_orig = Link.objects.filter(
resource=_lyr.resourcebase_ptr, resource_id=_lyr.resourcebase_ptr.id, link_type="original"
)
self.assertTrue(
_post_migrate_links_orig.exists(),
f"No 'original' links has been found for the layer '{_lyr.alternate}'",
)
# needed to update the csw_anytext field with the new link created
catalogue_post_save(instance=_lyr, sender=_lyr.__class__)
_lyr.refresh_from_db()
for _link_orig in _post_migrate_links_orig:
self.assertIn(
_link_orig.url,
Expand Down
24 changes: 24 additions & 0 deletions geonode/layers/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from guardian.shortcuts import assign_perm, get_anonymous_user
from geonode.geoserver.createlayer.utils import create_dataset

from geonode.base.models import Link
from geonode.base.populate_test_data import create_models, create_single_dataset
from geonode.layers.models import Attribute, Dataset
from geonode.maps.models import Map, MapLayer
Expand Down Expand Up @@ -415,3 +416,26 @@ def test_valid_metadata_file(self):
put_data = {"metadata_file": f}
response = self.client.put(url, data=put_data)
self.assertEqual(200, response.status_code)

def test_download_api(self):
dataset = create_single_dataset("test_dataset")
url = reverse("datasets-detail", kwargs={"pk": dataset.pk})
response = self.client.get(url)
self.assertTrue(response.status_code == 200)
data = response.json()["dataset"]
download_url_data = data["download_urls"][0]
download_url = reverse("dataset_download", args=[dataset.alternate])
self.assertEqual(download_url_data["default"], True)
self.assertEqual(download_url_data["ajax_safe"], True)
self.assertEqual(download_url_data["url"], download_url)

link = Link(link_type="original", url="https://myoriginal.org", resource=dataset)
link.save()

response = self.client.get(url)
data = response.json()["dataset"]
download_url_data = data["download_urls"][0]
download_url = reverse("dataset_download", args=[dataset.alternate])
self.assertEqual(download_url_data["default"], True)
self.assertEqual(download_url_data["ajax_safe"], False)
self.assertEqual(download_url_data["url"], "https://myoriginal.org")
Loading

0 comments on commit 58600fe

Please sign in to comment.