@@ -414,6 +414,93 @@ void testNodeCreation() throws Exception {
414
414
deleteNode (root .getStudyId (), children , false , Set .of (children .get (0 )), userId );
415
415
}
416
416
417
+ private void assertForbiddenNodeInsertions (UUID studyId , String userId ,
418
+ NetworkModificationNode construction2 ,
419
+ NetworkModificationNode construction1 ,
420
+ NetworkModificationNode security1 ,
421
+ NetworkModificationNode security2 ) throws Exception {
422
+ // Construction node cannot be inserted before a security node
423
+ mockMvc .perform (post ("/v1/studies/{studyUuid}/tree/nodes?nodeToCutUuid={nodeUuid}&referenceNodeUuid={referenceNodeUuid}&insertMode={insertMode}" ,
424
+ studyId , construction2 .getId (), security1 .getId (), InsertMode .BEFORE )
425
+ .header (USER_ID_HEADER , userId ))
426
+ .andExpect (status ().isForbidden ());
427
+
428
+ // Security node cannot be inserted before a construction node (not a NEW_BRANCH)
429
+ mockMvc .perform (post ("/v1/studies/{studyUuid}/tree/nodes?nodeToCutUuid={nodeUuid}&referenceNodeUuid={referenceNodeUuid}&insertMode={insertMode}" ,
430
+ studyId , security2 .getId (), construction2 .getId (), InsertMode .BEFORE )
431
+ .header (USER_ID_HEADER , userId ))
432
+ .andExpect (status ().isForbidden ());
433
+
434
+ // Security node cannot be inserted before another construction node at root level
435
+ mockMvc .perform (post ("/v1/studies/{studyUuid}/tree/nodes?nodeToCutUuid={nodeUuid}&referenceNodeUuid={referenceNodeUuid}&insertMode={insertMode}" ,
436
+ studyId , security2 .getId (), construction1 .getId (), InsertMode .BEFORE )
437
+ .header (USER_ID_HEADER , userId ))
438
+ .andExpect (status ().isForbidden ());
439
+ }
440
+
441
+ private void assertForbiddenSubtreeInsertions (UUID studyId , String userId ,
442
+ NetworkModificationNode subtreeRoot ,
443
+ NetworkModificationNode targetNode ) throws Exception {
444
+ // Construction subtree cannot be inserted as a child of a security node
445
+ mockMvc .perform (post ("/v1/studies/{studyUuid}/tree/subtrees?subtreeToCutParentNodeUuid={subtreeRoot}&referenceNodeUuid={targetNodeUuid}&insertMode={mode}" ,
446
+ studyId , subtreeRoot .getId (), targetNode .getId (), InsertMode .CHILD )
447
+ .header (USER_ID_HEADER , userId ))
448
+ .andExpect (status ().isForbidden ());
449
+
450
+ // Mixed subtree (construction + security) cannot be inserted into a security node
451
+ mockMvc .perform (post ("/v1/studies/{studyUuid}/tree/subtrees?subtreeToCutParentNodeUuid={subtreeRoot}&referenceNodeUuid={targetNodeUuid}&insertMode={mode}" ,
452
+ studyId , subtreeRoot .getId (), targetNode .getId (), InsertMode .CHILD )
453
+ .header (USER_ID_HEADER , userId ))
454
+ .andExpect (status ().isForbidden ());
455
+ }
456
+
457
+ @ Test
458
+ void testNodeAndSubtreeInsertionRules () throws Exception {
459
+ String userId = "userId" ;
460
+ RootNode root = createRoot ();
461
+ UUID studyId = root .getStudyId ();
462
+
463
+ // Create tree structure
464
+ final NetworkModificationNode construction1 = buildNetworkModificationConstructionNode (
465
+ "construction1" , "n1" , UUID .randomUUID (), "variant1" ,
466
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (),
467
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), BuildStatus .NOT_BUILT );
468
+ createNode (studyId , root , construction1 , userId );
469
+
470
+ final NetworkModificationNode construction2 = buildNetworkModificationConstructionNode (
471
+ "construction2" , "n2" , UUID .randomUUID (), "variant2" ,
472
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (),
473
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), BuildStatus .NOT_BUILT );
474
+ createNode (studyId , construction1 , construction2 , userId );
475
+
476
+ final NetworkModificationNode security1 = buildNetworkModificationSecurityNode (
477
+ "security1" , "sec1" , UUID .randomUUID (), VARIANT_ID ,
478
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (),
479
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), BuildStatus .NOT_BUILT );
480
+ createNode (studyId , root , security1 , userId );
481
+
482
+ final NetworkModificationNode security2 = buildNetworkModificationSecurityNode (
483
+ "security2" , "sec2" , UUID .randomUUID (), VARIANT_ID ,
484
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (),
485
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), BuildStatus .NOT_BUILT );
486
+ createNode (studyId , root , security2 , userId );
487
+
488
+ final NetworkModificationNode security3 = buildNetworkModificationSecurityNode (
489
+ "security3" , "sec3" , UUID .randomUUID (), VARIANT_ID ,
490
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (),
491
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), BuildStatus .NOT_BUILT );
492
+ createNode (studyId , security2 , security3 , userId );
493
+
494
+ final NetworkModificationNode security4 = buildNetworkModificationSecurityNode (
495
+ "security4" , "sec4" , UUID .randomUUID (), "variant2" ,
496
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (),
497
+ UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), UUID .randomUUID (), BuildStatus .NOT_BUILT );
498
+ createNode (studyId , construction2 , security4 , userId ); // Creates a mixed subtree
499
+
500
+ assertForbiddenNodeInsertions (studyId , userId , construction2 , construction1 , security1 , security2 );
501
+ assertForbiddenSubtreeInsertions (studyId , userId , construction1 , security1 );
502
+ }
503
+
417
504
@ Test
418
505
void testNodeCreationRules () throws Exception {
419
506
RootNode root = createRoot ();
0 commit comments