diff --git a/django/applications/catmaid/control/skeletonexport.py b/django/applications/catmaid/control/skeletonexport.py index 2a4da9bece..a4f3fbf529 100644 --- a/django/applications/catmaid/control/skeletonexport.py +++ b/django/applications/catmaid/control/skeletonexport.py @@ -65,6 +65,11 @@ def get_treenodes_qs(project_id=None, skeleton_id=None, with_labels:bool=True) - return treenode_qs, labels_qs, labelconnector_qs +def validate_skeleton_in_project(project_id:int, skeleton_id:int) -> None: + if not ClassInstance.objects.filter(pk=skeleton_id, project_id=project_id).exists(): + raise Http404(f"Skeleton #{skeleton_id} doesn't exist") + + def get_swc_string(project_id, skeleton_id, treenodes_qs:QuerySet, linearize_ids:bool=False, soma_markers:List[str]=None, get_extra_cols=None) -> str: """ @@ -347,6 +352,8 @@ def compact_skeleton_detail(request:HttpRequest, project_id=None, skeleton_id=No return_format = request.GET.get('format', 'json') ordered = get_request_bool(request.GET, "ordered", False) + validate_skeleton_in_project(project_id, skeleton_id) + result = _compact_skeleton(project_id, skeleton_id, with_connectors, with_tags, with_history, with_merge_history, with_reviews, with_annotations, with_user_info, diff --git a/django/applications/catmaid/tests/apis/test_skeletons.py b/django/applications/catmaid/tests/apis/test_skeletons.py index 3b4d4a3661..03044f6ee5 100644 --- a/django/applications/catmaid/tests/apis/test_skeletons.py +++ b/django/applications/catmaid/tests/apis/test_skeletons.py @@ -17,7 +17,7 @@ from catmaid.models import ( ClassInstance, ClassInstanceClassInstance, Log, Review, TreenodeConnector, ReviewerWhitelist, Treenode, User, ClientDatastore, ClientData, - TreenodeClassInstance + TreenodeClassInstance, Project ) from .common import CatmaidApiTestCase, CatmaidApiTransactionTestCase @@ -89,6 +89,30 @@ def test_skeleton_root(self): self.assertAlmostEqual(parsed_response['z'], 0) + def test_compact_skeleton_detail_requires_project_match(self): + self.fake_authentication() + wrong_project_id = 5 + skeleton_id = 373 + assign_perm('can_browse', self.test_user, + Project.objects.get(pk=wrong_project_id)) + + response = self.client.get( + f'/{self.test_project_id}/skeletons/{skeleton_id}/compact-detail') + self.assertStatus(response) + + response = self.client.get( + f'/{wrong_project_id}/skeletons/{skeleton_id}/compact-detail') + self.assertStatus(response, 404) + parsed_response = json.loads(response.content.decode('utf-8')) + self.assertEqual(f"Skeleton #{skeleton_id} doesn't exist", parsed_response['detail']) + + response = self.client.get( + f'/{wrong_project_id}/skeletons/{skeleton_id}/compact-detail', + {'with_history': True}) + self.assertStatus(response, 404) + parsed_response = json.loads(response.content.decode('utf-8')) + self.assertEqual(f"Skeleton #{skeleton_id} doesn't exist", parsed_response['detail']) + def test_import_skeleton_with_64_bit_ids(self): self.fake_authentication() assign_perm('can_import', self.test_user, self.test_project)