Skip to content

Commit

Permalink
[Issue #6684] GNIP-78: GeoNode generic "Apps" model to include plugga…
Browse files Browse the repository at this point in the history
…ble entities into the framework (#6713)

* [Hardening] - Recenet Activity List for Documents error when actor is None

* [Frontend] Monitoring: Bump "node-sass" to version 4.14.1

* [Frontend] Bump jquery to version 3.5.1

* [Fixes: #6519] Bump jquery to 3.5.1 (#6526)

(cherry picked from commit e532813)

# Conflicts:
#	geonode/static/lib/css/assets.min.css
#	geonode/static/lib/css/bootstrap-select.css
#	geonode/static/lib/css/bootstrap-table.css
#	geonode/static/lib/js/assets.min.js
#	geonode/static/lib/js/bootstrap-select.js
#	geonode/static/lib/js/bootstrap-table.js
#	geonode/static/lib/js/leaflet-plugins.min.js
#	geonode/static/lib/js/leaflet.js
#	geonode/static/lib/js/moment-timezone-with-data.js
#	geonode/static/lib/js/underscore.js

* Merge branch 'master' of https://github.com/GeoNode/geonode into rest_api_v2_proof_of_concept

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.

* [Hardening] Re-create the map thumbnail only if it is missing

* Fixes error with GDAL 3.0.4 due to a breaking change on GDAL (https://code.djangoproject.com/ticket/30645)

* Fixes error with GDAL 3.0.4 due to a breaking change on GDAL (https://code.djangoproject.com/ticket/30645)

* - Introducing the concept of "GeoNode App" Resource Base

* [GeoApps] Add "Create new" Button to the apps list page

* [GeoApps] Hooking Resources List pages

* [GeoApps] Hooking GeoApp List page

* [GeoApps] Hooking GeoApp rest v2 API serializers fixes

* [GeoApps] Fix resourcebase_api polymorphic ctype filter

* [GeoApps] REST API v2 "geostories" endpoints optimizations

* [REST APIs V2] Make use of the new "bbox_polygon" field based on GeoDjango

* [Fixes RemoteServices bbox parse] Merge branch 'search-by-extent' of https://github.com/mtnorthcott/geonode

* [Fix migrations] Merge branch 'search-by-extent' of https://github.com/mtnorthcott/geonode

* [Fix migrations] Merge branch 'search-by-extent' of https://github.com/mtnorthcott/geonode

* [GeoApps] Adding "geoapp_edit" page

* [GeoApps] Adding "geoapp_edit" page context

* [GeoApps] Adding security info (access_token, user, ...) to the page context

* [GeoApps] Adding client endpoints

* [GeoApps] Missing "post_save" signal

* [GeoApps] Finalize GeoApp resources management

* Fix "bbox_to_projection" coords order

* Fix 'bbox_to_projection' coords order

* Fix "bbox_to_projection" coords order

(cherry picked from commit 72d6c1e)

* Fix "bbox_to_projection" coords order: check GDAL version >= 3.0.4

* Include missing 'mapstore2_adapter.geoapps' app to default INSTALLED_APPS

* Include mapstore client branch dependencies into requirements

* Revert security commit on branch

* Minor review of the current advanced resource workflow implementation #6551

* Minor review of the current advanced resource workflow implementation #6551

* Fix tests on Travis

* Fix tests on Travis

* Fix tests on Travis

* Fix tests on Travis

* Fix tests on Travis

(cherry picked from commit c7f651c)

# Conflicts:
#	geonode/layers/tests.py

* Fix logical errors on approval workflow

* Fix logical errors on approval workflow

(cherry picked from commit 7a3d5d0)

* Fix tests on Travis

* Cleanup "app_embed" template

* Advanced workflow: remove change_permissions to the owner if not a manager

* Advanced workflow: remove change_permissions to the owner if not a manager

(cherry picked from commit 9a1552a)

* Fix app_embed template

* Advanced workflow: remove change_permissions to the owner if not a manager

* Advanced workflow: remove change_permissions to the owner if not a manager

* Advanced workflow: remove change_permissions to the owner if not a manager

(cherry picked from commit f23096c)

* Advanced workflow: remove change_permissions to the owner if not a manager

(cherry picked from commit bfe51a7)

* Advanced workflow: remove change_permissions to the owner if not a manager

* Advanced workflow: remove change_permissions to the owner if not a manager

(cherry picked from commit d9ec566)

* Advanced workflow: filter actions stream returned to the users accordingly to their perms

* Advanced workflow: filter actions stream returned to the users accordingly to their perms

(cherry picked from commit 7f51346)

* Advanced workflow: filter actions stream returned to the users accordingly to their perms

* Add new settings from django-allauth 0.43.0

* Advanced workflow: filter actions stream returned to the users accordingly to their perms

(cherry picked from commit e2522fd)

* Add new settings from django-allauth 0.43.0

(cherry picked from commit 00f4be1)

* Code styling alerts: remove unnecessary pass

* Refreshing static libs

* Refreshing static libs

* Code styling alerts: remove unnecessary pass

(cherry picked from commit 0676f6e)

* Refreshing static libs

(cherry picked from commit f27d0df)

* Refreshing static libs

(cherry picked from commit 5b166bc)

* Advanced Workflow: Make sure the APIs counters are coherent with the visible resources

* Advanced Workflow: Make sure the APIs counters are coherent with the visible resources

(cherry picked from commit 1855d74)

* fix english/italian translations (#6563)

* fix english/italian translations (#6563)

* Advanced Workflow: fix "request editing" action when published

* Advanced Workflow: fix "request editing" action when published -> send messages to group managers too

* Advanced Workflow: fix "request editing" action when published

(cherry picked from commit 1041b12)

* Advanced Workflow: fix "request editing" action when published -> send messages to group managers too

(cherry picked from commit 5c93ef3)

* Fix test on travis

* fix english/italian translations (#6563)

* fix english/italian translations (#6563)

* fix english/italian translations (#6563)

* Avoid override User settings on "set_attributes_from_geoserver"

* - Docs links to 3.x branch

* Improve Celery Async Tasks configuration

(cherry picked from commit 50e208a)

* Improve Celery Async Tasks configuration

(cherry picked from commit d5150e8)

* Improve Celery Async Tasks configuration

(cherry picked from commit 50e208a)

* - Replace build.geo-solutions.it with www.dropbox.com

(cherry picked from commit 882e3e5)
(cherry picked from commit 7b970f8)

* [Security] Hardening Advanced Workflow resources visibility

(cherry picked from commit 2103f13)
(cherry picked from commit 025c82e)

* [Hardening] Removing redundant and replacement of instance abstract from GeoServer

* Bump drf-yasg from 1.17.1 to 1.20.0

* [Hardening] Fixes: db connection closed and worker hangs with celery 4.2+ celery/celery#4878

* [Hardening] Optimizing celery tasks settings

* [Hardening] Optimizing celery tasks settings

* - Documents REST v2 APIs

* [Fixes #6596] Incorrect Legend displayed in the layer detail page

(cherry picked from commit 0aa6902)

* [Fixes #6596] Incorrect Legend displayed in the layer detail page

(cherry picked from commit 0aa6902)

* - Update travis dist to '20.04 focal'

* - Fix geolimits panel translations

* - Filter Comments on Recent Activities accordingly to the user's perms

* [Hardening] Remove wrong class initializer

* [Hardening] LGTM warning fixes

* [CI Optimizations] - Continuous integration builders: CircleCI config based on "spcgeonode" docker-compose

(cherry picked from commit 7f091a7)

* - Enable "memcached" plugins for monitoring

* - Extend "documents" to accept and render video, audio and more image formats

 - Add "attribution" field to ResourceBase model

* - Generating documents thumbnails for video and audio mime types

(cherry picked from commit d1f4251)
(cherry picked from commit 5c89762)

* - Merge with master branch

* - Generating documents thumbnails for video and audio mime types

(cherry picked from commit 197c7ab)

* - Fixing doc image thumn generation

* - Updating translations

* - expose documents 'href' from REST serializer API endpoint

* [Hardening] - expose **secured** documents 'href' from REST serializer API endpoint

* [Hardening] - generate **secured** thumbnail for uploaded images

* - Restore missing list key on GXP_PTYPES enumeration

(cherry picked from commit 2352613)

* [FIX #6626] add tinymce editor to resource text areas

(cherry picked from commit 45bb0dc)

* [FIX #6626] add tinymce editor to resource text areas

(cherry picked from commit 45bb0dc)

* [Hardening] Correctly manage "_resolve_object" exception as Django error templates

(cherry picked from commit 017d885)

# Conflicts:
#	geonode/views.py

* - Remove wrong migration

* [Hardening] Using "apply_async" instead of "delay" for async signals calls

* [Hardening] Avoid exit prematurely from geoserver cascading delete signal

* Fix travis tests

* [Fixes #5779] Data edition permissions set in GeoNode for a layer are not applied on the WFS

(cherry picked from commit 9e4e839)

* - Cleaning up wrong migrations

* [Performance] - Improve Style editing requests callbacks

* [Performance] - Transform "geoserver_post_save_layers" to an asynchronous task

* [Performance] - Improve Style editing requests callbacks

* [Optimization] Improve 'navbar' content reposition script

* [Performance] - Transform "geoserver_post_save_layers" to an asynchronous task

* [Performance] - Improve Style editing requests callbacks

* FIXES[#6653] Mail notifications for private datasets are public

* - exclude query optimization

* [Performance] Dinamically loading the list of users geo-limits

(cherry picked from commit c54cc61)
(cherry picked from commit 756c1aa)

* [Fixes: #6640] Style Tag outside of html (#6657)

* [Minor Layout Issue] - Missing title on "map list" page

(cherry picked from commit 971e65f)

* added Document Creation Fallback, fixed exclude_user_ids.append()

* - Correct "geoapps" notification types

* - Fix remaining issues: 1. Layer create does no send "title" before sending notifications - 2. Doc created does not set "permissions" before sending notifications

* Typo: _QUEUE_ALL_FLAG

* Typo: _QUEUE_ALL_FLAG

(cherry picked from commit 8d9118f)

* - Fix asynchronous notification engine task

* - Fix asynchronous notification engine task

(cherry picked from commit 79274eb)

* - Do not send notifications if the resource has no title

* - Do not send notifications if the resource has no title

(cherry picked from commit c3d470e)

* - Asynchronous "probe" task for Remote Services

* [FIXES #6653] Mail notifications for private datasets are public

* - Fixes rating notifications

* - Fixes rating notifications

(cherry picked from commit b814692)

* - Fixes "guardian.exceptions.ObjectNotPersisted: Object None needs to be persisted first" exception on "set_workflow_perms" calls

* - Fixes "guardian.exceptions.ObjectNotPersisted: Object None needs to be persisted first" exception on "set_workflow_perms" calls

(cherry picked from commit fe35d46)

* - Fixes "guardian.exceptions.ObjectNotPersisted: Object None needs to be persisted first" exception on "set_workflow_perms" calls

* - Fixes "guardian.exceptions.ObjectNotPersisted: Object None needs to be persisted first" exception on "set_workflow_perms" calls

(cherry picked from commit dee7de1)

* - Fix LGTM issues

* - Fix LGTM issues

(cherry picked from commit 08644a6)

* - Fix LGTM issues

* - Fix LGTM issues

(cherry picked from commit df112c8)

* no notifications for resource owner, except for comments. PEP 8 reformatting

* resource owners will get notified on updates of their resources

* [Fixes #6665] Improve WYSIWYG metadata editor to store formatted and plain texts

* - Travis test-cases: "ensure owner won't be notified on upload"

* [Hardening] Do not fail in case of datastore with multiple geometries

* - Minor refactoring and clean out of the "geoserver_post_save_layers" task body

* [Hardening] Make "set_attributes" method more resilient to "Attribute.MultipleObjectsReturned" exception

* [Hardening] Make "helpers" methods more resilient to "Layer.MultipleObjectsReturned" and "Layer.DoesNotExist" exceptions

* - Minor environmnet params improvements. Exposing DB connection timeouts to .env

* - Explicit error codes along with description on Layer Upload form

* [Transaltions] - Explicit error codes along with description on Layer Upload form

* [Transaltions] - Explicit error codes along with description on Layer Upload form

(cherry picked from commit 395089e)

# Conflicts:
#	geonode/static/geonode/js/upload/LayerInfo.js
(cherry picked from commit f62b69a)

* [Docker] Use local nginx build

* Merge branch 'master' of https://github.com/GeoNode/geonode into rest_api_v2_geonode_apps

* [Hardening] More resiliet to 'missing thumbnail' on filesystem issues

* - GeoApp Test Cases

* - Typo

* - Update mapstore client and adapter versions

* - Set local .sh files exec perms

* - Bump pycsw to version 2.6.0

* - Bump pycsw to version 2.6.0

* - Bump pycsw to version 2.6.0

* - Align "setup.cfg" to "requirements.txt"

* - Fix travis

Co-authored-by: Toni <toni.schoenbuchner@csgis.de>
Co-authored-by: Piotr Dankowski <dankowski.revolve@gmail.com>
Co-authored-by: Florian Hoedt <gannebamm@gmail.com>
  • Loading branch information
4 people authored Dec 10, 2020
1 parent 6527b05 commit f554424
Show file tree
Hide file tree
Showing 56 changed files with 3,236 additions and 23 deletions.
41 changes: 37 additions & 4 deletions geonode/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import json
import time

from django.apps import apps
from django.db.models import Q
from django.conf.urls import url
from django.contrib.auth import get_user_model
Expand Down Expand Up @@ -52,6 +53,7 @@
from geonode.base.models import ThesaurusKeywordLabel
from geonode.layers.models import Layer, Style
from geonode.maps.models import Map
from geonode.geoapps.models import GeoApp
from geonode.documents.models import Document
from geonode.groups.models import GroupProfile, GroupCategory
from django.core.serializers.json import DjangoJSONEncoder
Expand All @@ -67,7 +69,8 @@
FILTER_TYPES = {
'layer': Layer,
'map': Map,
'document': Document
'document': Document,
'geoapp': GeoApp
}


Expand All @@ -90,19 +93,37 @@ def get_resources_counts(self, options):
unpublished_not_visible=settings.RESOURCE_PUBLISHING,
private_groups_not_visibile=settings.GROUP_PRIVATE_RESOURCES)

subtypes = []
if resources and resources.count() > 0:
if options['title_filter']:
resources = resources.filter(title__icontains=options['title_filter'])

if options['type_filter']:
_type_filter = options['type_filter']

for label, app in apps.app_configs.items():
if hasattr(app, 'type') and app.type == 'GEONODE_APP':
if hasattr(app, 'default_model'):
_model = apps.get_model(label, app.default_model)
if issubclass(_model, _type_filter):
subtypes.append(
resources.filter(
polymorphic_ctype__model=_model.__name__.lower()))

if not isinstance(_type_filter, str):
_type_filter = _type_filter.__name__.lower()
resources = resources.filter(polymorphic_ctype__model=_type_filter)

counts = list(resources.values(options['count_type']).annotate(count=Count(options['count_type'])))
counts = list()
if subtypes:
for subtype in subtypes:
counts.append(
subtype.values(options['count_type']).annotate(count=Count(options['count_type'])).first()
)
else:
counts = list(resources.values(options['count_type']).annotate(count=Count(options['count_type'])))

return dict([(c[options['count_type']], c['count']) for c in counts])
return dict(
[(c[options['count_type']], c['count']) for c in counts if c and c['count'] and options['count_type']])

def to_json(self, data, options=None):
options = options or {}
Expand Down Expand Up @@ -869,8 +890,18 @@ def _get_resource_counts(request, resourcebase_filter_kwargs):
'layer',
'document',
'map',
'geoapp',
'all'
]

subtypes = []
for label, app in apps.app_configs.items():
if hasattr(app, 'type') and app.type == 'GEONODE_APP':
if hasattr(app, 'default_model'):
_model = apps.get_model(label, app.default_model)
if issubclass(_model, GeoApp):
types.append(_model.__name__.lower())
subtypes.append(_model.__name__.lower())
counts = {}
for type_ in types:
counts[type_] = {
Expand All @@ -881,6 +912,8 @@ def _get_resource_counts(request, resourcebase_filter_kwargs):
}
for record in qs:
resource_type = record['polymorphic_ctype__model']
if resource_type in subtypes:
resource_type = 'geoapp'
is_visible = all((record['is_approved'], record['is_published']))
counts['all']['total'] += record['counts']
counts['all']['visible'] += record['counts'] if is_visible else 0
Expand Down
66 changes: 66 additions & 0 deletions geonode/api/resourcebase_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
from geonode import get_version, qgis_server, geoserver
from geonode.layers.models import Layer
from geonode.maps.models import Map
from geonode.geoapps.models import GeoApp
from geonode.documents.models import Document
from geonode.base.models import ResourceBase
from geonode.base.models import HierarchicalKeyword
Expand Down Expand Up @@ -165,6 +166,8 @@ def build_filters(self, filters=None, ignore_bad_filters=False, **kwargs):
filters=filters, ignore_bad_filters=ignore_bad_filters, **kwargs)
if 'type__in' in filters and filters['type__in'] in FILTER_TYPES.keys():
orm_filters.update({'type': filters.getlist('type__in')})
if 'app_type__in' in filters:
orm_filters.update({'polymorphic_ctype__model': filters['app_type__in'].lower()})
if 'extent' in filters:
orm_filters.update({'extent': filters['extent']})
orm_filters['f_method'] = filters['f_method'] if 'f_method' in filters else 'and'
Expand Down Expand Up @@ -1016,6 +1019,69 @@ class Meta(CommonMetaApi):
GeonodeApiKeyAuthentication())


class GeoAppResource(CommonModelApi):

"""GeoApps API"""

def format_objects(self, objects):
"""
Formats the objects and provides reference to list of layers in GeoApp
resources.
:param objects: GeoApp objects
"""
formatted_objects = []
for obj in objects:
# convert the object to a dict using the standard values.
formatted_obj = model_to_dict(obj, fields=self.VALUES)
username = obj.owner.get_username()
full_name = (obj.owner.get_full_name() or username)
formatted_obj['owner__username'] = username
formatted_obj['owner_name'] = full_name
if obj.category:
formatted_obj['category__gn_description'] = obj.category.gn_description
if obj.group:
formatted_obj['group'] = obj.group
try:
formatted_obj['group_name'] = GroupProfile.objects.get(slug=obj.group.name)
except GroupProfile.DoesNotExist:
formatted_obj['group_name'] = obj.group

formatted_obj['keywords'] = [k.name for k in obj.keywords.all()] if obj.keywords else []
formatted_obj['regions'] = [r.name for r in obj.regions.all()] if obj.regions else []

if 'site_url' not in formatted_obj or len(formatted_obj['site_url']) == 0:
formatted_obj['site_url'] = settings.SITEURL

# Probe Remote Services
formatted_obj['store_type'] = 'geoapp'
formatted_obj['online'] = True

# replace thumbnail_url with curated_thumbs
try:
if hasattr(obj, 'curatedthumbnail'):
if hasattr(obj.curatedthumbnail.img_thumbnail, 'url'):
formatted_obj['thumbnail_url'] = obj.curatedthumbnail.thumbnail_url
else:
formatted_obj['thumbnail_url'] = ''
except Exception as e:
formatted_obj['thumbnail_url'] = ''
logger.exception(e)

formatted_objects.append(formatted_obj)
return formatted_objects

class Meta(CommonMetaApi):
paginator_class = CrossSiteXHRPaginator
filtering = CommonMetaApi.filtering
filtering.update({'app_type': ALL})
queryset = GeoApp.objects.distinct().order_by('-date')
resource_name = 'geoapps'
authentication = MultiAuthentication(SessionAuthentication(),
OAuthAuthentication(),
GeonodeApiKeyAuthentication())


class DocumentResource(CommonModelApi):

"""Documents API"""
Expand Down
1 change: 1 addition & 0 deletions geonode/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
api.register(resourcebase_resources.FeaturedResourceBaseResource())
api.register(resourcebase_resources.LayerResource())
api.register(resourcebase_resources.MapResource())
api.register(resourcebase_resources.GeoAppResource())
api.register(resourcebase_resources.ResourceBaseResource())

router = routers.DynamicRouter()
Expand Down
8 changes: 8 additions & 0 deletions geonode/base/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@
logger = logging.getLogger(__name__)


class ResourceBaseTypesSerializer(DynamicEphemeralSerializer):

class Meta:
name = 'resource-type'

resource_types = serializers.ListField()


class PermSpecSerialiazer(DynamicEphemeralSerializer):

class Meta:
Expand Down
64 changes: 60 additions & 4 deletions geonode/base/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,11 @@ def test_base_resources(self):
# Pagination
self.assertEqual(len(response.data['resources']), 17)

# Search
def test_search_resources(self):
"""
Ensure we can search across the Resource Base list.
"""
url = reverse('base-resources-list')
# Admin
self.assertTrue(self.client.login(username='admin', password='admin'))

Expand All @@ -209,7 +213,11 @@ def test_base_resources(self):
# Pagination
self.assertEqual(len(response.data['resources']), 1)

# Filtering
def test_filter_resources(self):
"""
Ensure we can filter across the Resource Base list.
"""
url = reverse('base-resources-list')
# Admin
self.assertTrue(self.client.login(username='admin', password='admin'))

Expand Down Expand Up @@ -297,7 +305,11 @@ def test_base_resources(self):
# Pagination
self.assertEqual(len(response.data['resources']), 12)

# Sorting
def test_sort_resources(self):
"""
Ensure we can sort the Resource Base list.
"""
url = reverse('base-resources-list')
# Admin
self.assertTrue(self.client.login(username='admin', password='admin'))

Expand Down Expand Up @@ -330,7 +342,11 @@ def test_base_resources(self):
reversed_resource_titles = sorted(resource_titles.copy())
self.assertNotEqual(resource_titles, reversed_resource_titles)

# Get & Set Permissions
def test_perms_resources(self):
"""
Ensure we can Get & Set Permissions across the Resource Base list.
"""
url = reverse('base-resources-list')
# Admin
self.assertTrue(self.client.login(username='admin', password='admin'))

Expand Down Expand Up @@ -371,3 +387,43 @@ def test_base_resources(self):
self.assertEqual(response.status_code, 200)
resource_perm_spec = response.data
self.assertFalse('norman' in resource_perm_spec['users'])

def test_featured_and_published_resources(self):
"""
Ensure we can Get & Set Permissions across the Resource Base list.
"""
url = reverse('base-resources-list')
# Admin
self.assertTrue(self.client.login(username='admin', password='admin'))

resources = ResourceBase.objects.filter(owner__username='bobby')

url = urljoin(f"{reverse('base-resources-list')}/", 'featured/')
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 5)
self.assertEqual(response.data['total'], 0)
# Pagination
self.assertEqual(len(response.data['resources']), 0)

resources.filter(resource_type='map').update(featured=True)
url = urljoin(f"{reverse('base-resources-list')}/", 'featured/')
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.data), 5)
self.assertEqual(response.data['total'], 2)
# Pagination
self.assertEqual(len(response.data['resources']), 2)

def test_resource_types(self):
"""
Ensure we can Get & Set Permissions across the Resource Base list.
"""
url = urljoin(f"{reverse('base-resources-list')}/", 'resource_types/')
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, 200)
self.assertTrue('resource_types' in response.data)
self.assertTrue('layer' in response.data['resource_types'])
self.assertTrue('map' in response.data['resource_types'])
self.assertTrue('document' in response.data['resource_types'])
self.assertTrue('service' in response.data['resource_types'])
2 changes: 1 addition & 1 deletion geonode/base/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@

router.register(r'users', views.UserViewSet, 'users')
router.register(r'groups', views.GroupViewSet, 'group-profiles')
router.register(r'base_resources', views.ResourceBaseViewSet, 'base-resources')
router.register(r'resources', views.ResourceBaseViewSet, 'base-resources')

urlpatterns = []
69 changes: 68 additions & 1 deletion geonode/base/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#########################################################################
from django.apps import apps
from django.conf import settings
from django.contrib.auth import get_user_model

Expand Down Expand Up @@ -45,7 +46,8 @@
UserSerializer,
PermSpecSerialiazer,
GroupProfileSerializer,
ResourceBaseSerializer
ResourceBaseSerializer,
ResourceBaseTypesSerializer
)
from .pagination import GeoNodeApiPagination

Expand Down Expand Up @@ -145,6 +147,71 @@ class ResourceBaseViewSet(DynamicModelViewSet):
serializer_class = ResourceBaseSerializer
pagination_class = GeoNodeApiPagination

def _filtered(self, request, filter):
paginator = GeoNodeApiPagination()
paginator.page_size = request.GET.get('page_size', 10)
resources = ResourceBase.objects.filter(**filter)
exclude = []
for resource in resources:
if not request.user.is_superuser and \
not request.user.has_perm('view_resourcebase', resource.get_self_resource()):
exclude.append(resource.id)
resources = resources.exclude(id__in=exclude)
result_page = paginator.paginate_queryset(resources, request)
serializer = ResourceBaseSerializer(result_page, embed=True, many=True)
return paginator.get_paginated_response({"resources": serializer.data})

@extend_schema(methods=['get'], responses={200: ResourceBaseSerializer(many=True)},
description="API endpoint allowing to retrieve the approved Resources.")
@action(detail=False, methods=['get'])
def approved(self, request):
return self._filtered(request, {"is_approved": True})

@extend_schema(methods=['get'], responses={200: ResourceBaseSerializer(many=True)},
description="API endpoint allowing to retrieve the published Resources.")
@action(detail=False, methods=['get'])
def published(self, request):
return self._filtered(request, {"is_published": True})

@extend_schema(methods=['get'], responses={200: ResourceBaseSerializer(many=True)},
description="API endpoint allowing to retrieve the featured Resources.")
@action(detail=False, methods=['get'])
def featured(self, request):
return self._filtered(request, {"featured": True})

@extend_schema(methods=['get'], responses={200: ResourceBaseTypesSerializer()},
description="""
Returns the list of available ResourceBase polymorphic_ctypes.
the mapping looks like:
```
{
"resource_types": [
"layer",
"map",
"document",
"service"
]
}
```
""")
@action(detail=False, methods=['get'])
def resource_types(self, request):
resource_types = []
for _model in apps.get_models():
if _model.__name__ == "ResourceBase":
resource_types = [_m.__name__.lower() for _m in _model.__subclasses__()]
if "geoapp" in resource_types:
from geonode.geoapps.models import GeoApp
resource_types.remove("geoapp")
for label, app in apps.app_configs.items():
if hasattr(app, 'type') and app.type == 'GEONODE_APP':
if hasattr(app, 'default_model'):
_model = apps.get_model(label, app.default_model)
if issubclass(_model, GeoApp):
resource_types.append(_model.__name__.lower())
return Response({"resource_types": resource_types})

@extend_schema(methods=['get'], responses={200: PermSpecSerialiazer()},
description="""
Gets an object's the permission levels based on the perm_spec JSON.
Expand Down
Loading

0 comments on commit f554424

Please sign in to comment.