@@ -587,6 +587,8 @@ def test_api_product_endpoint_cyclonedx_sbom_action(self):
587587 self .assertEqual ("Spec version 10.10 not supported" , response .data )
588588
589589 def test_api_product_endpoint_manage_permissions_action (self ):
590+ from django .contrib .auth .models import Group
591+
590592 url = reverse ("api_v2:product-manage-permissions" , args = [self .product1 .uuid ])
591593
592594 # Unauthenticated access is rejected with 403
@@ -604,17 +606,20 @@ def test_api_product_endpoint_manage_permissions_action(self):
604606 response = self .client .get (url )
605607 self .assertEqual (status .HTTP_403_FORBIDDEN , response .status_code )
606608
607- # Superuser can GET the permissions list
609+ # Superuser GET: response has "users" and "groups" keys
608610 self .client .login (username = self .super_user .username , password = "secret" )
609611 response = self .client .get (url )
610612 self .assertEqual (status .HTTP_200_OK , response .status_code )
613+ self .assertIn ("users" , response .data )
614+ self .assertIn ("groups" , response .data )
611615 # base_user has view_product at this point
612- self .assertEqual (1 , len (response .data ))
613- self .assertEqual (self .base_user .username , response .data [0 ]["username" ])
614- self .assertEqual (self .dataspace .name , response .data [0 ]["dataspace" ])
615- self .assertIn ("view_product" , response .data [0 ]["object_permissions" ])
616+ self .assertEqual (1 , len (response .data ["users" ]))
617+ self .assertEqual (self .base_user .username , response .data ["users" ][0 ]["username" ])
618+ self .assertEqual (self .dataspace .name , response .data ["users" ][0 ]["dataspace" ])
619+ self .assertIn ("view_product" , response .data ["users" ][0 ]["object_permissions" ])
620+ self .assertEqual ([], response .data ["groups" ])
616621
617- # Superuser can POST to assign multiple permissions at once
622+ # Superuser can POST to assign multiple permissions to a user at once
618623 data = {
619624 "user" : self .admin_user .username ,
620625 "permissions" : ["view_product" , "change_product" ],
@@ -625,14 +630,36 @@ def test_api_product_endpoint_manage_permissions_action(self):
625630 self .assertIn ("view_product" , get_perms (self .admin_user , self .product1 ))
626631 self .assertIn ("change_product" , get_perms (self .admin_user , self .product1 ))
627632
628- # Superuser can DELETE to remove permissions
633+ # Superuser can DELETE to remove user permissions
629634 data = {"user" : self .admin_user .username , "permissions" : ["view_product" , "change_product" ]}
630635 response = self .client .delete (url , data , content_type = "application/json" )
631636 self .assertEqual (status .HTTP_200_OK , response .status_code )
632637 self .assertEqual ({"status" : "permissions removed" }, response .data )
633638 self .assertNotIn ("view_product" , get_perms (self .admin_user , self .product1 ))
634639 self .assertNotIn ("change_product" , get_perms (self .admin_user , self .product1 ))
635640
641+ # Superuser can POST to assign permissions to a group
642+ team = Group .objects .create (name = "backend-team" )
643+ data = {"group" : team .name , "permissions" : ["view_product" , "change_product" ]}
644+ response = self .client .post (url , data , format = "json" )
645+ self .assertEqual (status .HTTP_200_OK , response .status_code )
646+ self .assertEqual ({"status" : "permissions assigned" }, response .data )
647+ self .assertIn ("view_product" , get_perms (team , self .product1 ))
648+ self .assertIn ("change_product" , get_perms (team , self .product1 ))
649+
650+ # GET lists the group with its permissions
651+ response = self .client .get (url )
652+ self .assertEqual (status .HTTP_200_OK , response .status_code )
653+ self .assertEqual (1 , len (response .data ["groups" ]))
654+ self .assertEqual (team .name , response .data ["groups" ][0 ]["name" ])
655+ self .assertIn ("view_product" , response .data ["groups" ][0 ]["object_permissions" ])
656+
657+ # Superuser can DELETE to remove group permissions
658+ data = {"group" : team .name , "permissions" : ["view_product" , "change_product" ]}
659+ response = self .client .delete (url , data , content_type = "application/json" )
660+ self .assertEqual (status .HTTP_200_OK , response .status_code )
661+ self .assertNotIn ("view_product" , get_perms (team , self .product1 ))
662+
636663 # Product creator (created_by) can GET, POST, and DELETE
637664 self .product1 .created_by = self .admin_user
638665 self .product1 .save ()
@@ -661,8 +688,18 @@ def test_api_product_endpoint_manage_permissions_action(self):
661688 response = self .client .delete (url , data , content_type = "application/json" )
662689 self .assertEqual (status .HTTP_200_OK , response .status_code )
663690
664- # Missing required fields returns 400
665- response = self .client .post (url , {}, format = "json" )
691+ # Neither user nor group returns 400
692+ response = self .client .post (url , {"permissions" : ["view_product" ]}, format = "json" )
693+ self .assertEqual (status .HTTP_400_BAD_REQUEST , response .status_code )
694+ self .assertIn ("errors" , response .data )
695+
696+ # Both user and group returns 400
697+ data = {
698+ "user" : self .base_user .username ,
699+ "group" : team .name ,
700+ "permissions" : ["view_product" ],
701+ }
702+ response = self .client .post (url , data , format = "json" )
666703 self .assertEqual (status .HTTP_400_BAD_REQUEST , response .status_code )
667704 self .assertIn ("errors" , response .data )
668705
0 commit comments