Skip to content

Commit 4e90c94

Browse files
committed
Add option to deactivate old project versions on BOM upload
Fixes DependencyTrack#4532 Signed-off-by: Christoffer Rumohr <[email protected]>
1 parent bcd2651 commit 4e90c94

File tree

3 files changed

+231
-16
lines changed

3 files changed

+231
-16
lines changed

src/main/java/org/dependencytrack/resources/v1/BomResource.java

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,14 @@ public Response uploadBom(@Parameter(required = true) BomSubmitRequest request)
344344
null, true, request.isLatestProjectVersion(), true);
345345
Principal principal = getPrincipal();
346346
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+
}
347355
} else {
348356
return Response.status(Response.Status.UNAUTHORIZED).entity("The principal does not have permission to create project.").build();
349357
}
@@ -404,6 +412,7 @@ public Response uploadBom(
404412
@FormDataParam("parentVersion") String parentVersion,
405413
@FormDataParam("parentUUID") String parentUUID,
406414
@DefaultValue("false") @FormDataParam("isLatest") boolean isLatest,
415+
@DefaultValue("false") @FormDataParam("deactivateOtherVersions") boolean deactivateOtherVersions,
407416
@Parameter(schema = @Schema(type = "string")) @FormDataParam("bom") final List<FormDataBodyPart> artifactParts
408417
) {
409418
if (projectUuid != null) { // behavior in v3.0.0
@@ -450,15 +459,25 @@ public Response uploadBom(
450459
project = qm.createProject(trimmedProjectName, null, trimmedProjectVersion, tags, parent, null, true, isLatest, true);
451460
Principal principal = getPrincipal();
452461
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+
}
453471
} else {
454472
return Response.status(Response.Status.UNAUTHORIZED).entity("The principal does not have permission to create project.").build();
455473
}
456474
}
457-
return process(qm, project, artifactParts);
475+
return process(qm, project, artifactParts);
458476
}
459477
}
460478
}
461479

480+
462481
@GET
463482
@Path("/token/{uuid}")
464483
@Produces(MediaType.APPLICATION_JSON)
@@ -501,6 +520,26 @@ public Response isTokenBeingProcessed (
501520
return Response.ok(response).build();
502521
}
503522

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+
504543
/**
505544
* Common logic that processes a BOM given a project and encoded payload.
506545
*/

src/main/java/org/dependencytrack/resources/v1/vo/BomSubmitRequest.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,17 @@ public final class BomSubmitRequest {
7474

7575
private final boolean isLatestProjectVersion;
7676

77+
private final boolean deactivateOtherVersions;
78+
7779
public BomSubmitRequest(String project,
7880
String projectName,
7981
String projectVersion,
8082
List<Tag> projectTags,
8183
boolean autoCreate,
8284
boolean isLatestProjectVersion,
85+
boolean deactivateOtherProjectVersions,
8386
String bom) {
84-
this(project, projectName, projectVersion, projectTags, autoCreate, null, null, null, isLatestProjectVersion, bom);
87+
this(project, projectName, projectVersion, projectTags, autoCreate, null, null, null, isLatestProjectVersion, deactivateOtherProjectVersions, bom);
8588
}
8689

8790
@JsonCreator
@@ -94,6 +97,7 @@ public BomSubmitRequest(@JsonProperty(value = "project") String project,
9497
@JsonProperty(value = "parentName") String parentName,
9598
@JsonProperty(value = "parentVersion") String parentVersion,
9699
@JsonProperty(value = "isLatestProjectVersion", defaultValue = "false") boolean isLatestProjectVersion,
100+
@JsonProperty(value = "deactivateOtherVersions", defaultValue = "false") boolean deactivateOtherVersions,
97101
@JsonProperty(value = "bom", required = true) String bom) {
98102
this.project = project;
99103
this.projectName = projectName;
@@ -104,6 +108,7 @@ public BomSubmitRequest(@JsonProperty(value = "project") String project,
104108
this.parentName = parentName;
105109
this.parentVersion = parentVersion;
106110
this.isLatestProjectVersion = isLatestProjectVersion;
111+
this.deactivateOtherVersions = deactivateOtherVersions;
107112
this.bom = bom;
108113
}
109114

@@ -149,6 +154,10 @@ public boolean isAutoCreate() {
149154
@JsonProperty("isLatestProjectVersion")
150155
public boolean isLatestProjectVersion() { return isLatestProjectVersion; }
151156

157+
public boolean isDeactivateOtherVersions() {
158+
return deactivateOtherVersions;
159+
}
160+
152161
@Schema(
153162
description = "Base64 encoded BOM",
154163
required = true,

0 commit comments

Comments
 (0)