diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b9a55d7720e4..333fec034948 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -52,12 +52,6 @@ updates: - dependency-name: "org.springframework.ldap:*" # Spring ldap 3.x requires Spring 6 (see above) versions: - ">= 3.0" - - dependency-name: "org.hisp.dhis.parser:*" # Antlr parser must be upgraded manually due to circular dependency with rule engine - versions: - - ">= 1.0" - - dependency-name: "org.hisp.dhis.rules:*" # Rule engine must be upgraded manually due to circular dependency with ANTLR parser - versions: - - ">= 2.0" - dependency-name: "org.slf4j:slf4j-api" # will update in https://dhis2.atlassian.net/browse/DHIS2-16504 versions: - ">= 2.0" @@ -138,12 +132,6 @@ updates: - dependency-name: "org.springframework.ldap:*" # Spring ldap 3.x requires Spring 6 (see above) versions: - ">= 3.0" - - dependency-name: "org.hisp.dhis.parser:*" # Antlr parser must be upgraded manually due to circular dependency with rule engine - versions: - - ">= 1.0" - - dependency-name: "org.hisp.dhis.rules:*" # Rule engine must be upgraded manually due to circular dependency with ANTLR parser - versions: - - ">= 2.0" - dependency-name: "org.flywaydb:flyway-core" # It requires Postgres version to be >= 11 versions: - "> 9.22.3" diff --git a/.github/workflows/generate-merge-boms.yml b/.github/workflows/generate-merge-boms.yml new file mode 100644 index 000000000000..50b23f38f675 --- /dev/null +++ b/.github/workflows/generate-merge-boms.yml @@ -0,0 +1,51 @@ +name: Generate and Merge SBOMs and Upload them to DependencyTrack every night + +on: + schedule: + - cron: "0 0 * * *" # Run every day at midnight + +concurrency: + group: ${{ github.workflow}}-${{ github.ref }} + cancel-in-progress: true + +jobs: + create-boms: + runs-on: ubuntu-latest + defaults: + run: + working-directory: dhis-2/ + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: temurin + cache: maven + + - name: Install CycloneDX CLI + run: | + curl -s https://api.github.com/repos/CycloneDX/cyclonedx-cli/releases/latest | grep "browser_download_url.*linux.x64" | cut -d '"' -f 4 | wget -i - + sudo mv cyclonedx-linux-x64 /usr/local/bin/ + sudo chmod +x /usr/local/bin/cyclonedx-linux-x64 + + - name: Generate BOMs + run: mvn cyclonedx:makeBom + + - name: Merge BOMs + run: cyclonedx-linux-x64 merge --input-files $(find . -name 'dxbom.json') --input-format json --output-file target/merged-bom.json --output-format json + + - name: Upload SBOM to DependencyTrack + env: + DEPENDENCY_TRACK_API: "https://dt.security.dhis2.org/api/v1/bom" + run: | + curl -X POST "$DEPENDENCY_TRACK_API" \ + --fail-with-body \ + -H "Content-Type: multipart/form-data" \ + -H "X-Api-Key: ${{ secrets.DEPENDENCYTRACK_APIKEY }}" \ + -F "project=56383704-d5a2-4a35-ad6a-081f80f5d6d3" \ + -F "bom=@target/merged-bom.json" diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/enrollment/HibernateEnrollmentStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/enrollment/HibernateEnrollmentStore.java index 49f165a22cc2..d67e20076ef6 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/enrollment/HibernateEnrollmentStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/enrollment/HibernateEnrollmentStore.java @@ -279,7 +279,7 @@ private static String orderBy(List orders) { orderJoiner.add( order.getField() + " " + (order.getDirection().isAscending() ? "asc" : "desc")); } - return " order by " + orderJoiner; + return " order by " + orderJoiner + ", " + DEFAULT_ORDER; } @Getter diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/JdbcEventStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/JdbcEventStore.java index 09c6e1c9a542..2b5d9f11e8b6 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/JdbcEventStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/event/JdbcEventStore.java @@ -1612,7 +1612,7 @@ private String getOrderQuery(EventQueryParams params) { } if (!orderFields.isEmpty()) { - return "order by " + StringUtils.join(orderFields, ',') + " "; + return "order by " + StringUtils.join(orderFields, ',') + ", " + DEFAULT_ORDER + " "; } else { return "order by " + DEFAULT_ORDER + " "; } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java index 05801268d0c3..90c1715f9e8c 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/relationship/HibernateRelationshipStore.java @@ -41,6 +41,7 @@ import java.util.Set; import java.util.function.Function; import java.util.function.LongSupplier; +import java.util.stream.Stream; import javax.annotation.Nonnull; import org.apache.commons.collections4.CollectionUtils; import org.hisp.dhis.common.IdentifiableObject; @@ -264,10 +265,13 @@ private String getRelationshipEntityType(T entity private List orderBy( RelationshipQueryParams queryParams, CriteriaBuilder builder, Root root) { + List defaultOrder = orderBy(List.of(DEFAULT_ORDER), builder, root); if (!queryParams.getOrder().isEmpty()) { - return orderBy(queryParams.getOrder(), builder, root); + return Stream.concat( + orderBy(queryParams.getOrder(), builder, root).stream(), defaultOrder.stream()) + .toList(); } else { - return orderBy(List.of(DEFAULT_ORDER), builder, root); + return defaultOrder; } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/HibernateTrackedEntityStore.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/HibernateTrackedEntityStore.java index 8aa3221956e8..948d63004212 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/HibernateTrackedEntityStore.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/export/trackedentity/HibernateTrackedEntityStore.java @@ -1007,10 +1007,10 @@ private String getQueryOrderBy(TrackedEntityQueryParams params, boolean innerOrd } if (!orderFields.isEmpty()) { - return "ORDER BY " + StringUtils.join(orderFields, ',') + SPACE; + return "ORDER BY " + StringUtils.join(orderFields, ',') + ", " + DEFAULT_ORDER + SPACE; } - return "ORDER BY " + DEFAULT_ORDER + " "; + return "ORDER BY " + DEFAULT_ORDER + SPACE; } /** diff --git a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/OrderAndPaginationExporterTest.java b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/OrderAndPaginationExporterTest.java index b925005fca34..3106c4c8b009 100644 --- a/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/OrderAndPaginationExporterTest.java +++ b/dhis-2/dhis-test-integration/src/test/java/org/hisp/dhis/tracker/export/OrderAndPaginationExporterTest.java @@ -207,6 +207,32 @@ void shouldReturnPaginatedTrackedEntitiesGivenNonDefaultPageSizeAndTotalPages() trackedEntityService.getTrackedEntities(params, new PageParams(3, 3, true)).getItems()); } + @Test + void shouldOrderTrackedEntitiesByInactiveAndByDefaultOrder() + throws ForbiddenException, BadRequestException, NotFoundException { + List expected = + Stream.of( + get(TrackedEntity.class, "QesgJkTyTCk"), + get(TrackedEntity.class, "dUE514NMOlo"), + get(TrackedEntity.class, "mHWCacsGYYn")) + .sorted(Comparator.comparing(TrackedEntity::getId).reversed()) // reversed = desc + .map(TrackedEntity::getUid) + .toList(); + + TrackedEntityOperationParams params = + TrackedEntityOperationParams.builder() + .organisationUnits(orgUnit) + .orgUnitMode(SELECTED) + .trackedEntities(UID.of("mHWCacsGYYn", "QesgJkTyTCk", "dUE514NMOlo")) + .trackedEntityType(trackedEntityType) + .orderBy("inactive", SortDirection.ASC) + .build(); + + List trackedEntities = getTrackedEntities(params); + + assertEquals(expected, trackedEntities); + } + @Test void shouldOrderTrackedEntitiesByPrimaryKeyDescByDefault() throws ForbiddenException, BadRequestException, NotFoundException { @@ -566,6 +592,28 @@ void shouldOrderTrackedEntitiesByInactiveAsc() assertEquals(List.of("dUE514NMOlo", "QS6w44flWAf"), trackedEntities); } + @Test + void shouldOrderEnrollmentsByStatusAndByDefaultOrder() + throws ForbiddenException, BadRequestException { + List expected = + Stream.of(get(Enrollment.class, "HDWTYSYkICe"), get(Enrollment.class, "GYWSSZunTLk")) + .sorted(Comparator.comparing(Enrollment::getId).reversed()) // reversed = desc + .map(Enrollment::getUid) + .toList(); + + EnrollmentOperationParams operationParams = + EnrollmentOperationParams.builder() + .orgUnits(get(OrganisationUnit.class, "DiszpKrYNg8")) + .orgUnitMode(SELECTED) + .enrollments(UID.of("HDWTYSYkICe", "GYWSSZunTLk")) + .orderBy("status", SortDirection.DESC) + .build(); + + List actual = getEnrollments(operationParams); + + assertEquals(expected, actual); + } + @Test void shouldReturnPaginatedEnrollmentsGivenNonDefaultPageSize() throws ForbiddenException, BadRequestException { @@ -677,6 +725,29 @@ void shouldOrderEnrollmentsByEnrolledAtDesc() throws ForbiddenException, BadRequ assertEquals(List.of("TvctPPhpD8z", "nxP7UnKhomJ"), enrollments); } + @Test + void shouldOrderEventsByStatusAndByDefaultOrder() throws ForbiddenException, BadRequestException { + List expected = + Stream.of( + get(Event.class, "ck7DzdxqLqA"), + get(Event.class, "kWjSezkXHVp"), + get(Event.class, "OTmjvJDn0Fu")) + .sorted(Comparator.comparing(Event::getId).reversed()) // reversed = desc + .map(Event::getUid) + .toList(); + + EventOperationParams operationParams = + eventParamsBuilder + .orgUnit(get(OrganisationUnit.class, "DiszpKrYNg8")) + .events(UID.of("ck7DzdxqLqA", "kWjSezkXHVp", "OTmjvJDn0Fu")) + .orderBy("status", SortDirection.DESC) + .build(); + + List actual = getEvents(operationParams); + + assertEquals(expected, actual); + } + @Test void shouldReturnPaginatedEventsWithNotesGivenNonDefaultPageSize() throws ForbiddenException, BadRequestException { @@ -1274,6 +1345,29 @@ void shouldOrderByFieldInAscendingOrderWhenModeDescendants( assertEquals(List.of(firstEvent, secondEvent), events); } + @Test + void shouldOrderRelationshipsByCreatedAtClientAndByDefaultOrder() + throws ForbiddenException, BadRequestException, NotFoundException { + Relationship oLT07jKRu9e = get(Relationship.class, "fHn74P5T3r1"); + Relationship yZxjxJli9mO = get(Relationship.class, "yZxjxJli9mO"); + List expected = + Stream.of(oLT07jKRu9e, yZxjxJli9mO) + .sorted(Comparator.comparing(Relationship::getId).reversed()) // reversed = desc + .map(Relationship::getUid) + .toList(); + + RelationshipOperationParams params = + RelationshipOperationParams.builder() + .type(TrackerType.TRACKED_ENTITY) + .identifier(UID.of("dUE514NMOlo")) + .orderBy("createdAtClient", SortDirection.DESC) + .build(); + + List relationships = getRelationships(params); + + assertEquals(expected, relationships); + } + @Test void shouldOrderRelationshipsByPrimaryKeyDescByDefault() throws ForbiddenException, BadRequestException, NotFoundException { diff --git a/dhis-2/dhis-test-integration/src/test/resources/tracker/event_and_enrollment.json b/dhis-2/dhis-test-integration/src/test/resources/tracker/event_and_enrollment.json index d5ea8bc6e580..27db31bb7b87 100644 --- a/dhis-2/dhis-test-integration/src/test/resources/tracker/event_and_enrollment.json +++ b/dhis-2/dhis-test-integration/src/test/resources/tracker/event_and_enrollment.json @@ -1309,6 +1309,22 @@ "to": { "event": "pTzf9KYMk72" } + }, + { + "relationship": "fHn74P5T3r1", + "relationshipType": { + "idScheme": "UID", + "identifier": "TV9oB9LT3sh" + }, + "createdAtClient": "2018-11-01T13:24:37.118", + "bidirectional": false, + "deleted": false, + "from": { + "trackedEntity": "dUE514NMOlo" + }, + "to": { + "event": "D9PbzJY8bJM" + } } ], "username": "system-process" diff --git a/dhis-2/pom.xml b/dhis-2/pom.xml index ead83aebaee0..164856cbd652 100644 --- a/dhis-2/pom.xml +++ b/dhis-2/pom.xml @@ -85,7 +85,7 @@ - 3.1.0 + 3.2.1 0.6.1 @@ -104,7 +104,7 @@ 6.1.12 - 3.4.0 + 3.4.1 2.7.18 2.7.4 1.1.5.RELEASE @@ -428,16 +428,6 @@ org.hisp.dhis.rules rule-engine-jvm ${dhis2-rule-engine.version} - - - commons-logging - commons-logging - - - org.slf4j - slf4j-simple - - @@ -1882,6 +1872,28 @@ sonar-maven-plugin 5.0.0.4389 + + org.cyclonedx + cyclonedx-maven-plugin + + library + 1.6 + true + true + true + true + true + false + false + true + all + dxbom + ${project.build.directory} + + false + + + org.codehaus.mojo versions-maven-plugin