Skip to content

Commit

Permalink
[Fixes GeoNode#11847] Implement the option to hide resources from sea…
Browse files Browse the repository at this point in the history
…rch and… (GeoNode#11848)

* [Fixes GeoNode#11847] Implement the option to hide resources from search and catalogue listing

* [Fixes GeoNode#11847] Fix broken test

* [Fixes GeoNode#11847] Implement the option to hide resources from search and catalogue listing

* [Fixes GeoNode#11847] Implement the option to hide resources from search and catalogue listing

* [Fixes GeoNode#11847] Implement the option to hide resources from search and catalogue listing

* [Fixes GeoNode#11847] Implement the option to hide resources from search and catalogue listing
  • Loading branch information
mattiagiupponi authored Jan 17, 2024
1 parent 5aabd6c commit 5950784
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 1 deletion.
1 change: 1 addition & 0 deletions geonode/base/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ def __init__(self, *args, **kwargs):
self.fields["share_count"] = serializers.CharField(required=False)
self.fields["rating"] = serializers.CharField(required=False)
self.fields["featured"] = serializers.BooleanField(required=False)
self.fields["advertised"] = serializers.BooleanField(required=False)
self.fields["is_published"] = serializers.BooleanField(required=False, read_only=True)
self.fields["is_approved"] = serializers.BooleanField(required=False, read_only=True)
self.fields["detail_url"] = DetailUrlField(read_only=True)
Expand Down
90 changes: 90 additions & 0 deletions geonode/base/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2511,6 +2511,96 @@ def test_base_resources_return_download_links_for_datasets(self):
download_url = response.json().get("resource").get("download_urls")
self.assertEqual(expected_payload, download_url)

def test_api_should_return_all_resources_for_admin(self):
"""
Api whould return all resources even if advertised=False.
"""
url = reverse("base-resources-list")
self.client.login(username="admin", password="admin")
payload = self.client.get(url)
prev_count = payload.json().get("total")
# update all the resource to advertised=False
Dataset.objects.update(advertised=False)
url = reverse("base-resources-list")
payload = self.client.get(url)
new_count = payload.json().get("total")
self.assertEqual(new_count, prev_count)

Dataset.objects.update(advertised=True)

def test_api_should_return_advertised_resource_if_anonymous(self):
"""
If anonymous user, only the advertised resoruces whould be returned by the API.
"""
url = reverse("base-resources-list")
payload = self.client.get(url)
prev_count = payload.json().get("total")
# update all the resource to advertised=False
Dataset.objects.update(advertised=False)
url = reverse("base-resources-list")
payload = self.client.get(url)
new_count = payload.json().get("total")
self.assertNotEqual(new_count, prev_count)

Dataset.objects.update(advertised=True)

def test_api_should_return_only_the_advertised_false_where_user_is_owner(self):
"""
Api Should return all the resource with advertised=True
And the resource with advertised=False if is owner of it
"""
# defining a new user
test_user_for_api = get_user_model().objects.create(username="test_user_for_api", password="password")
# creating a new resource for the user with advertised=False
dataset = create_single_dataset(name="test_resource_for_api", owner=test_user_for_api, advertised=False)
url = reverse("base-resources-list")
self.client.force_login(test_user_for_api)
payload = self.client.get(f"{url}?limit=1000")
# the uuid of the dataset is in the returned payload
self.assertTrue(dataset.uuid in [k["uuid"] for k in payload.json()["resources"]])
# bobby is not able to see the dataset belonging to the previous user
self.client.login(username="bobby", password="bob")
payload = self.client.get(url)
self.assertFalse(dataset.uuid in [k["uuid"] for k in payload.json()["resources"]])

# cleanup
dataset.delete()
test_user_for_api.delete()

def test_api_should_filter_by_advertised_param(self):
"""
If anonymous user, only the advertised resoruces whould be returned by the API.
"""
dts = create_single_dataset("advertised_false")
dts.advertised = False
dts.save()
# should show the result based on the logic
url = reverse("base-resources-list")
payload = self.client.get(url)
prev_count = payload.json().get("total")
# the user can see only the advertised resources
self.assertEqual(ResourceBase.objects.filter(advertised=True).count(), prev_count)

payload = self.client.get(f"{url}?advertised=True")
# so if advertised is True, we dont see the advertised=False resource
new_count = payload.json().get("total")
# recheck the count
self.assertEqual(new_count, prev_count)

payload = self.client.get(f"{url}?advertised=False")
# so if advertised is False, we see only the resource with advertised==False
new_count = payload.json().get("total")
# recheck the count
self.assertEqual(new_count, 1)

# if all is requested, we will see all the resources
payload = self.client.get(f"{url}?advertised=all")
new_count = payload.json().get("total")
# recheck the count
self.assertEqual(new_count, prev_count + 1)

Dataset.objects.update(advertised=True)


class TestExtraMetadataBaseApi(GeoNodeBaseTestSupport):
def setUp(self):
Expand Down
36 changes: 36 additions & 0 deletions geonode/base/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#
#########################################################################
import ast
from distutils.util import strtobool
import json
import re

Expand Down Expand Up @@ -372,6 +373,41 @@ def _filtered(self, request, filter):
serializer = ResourceBaseSerializer(result_page, embed=True, many=True)
return paginator.get_paginated_response({"resources": serializer.data})

def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())

# advertised
# if superuser, all resources will be visible, otherwise only the advertised once and
# the resource which the user is owner will be returned
# if the filter{advertised} is sent, is going to be used after the list of the
# resources is generated
user = request.user
try:
_filter = request.query_params.get("advertised", "None")
advertised = strtobool(_filter) if _filter.lower() != "all" else "all"
except Exception:
advertised = None

if advertised is not None and advertised != "all":
queryset = queryset.filter(advertised=advertised)
else:
is_admin = user.is_superuser if user and user.is_authenticated else False

if advertised == "all":
pass
elif not is_admin and user and not user.is_anonymous:
queryset = (queryset.filter(advertised=True) | queryset.filter(owner=user)).distinct()
elif not user or user.is_anonymous:
queryset = queryset.filter(advertised=True)

page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)

serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

@extend_schema(
methods=["get"],
responses={200: ResourceBaseSerializer(many=True)},
Expand Down
18 changes: 18 additions & 0 deletions geonode/base/migrations/0089_resourcebase_advertised.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.23 on 2024-01-16 14:18

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('base', '0088_auto_20231019_1244'),
]

operations = [
migrations.AddField(
model_name='resourcebase',
name='advertised',
field=models.BooleanField(default=True, help_text='If False, will hide the resource from search results and catalog listings', verbose_name='Advertised'),
),
]
6 changes: 5 additions & 1 deletion geonode/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,11 @@ class ResourceBase(PolymorphicModel, PermissionLevelMixin, ItemBase):
is_approved = models.BooleanField(
_("Approved"), default=True, help_text=_("Is this resource validated from a publisher or editor?")
)

advertised = models.BooleanField(
_("Advertised"),
default=True,
help_text=_("If False, will hide the resource from search results and catalog listings"),
)
# fields necessary for the apis
thumbnail_url = models.TextField(_("Thumbnail url"), null=True, blank=True)
thumbnail_path = models.TextField(_("Thumbnail path"), null=True, blank=True)
Expand Down
5 changes: 5 additions & 0 deletions geonode/documents/templates/layouts/doc_panels.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#mdeditor_form #id_resource-metadata_uploaded_preserve,
#mdeditor_form #id_resource-is_approved,
#mdeditor_form #id_resource-is_published,
#mdeditor_form #id_resource-advertised,
#mdeditor_form #id_resource-featured {
float: right;
}
Expand Down Expand Up @@ -649,6 +650,10 @@
{{ document_form.featured }}
</div>
{% endif %}
<div>
<span><label for="{{ document_form.advertised|id }}">{{ document_form.advertised.label }}</label></span>
{{ document_form.advertised }}
</div>
</div>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions geonode/geoapps/templates/layouts/app_panels.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#mdeditor_form #id_resource-metadata_uploaded_preserve,
#mdeditor_form #id_resource-is_approved,
#mdeditor_form #id_resource-is_published,
#mdeditor_form #id_resource-advertised,
#mdeditor_form #id_resource-featured {
float: right;
}
Expand Down Expand Up @@ -577,6 +578,10 @@
{{ geoapp_form.featured }}
</div>
{% endif %}
<div>
<span><label for="{{ geoapp_form.advertised|id }}">{{ geoapp_form.advertised.label }}</label></span>
{{ geoapp_form.advertised }}
</div>
</div>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions geonode/layers/templates/layouts/panels.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#mdeditor_form #id_resource-metadata_uploaded_preserve,
#mdeditor_form #id_resource-is_approved,
#mdeditor_form #id_resource-is_published,
#mdeditor_form #id_resource-advertised,
#mdeditor_form #id_resource-featured {
float: right;
}
Expand Down Expand Up @@ -702,6 +703,10 @@
{{ dataset_form.featured }}
</div>
{% endif %}
<div>
<span><label for="{{ dataset_form.advertised|id }}">{{ dataset_form.advertised.label }}</label></span>
{{ dataset_form.advertised }}
</div>
</div>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions geonode/maps/templates/layouts/map_panels.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#mdeditor_form #id_resource-metadata_uploaded_preserve,
#mdeditor_form #id_resource-is_approved,
#mdeditor_form #id_resource-is_published,
#mdeditor_form #id_resource-advertised,
#mdeditor_form #id_resource-featured {
float: right;
}
Expand Down Expand Up @@ -627,6 +628,10 @@
{{ map_form.featured }}
</div>
{% endif %}
<div>
<span><label for="{{ map_form.advertised|id }}">{{ map_form.advertised.label }}</label></span>
{{ map_form.advertised }}
</div>
</div>
</div>
</div>
Expand Down

0 comments on commit 5950784

Please sign in to comment.