Skip to content

Commit f199bda

Browse files
committed
refine code and add tests
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent 1d95465 commit f199bda

2 files changed

Lines changed: 29 additions & 7 deletions

File tree

dje/api_permissions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class ObjectPermissionsMixin:
9292
methods=["get", "post", "delete"],
9393
url_path="permissions",
9494
serializer_class=ObjectPermissionSerializer,
95-
permission_classes=[CanManageObjectPermissions],
95+
permission_classes=[permissions.IsAuthenticated, CanManageObjectPermissions],
9696
)
9797
def manage_permissions(self, request, *args, **kwargs):
9898
"""
@@ -139,7 +139,7 @@ def manage_permissions(self, request, *args, **kwargs):
139139
try:
140140
remove_perm(perm, user, obj)
141141
except ObjectDoesNotExist:
142-
errors.append(f"Cannot assign permission '{perm}' due to an internal error.")
142+
errors.append(f"Cannot remove permission '{perm}' due to an internal error.")
143143

144144
if errors:
145145
return Response({"errors": errors}, status=status.HTTP_400_BAD_REQUEST)

product_portfolio/tests/test_api.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,11 @@ def test_api_product_endpoint_cyclonedx_sbom_action(self):
589589
def test_api_product_endpoint_manage_permissions_action(self):
590590
url = reverse("api_v2:product-manage-permissions", args=[self.product1.uuid])
591591

592+
# Unauthenticated access is rejected with 403
593+
self.client.logout()
594+
response = self.client.get(url)
595+
self.assertEqual(status.HTTP_403_FORBIDDEN, response.status_code)
596+
592597
# User without view_product gets 404 (object not in secured queryset)
593598
self.client.login(username=self.base_user.username, password="secret")
594599
response = self.client.get(url)
@@ -606,38 +611,55 @@ def test_api_product_endpoint_manage_permissions_action(self):
606611
# base_user has view_product at this point
607612
self.assertEqual(1, len(response.data))
608613
self.assertEqual(self.base_user.username, response.data[0]["username"])
614+
self.assertEqual(self.dataspace.name, response.data[0]["dataspace"])
609615
self.assertIn("view_product", response.data[0]["object_permissions"])
610616

611-
# Superuser can POST to assign permissions
612-
data = {"user": self.admin_user.username, "permissions": ["view_product"]}
617+
# Superuser can POST to assign multiple permissions at once
618+
data = {
619+
"user": self.admin_user.username,
620+
"permissions": ["view_product", "change_product"],
621+
}
613622
response = self.client.post(url, data, format="json")
614623
self.assertEqual(status.HTTP_200_OK, response.status_code)
615624
self.assertEqual({"status": "permissions assigned"}, response.data)
616625
self.assertIn("view_product", get_perms(self.admin_user, self.product1))
626+
self.assertIn("change_product", get_perms(self.admin_user, self.product1))
617627

618628
# Superuser can DELETE to remove permissions
619-
data = {"user": self.admin_user.username, "permissions": ["view_product"]}
629+
data = {"user": self.admin_user.username, "permissions": ["view_product", "change_product"]}
620630
response = self.client.delete(url, data, content_type="application/json")
621631
self.assertEqual(status.HTTP_200_OK, response.status_code)
622632
self.assertEqual({"status": "permissions removed"}, response.data)
623633
self.assertNotIn("view_product", get_perms(self.admin_user, self.product1))
634+
self.assertNotIn("change_product", get_perms(self.admin_user, self.product1))
624635

625-
# Product creator (created_by) can manage permissions
636+
# Product creator (created_by) can GET, POST, and DELETE
626637
self.product1.created_by = self.admin_user
627638
self.product1.save()
628639
assign_perm("view_product", self.admin_user, self.product1)
629640
self.client.login(username=self.admin_user.username, password="secret")
641+
642+
response = self.client.get(url)
643+
self.assertEqual(status.HTTP_200_OK, response.status_code)
644+
630645
data = {"user": self.base_user.username, "permissions": ["change_product"]}
631646
response = self.client.post(url, data, format="json")
632647
self.assertEqual(status.HTTP_200_OK, response.status_code)
633648
self.assertIn("change_product", get_perms(self.base_user, self.product1))
634649

635-
# Invalid permission codename returns 400
650+
response = self.client.delete(url, data, content_type="application/json")
651+
self.assertEqual(status.HTTP_200_OK, response.status_code)
652+
self.assertNotIn("change_product", get_perms(self.base_user, self.product1))
653+
654+
# Invalid permission codename on POST returns 400
636655
self.client.login(username=self.super_user.username, password="secret")
637656
data = {"user": self.base_user.username, "permissions": ["nonexistent_perm"]}
638657
response = self.client.post(url, data, format="json")
639658
self.assertEqual(status.HTTP_400_BAD_REQUEST, response.status_code)
640659
self.assertIn("errors", response.data)
660+
# DELETE with unknown codename is a no-op (guardian remove_perm is idempotent)
661+
response = self.client.delete(url, data, content_type="application/json")
662+
self.assertEqual(status.HTTP_200_OK, response.status_code)
641663

642664
# Missing required fields returns 400
643665
response = self.client.post(url, {}, format="json")

0 commit comments

Comments
 (0)