Skip to content

Commit

Permalink
Merge branch '4.2.x' of github.com:GeoNode/geonode into 4.2.x
Browse files Browse the repository at this point in the history
  • Loading branch information
jdonlucas committed Aug 15, 2024
2 parents 8f8ab97 + 5a3576d commit 6c7cced
Show file tree
Hide file tree
Showing 17 changed files with 153 additions and 53 deletions.
2 changes: 1 addition & 1 deletion docker-compose-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: '3.9'
# Common Django template for GeoNode and Celery services below
x-common-django:
&default-common-django
image: geonode/geonode:local
image: geonode/geonode:4.2.5
build:
context: ./
dockerfile: Dockerfile
Expand Down
10 changes: 5 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ version: '3.9'
# Common Django template for GeoNode and Celery services below
x-common-django:
&default-common-django
image: geonode/geonode:4.2.3
build:
context: ./
dockerfile: Dockerfile
image: geonode/geonode:4.2.5
#build:
# context: ./
# dockerfile: Dockerfile
restart: unless-stopped
env_file:
- .env
Expand Down Expand Up @@ -118,7 +118,7 @@ services:
condition: service_healthy

data-dir-conf:
image: geonode/geoserver_data:2.24.2-v1
image: geonode/geoserver_data:2.24.2-v2
container_name: gsconf4${COMPOSE_PROJECT_NAME}
entrypoint: sleep infinity
volumes:
Expand Down
2 changes: 1 addition & 1 deletion geonode/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import os

__version__ = (4, 2, 3, "final", 0)
__version__ = (4, 2, 6, "dev", 0)


default_app_config = "geonode.apps.AppConfig"
Expand Down
6 changes: 3 additions & 3 deletions geonode/base/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1951,10 +1951,10 @@ def test_set_resource_thumbnail(self):
self.assertEqual(response.json(), "The url must be of an image with format (png, jpeg or jpg)")

# using Base64 data as an ASCII byte string
data["file"] = (
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\
data[
"file"
] = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAABHNCSVQICAgI\
fAhkiAAAABl0RVh0U29mdHdhcmUAZ25vbWUtc2NyZWVuc2hvdO8Dvz4AAAANSURBVAiZYzAxMfkPAALYAZzx61+bAAAAAElFTkSuQmCC"
)
with patch("geonode.base.models.is_monochromatic_image") as _mck:
_mck.return_value = False
response = self.client.put(url, data=data, format="json")
Expand Down
1 change: 0 additions & 1 deletion geonode/base/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,6 @@ def linked_resources(self, request, pk, *args, **kwargs):


def base_linked_resources(instance, user, params):

try:
resource_type = params.get("resource_type")
link_type = params.get("link_type")
Expand Down
11 changes: 7 additions & 4 deletions geonode/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1707,8 +1707,7 @@ def set_contact_roles_from_metadata_edit(self, resource_base_form) -> bool:
failed = False
for role in self.get_multivalue_role_property_names():
try:
if resource_base_form.cleaned_data[role].exists():
self.__setattr__(role, resource_base_form.cleaned_data[role])
self.__setattr__(role, resource_base_form.cleaned_data[role])
except AttributeError:
logger.warning(f"unable to set contact role {role} for {self} ...")
failed = True
Expand Down Expand Up @@ -1753,9 +1752,13 @@ def __create_role__(
ContactRole.objects.filter(role=role, resource=self).delete()
return __create_role__(self, role, user_profile)

elif isinstance(user_profile, list) and all(isinstance(x, get_user_model()) for x in user_profile):
elif isinstance(user_profile, list) and all(
get_user_model().objects.filter(username=x).exists() for x in user_profile
):
ContactRole.objects.filter(role=role, resource=self).delete()
return [__create_role__(self, role, profile) for profile in user_profile]
return [
__create_role__(self, role, user) for user in get_user_model().objects.filter(username__in=user_profile)
]

elif user_profile is None:
ContactRole.objects.filter(role=role, resource=self).delete()
Expand Down
12 changes: 6 additions & 6 deletions geonode/base/widgets.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import List

from dal_select2_taggit.widgets import TaggitSelect2
from django.http.request import QueryDict


class TaggitSelect2Custom(TaggitSelect2):
Expand Down Expand Up @@ -32,9 +33,8 @@ def value_from_datadict(self, data, files, name) -> List[str]:
returns list of selected elements
"""
try:
ret_list = data[name]
except KeyError:
ret_list = []
finally:
return ret_list
if type(data) is dict and name in data:
return data[name]
elif type(data) is QueryDict:
return data.getlist(name)
return []
16 changes: 0 additions & 16 deletions geonode/documents/templates/layouts/doc_panels.html
Original file line number Diff line number Diff line change
Expand Up @@ -596,22 +596,6 @@
</div>
</div>
{% endblock document_more_contact_roles %}

<div class="panel panel-default">
<div class="panel-heading">{% trans "Responsible and Permissions" %}</div>
<div class="panel-body">
<div>
<span><label for="{{ document_form.owner|id }}">{{ document_form.owner.label }}</label></span>
<!--<p class="xxs-font-size">(Responsible of the cited resource)</p>-->
{{ document_form.owner }}
</div>
<div>
<span><label for="{{ document_form.metadata_author|id }}">{{ document_form.metadata_author.label }}</label></span>
<!--<p class="xxs-font-size">(Author of the metadata)</p>-->
{{ document_form.metadata_author }}
</div>
</div>
</div>
<!--End Contact Roles -->
</div>
</div>
Expand Down
6 changes: 0 additions & 6 deletions geonode/geoapps/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ def extra_create_checks(self, validated_data):

self.extra_update_checks(validated_data)

def validate(self, data):
request = self.context.get("request")
if request:
data["owner"] = request.user
return data

def _sanitize_validated_data(self, validated_data, instance=None):
# Extract users' profiles
_user_profiles = {}
Expand Down
45 changes: 45 additions & 0 deletions geonode/geoapps/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,3 +205,48 @@ def test_create_checks_duplicated(self):
self.assertEqual(exp.exception.category, "geoapp_api")
self.assertEqual(exp.exception.default_code, "geoapp_exception")
self.assertEqual(str(exp.exception.detail), "A GeoApp with the same 'name' already exists!")

def test_geoapp_creation_owner_is_mantained(self):
"""
https://github.com/GeoNode/geonode/issues/12261
The geoapp owner should be mantained even if another
user save the instance.
"""

url = f"{reverse('geoapps-list')}?include[]=data"
data = {
"name": "Test Create",
"title": "Test Create",
"resource_type": "geostory",
"extent": {"coords": [1123692.0, 5338214.0, 1339852.0, 5482615.0], "srid": "EPSG:3857"},
}

self.assertTrue(self.client.login(username="norman", password="norman"))

response = self.client.post(url, data=data, format="json")

self.assertEqual(201, response.status_code)
# let's check that the owner is the request one
self.assertEqual("norman", response.json()["geoapp"]["owner"]["username"])

# let's change the user of the request
self.assertTrue(self.client.login(username="admin", password="admin"))

sut = GeoApp.objects.get(pk=response.json()["geoapp"]["pk"])
# Update: PATCH
# we ensure that norman is the resource owner
self.assertEqual("norman", sut.owner.username)

url = reverse("geoapps-detail", kwargs={"pk": sut.pk})
data = {"blob": {"test_data": {"test": ["test_4", "test_5", "test_6"]}}}
# sending the update of the geoapp
response = self.client.patch(url, data=json.dumps(data), content_type="application/json")

self.assertEqual(response.status_code, 200)

# ensure that the value of the owner is not changed
sut.refresh_from_db()
self.assertEqual("norman", sut.owner.username)

# cleanup
sut.delete()
8 changes: 8 additions & 0 deletions geonode/geoapps/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,11 @@ class GeoAppViewSet(DynamicModelViewSet):
queryset = GeoApp.objects.all().order_by("-created")
serializer_class = GeoAppSerializer
pagination_class = GeoNodeApiPagination

def perform_create(self, serializer):
"""
The owner is not passed from the FE
so we force the request.user to be the owner
in creation
"""
return serializer.save(owner=self.request.user)
14 changes: 12 additions & 2 deletions geonode/resource/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,12 @@ def _safe_assign_perm(perm, user_or_group, obj=None):
)
else:
for user_group in get_user_groups(_owner):
if not skip_registered_members_common_group(user_group):
# if AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() is False,
# means that at least one config of the advanced workflow is set, which means that users group get view_permissions
if (
not skip_registered_members_common_group(user_group)
and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow()
):
_safe_assign_perm("view_resourcebase", user_group, _resource.get_self_resource())
_prev_perm = (
_perm_spec["groups"].get(user_group, []) if "groups" in _perm_spec else []
Expand All @@ -883,7 +888,12 @@ def _safe_assign_perm(perm, user_or_group, obj=None):
)
else:
for user_group in get_user_groups(_owner):
if not skip_registered_members_common_group(user_group):
# if AdvancedSecurityWorkflowManager.is_auto_publishing_workflow() is False,
# means that at least one config of the advanced workflow is set, which means that users group get view_permissions
if (
not skip_registered_members_common_group(user_group)
and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow()
):
_safe_assign_perm(
"download_resourcebase", user_group, _resource.get_self_resource()
)
Expand Down
14 changes: 12 additions & 2 deletions geonode/security/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,25 @@ def set_default_permissions(self, owner=None, created=False):
perm_spec["groups"][anonymous_group] = ["view_resourcebase"]
else:
for user_group in user_groups:
if not skip_registered_members_common_group(user_group):
# if aswm.is_auto_publishing_workflow() is False, means that at least one config of the advanced workflow
# is set, which means that users group get view_permissions
if (
not skip_registered_members_common_group(user_group)
and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow()
):
perm_spec["groups"][user_group] = ["view_resourcebase"]

anonymous_can_download = settings.DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION
if anonymous_can_download:
perm_spec["groups"][anonymous_group] = ["view_resourcebase", "download_resourcebase"]
else:
for user_group in user_groups:
if not skip_registered_members_common_group(user_group):
# if aswm.is_auto_publishing_workflow() is False, means that at least one config of the advanced workflow
# is set, which means that users group get view_permissions
if (
not skip_registered_members_common_group(user_group)
and not AdvancedSecurityWorkflowManager.is_auto_publishing_workflow()
):
perm_spec["groups"][user_group] = ["view_resourcebase", "download_resourcebase"]

AdvancedSecurityWorkflowManager.handle_moderated_uploads(self.uuid, instance=self)
Expand Down
48 changes: 48 additions & 0 deletions geonode/security/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import json
import base64
import logging
import uuid
import requests
import importlib
import mock
Expand Down Expand Up @@ -2267,6 +2268,53 @@ def test_permissions_on_user_role_promote_to_manager_only_RESOURCE_PUBLISHING_ac
set(expected_perms), set(perms_got), msg=f"use case #0 - user: {authorized_subject.username}"
)

@override_settings(DEFAULT_ANONYMOUS_VIEW_PERMISSION=False)
def test_if_anonymoys_default_perms_is_false_should_not_assign_perms_to_user_group(self):
"""
if DEFAULT_ANONYMOUS_VIEW_PERMISSION is False, the user's group should not get any permission
"""

resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member})
self.assertFalse(self.group_profile.group in resource.get_all_level_info()["groups"].keys())

@override_settings(DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=False)
def test_if_anonymoys_default_download_perms_is_false_should_not_assign_perms_to_user_group(self):
"""
if DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION is False, the user's group should not get any permission
"""

resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member})
self.assertFalse(self.group_profile.group in resource.get_all_level_info()["groups"].keys())

@override_settings(DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=False)
@override_settings(RESOURCE_PUBLISHING=True)
def test_if_anonymoys_default_perms_is_false_should_assign_perms_to_user_group_if_advanced_workflow_is_on(self):
"""
if DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION is False and the advanced workflow is activate
the user's group should get the view and download permission
"""

resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member})
self.assertTrue(self.group_profile.group in resource.get_all_level_info()["groups"].keys())
group_val = resource.get_all_level_info()["groups"][self.group_profile.group]
self.assertSetEqual({"view_resourcebase", "download_resourcebase"}, set(group_val))

@override_settings(DEFAULT_ANONYMOUS_VIEW_PERMISSION=False)
@override_settings(ADMIN_MODERATE_UPLOADS=True)
def test_if_anonymoys_default_perms_is_false_should_assign_perms_to_user_group_if_advanced_workflow_is_on_moderate(
self,
):
"""
if DEFAULT_ANONYMOUS_VIEW_PERMISSION is False and the advanced workflow is activate
the user's group should get the view and download permission
"""

resource = resource_manager.create(str(uuid.uuid4), Dataset, defaults={"owner": self.group_member})

self.assertTrue(self.group_profile.group in resource.get_all_level_info()["groups"].keys())
group_val = resource.get_all_level_info()["groups"][self.group_profile.group]
self.assertSetEqual({"view_resourcebase", "download_resourcebase"}, set(group_val))


@override_settings(RESOURCE_PUBLISHING=True)
@override_settings(ADMIN_MODERATE_UPLOADS=True)
Expand Down
3 changes: 1 addition & 2 deletions geonode/security/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ def get_geoapp_subtypes():


def skip_registered_members_common_group(user_group):
_members_group_name = groups_settings.REGISTERED_MEMBERS_GROUP_NAME
if (settings.RESOURCE_PUBLISHING or settings.ADMIN_MODERATE_UPLOADS) and _members_group_name == user_group.name:
if groups_settings.REGISTERED_MEMBERS_GROUP_NAME == user_group.name:
return True
return False

Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ pinax-notifications==6.0.0
pinax-ratings==4.0.0

# GeoNode org maintained apps.
django-geonode-mapstore-client==4.2.0
geonode-importer==1.0.8
-e git+https://github.com/GeoNode/geonode-mapstore-client.git@4.2.x#egg=django_geonode_mapstore_client
-e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer
django-avatar==7.1.1
geonode-oauth-toolkit==2.2.2
geonode-user-messages==2.0.2
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ install_requires =
pinax-ratings==4.0.0

# GeoNode org maintained apps.
django-geonode-mapstore-client==4.2.0
geonode-importer==1.0.8
django-geonode-mapstore-client>=4.2.0,<5.0.0
geonode-importer>=1.0.8
django-avatar==7.1.1
geonode-oauth-toolkit==2.2.2
geonode-user-messages==2.0.2
Expand Down

0 comments on commit 6c7cced

Please sign in to comment.