diff --git a/docs/antora.yml b/docs/antora.yml new file mode 100644 index 0000000..3923d0a --- /dev/null +++ b/docs/antora.yml @@ -0,0 +1,3 @@ +name: onecx-announcement +title: Announcement Management +version: latest \ No newline at end of file diff --git a/docs/modules/onecx-announcement-bff/nav.adoc b/docs/modules/onecx-announcement-bff/nav.adoc new file mode 100644 index 0000000..2964da1 --- /dev/null +++ b/docs/modules/onecx-announcement-bff/nav.adoc @@ -0,0 +1 @@ +* xref:onecx-announcement-bff:index.adoc[Announcement Bff] \ No newline at end of file diff --git a/docs/modules/onecx-announcement-bff/pages/index.adoc b/docs/modules/onecx-announcement-bff/pages/index.adoc new file mode 100644 index 0000000..03e2fc5 --- /dev/null +++ b/docs/modules/onecx-announcement-bff/pages/index.adoc @@ -0,0 +1,8 @@ +include::onecx-announcement-bff-attributes.adoc[opts=optional] + +== onecx-announcement-bff + +include::docs.adoc[opts=optional] + + +include::onecx-announcement-bff-docs.adoc[opts=optional] diff --git a/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-attributes.adoc b/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-attributes.adoc new file mode 100644 index 0000000..bebedc2 --- /dev/null +++ b/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-attributes.adoc @@ -0,0 +1,5 @@ + +:docker-registry: https://github.com/onecx/onecx-announcement-bff/pkgs/container/onecx-announcement-bff +:helm-registry: https://github.com/onecx/onecx-announcement-bff/pkgs/container/charts%2Fonecx-announcement-bff +:properties-file: src/main/resources/application.properties +:helm-file: src/main/helm/values.yaml \ No newline at end of file diff --git a/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-docs.adoc b/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-docs.adoc new file mode 100644 index 0000000..9cc0140 --- /dev/null +++ b/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-docs.adoc @@ -0,0 +1,68 @@ + +include::onecx-announcement-bff-attributes.adoc[opts=optional] + +=== Default properties + +.{properties-file} +[%collapsible%open] +==== +[source,properties,subs=attributes+] +---- +quarkus.http.auth.permission.health.paths=/q/* +quarkus.http.auth.permission.health.policy=permit +quarkus.http.auth.permission.default.paths=/* +quarkus.http.auth.permission.default.policy=authenticated +onecx.permissions.application-id=${quarkus.application.name} +org.eclipse.microprofile.rest.client.propagateHeaders=apm-principal-token +%prod.quarkus.rest-client.onecx_announcement_svc.url=http://onecx-announcement-svc:8080 +%prod.quarkus.rest-client.onecx_workspace_svc_v1.url=http://onecx-workspace-svc:8080 +%prod.quarkus.oidc-client.client-id=${quarkus.application.name} +quarkus.openapi-generator.codegen.input-base-dir=target/tmp/openapi +quarkus.openapi-generator.codegen.spec.onecx_announcement_svc_yaml.config-key=onecx_announcement_svc +quarkus.openapi-generator.codegen.spec.onecx_announcement_svc_yaml.base-package=gen.org.tkit.onecx.announcement.client +quarkus.openapi-generator.codegen.spec.onecx_announcement_svc_yaml.return-response=true +quarkus.openapi-generator.codegen.spec.onecx_announcement_svc.additional-api-type-annotations=@org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +quarkus.openapi-generator.codegen.spec.onecx_announcement_svc.additional-model-type-annotations=@io.quarkus.runtime.annotations.RegisterForReflection; +quarkus.openapi-generator.codegen.spec.onecx_workspace_svc_v1_yaml.config-key=onecx_workspace_svc_v1 +quarkus.openapi-generator.codegen.spec.onecx_workspace_svc_v1_yaml.base-package=gen.org.tkit.onecx.workspace.client +quarkus.openapi-generator.codegen.spec.onecx_workspace_svc_v1_yaml.return-response=true +quarkus.openapi-generator.codegen.spec.onecx_workspace_svc_v1_yaml.additional-api-type-annotations=@org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders; +quarkus.openapi-generator.codegen.spec.onecx_workspace_svc_v1_yaml.additional-model-type-annotations=@io.quarkus.runtime.annotations.RegisterForReflection; +onecx.permissions.product-name=application +---- +==== + +=== Extensions + +include::onecx-announcement-bff-extensions.adoc[opts=optional] + +=== Container + +{docker-registry}[Docker registry] + + +=== Helm + +{helm-registry}[Helm registry] + +Default values + +.{helm-file} +[source,yaml] +---- +app: + name: bff + image: + repository: "onecx/onecx-announcement-bff" + operator: + # Permission + permission: + enabled: true + spec: + permissions: + announcement: + read: permission on all GET requests and POST search + write: permission on PUT, POST, PATCH requests, where objects are saved or updated + delete: permission on all DELETE requests +---- + diff --git a/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-extensions.adoc b/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-extensions.adoc new file mode 100644 index 0000000..b0f3254 --- /dev/null +++ b/docs/modules/onecx-announcement-bff/pages/onecx-announcement-bff-extensions.adoc @@ -0,0 +1,139 @@ + +include::onecx-announcement-bff-attributes.adoc[opts=optional] + +[.extension.table.searchable, cols="50,.^15,.^15,.^20"] +|=== +h| Extensions +h| Documentation +h| Configuration +h| Version + +| quarkus-rest + +| https://quarkus.io/guides/rest[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-rest.adoc[Link] +| 3.9.3 + +| quarkus-smallrye-openapi + +| https://quarkus.io/guides/openapi-swaggerui[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-smallrye-openapi.adoc[Link] +| 3.9.3 + +| quarkus-rest-jackson + +| https://quarkus.io/guides/rest-json[Link] +| +| 3.9.3 + +| quarkus-smallrye-health + +| https://quarkus.io/guides/smallrye-health[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-smallrye-health.adoc[Link] +| 3.9.3 + +| quarkus-openapi-generator + +| https://docs.quarkiverse.io/quarkus-openapi-generator/dev/index.html[Link] +| https://github.com/quarkiverse/quarkus-openapi-generator/blob/2.4.1/docs/modules/ROOT/pages/includes/quarkus-openapi-generator.adoc[Link] +| 2.4.1 + +| quarkus-rest-client-reactive-jackson + +| https://quarkus.io/guides/rest-client[Link] +| +| 3.9.3 + +| tkit-quarkus-log-cdi + +| https://1000kit.github.io/tkit-quarkus/current/tkit-quarkus/tkit-quarkus-log-cdi.html[Link] +| https://github.com/1000kit/tkit-quarkus/blob/2.22.0/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-log-cdi.adoc[Link] +| 2.22.0 + +| tkit-quarkus-log-rs + +| https://1000kit.github.io/tkit-quarkus/current/tkit-quarkus/tkit-quarkus-log-rs.html[Link] +| https://github.com/1000kit/tkit-quarkus/blob/2.22.0/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-log-rs.adoc[Link] +| 2.22.0 + +| tkit-quarkus-log-json + +| https://1000kit.github.io/tkit-quarkus/current/tkit-quarkus/tkit-quarkus-log-json.html[Link] +| https://github.com/1000kit/tkit-quarkus/blob/2.22.0/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-log-json.adoc[Link] +| 2.22.0 + +| tkit-quarkus-rest + +| https://1000kit.github.io/tkit-quarkus/current/tkit-quarkus/tkit-quarkus-rest.html[Link] +| https://github.com/1000kit/tkit-quarkus/blob/2.22.0/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-rest.adoc[Link] +| 2.22.0 + +| tkit-quarkus-rest-context + +| https://1000kit.github.io/tkit-quarkus/current/tkit-quarkus/tkit-quarkus-rest-context.html[Link] +| https://github.com/1000kit/tkit-quarkus/blob/2.22.0/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-rest-context.adoc[Link] +| 2.22.0 + +| quarkus-hibernate-validator + +| https://quarkus.io/guides/validation[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-hibernate-validator.adoc[Link] +| 3.9.3 + +| quarkus-opentelemetry + +| https://quarkus.io/guides/opentelemetry[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-opentelemetry.adoc[Link] +| 3.9.3 + +| quarkus-micrometer-registry-prometheus + +| https://quarkus.io/guides/telemetry-micrometer[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-micrometer-registry-prometheus.adoc[Link] +| 3.9.3 + +| onecx-permissions + +| https://onecx.github.io/docs/onecx-quarkus/current/onecx-quarkus/onecx-permissions.html[Link] +| https://github.com/onecx/onecx-quarkus/blob/0.17.0/docs/modules/onecx-quarkus/pages/includes/onecx-permissions.adoc[Link] +| 0.17.0 + +| quarkus-oidc + +| https://quarkus.io/guides/security-oidc-bearer-token-authentication-tutorial[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-oidc.adoc[Link] +| 3.9.3 + +| quarkus-oidc-client-reactive-filter + +| https://quarkus.io/guides/security-openid-connect-client-reference[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-oidc-client-reactive-filter.adoc[Link] +| 3.9.3 + +| tkit-quarkus-security + +| https://1000kit.github.io/tkit-quarkus/current/tkit-quarkus/tkit-quarkus-security.html[Link] +| https://github.com/1000kit/tkit-quarkus/blob/2.22.0/docs/modules/tkit-quarkus/pages/includes/tkit-quarkus-security.adoc[Link] +| 2.22.0 + +| onecx-core + +| https://onecx.github.io/docs/onecx-quarkus/current/onecx-quarkus/onecx-core.html[Link] +| +| 0.17.0 + +| quarkus-arc + +| https://quarkus.io/guides/cdi-reference[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-arc.adoc[Link] +| 3.9.3 + +| quarkus-container-image-docker + +| https://quarkus.io/guides/container-image[Link] +| https://github.com/quarkusio/quarkusio.github.io/blob/develop/_generated-doc/latest/config/quarkus-container-image-docker.adoc[Link] +| 3.9.3 + + + +|=== \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2170e14..29df6fc 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.tkit.onecx onecx-quarkus3-parent - 0.37.0 + 0.47.0 onecx-announcement-bff @@ -15,7 +15,7 @@ io.quarkus - quarkus-resteasy-reactive + quarkus-rest io.quarkus @@ -23,7 +23,7 @@ io.quarkus - quarkus-resteasy-reactive-jackson + quarkus-rest-jackson io.quarkus diff --git a/src/main/java/org/tkit/onecx/announcement/bff/rs/controller/AnnouncementRestController.java b/src/main/java/org/tkit/onecx/announcement/bff/rs/controller/AnnouncementRestController.java index b1a2e81..8b32d99 100644 --- a/src/main/java/org/tkit/onecx/announcement/bff/rs/controller/AnnouncementRestController.java +++ b/src/main/java/org/tkit/onecx/announcement/bff/rs/controller/AnnouncementRestController.java @@ -6,10 +6,10 @@ import jakarta.inject.Inject; import jakarta.transaction.Transactional; import jakarta.validation.ConstraintViolationException; -import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Response; import org.eclipse.microprofile.rest.client.inject.RestClient; +import org.jboss.resteasy.reactive.ClientWebApplicationException; import org.jboss.resteasy.reactive.RestResponse; import org.jboss.resteasy.reactive.server.ServerExceptionMapper; import org.tkit.onecx.announcement.bff.rs.mappers.AnnouncementMapper; @@ -91,6 +91,23 @@ public Response getAnnouncementById(String id) { } } + @Override + public Response searchActiveAnnouncements(ActiveAnnouncementsSearchCriteriaDTO activeAnnouncementsSearchCriteriaDTO) { + var searchCriteria = announcementMapper.mapActiveAnnouncementSearchCriteria(activeAnnouncementsSearchCriteriaDTO); + searchCriteria.setPageSize(100); + searchCriteria.setPageNumber(0); + try (Response response = client + .getAnnouncements(searchCriteria)) { + AnnouncementPageResult announcementPageResult = response.readEntity(AnnouncementPageResult.class); + ActiveAnnouncementsPageResultDTO announcementPageResultDTO = announcementMapper + .mapAnnouncementPageResultToActiveAnnouncementPageResultDTO(announcementPageResult); + announcementPageResultDTO = announcementMapper.filterAndSort(announcementPageResultDTO, + activeAnnouncementsSearchCriteriaDTO); + + return Response.status(response.getStatus()).entity(announcementPageResultDTO).build(); + } + } + @Override public Response searchAnnouncements(AnnouncementSearchCriteriaDTO announcementSearchCriteriaDTO) { @@ -116,13 +133,11 @@ public Response updateAnnouncementById(String id, UpdateAnnouncementRequestDTO u @ServerExceptionMapper public RestResponse constraint(ConstraintViolationException ex) { - return exceptionMapper.constraint(ex); } @ServerExceptionMapper - public Response restException(WebApplicationException ex) { - - return Response.status(ex.getResponse().getStatus()).build(); + public Response restException(ClientWebApplicationException ex) { + return exceptionMapper.clientException(ex); } } diff --git a/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/AnnouncementMapper.java b/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/AnnouncementMapper.java index 60ade18..f9a9043 100644 --- a/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/AnnouncementMapper.java +++ b/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/AnnouncementMapper.java @@ -1,6 +1,6 @@ package org.tkit.onecx.announcement.bff.rs.mappers; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import org.mapstruct.Mapper; @@ -33,4 +33,74 @@ default Set workspaceNames(WorkspacePageResult result) { @Mapping(target = "removeStreamItem", ignore = true) AnnouncementPageResultDTO mapAnnouncementPageResultToAnnouncementPageResultDTO( AnnouncementPageResult announcementPageResult); + + @Mapping(target = "type", ignore = true) + @Mapping(target = "title", ignore = true) + @Mapping(target = "status", constant = "ACTIVE") + @Mapping(target = "startDateTo", source = "currentDate") + @Mapping(target = "startDateFrom", ignore = true) + @Mapping(target = "priority", ignore = true) + @Mapping(target = "endDateTo", ignore = true) + @Mapping(target = "endDateFrom", source = "currentDate") + @Mapping(target = "content", ignore = true) + @Mapping(target = "appId", ignore = true) + @Mapping(target = "workspaceName", ignore = true) + AnnouncementSearchCriteria mapActiveAnnouncementSearchCriteria( + ActiveAnnouncementsSearchCriteriaDTO activeAnnouncementsSearchCriteriaDTO); + + @Mapping(target = "removeStreamItem", ignore = true) + ActiveAnnouncementsPageResultDTO mapAnnouncementPageResultToActiveAnnouncementPageResultDTO( + AnnouncementPageResult announcementPageResult); + + default List sort(List mergedResult) { + List sortedList = new ArrayList<>(mergedResult); + sortedList.sort(Comparator.comparing(AnnouncementAbstractDTO::getPriority) + .thenComparing((AnnouncementAbstractDTO item) -> item.getWorkspaceName() == null ? 0 : 1) + .thenComparing(AnnouncementAbstractDTO::getTitle)); + return sortedList; + } + + default ActiveAnnouncementsPageResultDTO filterAndSort(ActiveAnnouncementsPageResultDTO announcementPageResultDTO, + ActiveAnnouncementsSearchCriteriaDTO activeAnnouncementsSearchCriteriaDTO) { + ActiveAnnouncementsPageResultDTO pageResult = new ActiveAnnouncementsPageResultDTO(); + + if (activeAnnouncementsSearchCriteriaDTO.getWorkspaceName() != null) { + pageResult.setStream(announcementPageResultDTO.getStream().stream() + .filter(announcementAbstractDTO -> announcementAbstractDTO.getWorkspaceName() == null + || announcementAbstractDTO.getWorkspaceName().equals(activeAnnouncementsSearchCriteriaDTO + .getWorkspaceName())) + .toList()); + } else { + pageResult.setStream(announcementPageResultDTO.getStream().stream() + .filter(announcementAbstractDTO -> announcementAbstractDTO.getWorkspaceName() == null).toList()); + } + //remove duplicates + HashSet set = new HashSet<>(pageResult.getStream()); + pageResult.setStream(sort(set.stream().toList())); + + pageResult.setTotalElements((long) pageResult.getStream().size()); + pageResult.setNumber(activeAnnouncementsSearchCriteriaDTO.getPageNumber()); + pageResult.setSize(activeAnnouncementsSearchCriteriaDTO.getPageSize()); + pageResult.setTotalPages(1L); + if (pageResult.getTotalElements() / pageResult.getSize() > 0) { + pageResult.setTotalPages(pageResult.getTotalElements() / pageResult.getSize()); + } + int startIndex = 0; + int endIndex = Math.toIntExact(pageResult.getTotalElements()); + if (activeAnnouncementsSearchCriteriaDTO.getPageNumber() != 0) { + startIndex = (activeAnnouncementsSearchCriteriaDTO.getPageSize() + * activeAnnouncementsSearchCriteriaDTO.getPageNumber()); + endIndex = startIndex + activeAnnouncementsSearchCriteriaDTO.getPageSize() - 1; + } + if (activeAnnouncementsSearchCriteriaDTO.getPageSize() != 100) { + endIndex = startIndex + activeAnnouncementsSearchCriteriaDTO.getPageSize(); + } + if (startIndex <= pageResult.getStream().size()) { + pageResult.setStream( + pageResult.getStream().subList(startIndex, Math.min(endIndex, pageResult.getStream().size()))); + } else { + pageResult.setStream(new ArrayList<>()); + } + return pageResult; + } } diff --git a/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/ExceptionMapper.java b/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/ExceptionMapper.java index 33b303d..199e0ba 100644 --- a/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/ExceptionMapper.java +++ b/src/main/java/org/tkit/onecx/announcement/bff/rs/mappers/ExceptionMapper.java @@ -1,5 +1,7 @@ package org.tkit.onecx.announcement.bff.rs.mappers; +import static jakarta.ws.rs.core.MediaType.APPLICATION_JSON; + import java.util.List; import java.util.Map; import java.util.Set; @@ -9,6 +11,7 @@ import jakarta.validation.Path; import jakarta.ws.rs.core.Response; +import org.jboss.resteasy.reactive.ClientWebApplicationException; import org.jboss.resteasy.reactive.RestResponse; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -17,6 +20,7 @@ import gen.org.tkit.onecx.announcement.bff.rs.internal.model.ProblemDetailInvalidParamDTO; import gen.org.tkit.onecx.announcement.bff.rs.internal.model.ProblemDetailParamDTO; import gen.org.tkit.onecx.announcement.bff.rs.internal.model.ProblemDetailResponseDTO; +import gen.org.tkit.onecx.announcement.client.model.ProblemDetailResponse; @Mapper(uses = { OffsetDateTimeMapper.class }) public interface ExceptionMapper { @@ -27,6 +31,24 @@ default RestResponse constraint(ConstraintViolationExc return RestResponse.status(Response.Status.BAD_REQUEST, dto); } + default Response clientException(ClientWebApplicationException ex) { + if (ex.getResponse().getStatus() == 500) { + return Response.status(400).build(); + } else { + if (ex.getResponse().getMediaType() != null + && ex.getResponse().getMediaType().toString().equals(APPLICATION_JSON)) { + return Response.status(ex.getResponse().getStatus()) + .entity(map(ex.getResponse().readEntity(ProblemDetailResponse.class))).build(); + } else { + return Response.status(ex.getResponse().getStatus()).build(); + } + } + } + + @Mapping(target = "removeParamsItem", ignore = true) + @Mapping(target = "removeInvalidParamsItem", ignore = true) + ProblemDetailResponseDTO map(ProblemDetailResponse problemDetailResponse); + @Mapping(target = "removeParamsItem", ignore = true) @Mapping(target = "params", ignore = true) @Mapping(target = "invalidParams", ignore = true) diff --git a/src/main/openapi/openapi-bff.yaml b/src/main/openapi/openapi-bff.yaml index 5aab436..6d32d40 100644 --- a/src/main/openapi/openapi-bff.yaml +++ b/src/main/openapi/openapi-bff.yaml @@ -37,6 +37,35 @@ paths: application/json: schema: $ref: '#/components/schemas/ProblemDetailResponse' + /announcements/active/search: + post: + x-onecx: + permissions: + announcement: + - read + tags: + - AnnouncementInternal + summary: Find active announcements by criteria + operationId: searchActiveAnnouncements + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ActiveAnnouncementsSearchCriteria' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/ActiveAnnouncementsPageResult' + "400": + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/ProblemDetailResponse' /announcements: post: x-onecx: @@ -337,6 +366,60 @@ components: type: array items: $ref: '#/components/schemas/Announcement' + ActiveAnnouncementsSearchCriteria: + type: object + required: + - currentDate + properties: + currentDate: + $ref: '#/components/schemas/OffsetDateTime' + workspaceName: + type: string + pageNumber: + format: int32 + description: The number of page. + default: 0 + type: integer + pageSize: + format: int32 + description: The size of page + default: 100 + type: integer + ActiveAnnouncementsPageResult: + type: object + properties: + totalElements: + format: int64 + description: The total elements in the resource. + type: integer + number: + format: int32 + type: integer + size: + format: int32 + type: integer + totalPages: + format: int64 + type: integer + stream: + type: array + items: + $ref: '#/components/schemas/AnnouncementAbstract' + AnnouncementAbstract: + type: object + properties: + id: + type: string + title: + type: string + content: + type: string + type: + $ref: '#/components/schemas/AnnouncementType' + priority: + $ref: '#/components/schemas/AnnouncementPriorityType' + workspaceName: + type: string AnnouncementPriorityType: enum: - IMPORTANT diff --git a/src/test/java/org/tkit/onecx/announcement/bff/rs/AnnouncementRestControllerTest.java b/src/test/java/org/tkit/onecx/announcement/bff/rs/AnnouncementRestControllerTest.java index 3588380..daf249d 100644 --- a/src/test/java/org/tkit/onecx/announcement/bff/rs/AnnouncementRestControllerTest.java +++ b/src/test/java/org/tkit/onecx/announcement/bff/rs/AnnouncementRestControllerTest.java @@ -419,4 +419,92 @@ void getAllWorkspaceNames() { Assertions.assertNotNull(response); Assertions.assertTrue(response.contains("testWorkspace")); } + + @Test + void searchActiveAnnouncements_shouldReturnAnnouncementPageResults() { + + Announcement a1 = new Announcement(); + a1.setAppId("appId"); + a1.setContent("AnnouncmentContent"); + a1.setPriority(AnnouncementPriorityType.IMPORTANT); + a1.setTitle("A1"); + a1.setWorkspaceName("w1"); + a1.setStartDate(OffsetDateTime.parse("2024-04-11T10:09:24-04:00")); + a1.setEndDate(OffsetDateTime.parse("2024-04-25T10:09:24-04:00")); + Announcement a2 = new Announcement(); + a2.setAppId("appId"); + a2.setContent("AnnouncmentContent"); + a2.setPriority(AnnouncementPriorityType.NORMAL); + a2.setTitle("A2"); + a2.setWorkspaceName("w1"); + a2.setStartDate(OffsetDateTime.parse("2024-04-11T10:09:24-04:00")); + a2.setEndDate(OffsetDateTime.parse("2024-04-25T10:09:24-04:00")); + Announcement a3 = new Announcement(); + a3.setAppId("appId"); + a3.setContent("AnnouncmentContent"); + a3.setPriority(AnnouncementPriorityType.IMPORTANT); + a3.setTitle("A3"); + a3.setWorkspaceName(null); + a3.setStartDate(OffsetDateTime.parse("2024-04-11T10:09:24-04:00")); + a3.setEndDate(OffsetDateTime.parse("2024-04-25T10:09:24-04:00")); + Announcement a4 = new Announcement(); + a4.setAppId("appId"); + a4.setContent("Shouldn't be returned"); + a4.setPriority(AnnouncementPriorityType.IMPORTANT); + a4.setTitle("A4"); + a4.setWorkspaceName("w2"); + a4.setStartDate(OffsetDateTime.parse("2024-04-11T10:09:24-04:00")); + a4.setEndDate(OffsetDateTime.parse("2024-04-25T10:09:24-04:00")); + List announcements = new ArrayList<>(); + announcements.add(a1); + announcements.add(a2); + announcements.add(a3); + announcements.add(a4); + + // Request data to svc + AnnouncementPageResult data = new AnnouncementPageResult(); + data.setSize(2); + data.setTotalPages(1L); + data.setNumber(0); + data.setStream(announcements); + + AnnouncementSearchCriteria criteria1 = new AnnouncementSearchCriteria(); + + // svc call prepare mock endpoint + mockServerClient + .when(request().withPath(ANNOUNCEMENT_SVC_INTERNAL_API_BASE_PATH + "/search") + .withBody(JsonBody.json(criteria1)) + .withMethod(HttpMethod.POST)) + .withId(mockId) + .respond(httpRequest -> response().withStatusCode(Response.Status.OK.getStatusCode()) + .withContentType(MediaType.APPLICATION_JSON) + .withBody(JsonBody.json(data))); + + // bff call input + ActiveAnnouncementsSearchCriteriaDTO input = new ActiveAnnouncementsSearchCriteriaDTO(); + input.setWorkspaceName("w1"); + input.setCurrentDate(OffsetDateTime.parse("2024-04-24T12:15:50-04:00")); + + // bff call + var response = given() + .when() + .auth().oauth2(keycloakClient.getAccessToken(ADMIN)) + .header(APM_HEADER_PARAM, ADMIN) + .contentType(APPLICATION_JSON) + .body(input) + .post("/active/search") + .then() + .statusCode(Response.Status.OK.getStatusCode()) + .contentType(APPLICATION_JSON) + .extract().as(AnnouncementPageResult.class); + + // Assertions + Assertions.assertNotNull(response); + Assertions.assertEquals(3, response.getStream().size()); + Assertions.assertEquals(AnnouncementPriorityType.IMPORTANT, response.getStream().get(0).getPriority()); + Assertions.assertNull(response.getStream().get(0).getWorkspaceName()); + Assertions.assertEquals(AnnouncementPriorityType.IMPORTANT, response.getStream().get(1).getPriority()); + Assertions.assertEquals("w1", response.getStream().get(1).getWorkspaceName()); + + } }