diff --git a/kraken-app/kraken-app-portal/src/pages/StandardAPIMapping/index.tsx b/kraken-app/kraken-app-portal/src/pages/StandardAPIMapping/index.tsx index 9a0166129..7f2e1c36c 100644 --- a/kraken-app/kraken-app-portal/src/pages/StandardAPIMapping/index.tsx +++ b/kraken-app/kraken-app-portal/src/pages/StandardAPIMapping/index.tsx @@ -1,3 +1,4 @@ +import { AxiosError} from 'axios' import RollbackIcon from "@/assets/newAPIMapping/Rollback.svg"; import BreadCrumb from "@/components/Breadcrumb"; import DeployStage from "@/components/DeployStage"; @@ -14,6 +15,7 @@ import { useMappingUiStore } from "@/stores/mappingUi.store"; import { useNewApiMappingStore } from "@/stores/newApiMapping.store"; import buildInitListMapping from "@/utils/helpers/buildInitListMapping"; import groupByPath from "@/utils/helpers/groupByPath"; +import { BackendErrorResponse } from "@/utils/types/common.type"; import { IMappers } from "@/utils/types/component.type"; import { IMapperDetails } from "@/utils/types/env.type"; import { Flex, Spin, Button, Tooltip, notification, Drawer } from "antd"; @@ -345,12 +347,14 @@ const StandardAPIMapping = () => { callback && callback(); return true; } catch (error) { + const err = error as AxiosError; + const reason = + err?.response?.data?.reason ?? + err?.response?.data?.message ?? + err?.message ?? + "Error on creating/updating mapping"; notification.error({ - message: get( - error, - "reason", - get(error, "message", "Error on creating/updating mapping") - ), + message: reason, }); } }; diff --git a/kraken-app/kraken-app-portal/src/utils/types/common.type.ts b/kraken-app/kraken-app-portal/src/utils/types/common.type.ts index 4869c5e95..bb7e25d67 100644 --- a/kraken-app/kraken-app-portal/src/utils/types/common.type.ts +++ b/kraken-app/kraken-app-portal/src/utils/types/common.type.ts @@ -95,3 +95,11 @@ export interface IPagination { size: number; total: number; } + + +export interface BackendErrorResponse { + code?: string; + reason?: string; + message?: string; + referenceError?: string; +} \ No newline at end of file diff --git a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/ApiComponentService.java b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/ApiComponentService.java index 89c6eecfe..1666bdaee 100644 --- a/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/ApiComponentService.java +++ b/kraken-java-sdk/kraken-java-sdk-controller/src/main/java/com/consoleconnect/kraken/operator/controller/service/ApiComponentService.java @@ -181,8 +181,20 @@ private void validateMapper(UnifiedAsset request, UnifiedAssetDto origin) { ComponentAPITargetFacets.Endpoint endpoint = requestFacets.getEndpoints().get(0); ComponentAPITargetFacets.Mappers requestMapper = endpoint.getMappers(); // check source and target contains sensitive tokens in the updateMapper - requestMapper.getRequest().forEach(mapper -> SecurityTool.evaluate(mapper.getSource())); - requestMapper.getResponse().forEach(mapper -> SecurityTool.evaluate(mapper.getTarget())); + requestMapper + .getRequest() + .forEach( + mapper -> { + SecurityTool.evaluate(mapper.getSource()); + checkLocationExisted(mapper); + }); + requestMapper + .getResponse() + .forEach( + mapper -> { + checkLocationExisted(mapper); + SecurityTool.evaluate(mapper.getTarget()); + }); ComponentAPITargetFacets.Mappers originMapper = originFacets.getEndpoints().get(0).getMappers(); if (originMapper == null) { @@ -226,6 +238,19 @@ private void checkMapper( }); } + private void checkLocationExisted(ComponentAPITargetFacets.Mapper updateMapper) { + if (StringUtils.isNotBlank(updateMapper.getSource()) + && StringUtils.isBlank(updateMapper.getSourceLocation())) { + throw KrakenException.badRequest( + "The field: " + updateMapper.getSource() + " should not have blank source location!"); + } + if (StringUtils.isNotBlank(updateMapper.getTarget()) + && StringUtils.isBlank(updateMapper.getTargetLocation())) { + throw KrakenException.badRequest( + "The field: " + updateMapper.getTarget() + " should not have blank target location!"); + } + } + private void compareProperty(Object o1, Object o2) { if (!Objects.deepEquals(o1, o2)) { throw KrakenException.badRequest( diff --git a/kraken-java-sdk/kraken-java-sdk-controller/src/test/java/com/consoleconnect/kraken/operator/controller/ComponentMgmtControllerTest.java b/kraken-java-sdk/kraken-java-sdk-controller/src/test/java/com/consoleconnect/kraken/operator/controller/ComponentMgmtControllerTest.java index 79a1e12ce..d66feb609 100644 --- a/kraken-java-sdk/kraken-java-sdk-controller/src/test/java/com/consoleconnect/kraken/operator/controller/ComponentMgmtControllerTest.java +++ b/kraken-java-sdk/kraken-java-sdk-controller/src/test/java/com/consoleconnect/kraken/operator/controller/ComponentMgmtControllerTest.java @@ -575,4 +575,120 @@ void givenMapper_whenIncludeMaliciousTokens_thenThrowError() { JsonToolkit.toJson(facets), new TypeReference>() {})); assertUpdateErrorResult(maliciousAsset); } + + @SneakyThrows + @Test + void givenEmptySourceLocation_whenUpdateTargetMapper_thenThrowsException() { + UnifiedAssetDto assetDto = + unifiedAssetService.findOne("mef.sonata.api-target-mapper.order.eline.add"); + Optional mapperAssetOpt = + YamlToolkit.parseYaml( + readFileToString( + "deployment-config/api-targets-mappers/api-target-mapper.order.eline.add.yaml"), + UnifiedAsset.class); + if (mapperAssetOpt.isPresent()) { + UnifiedAsset targetMapperAsset = mapperAssetOpt.get(); + ComponentAPITargetFacets newFacets = + UnifiedAsset.getFacets(targetMapperAsset, ComponentAPITargetFacets.class); + ComponentAPITargetFacets.Endpoint newEndpoints = newFacets.getEndpoints().get(0); + ComponentAPITargetFacets existFacets = + UnifiedAsset.getFacets(assetDto, ComponentAPITargetFacets.class); + ComponentAPITargetFacets.Endpoint existEndpoints = existFacets.getEndpoints().get(0); + fillRequestMappers(existEndpoints); + existFacets.getEndpoints().set(0, existEndpoints); + assetDto.setFacets( + JsonToolkit.fromJson( + JsonToolkit.toJson(existFacets), new TypeReference>() {})); + FacetsMapper.INSTANCE.toEndpoint(newEndpoints, existEndpoints); + } + log.info(JsonToolkit.toJson(assetDto)); + webTestClient + .mutate() + .responseTimeout(Duration.ofSeconds(600)) + .build() + .patch() + .uri( + uriBuilder -> + uriBuilder + .path(UPDATE_COMPONENT) + .build("mef.sonata.api-target-mapper.order.eline.add")) + .bodyValue(assetDto) + .exchange() + .expectBody() + .consumeWith( + response -> { + String bodyStr = new String(Objects.requireNonNull(response.getResponseBody())); + assertThat(bodyStr, hasJsonPath("$.code", is("invalidBody"))); + }); + } + + @SneakyThrows + @Test + void givenEmptyTargetLocation_whenUpdateTargetMapper_thenThrowsException() { + UnifiedAssetDto assetDto = + unifiedAssetService.findOne("mef.sonata.api-target-mapper.order.eline.add"); + Optional mapperAssetOpt = + YamlToolkit.parseYaml( + readFileToString( + "deployment-config/api-targets-mappers/api-target-mapper.order.eline.add.yaml"), + UnifiedAsset.class); + if (mapperAssetOpt.isPresent()) { + UnifiedAsset targetMapperAsset = mapperAssetOpt.get(); + ComponentAPITargetFacets newFacets = + UnifiedAsset.getFacets(targetMapperAsset, ComponentAPITargetFacets.class); + ComponentAPITargetFacets.Endpoint newEndpoints = newFacets.getEndpoints().get(0); + ComponentAPITargetFacets existFacets = + UnifiedAsset.getFacets(assetDto, ComponentAPITargetFacets.class); + ComponentAPITargetFacets.Endpoint existEndpoints = existFacets.getEndpoints().get(0); + fillResponseMappers(existEndpoints); + existFacets.getEndpoints().set(0, existEndpoints); + assetDto.setFacets( + JsonToolkit.fromJson( + JsonToolkit.toJson(existFacets), new TypeReference>() {})); + FacetsMapper.INSTANCE.toEndpoint(newEndpoints, existEndpoints); + } + log.info(JsonToolkit.toJson(assetDto)); + webTestClient + .mutate() + .responseTimeout(Duration.ofSeconds(600)) + .build() + .patch() + .uri( + uriBuilder -> + uriBuilder + .path(UPDATE_COMPONENT) + .build("mef.sonata.api-target-mapper.order.eline.add")) + .bodyValue(assetDto) + .exchange() + .expectBody() + .consumeWith( + response -> { + String bodyStr = new String(Objects.requireNonNull(response.getResponseBody())); + assertThat(bodyStr, hasJsonPath("$.code", is("invalidBody"))); + }); + } + + private void fillRequestMappers(ComponentAPITargetFacets.Endpoint existEndpoints) { + List request = new ArrayList<>(); + ComponentAPITargetFacets.Mapper mapper1 = new ComponentAPITargetFacets.Mapper(); + mapper1.setSource("@{{productOrderItem[0].product.productConfiguration.dcfName}}"); + request.add(mapper1); + List response = new ArrayList<>(); + ComponentAPITargetFacets.Mappers mappers = new ComponentAPITargetFacets.Mappers(); + mappers.setRequest(request); + mappers.setResponse(response); + existEndpoints.setMappers(mappers); + } + + private void fillResponseMappers(ComponentAPITargetFacets.Endpoint existEndpoints) { + List request = new ArrayList<>(); + List response = new ArrayList<>(); + ComponentAPITargetFacets.Mapper mapper1 = new ComponentAPITargetFacets.Mapper(); + mapper1.setTarget("@{{note[*].author}}"); + response.add(mapper1); + ComponentAPITargetFacets.Mappers mappers = new ComponentAPITargetFacets.Mappers(); + mappers.setRequest(request); + mappers.setResponse(response); + existEndpoints.setMappers(mappers); + } } diff --git a/kraken-java-sdk/kraken-java-sdk-test/src/main/java/com/consoleconnect/kraken/operator/test/KrakenPostgresqlContainer.java b/kraken-java-sdk/kraken-java-sdk-test/src/main/java/com/consoleconnect/kraken/operator/test/KrakenPostgresqlContainer.java index 8089dfff6..4a8f392cf 100644 --- a/kraken-java-sdk/kraken-java-sdk-test/src/main/java/com/consoleconnect/kraken/operator/test/KrakenPostgresqlContainer.java +++ b/kraken-java-sdk/kraken-java-sdk-test/src/main/java/com/consoleconnect/kraken/operator/test/KrakenPostgresqlContainer.java @@ -14,7 +14,7 @@ public KrakenPostgresqlContainer() { public static KrakenPostgresqlContainer getInstance() { if (container == null) { container = new KrakenPostgresqlContainer(); - container.addFixedExposedPort(6432, 5432); + container.addFixedExposedPort(6433, 5432); } return container; }