@@ -344,6 +344,14 @@ public Response uploadBom(@Parameter(required = true) BomSubmitRequest request)
344
344
null , true , request .isLatestProjectVersion (), true );
345
345
Principal principal = getPrincipal ();
346
346
qm .updateNewProjectACL (project , principal );
347
+ if (request .isDeactivateOtherVersions ()) {
348
+ if (!request .isLatestProjectVersion ()) {
349
+ var message = "Value \" isLatest=true\" required when \" deactivateOtherVersions=true\" ." ;
350
+ LOGGER .error (message );
351
+ return Response .status (Response .Status .NOT_ACCEPTABLE ).entity (message ).build ();
352
+ }
353
+ qm .runInTransaction (() -> deactivateOtherVersions (qm , trimmedProjectName ));
354
+ }
347
355
} else {
348
356
return Response .status (Response .Status .UNAUTHORIZED ).entity ("The principal does not have permission to create project." ).build ();
349
357
}
@@ -404,6 +412,7 @@ public Response uploadBom(
404
412
@ FormDataParam ("parentVersion" ) String parentVersion ,
405
413
@ FormDataParam ("parentUUID" ) String parentUUID ,
406
414
@ DefaultValue ("false" ) @ FormDataParam ("isLatest" ) boolean isLatest ,
415
+ @ DefaultValue ("false" ) @ FormDataParam ("deactivateOtherVersions" ) boolean deactivateOtherVersions ,
407
416
@ Parameter (schema = @ Schema (type = "string" )) @ FormDataParam ("bom" ) final List <FormDataBodyPart > artifactParts
408
417
) {
409
418
if (projectUuid != null ) { // behavior in v3.0.0
@@ -450,15 +459,25 @@ public Response uploadBom(
450
459
project = qm .createProject (trimmedProjectName , null , trimmedProjectVersion , tags , parent , null , true , isLatest , true );
451
460
Principal principal = getPrincipal ();
452
461
qm .updateNewProjectACL (project , principal );
462
+
463
+ if (deactivateOtherVersions ) {
464
+ if (!isLatest ) {
465
+ var message = "Value \" isLatest=true\" required when \" deactivateOtherVersions=true\" ." ;
466
+ LOGGER .error (message );
467
+ return Response .status (Response .Status .NOT_ACCEPTABLE ).entity (message ).build ();
468
+ }
469
+ qm .runInTransaction (() -> deactivateOtherVersions (qm , trimmedProjectName ));
470
+ }
453
471
} else {
454
472
return Response .status (Response .Status .UNAUTHORIZED ).entity ("The principal does not have permission to create project." ).build ();
455
473
}
456
474
}
457
- return process (qm , project , artifactParts );
475
+ return process (qm , project , artifactParts );
458
476
}
459
477
}
460
478
}
461
479
480
+
462
481
@ GET
463
482
@ Path ("/token/{uuid}" )
464
483
@ Produces (MediaType .APPLICATION_JSON )
@@ -501,6 +520,26 @@ public Response isTokenBeingProcessed (
501
520
return Response .ok (response ).build ();
502
521
}
503
522
523
+ /**
524
+ * Deactivates all non-latest versions of a specific project.
525
+ * Ensures that only the latest version of a project remains active.
526
+ * If the principal does not have access to a project version, an exception is thrown.
527
+ *
528
+ * @param qm The QueryManager instance used to query and manage projects.
529
+ * @param projectName A string representing the name of the project versions to be evaluated.
530
+ */
531
+ private void deactivateOtherVersions (QueryManager qm , String projectName ) {
532
+ qm .getProjects (projectName , true , false , null ).getList (Project .class ).forEach (p -> {
533
+ if (p .isLatest ()) {
534
+ return ;
535
+ } else if (!qm .hasAccess (super .getPrincipal (), p )) {
536
+ throw new WebApplicationException ("Could not deactivate project, no access: " + p .getUuid () + " / " + p .getName ());
537
+ }
538
+ p .setActive (false );
539
+ qm .updateProject (p , true );
540
+ });
541
+ }
542
+
504
543
/**
505
544
* Common logic that processes a BOM given a project and encoded payload.
506
545
*/
0 commit comments