Skip to content

Commit b840f33

Browse files
authored
Merge pull request #2 from nscuro/issue-2041-resolve-merge-conflicts
Collection projects suggestions and cleanup
2 parents f9769d5 + 111900a commit b840f33

File tree

9 files changed

+108
-80
lines changed

9 files changed

+108
-80
lines changed

src/main/java/org/dependencytrack/model/Project.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import com.github.packageurl.MalformedPackageURLException;
3535
import com.github.packageurl.PackageURL;
3636
import io.swagger.v3.oas.annotations.media.Schema;
37-
3837
import org.dependencytrack.parser.cyclonedx.util.ModelConverter;
3938
import org.dependencytrack.persistence.converter.OrganizationalContactsJsonConverter;
4039
import org.dependencytrack.persistence.converter.OrganizationalEntityJsonConverter;
@@ -104,11 +103,19 @@
104103
}),
105104
@FetchGroup(name = "METRICS_UPDATE", members = {
106105
@Persistent(name = "id"),
106+
@Persistent(name = "parent"),
107+
@Persistent(name = "collectionLogic"),
108+
@Persistent(name = "collectionTag"),
107109
@Persistent(name = "lastInheritedRiskScore"),
108110
@Persistent(name = "uuid")
109111
}),
110112
@FetchGroup(name = "PARENT", members = {
111113
@Persistent(name = "parent")
114+
}),
115+
@FetchGroup(name = "PORTFOLIO_METRICS_UPDATE", members = {
116+
@Persistent(name = "id"),
117+
@Persistent(name = "lastInheritedRiskScore"),
118+
@Persistent(name = "uuid")
112119
})
113120
})
114121
@JsonInclude(JsonInclude.Include.NON_NULL)
@@ -123,7 +130,8 @@ public enum FetchGroup {
123130
ALL,
124131
METADATA,
125132
METRICS_UPDATE,
126-
PARENT
133+
PARENT,
134+
PORTFOLIO_METRICS_UPDATE
127135
}
128136

129137
@PrimaryKey
@@ -190,10 +198,9 @@ public enum FetchGroup {
190198
private Classifier classifier;
191199

192200
@Persistent
193-
@Column(name = "COLLECTION_LOGIC", jdbcType = "VARCHAR", allowsNull = "true", defaultValue = "NONE") // New column, must allow nulls on existing databases
194-
@Index(name = "PROJECT_COLLECTION_LOGIC_IDX")
201+
@Column(name = "COLLECTION_LOGIC", jdbcType = "VARCHAR", allowsNull = "true")
195202
@Extension(vendorName = "datanucleus", key = "enum-check-constraint", value = "true")
196-
private ProjectCollectionLogic collectionLogic = ProjectCollectionLogic.NONE;
203+
private ProjectCollectionLogic collectionLogic;
197204

198205
@Persistent(defaultFetchGroup = "true")
199206
@Column(name = "COLLECTION_TAG", allowsNull = "true")
@@ -405,13 +412,16 @@ public void setClassifier(Classifier classifier) {
405412
this.classifier = classifier;
406413
}
407414

408-
409415
public ProjectCollectionLogic getCollectionLogic() {
410-
return collectionLogic;
416+
return collectionLogic == null
417+
? ProjectCollectionLogic.NONE
418+
: collectionLogic;
411419
}
412420

413421
public void setCollectionLogic(ProjectCollectionLogic collectionLogic) {
414-
this.collectionLogic = collectionLogic;
422+
this.collectionLogic = collectionLogic != ProjectCollectionLogic.NONE
423+
? collectionLogic
424+
: null;
415425
}
416426

417427
public Tag getCollectionTag() {

src/main/java/org/dependencytrack/model/ProjectCollectionLogic.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* by this type.
2626
*
2727
* @author Ralf King
28-
* @since 4.11.0
28+
* @since 4.13.0
2929
*/
3030
public enum ProjectCollectionLogic {
3131
/**

src/main/java/org/dependencytrack/model/ProjectMetrics.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,12 @@ public class ProjectMetrics implements Serializable {
172172
private Integer policyViolationsOperationalUnaudited;
173173

174174
@Persistent
175-
@Column(name = "COLLECTION_LOGIC", allowsNull = "true") // New column, must allow nulls on existing data bases
175+
@Column(name = "COLLECTION_LOGIC", allowsNull = "true")
176176
private ProjectCollectionLogic collectionLogic;
177177

178178
@Persistent
179-
@Column(name = "COLLECTION_LOGIC_CHANGED", allowsNull = "true") // New column, must allow nulls on existing data bases
180-
private Boolean collectionLogicChanged = false;
179+
@Column(name = "COLLECTION_LOGIC_CHANGED", allowsNull = "false", defaultValue = "false")
180+
private boolean collectionLogicChanged = false;
181181

182182
@Persistent
183183
@Column(name = "FIRST_OCCURRENCE", allowsNull = "false")
@@ -433,16 +433,23 @@ public void setPolicyViolationsOperationalUnaudited(int policyViolationsOperatio
433433
this.policyViolationsOperationalUnaudited = policyViolationsOperationalUnaudited;
434434
}
435435

436-
public ProjectCollectionLogic getCollectionLogic() { return collectionLogic; }
436+
public ProjectCollectionLogic getCollectionLogic() {
437+
return collectionLogic == null
438+
? ProjectCollectionLogic.NONE
439+
: collectionLogic;
440+
}
437441

438442
public void setCollectionLogic(ProjectCollectionLogic collectionLogic) {
439-
// convert old NULL values from DB to NONE
440-
this.collectionLogic = collectionLogic != null ? collectionLogic : ProjectCollectionLogic.NONE;
443+
this.collectionLogic = collectionLogic != ProjectCollectionLogic.NONE
444+
? collectionLogic
445+
: null;
441446
}
442447

443-
public Boolean isCollectionLogicChanged() { return collectionLogicChanged; }
448+
public boolean isCollectionLogicChanged() {
449+
return collectionLogicChanged;
450+
}
444451

445-
public void setCollectionLogicChanged(Boolean collectionLogicChanged) {
452+
public void setCollectionLogicChanged(boolean collectionLogicChanged) {
446453
this.collectionLogicChanged = collectionLogicChanged;
447454
}
448455

src/main/java/org/dependencytrack/persistence/ProjectQueryManager.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -596,11 +596,6 @@ public Project updateProject(Project transientProject, boolean commitIndex) {
596596
} else {
597597
project.setCollectionTag(null);
598598
}
599-
// Force loading parent. This seems useless but somehow the code block above magically unloads the parent,
600-
// making it missing in the API response. Following line enforces it to be available again.
601-
// For reference see following Unit Test which would fail without this:
602-
// org.dependencytrack.resources.v1.ProjectResourceTest.patchProjectParentTest
603-
project.getParent();
604599

605600
return persist(project);
606601
});

src/main/java/org/dependencytrack/tasks/metrics/PortfolioMetricsUpdateTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ private List<Project> fetchNextActiveProjectsBatch(final PersistenceManager pm,
189189

190190
// NB: Set fetch group on PM level to avoid fields of the default fetch group from being loaded.
191191
try (var ignoredPersistenceCustomization = new ScopedCustomization(pm)
192-
.withFetchGroup(Project.FetchGroup.METRICS_UPDATE.name())) {
192+
.withFetchGroup(Project.FetchGroup.PORTFOLIO_METRICS_UPDATE.name())) {
193193
return List.copyOf(query.executeList());
194194
} finally {
195195
query.closeAll();

src/main/java/org/dependencytrack/tasks/metrics/ProjectMetricsUpdateTask.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ public void inform(final Event e) {
6262
}
6363
}
6464

65-
private void updateMetrics(final UUID uuid) throws Exception {
65+
private void updateMetrics(final UUID uuid) {
6666
final var counters = new Counters();
6767

6868
try (final QueryManager qm = new QueryManager()) {
6969
final PersistenceManager pm = qm.getPersistenceManager();
7070

71-
final Project project = qm.getObjectByUuid(Project.class, uuid, List.of(Project.FetchGroup.METRICS_UPDATE.name()));
71+
final Project project = fetchProject(pm, uuid);
7272
if (project == null) {
7373
throw new NoSuchElementException("Project " + uuid + " does not exist");
7474
}
@@ -115,7 +115,7 @@ private void updateMetrics(final UUID uuid) throws Exception {
115115
}
116116
}
117117

118-
private void updateRegularProjectMetrics(final Project project, final PersistenceManager pm, final Counters counters) throws Exception {
118+
private void updateRegularProjectMetrics(final Project project, final PersistenceManager pm, final Counters counters) {
119119
final UUID uuid = project.getUuid();
120120

121121
LOGGER.debug("Fetching first components page for project " + uuid);
@@ -240,13 +240,10 @@ private void updateAggregateDirectChildrenWithTagCollectionMetrics(final Project
240240
}
241241

242242
private void updateLatestVersionChildrenCollectionMetrics(final Project project, final PersistenceManager pm, final Counters counters) {
243-
LOGGER.warn("Collection logic LATEST_VERSION_CHILDREN not yet implemented. Waiting for https://github.com/DependencyTrack/dependency-track/issues/4148");
244-
/*
245-
TODO: Create Test case in ProjectMetricsUpdateTaskTest*/
246243
LOGGER.debug("Fetching metrics of children of collection project " + project.getUuid() +
247244
" using collection logic " + project.getCollectionLogic());
248245

249-
Query subQuery = pm.newQuery(ProjectMetrics.class);
246+
Query<ProjectMetrics> subQuery = pm.newQuery(ProjectMetrics.class);
250247
subQuery.setFilter("project == :project");
251248
subQuery.setResult("max(lastOccurrence)");
252249

@@ -266,6 +263,20 @@ private void updateLatestVersionChildrenCollectionMetrics(final Project project,
266263
}
267264
}
268265

266+
private Project fetchProject(final PersistenceManager pm, final UUID uuid) {
267+
final Query<Project> query = pm.newQuery(Project.class);
268+
query.setFilter("uuid == :uuid");
269+
query.setParameters(uuid);
270+
271+
// NB: Set fetch group on PM level to avoid fields of the default fetch group from being loaded.
272+
try (var ignoredPersistenceCustomization = new ScopedCustomization(pm)
273+
.withFetchGroup(Project.FetchGroup.METRICS_UPDATE.name())) {
274+
return query.executeUnique();
275+
} finally {
276+
query.closeAll();
277+
}
278+
}
279+
269280
private List<Component> fetchNextComponentsPage(final PersistenceManager pm, final Project project, final Long lastId) {
270281
final Query<Component> query = pm.newQuery(Component.class);
271282
if (lastId == null) {
@@ -293,7 +304,7 @@ private void addToCounters(Counters counters, ProjectMetrics projectMetrics) {
293304
counters.medium += projectMetrics.getMedium();
294305
counters.low += projectMetrics.getLow();
295306
counters.unassigned += projectMetrics.getUnassigned();
296-
counters.vulnerabilities += projectMetrics.getVulnerabilities();
307+
counters.vulnerabilities += Math.toIntExact(projectMetrics.getVulnerabilities());
297308

298309
counters.findingsTotal += projectMetrics.getFindingsTotal();
299310
counters.findingsAudited += projectMetrics.getFindingsAudited();

src/main/java/org/dependencytrack/upgrade/UpgradeItems.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ class UpgradeItems {
4141
UPGRADE_ITEMS.add(org.dependencytrack.upgrade.v4110.v4110Updater.class);
4242
UPGRADE_ITEMS.add(org.dependencytrack.upgrade.v4120.v4120Updater.class);
4343
UPGRADE_ITEMS.add(org.dependencytrack.upgrade.v4122.v4122Updater.class);
44-
UPGRADE_ITEMS.add(org.dependencytrack.upgrade.v4130.v4130Updater.class);
4544
}
4645

4746
static List<Class<? extends UpgradeItem>> getUpgradeItems() {

src/main/java/org/dependencytrack/upgrade/v4130/v4130Updater.java

Lines changed: 0 additions & 48 deletions
This file was deleted.

src/test/java/org/dependencytrack/resources/v1/ProjectResourceTest.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,60 @@ public void updateProjectAsLatestWithACLAndNoAccessTest() {
12211221
Assert.assertTrue(qm.getProject(noAccessLatestProject.getName(), noAccessLatestProject.getVersion()).isLatest());
12221222
}
12231223

1224+
@Test
1225+
public void updateProjectToCollectionProjectWhenHavingComponentsTest() {
1226+
final var project = new Project();
1227+
project.setName("acme-app");
1228+
qm.persist(project);
1229+
1230+
final var component = new Component();
1231+
component.setProject(project);
1232+
component.setName("acme-lib");
1233+
qm.persist(component);
1234+
1235+
final Response response = jersey.target(V1_PROJECT)
1236+
.request()
1237+
.header(X_API_KEY, apiKey)
1238+
.post(Entity.json(/* language=JSON */ """
1239+
{
1240+
"uuid": "%s",
1241+
"name": "acme-app",
1242+
"collectionLogic": "AGGREGATE_DIRECT_CHILDREN"
1243+
}
1244+
""".formatted(project.getUuid())));
1245+
assertThat(response.getStatus()).isEqualTo(409);
1246+
assertThat(getPlainTextBody(response)).isEqualTo("""
1247+
Project cannot be made a collection project while it has \
1248+
components or services!""");
1249+
}
1250+
1251+
@Test
1252+
public void updateProjectToCollectionProjectWhenHavingServicesTest() {
1253+
final var project = new Project();
1254+
project.setName("acme-app");
1255+
qm.persist(project);
1256+
1257+
final var service = new ServiceComponent();
1258+
service.setProject(project);
1259+
service.setName("some-service");
1260+
qm.persist(service);
1261+
1262+
final Response response = jersey.target(V1_PROJECT)
1263+
.request()
1264+
.header(X_API_KEY, apiKey)
1265+
.post(Entity.json(/* language=JSON */ """
1266+
{
1267+
"uuid": "%s",
1268+
"name": "acme-app",
1269+
"collectionLogic": "AGGREGATE_DIRECT_CHILDREN"
1270+
}
1271+
""".formatted(project.getUuid())));
1272+
assertThat(response.getStatus()).isEqualTo(409);
1273+
assertThat(getPlainTextBody(response)).isEqualTo("""
1274+
Project cannot be made a collection project while it has \
1275+
components or services!""");
1276+
}
1277+
12241278
@Test
12251279
public void deleteProjectTest() {
12261280
Project project = qm.createProject("ABC", null, "1.0", null, null, null, true, false);

0 commit comments

Comments
 (0)