Skip to content

Commit

Permalink
[Fixes GeoNode#12594] Error when saving a new map (GeoNode#12595)
Browse files Browse the repository at this point in the history
* Fix maps creation issue

* Fix maps creation issue

* [Fixes GeoNode#12594] Error when saing a new map

* [Fixes GeoNode#12594] Error when saing a new map

* [Fixes GeoNode#12594] Error when saing a new map

* [Fixes GeoNode#12594] Error when saing a new map

* [Fixes GeoNode#12594] Error when saing a new map

* [Fixes GeoNode#12594] Error when saing a new map
  • Loading branch information
mattiagiupponi authored Sep 26, 2024
1 parent 32f1cbc commit 30b84a2
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 35 deletions.
35 changes: 16 additions & 19 deletions geonode/base/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,22 +552,6 @@ def to_representation(self, instance):
return ret


class ResourceManagementField(serializers.BooleanField):
MAPPING = {"is_approved": "can_approve", "is_published": "can_publish", "featured": "can_feature"}

def to_internal_value(self, data):
new_val = super().to_internal_value(data)
user = self.context["request"].user
user_action = self.MAPPING.get(self.field_name)
instance = self.root.instance or ResourceBase.objects.get(pk=self.root.initial_data["pk"])
if getattr(user, user_action)(instance):
logger.debug("User can perform the action, the new value is returned")
return new_val
else:
logger.warning(f"The user does not have the perms to update the value of {self.field_name}")
return getattr(instance, self.field_name)


class ResourceBaseSerializer(DynamicModelSerializer):
pk = serializers.CharField(read_only=True)
uuid = serializers.CharField(read_only=True)
Expand Down Expand Up @@ -608,10 +592,10 @@ class ResourceBaseSerializer(DynamicModelSerializer):
popular_count = serializers.CharField(required=False)
share_count = serializers.CharField(required=False)
rating = serializers.CharField(required=False)
featured = ResourceManagementField(required=False)
featured = serializers.BooleanField(required=False)
advertised = serializers.BooleanField(required=False)
is_published = ResourceManagementField(required=False)
is_approved = ResourceManagementField(required=False)
is_published = serializers.BooleanField(required=False)
is_approved = serializers.BooleanField(required=False)
detail_url = DetailUrlField(read_only=True)
created = serializers.DateTimeField(read_only=True)
last_updated = serializers.DateTimeField(read_only=True)
Expand Down Expand Up @@ -751,6 +735,13 @@ def to_internal_value(self, data):
data = super(ResourceBaseSerializer, self).to_internal_value(data)
return data

def update(self, instance, validated_data):
user = self.context["request"].user
for field in instance.ROLE_BASED_MANAGED_FIELDS:
if not user.can_change_resource_field(instance, field) and field in validated_data:
validated_data.pop(field)
return super().update(instance, validated_data)

def save(self, **kwargs):
extent = self.validated_data.pop("extent", None)
instance = super().save(**kwargs)
Expand All @@ -767,6 +758,12 @@ def save(self, **kwargs):
logger.exception(e)
raise InvalidResourceException("The standard bbox provided is invalid")
instance.set_bbox_polygon(coords, srid)

user = self.context["request"].user
for field in instance.ROLE_BASED_MANAGED_FIELDS:
if not user.can_change_resource_field(instance, field):
logger.debug("User can perform the action, the default value is set")
setattr(user, field, getattr(ResourceBase, field).field.default)
return instance


Expand Down
15 changes: 0 additions & 15 deletions geonode/base/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,21 +826,6 @@ def test_resource_settings_field(self):
self.assertIsNotNone(field)
self.assertTrue(field.to_internal_value(True))

def test_resource_settings_field_non_admin(self):
"""
Non-Admin is not able to change the is_published value
if he is not the owner of the resource
"""
doc = create_single_doc("my_custom_doc")
factory = RequestFactory()
rq = factory.get("test")
rq.user = get_user_model().objects.get(username="bobby")
serializer = ResourceBaseSerializer(doc, context={"request": rq})
field = serializer.fields["is_published"]
self.assertIsNotNone(field)
# the original value was true, so it should not return false
self.assertTrue(field.to_internal_value(False))

def test_delete_user_with_resource(self):
owner, created = get_user_model().objects.get_or_create(username="delet-owner")
Dataset(
Expand Down
3 changes: 3 additions & 0 deletions geonode/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,9 @@ class ResourceBase(PolymorphicModel, PermissionLevelMixin, ItemBase):
Base Resource Object loosely based on ISO 19115:2003
"""

# fixing up the publishing option based on user permissions
ROLE_BASED_MANAGED_FIELDS = ["is_approved", "is_published", "featured"]

BASE_PERMISSIONS = {
"read": ["view_resourcebase"],
"write": ["change_resourcebase_metadata"],
Expand Down
25 changes: 25 additions & 0 deletions geonode/maps/api/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,31 @@ def test_create_map(self):
self.assertIsNotNone(response_maplayer["dataset"])
self.assertIsNotNone(response.data["map"]["thumbnail_url"])

def test_create_map_featured_status_admin(self):
"""
Post to maps/
User with perms should be able to change the value in the post payload
"""
# Get Layers List (backgrounds)
url = reverse("maps-list")

data = {
"title": "Map should be approved",
"featured": True,
"is_approved": False,
"is_published": False,
"data": DUMMY_MAPDATA,
"maplayers": DUMMY_MAPLAYERS_DATA,
}
# if has perms, the user should be able to change the field
# featured/approved/published
self.client.login(username="admin", password="admin")
response = self.client.post(f"{url}?include[]=data", data=data, format="json")
self.assertEqual(response.status_code, 201)
self.assertFalse(response.json()["map"]["is_published"])
self.assertFalse(response.json()["map"]["is_approved"])
self.assertTrue(response.json()["map"]["featured"])

def test_create_map_with_extra_maplayer_info(self):
"""
Post to maps/
Expand Down
9 changes: 9 additions & 0 deletions geonode/people/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,15 @@ def send_mail(self, template_prefix, context):
if self.email:
get_adapter().send_mail(template_prefix, self.email, context)

def can_change_resource_field(self, resource, field):
match field:
case "is_approved":
return self.can_approve(resource)
case "is_published":
return self.can_publish(resource)
case "featured":
return self.can_feature(resource)

def can_approve(self, resource):
return can_approve(self, resource)

Expand Down
2 changes: 1 addition & 1 deletion geonode/security/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,6 @@ def can_publish(user, resource):
if is_superuser:
return True
elif AdvancedSecurityWorkflowManager.is_manager_publish_mode():
return is_manager and can_publish
return is_manager
else:
return is_owner or is_manager

0 comments on commit 30b84a2

Please sign in to comment.