@@ -1671,3 +1671,77 @@ def test_user_permissions_reflected_in_job_detail(self):
1671
1671
response = self .client .get (f"/api/v2/jobs/{ job .pk } /" )
1672
1672
self .assertEqual (response .status_code , 200 )
1673
1673
self .assertNotIn ("run" , response .data .get ("user_permissions" , []))
1674
+
1675
+
1676
+ class TestRunSingleImageJobPermission (APITestCase ):
1677
+ def setUp (self ):
1678
+ super ().setUp ()
1679
+ self .user = User .objects .create_user (
1680
+ email = "regularuser@insectai.org" ,
1681
+ password = "password123" ,
1682
+ )
1683
+ self .project = Project .objects .create (name = "Single Image Project" , description = "Testing single image job" )
1684
+ self .pipeline = Pipeline .objects .create (
1685
+ name = "Test ML pipeline" ,
1686
+ description = "Test ML pipeline" ,
1687
+ )
1688
+ self .pipeline .projects .add (self .project )
1689
+ self .deployment = Deployment .objects .create (name = "Test Deployment" , project = self .project )
1690
+ create_captures (deployment = self .deployment )
1691
+ group_images_into_events (deployment = self .deployment )
1692
+ self .capture = self .deployment .captures .first ()
1693
+ self .client .force_authenticate (self .user )
1694
+
1695
+ def _grant_create_job__and_run_single_image_perm (self ):
1696
+ """Grants run_single_image_job permission on a specific capture to the user."""
1697
+ assign_perm (Project .Permissions .CREATE_JOB , self .user , self .project )
1698
+ assign_perm (Project .Permissions .RUN_SINGLE_IMAGE_JOB , self .user , self .project )
1699
+
1700
+ def _remove_run_single_image_perm (self ):
1701
+ remove_perm (Project .Permissions .RUN_SINGLE_IMAGE_JOB , self .user , self .project )
1702
+
1703
+ def test_user_can_run_single_image_job_and_perm_is_reflected (self ):
1704
+ self ._grant_create_job__and_run_single_image_perm ()
1705
+
1706
+ # Verify permission is reflected in capture detail response
1707
+ capture_detail_url = f"/api/v2/captures/{ self .capture .pk } /"
1708
+ response = self .client .get (capture_detail_url )
1709
+ self .assertEqual (response .status_code , 200 )
1710
+ self .assertIn (
1711
+ "run_single_image_ml_job" ,
1712
+ response .data .get ("user_permissions" , []),
1713
+ "run_single_image permission not reflected" ,
1714
+ )
1715
+
1716
+ # Try to run a job using source_image_single_id
1717
+ run_url = "/api/v2/jobs/?start_now"
1718
+ payload = {
1719
+ "delay" : 0 ,
1720
+ "name" : f"Capture #{ self .capture .pk } " ,
1721
+ "project_id" : str (self .project .pk ),
1722
+ "pipeline_id" : str (self .pipeline .pk ),
1723
+ "source_image_single_id" : str (self .capture .pk ),
1724
+ }
1725
+ response = self .client .post (run_url , payload , format = "json" )
1726
+ self .assertEqual (
1727
+ response .status_code , 201 , f"User should be able to run single image job, got { response .status_code } "
1728
+ )
1729
+ # Remove permission
1730
+ self ._remove_run_single_image_perm ()
1731
+
1732
+ # Permission should no longer appear in capture detail
1733
+ response = self .client .get (capture_detail_url )
1734
+ self .assertEqual (response .status_code , 200 )
1735
+ self .assertNotIn (
1736
+ "run_single_image_ml_job" ,
1737
+ response .data .get ("user_permissions" , []),
1738
+ "run_single_image permission should be removed but still present" ,
1739
+ )
1740
+
1741
+ # Should not be able to run job now
1742
+ response = self .client .post (run_url , payload , format = "json" )
1743
+ self .assertEqual (
1744
+ response .status_code ,
1745
+ 403 ,
1746
+ f"User should NOT be able to run single image job after permission removal, got { response .status_code } " ,
1747
+ )
0 commit comments