diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9b73abf..1f16c91 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,9 +8,8 @@ on: - alpha - development - jobs: - unit-tests: + app-unit-tests: runs-on: ubuntu-latest steps: @@ -27,3 +26,34 @@ jobs: cd clearing-house-app cargo build --verbose cargo test --verbose + + edc-unit-tests: + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Setup JDK 17 + uses: actions/setup-java@v2 + with: + java-version: '17' + distribution: 'temurin' + + - name: Run Unit Tests + run: | + cd clearing-house-edc + ./gradlew test jacocoTestReport + + - name: Add Coverage Report + id: jacoco + uses: madrapps/jacoco-report@v1.6.1 + with: + paths: | + ${{ github.workspace }}/clearing-house-edc/core/build/reports/jacoco/test/jacocoTestReport.xml, + ${{ github.workspace }}clearing-house-edc/extensions/multipart/build/reports/jacoco/test/jacocoTestReport.xml + token: ${{ secrets.GITHUB_TOKEN }} + min-coverage-overall: 70 + min-coverage-changed-files: 80 diff --git a/clearing-house-edc/README.md b/clearing-house-edc/README.md new file mode 100644 index 0000000..6862e27 --- /dev/null +++ b/clearing-house-edc/README.md @@ -0,0 +1,44 @@ +## CLEARING HOUSE EDC +This repository contains the Clearing House Extension that works with the Eclipse Dataspace Connector +allowing logging operations. + +## Install +### Configurations +It is required to configure those parameters: + +| Parameter name | Description | Default value | +|----------------------------------------|----------------------------------------------|------------------------| +| `truzzt.clearinghouse.jwt.audience` | Defines the intended recipients of the token | 1 | +| `truzzt.clearinghouse.jwt.issuer` | Person or entity offering the token | 1 | +| `truzzt.clearinghouse.jwt.sign.secret` | Secret key to encode the token | 123 | +| `truzzt.clearinghouse.jwt.expires.at` | Time to token Expiration (in Seconds) | 30 | +| `truzzt.clearinghouse.app.base.url` | Base URL from the clearing house app | http://localhost:8000 | + +### Build +To build the project run the command below: + + ./gradlew build + + +### Running +Local execution: + + java -Dedc.fs.config=launchers/connector-local/resources/config.properties -Dedc.keystore=launchers/connector-local/resources/keystore.jks -Dedc.keystore.password=password -Dedc.vault=launchers/connector-local/resources/vault.properties -jar launchers/connector-local/build/libs/clearing-house-edc.jar + +## Tests + +### Running Tests +To run the unit-tests execute the following command: + + ./gradlew test + + +### Test Coverage +To generate the tests coverage execute the following command: + + ./gradlew jacocoTestReport + +The coverage reports will be available in the following folders: + +- [core/build/reports/jacoco/test/html/index.html](./core/build/reports/jacoco/test/html/index.html) +- [extensions/multipart/build/reports/jacoco/test/html/index.html](./extensions/multipart/build/reports/jacoco/test/html/index.html) diff --git a/clearing-house-edc/build.gradle.kts b/clearing-house-edc/build.gradle.kts index b9a452e..589224c 100644 --- a/clearing-house-edc/build.gradle.kts +++ b/clearing-house-edc/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,12 +8,12 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * Microsoft Corporation - initial implementation + * truzzt GmbH - Initial implementation * */ plugins { - `java-library` + `java-base` } val javaVersion: String by project @@ -22,4 +22,4 @@ java { toolchain { languageVersion = JavaLanguageVersion.of(javaVersion) } -} \ No newline at end of file +} diff --git a/clearing-house-edc/core/build.gradle.kts b/clearing-house-edc/core/build.gradle.kts index 38506d5..8fe966c 100644 --- a/clearing-house-edc/core/build.gradle.kts +++ b/clearing-house-edc/core/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,22 +8,50 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * Microsoft Corporation - Initial implementation + * truzzt GmbH - Initial implementation * */ plugins { `java-library` + `java-test-fixtures` + jacoco } val auth0JWTVersion: String by project +configurations.all { + exclude(group = "de.fraunhofer.iais.eis.ids.infomodel", module = "java") +} + dependencies { api(edc.spi.core) implementation(edc.ids) implementation(edc.ids.jsonld.serdes) implementation(edc.api.management.config) - + implementation(libs.jersey.multipart) implementation("com.auth0:java-jwt:${auth0JWTVersion}") + + implementation(":infomodel-java-4.1.3") + implementation(":infomodel-util-4.0.4") + + testImplementation(libs.junit.jupiter.api) + testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.inline) + + testFixturesImplementation(edc.ids) + testFixturesImplementation("com.auth0:java-jwt:${auth0JWTVersion}") + + testRuntimeOnly(libs.junit.jupiter.engine) +} + +tasks.test { + useJUnitPlatform() +} +tasks.jacocoTestReport { + reports { + xml.required = true + } + dependsOn(tasks.test) } diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/AppSender.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/AppSender.java index 978b227..f0584de 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/AppSender.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/AppSender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 sovity GmbH + * Copyright (c) 2023 truzzt GmbH * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,7 +8,7 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * sovity GmbH - initial API and implementation + * truzzt GmbH - Initial implementation * */ package de.truzzt.clearinghouse.edc.app; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/AppSenderDelegate.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/AppSenderDelegate.java index bd807ea..95ecb31 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/AppSenderDelegate.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/AppSenderDelegate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 sovity GmbH + * Copyright (c) 2023 truzzt GmbH * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,7 +8,7 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * sovity GmbH - initial API and implementation + * truzzt GmbH - Initial implementation * */ package de.truzzt.clearinghouse.edc.app.delegate; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/LoggingMessageDelegate.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/LoggingMessageDelegate.java index 7734ce6..bbc9892 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/LoggingMessageDelegate.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/app/delegate/LoggingMessageDelegate.java @@ -1,3 +1,16 @@ +/* + * Copyright (c) 2023 truzzt GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * truzzt GmbH - Initial implementation + * + */ package de.truzzt.clearinghouse.edc.app.delegate; import de.truzzt.clearinghouse.edc.dto.HandlerRequest; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/AppSenderRequest.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/AppSenderRequest.java index a1af118..dfd7397 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/AppSenderRequest.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/AppSenderRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 truzzt GmbH * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,10 +8,9 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * Microsoft Corporation - Initial implementation + * truzzt GmbH - Initial implementation * */ - package de.truzzt.clearinghouse.edc.dto; import org.jetbrains.annotations.NotNull; @@ -24,7 +23,7 @@ public class AppSenderRequest { private final String token; private final B body; - private AppSenderRequest(@NotNull String url, @NotNull String token, @NotNull B body) { + public AppSenderRequest(@NotNull String url, @NotNull String token, @NotNull B body) { this.url = url; this.token = token; this.body = body; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerRequest.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerRequest.java index 554601c..090ed37 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerRequest.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.dto; import de.truzzt.clearinghouse.edc.types.ids.Message; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerResponse.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerResponse.java index fbb048b..e79ae88 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerResponse.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/HandlerResponse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.dto; import de.truzzt.clearinghouse.edc.types.ids.Message; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageRequest.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageRequest.java index 172c84c..32c96a6 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageRequest.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageRequest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 truzzt GmbH * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,10 +8,9 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * Microsoft Corporation - Initial implementation + * truzzt GmbH - Initial implementation * */ - package de.truzzt.clearinghouse.edc.dto; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageResponse.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageResponse.java index 0db5f92..ac90345 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageResponse.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/dto/LoggingMessageResponse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 truzzt GmbH * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,10 +8,9 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * Microsoft Corporation - Initial implementation + * truzzt GmbH - Initial implementation * */ - package de.truzzt.clearinghouse.edc.dto; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/Handler.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/Handler.java index c70a71d..88cc093 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/Handler.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/Handler.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2023 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation + * + */ package de.truzzt.clearinghouse.edc.handler; import com.auth0.jwt.JWT; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/LogMessageHandler.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/LogMessageHandler.java index ecab1df..2d48528 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/LogMessageHandler.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/handler/LogMessageHandler.java @@ -1,3 +1,16 @@ +/* + * Copyright (c) 2023 truzzt GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * truzzt GmbH - Initial implementation + * + */ package de.truzzt.clearinghouse.edc.handler; import de.truzzt.clearinghouse.edc.app.AppSender; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/TypeManagerUtil.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/TypeManagerUtil.java index b4d744b..370002f 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/TypeManagerUtil.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/TypeManagerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,10 +8,10 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * truzzt GmbH - Initial implementation + * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types; import com.fasterxml.jackson.core.JsonProcessingException; @@ -37,9 +37,9 @@ public T parse(InputStream inputStream, Class type) { } } - public byte[] toJson(Object object) { + public String toJson(Object object) { try { - return mapper.writeValueAsBytes(object); + return mapper.writeValueAsString(object); } catch (JsonProcessingException e) { throw new EdcException("Error converting to JSON", e); } diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Context.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Context.java index f0b800a..a835cde 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Context.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Context.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.clearinghouse; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Header.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Header.java index dfc3dd6..f5e55c7 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Header.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/Header.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.clearinghouse; import com.fasterxml.jackson.annotation.JsonFormat; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/SecurityToken.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/SecurityToken.java index 8ca532b..9f34154 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/SecurityToken.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/SecurityToken.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.clearinghouse; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/TokenFormat.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/TokenFormat.java index 216c4ad..13fd596 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/TokenFormat.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/clearinghouse/TokenFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.clearinghouse; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Context.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Context.java index 14a2223..d0bd908 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Context.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Context.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.ids; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Message.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Message.java index 323c3dd..c363fbc 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Message.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/Message.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.ids; import com.fasterxml.jackson.annotation.JsonFormat; @@ -53,7 +53,7 @@ public class Message { String modelVersion; @JsonProperty("ids:issued") - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSzzz") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS") @NotNull XMLGregorianCalendar issued; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionMessage.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionMessage.java index ce4652a..f6a77ca 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionMessage.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.ids; import com.fasterxml.jackson.annotation.JsonProperty; @@ -25,6 +25,8 @@ public class RejectionMessage extends Message { @NotNull RejectionReason rejectionReason; + public RejectionMessage() { + } public RejectionMessage(@NotNull URI id) { super(id); } diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionReason.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionReason.java index 9fdde06..506998b 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionReason.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/RejectionReason.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.ids; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/SecurityToken.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/SecurityToken.java index 795e708..b8f1b46 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/SecurityToken.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/SecurityToken.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.ids; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/TokenFormat.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/TokenFormat.java index 6d05134..56d86cd 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/TokenFormat.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/TokenFormat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.ids; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/util/VocabUtil.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/util/VocabUtil.java index 5f16361..15a7680 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/util/VocabUtil.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/types/ids/util/VocabUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,9 +9,9 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - package de.truzzt.clearinghouse.edc.types.ids.util; import java.net.MalformedURLException; diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/ResponseUtil.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/ResponseUtil.java index 11699de..0403b3b 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/ResponseUtil.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/ResponseUtil.java @@ -1,15 +1,34 @@ +/* + * Copyright (c) 2023 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation + * + */ package de.truzzt.clearinghouse.edc.util; import de.truzzt.clearinghouse.edc.dto.HandlerResponse; +import de.truzzt.clearinghouse.edc.types.TypeManagerUtil; import de.truzzt.clearinghouse.edc.types.ids.Message; import de.truzzt.clearinghouse.edc.types.ids.RejectionMessage; import de.truzzt.clearinghouse.edc.types.ids.RejectionReason; +import jakarta.ws.rs.core.MediaType; import org.eclipse.edc.protocol.ids.spi.domain.IdsConstants; import org.eclipse.edc.protocol.ids.spi.types.IdsId; import org.eclipse.edc.protocol.ids.spi.types.IdsType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.glassfish.jersey.media.multipart.FormDataMultiPart; + import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; @@ -22,6 +41,29 @@ public class ResponseUtil { private static final String PROCESSED_NOTIFICATION_TYPE = "ids:MessageProcessedNotificationMessage"; + public static FormDataMultiPart createFormDataMultiPart(TypeManagerUtil typeManagerUtil, + String headerName, + Message headerValue, + String payloadName, + Object payloadValue) { + var multiPart = createFormDataMultiPart(typeManagerUtil, headerName, headerValue); + + if (payloadValue != null) { + multiPart.bodyPart(new FormDataBodyPart(payloadName, typeManagerUtil.toJson(payloadValue), MediaType.APPLICATION_JSON_TYPE)); + } + + return multiPart; + } + + public static FormDataMultiPart createFormDataMultiPart(TypeManagerUtil typeManagerUtil, String headerName, Message headerValue) { + var multiPart = new FormDataMultiPart(); + + if (headerValue != null) { + multiPart.bodyPart(new FormDataBodyPart(headerName, typeManagerUtil.toJson(headerValue), MediaType.APPLICATION_JSON_TYPE)); + } + return multiPart; + } + public static HandlerResponse createMultipartResponse(@NotNull Message header, @NotNull Object payload) { return HandlerResponse.Builder.newInstance() .header(header) @@ -96,11 +138,21 @@ private static RejectionMessage createRejectionMessage(@Nullable Message correla return rejectionMessage; } + @NotNull + public static RejectionMessage createRejectionMessage(@NotNull RejectionReason reason, + @Nullable Message correlationMessage, + @NotNull IdsId connectorId) { + RejectionMessage rejectionMessage = createRejectionMessage(correlationMessage, connectorId); + rejectionMessage.setRejectionReason(reason); + + return rejectionMessage; + } + private static URI getMessageId() { return IdsId.Builder.newInstance().value(UUID.randomUUID().toString()).type(IdsType.MESSAGE).build().toUri(); } - public static XMLGregorianCalendar gregorianNow() { + private static XMLGregorianCalendar gregorianNow() { try { GregorianCalendar gregorianCalendar = GregorianCalendar.from(ZonedDateTime.now()); return DatatypeFactory.newInstance().newXMLGregorianCalendar(gregorianCalendar); diff --git a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/SettingsConstants.java b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/SettingsConstants.java index ddef2f4..79b75ec 100644 --- a/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/SettingsConstants.java +++ b/clearing-house-edc/core/src/main/java/de/truzzt/clearinghouse/edc/util/SettingsConstants.java @@ -1,3 +1,16 @@ +/* + * Copyright (c) 2023 truzzt GmbH + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * truzzt GmbH - initial implementation + * + */ package de.truzzt.clearinghouse.edc.util; public class SettingsConstants { diff --git a/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/app/AppSenderTest.java b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/app/AppSenderTest.java new file mode 100644 index 0000000..d25e793 --- /dev/null +++ b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/app/AppSenderTest.java @@ -0,0 +1,105 @@ +package de.truzzt.clearinghouse.edc.app; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.truzzt.clearinghouse.edc.tests.TestUtils; +import de.truzzt.clearinghouse.edc.app.delegate.LoggingMessageDelegate; +import de.truzzt.clearinghouse.edc.types.TypeManagerUtil; +import okhttp3.Request; +import okhttp3.ResponseBody; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.monitor.Monitor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +public class AppSenderTest { + + private AppSender sender; + @Mock + private Monitor monitor; + @Mock + private TypeManagerUtil typeManagerUtil; + @Mock + private LoggingMessageDelegate senderDelegate; + @Mock + private EdcHttpClient httpClient; + + private final ObjectMapper mapper = new ObjectMapper(); + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + senderDelegate = spy(new LoggingMessageDelegate(typeManagerUtil)); + sender = new AppSender(monitor, httpClient ,typeManagerUtil); + } + + @Test + public void sendSuccessful() throws IOException { + + doReturn(TestUtils.getValidHandlerRequest(mapper).toString()) + .when(typeManagerUtil).toJson(any(Object.class)); + doReturn(TestUtils.getValidResponse(TestUtils.getValidAppSenderRequest(mapper).getUrl())) + .when(httpClient).execute(any(Request.class)); + doReturn(TestUtils.getValidLoggingMessageResponse(TestUtils.getValidAppSenderRequest(mapper).getUrl(), mapper)) + .when(senderDelegate).parseResponseBody(any(ResponseBody.class)); + + var response = sender.send(TestUtils.getValidAppSenderRequest(mapper), senderDelegate); + + assertNotNull(response); + } + + @Test + public void sendWithHttpRequestError() throws IOException { + + doReturn(TestUtils.getValidHandlerRequest(mapper).toString()) + .when(typeManagerUtil).toJson(any(Object.class)); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> + sender.send(TestUtils.getInvalidUrlAppSenderRequest(mapper), senderDelegate)); + + assertEquals("Expected URL scheme 'http' or 'https'", exception.getMessage().substring(0,37)); + } + + @Test + public void sendWithUnsuccessfulResponseBodyError() throws IOException { + + doReturn(TestUtils.getValidHandlerRequest(mapper).toString()) + .when(typeManagerUtil).toJson(any(Object.class)); + doReturn(TestUtils.getUnsuccessfulResponse(TestUtils.getValidAppSenderRequest(mapper).getUrl())) + .when(httpClient).execute(any(Request.class)); + doReturn(TestUtils.getValidLoggingMessageResponse(TestUtils.getValidAppSenderRequest(mapper).getUrl(), mapper)) + .when(senderDelegate).parseResponseBody(any(ResponseBody.class)); + + EdcException exception = assertThrows(EdcException.class, () -> + sender.send(TestUtils.getValidAppSenderRequest(mapper), senderDelegate)); + + assertEquals("Received an error from Clearing House App. Status: 401, message: Unauthorized", exception.getMessage()); + } + + @Test + public void sendWithNullResponseBodyError() throws IOException { + + doReturn(TestUtils.getValidHandlerRequest(mapper).toString()) + .when(typeManagerUtil).toJson(any(Object.class)); + doReturn(TestUtils.getResponseWithoutBody(TestUtils.getValidAppSenderRequest(mapper).getUrl())) + .when(httpClient).execute(any(Request.class)); + doReturn(TestUtils.getValidLoggingMessageResponse(TestUtils.getValidAppSenderRequest(mapper).getUrl(), mapper)) + .when(senderDelegate).parseResponseBody(any(ResponseBody.class)); + + EdcException exception = assertThrows(EdcException.class, () -> + sender.send(TestUtils.getValidAppSenderRequest(mapper), senderDelegate)); + + assertEquals("Error reading Clearing House App response body", exception.getMessage()); + } +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/app/delegate/LoggingMessageDelegateTest.java b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/app/delegate/LoggingMessageDelegateTest.java new file mode 100644 index 0000000..9e92711 --- /dev/null +++ b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/app/delegate/LoggingMessageDelegateTest.java @@ -0,0 +1,68 @@ +package de.truzzt.clearinghouse.edc.app.delegate; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.truzzt.clearinghouse.edc.tests.TestUtils; +import de.truzzt.clearinghouse.edc.dto.HandlerRequest; +import de.truzzt.clearinghouse.edc.dto.LoggingMessageRequest; +import de.truzzt.clearinghouse.edc.dto.LoggingMessageResponse; +import de.truzzt.clearinghouse.edc.types.TypeManagerUtil; +import okhttp3.ResponseBody; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +class LoggingMessageDelegateTest { + + @Mock + private TypeManagerUtil typeManagerUtil; + @Mock + private LoggingMessageDelegate senderDelegate; + + private final ObjectMapper mapper = new ObjectMapper(); + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + senderDelegate = spy(new LoggingMessageDelegate(typeManagerUtil)); + } + + @Test + public void successfulBuildRequestUrl() { + + HandlerRequest request = TestUtils.getValidHandlerRequest(mapper); + + String response = senderDelegate.buildRequestUrl(TestUtils.TEST_BASE_URL, request); + + assertNotNull(response); + assertEquals(response, "http://localhost:8000/messages/log/" +request.getPid()); + } + + @Test + public void successfulBuildRequestBody() { + + HandlerRequest request = TestUtils.getValidHandlerRequest(mapper); + + LoggingMessageRequest response = senderDelegate.buildRequestBody(request); + + assertNotNull(response); + } + + @Test + public void successfulParseResponseBody() { + + ResponseBody body = TestUtils.getValidResponseBody(); + doReturn(TestUtils.getValidLoggingMessageResponse(TestUtils.getValidAppSenderRequest(mapper).getUrl(), mapper)) + .when(senderDelegate).parseResponseBody(any(ResponseBody.class)); + + LoggingMessageResponse response = senderDelegate.parseResponseBody(body); + + assertNotNull(response); + } +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/handler/LogMessageHandlerTest.java b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/handler/LogMessageHandlerTest.java new file mode 100644 index 0000000..f72e158 --- /dev/null +++ b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/handler/LogMessageHandlerTest.java @@ -0,0 +1,115 @@ +package de.truzzt.clearinghouse.edc.handler; + +import com.auth0.jwt.JWT; +import com.fasterxml.jackson.databind.ObjectMapper; +import de.truzzt.clearinghouse.edc.tests.TestUtils; +import de.truzzt.clearinghouse.edc.app.AppSender; +import de.truzzt.clearinghouse.edc.app.delegate.LoggingMessageDelegate; +import de.truzzt.clearinghouse.edc.dto.HandlerRequest; +import de.truzzt.clearinghouse.edc.dto.HandlerResponse; +import de.truzzt.clearinghouse.edc.types.TypeManagerUtil; +import de.truzzt.clearinghouse.edc.types.ids.SecurityToken; +import okhttp3.ResponseBody; +import org.eclipse.edc.protocol.ids.spi.types.IdsId; +import org.eclipse.edc.spi.EdcException; +import org.eclipse.edc.spi.http.EdcHttpClient; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.system.ServiceExtensionContext; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static de.truzzt.clearinghouse.edc.util.SettingsConstants.APP_BASE_URL_DEFAULT_VALUE; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; + +class LogMessageHandlerTest { + @Mock + private Monitor monitor; + @Mock + private IdsId connectorId; + @Mock + private TypeManagerUtil typeManagerUtil; + @Mock + private AppSender appSender; + @Mock + private ServiceExtensionContext context; + @Mock + private LogMessageHandler logMessageHandler; + @Mock + private LoggingMessageDelegate senderDelegate; + + private final ObjectMapper mapper = new ObjectMapper(); + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + senderDelegate = spy(new LoggingMessageDelegate(typeManagerUtil)); + logMessageHandler = spy(new LogMessageHandler(monitor, connectorId, typeManagerUtil, appSender, context)); + } + + @Test + public void successfulCanHandle(){ + + HandlerRequest request = TestUtils.getValidHandlerRequest(mapper); + + Boolean response = logMessageHandler.canHandle(request); + + assertNotNull(response); + assertEquals(response, true); + } + + @Test + public void invalidMessageTypeCanHandle(){ + + HandlerRequest request = TestUtils.getInvalidHandlerRequest(mapper); + + Boolean response = logMessageHandler.canHandle(request); + + assertNotNull(response); + assertEquals(response, false); + } + + @Test + public void successfulHandleRequest(){ + HandlerRequest request = TestUtils.getValidHandlerRequest(mapper); + doReturn(JWT.create().toString()) + .when(logMessageHandler).buildJWTToken(any(SecurityToken.class), any(ServiceExtensionContext.class)); + doReturn(TestUtils.getValidLoggingMessageResponse(TestUtils.getValidAppSenderRequest(mapper).getUrl(), mapper)) + .when(senderDelegate).parseResponseBody(any(ResponseBody.class)); + doReturn(APP_BASE_URL_DEFAULT_VALUE+ "/headers/log/" + request.getPid()) + .when(senderDelegate) + .buildRequestUrl(any(String.class), any(HandlerRequest.class)); + doReturn(TestUtils.getValidLoggingMessageRequest(request)) + .when(senderDelegate).buildRequestBody(any(HandlerRequest.class)); + + HandlerResponse response = logMessageHandler.handleRequest(request); + + assertNotNull(response); + assertEquals(response.getHeader().getType(), "ids:MessageProcessedNotificationMessage"); + } + + @Test + public void missingSubjectBuildJwtToken() { + EdcException exception = assertThrows(EdcException.class, () -> logMessageHandler.buildJWTToken( + TestUtils.getInvalidTokenHandlerRequest(mapper) + .getHeader() + .getSecurityToken(), context)); + + assertEquals("JWT Token subject is missing",exception.getMessage()); + } + @Test + public void successfulBuildJwtToken() { + doReturn("1").when(context).getSetting(anyString(), anyString()); + var response = logMessageHandler.buildJWTToken( + TestUtils.getValidHandlerRequest(mapper) + .getHeader() + .getSecurityToken(), context); + + assertNotNull(response); + } +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/tests/TestUtils.java b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/tests/TestUtils.java new file mode 100644 index 0000000..f1a4458 --- /dev/null +++ b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/tests/TestUtils.java @@ -0,0 +1,171 @@ +package de.truzzt.clearinghouse.edc.tests; + +import com.auth0.jwt.JWT; +import com.fasterxml.jackson.databind.ObjectMapper; +import de.truzzt.clearinghouse.edc.dto.AppSenderRequest; +import de.truzzt.clearinghouse.edc.dto.HandlerRequest; +import de.truzzt.clearinghouse.edc.dto.LoggingMessageRequest; +import de.truzzt.clearinghouse.edc.dto.LoggingMessageResponse; +import de.truzzt.clearinghouse.edc.types.clearinghouse.Context; +import de.truzzt.clearinghouse.edc.types.clearinghouse.Header; +import de.truzzt.clearinghouse.edc.types.clearinghouse.SecurityToken; +import de.truzzt.clearinghouse.edc.types.clearinghouse.TokenFormat; +import de.truzzt.clearinghouse.edc.types.ids.Message; +import okhttp3.*; +import org.eclipse.edc.spi.EdcException; + +import java.io.File; +import java.io.IOException; +import java.util.UUID; + +public class TestUtils extends BaseTestUtils { + + public static final String TEST_BASE_URL = "http://localhost:8000"; + + private static final String TEST_PAYLOAD = "Hello World"; + private static final String VALID_HEADER_JSON = "headers/valid-header.json"; + private static final String INVALID_HEADER_JSON = "headers/invalid-header.json"; + private static final String INVALID_TYPE_HEADER_JSON = "headers/invalid-type.json"; + private static final String INVALID_TOKEN_HEADER_JSON = "headers/invalid-token.json"; + + public static Message getValidHeader(ObjectMapper mapper) { + return parseFile(mapper, Message.class, VALID_HEADER_JSON); + } + + public static Message getInvalidTokenHeader(ObjectMapper mapper) { + return parseFile(mapper, Message.class, INVALID_TOKEN_HEADER_JSON); + } + + public static Message getInvalidTypeHeader(ObjectMapper mapper) { + return parseFile(mapper, Message.class, INVALID_TYPE_HEADER_JSON); + } + + public static Response getValidResponse(String url) { + + Request mockRequest = new Request.Builder() + .url(url) + .build(); + ResponseBody body = getValidResponseBody(); + + Headers headers = new Headers.Builder().add("Test","Test").build(); + + return new Response(mockRequest, Protocol.HTTP_2, "", 200, null, + headers, body, null, null, + null, 1000L, 1000L, null); + } + + public static Response getResponseWithoutBody(String url) { + + Request mockRequest = new Request.Builder() + .url(url) + .build(); + + Headers headers = new Headers.Builder().add("Test","Test").build(); + + return new Response(mockRequest, Protocol.HTTP_2, "", 200, null, + headers, null, null, null, + null, 1000L, 1000L, null); + } + + public static Response getUnsuccessfulResponse(String url) { + + Request mockRequest = new Request.Builder() + .url(url) + .build(); + ResponseBody body = getValidResponseBody(); + + Headers headers = new Headers.Builder().add("Test","Test").build(); + + return new Response(mockRequest, Protocol.HTTP_2, "Unauthorized", 401, null, + headers, body, null, null, + null, 1000L, 1000L, null); + } + + public static LoggingMessageResponse getValidLoggingMessageResponse(String url, ObjectMapper mapper) { + try { + return mapper.readValue(getValidResponse(url).body().byteStream(), LoggingMessageResponse.class); + + } catch (IOException e) { + throw new EdcException("Error parsing response", e); + } + } + + public static LoggingMessageRequest getValidLoggingMessageRequest(HandlerRequest handlerRequest) { + + var header = handlerRequest.getHeader(); + + var multipartContext = header.getContext(); + var context = new Context(multipartContext.getIds(), multipartContext.getIdsc()); + + var multipartSecurityToken = header.getSecurityToken(); + var multipartTokenFormat = multipartSecurityToken.getTokenFormat(); + var securityToken = SecurityToken.Builder.newInstance(). + type(multipartSecurityToken.getType()). + id(multipartSecurityToken.getId()). + tokenFormat(new TokenFormat(multipartTokenFormat.getId())). + tokenValue(multipartSecurityToken.getTokenValue()). + build(); + + var requestHeader = Header.Builder.newInstance() + .context(context) + .id(header.getId()) + .type(header.getType()) + .securityToken(securityToken) + .issuerConnector(header.getIssuerConnector()) + .modelVersion(header.getModelVersion()) + .issued(header.getIssued()) + .senderAgent(header.getSenderAgent()) + .build(); + + return new LoggingMessageRequest(requestHeader, handlerRequest.getPayload()); + } + + public static ResponseBody getValidResponseBody(){ + return ResponseBody.create( + MediaType.get("application/json; charset=utf-8"), + "{}" + ); + } + + public static HandlerRequest getValidHandlerRequest(ObjectMapper mapper){ + return HandlerRequest.Builder.newInstance() + .pid(UUID.randomUUID().toString()) + .header(getValidHeader(mapper)) + .payload(TEST_PAYLOAD).build(); + } + + public static HandlerRequest getInvalidTokenHandlerRequest(ObjectMapper mapper){ + return HandlerRequest.Builder.newInstance() + .pid(UUID.randomUUID().toString()) + .header(getInvalidTokenHeader(mapper)) + .payload(TEST_PAYLOAD).build(); + } + + public static HandlerRequest getInvalidHandlerRequest(ObjectMapper mapper){ + return HandlerRequest.Builder.newInstance() + .pid(UUID.randomUUID().toString()) + .header(getInvalidTypeHeader(mapper) ) + .payload(TEST_PAYLOAD).build(); + } + + public static AppSenderRequest getValidAppSenderRequest(ObjectMapper mapper){ + return new AppSenderRequest(TEST_BASE_URL+ "/headers/log/" + UUID.randomUUID(), + JWT.create().toString(), + getValidHandlerRequest(mapper) + ); + } + + public static AppSenderRequest getInvalidUrlAppSenderRequest(ObjectMapper mapper){ + return new AppSenderRequest(UUID.randomUUID().toString(), + JWT.create().toString(), + getValidHandlerRequest(mapper) + ); + } + + public static File getValidHeaderFile() { + return getFile(VALID_HEADER_JSON).toFile(); + } + public static File getInvalidHeaderFile() { + return getFile(INVALID_HEADER_JSON).toFile(); + } +} diff --git a/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/types/TypeManagerUtilTest.java b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/types/TypeManagerUtilTest.java new file mode 100644 index 0000000..7fa48ac --- /dev/null +++ b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/types/TypeManagerUtilTest.java @@ -0,0 +1,86 @@ +package de.truzzt.clearinghouse.edc.types; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.truzzt.clearinghouse.edc.tests.TestUtils; +import de.truzzt.clearinghouse.edc.types.ids.Message; +import org.eclipse.edc.spi.EdcException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; + +class TypeManagerUtilTest { + + @Mock + private TypeManagerUtil typeManagerUtil; + + private final ObjectMapper mapper = new ObjectMapper(); + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + typeManagerUtil = new TypeManagerUtil(mapper); + } + + @Test + void successfulParse() throws IOException { + InputStream is = new FileInputStream(TestUtils.getValidHeaderFile()); + + Message msg = typeManagerUtil.parse(is, Message.class); + assertNotNull(msg); + assertEquals("ids:LogMessage", msg.getType()); + } + + @Test + void typeErrorParse() { + EdcException exception = + assertThrows(EdcException.class, + () -> typeManagerUtil.parse( + new FileInputStream(TestUtils.getInvalidHeaderFile()), + Message.class) + ); + assertEquals("Error parsing to type class de.truzzt.clearinghouse.edc.types.ids.Message", exception.getMessage()); + } + + @Test + void successfulToJson() throws IOException { + Message msgBefore = mapper.readValue(TestUtils.getValidHeaderFile(), Message.class); + + var json = typeManagerUtil.toJson(msgBefore); + assertNotNull(json); + + InputStream is = new ByteArrayInputStream(json.getBytes()); + Message msgAfter = typeManagerUtil.parse(is, Message.class); + + assertEquals(msgBefore.getType(), msgAfter.getType()); + } + + @Test + void errorConvertingToJson() throws IOException { + + var mockedMapper = mock(ObjectMapper.class); + doThrow(new EdcException("Error converting to JSON")) + .when(mockedMapper).writeValueAsString(anyString()); + + typeManagerUtil = new TypeManagerUtil(mockedMapper); + + EdcException exception = + assertThrows(EdcException.class, + () -> typeManagerUtil.toJson("fadsfsdafd") + ); + + assertEquals("Error converting to JSON",exception.getMessage() ); + } +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/types/ids/util/VocabUtilTest.java b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/types/ids/util/VocabUtilTest.java new file mode 100644 index 0000000..5d8da42 --- /dev/null +++ b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/types/ids/util/VocabUtilTest.java @@ -0,0 +1,46 @@ +package de.truzzt.clearinghouse.edc.types.ids.util; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class VocabUtilTest { + @Mock + private VocabUtil vocabUtil; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void successfulCreateRandomUrl() { + vocabUtil.randomUrlBase = "http://www.test"; + var response = vocabUtil.createRandomUrl("test-successful"); + assertNotNull(response); + assertEquals("http://www.test/test-successful/", response.toString().substring(0,32)); + } + + @Test + void errorInvalidUrlCreateRandomUrl() { + vocabUtil.randomUrlBase = "htt://....."; + RuntimeException exception = assertThrows(RuntimeException.class, () -> + vocabUtil.createRandomUrl("test-successful")); + + assertNotNull(exception); + assertEquals("java.net.MalformedURLException: unknown protocol: htt", exception.getMessage()); + } + + @Test + void successfulNullRandomUrlCreateRandomUrl() { + vocabUtil.randomUrlBase = null; + var response = vocabUtil.createRandomUrl("test-successful"); + assertNotNull(response); + assertEquals("https://w3id.org/idsa/autogen/test-successful/", response.toString().substring(0,46)); + } +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/util/ResponseUtilTest.java b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/util/ResponseUtilTest.java new file mode 100644 index 0000000..8adabf0 --- /dev/null +++ b/clearing-house-edc/core/src/test/java/de/truzzt/clearinghouse/edc/util/ResponseUtilTest.java @@ -0,0 +1,94 @@ +package de.truzzt.clearinghouse.edc.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.truzzt.clearinghouse.edc.tests.TestUtils; +import de.truzzt.clearinghouse.edc.types.TypeManagerUtil; +import org.eclipse.edc.protocol.ids.spi.types.IdsId; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class ResponseUtilTest { + + @Mock + private TypeManagerUtil typeManagerUtil; + @Mock + private IdsId connectorId; + + private final ObjectMapper mapper = new ObjectMapper(); + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + typeManagerUtil = new TypeManagerUtil(new ObjectMapper()); + } + + @Test + public void createFormDataMultiPart() { + + var response = ResponseUtil.createFormDataMultiPart(typeManagerUtil, + "Header Name", + TestUtils.getValidHeader(new ObjectMapper()), + "Payload", + "Payload Value" + ); + + assertNotNull(response); + } + + @Test + public void testCreateFormDataMultiPart() { + var response = ResponseUtil.createFormDataMultiPart(typeManagerUtil, + "Header Name", + TestUtils.getValidHeader(mapper) + ); + + assertNotNull(response); + } + + @Test + public void createMultipartResponse() { + var response = ResponseUtil.createMultipartResponse(TestUtils.getValidHeader(mapper), + "Payload Value"); + + assertNotNull(response); + } + + @Test + public void messageProcessedNotification() { + var response = ResponseUtil.messageProcessedNotification(TestUtils.getValidHeader(mapper), connectorId); + + assertNotNull(response); + } + + @Test + public void notAuthenticated() { + var response = ResponseUtil.notAuthenticated(TestUtils.getValidHeader(mapper), connectorId); + + assertNotNull(response); + } + + @Test + public void malformedMessage() { + var response = ResponseUtil.malformedMessage(TestUtils.getValidHeader(mapper), connectorId); + + assertNotNull(response); + } + + @Test + public void messageTypeNotSupported() { + var response = ResponseUtil.messageTypeNotSupported(TestUtils.getValidHeader(mapper), connectorId); + + assertNotNull(response); + } + + @Test + public void internalRecipientError() { + var response = ResponseUtil.internalRecipientError(TestUtils.getValidHeader(mapper), connectorId); + + assertNotNull(response); + } +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/resources/headers/invalid-header.json b/clearing-house-edc/core/src/test/resources/headers/invalid-header.json new file mode 100644 index 0000000..58522c0 --- /dev/null +++ b/clearing-house-edc/core/src/test/resources/headers/invalid-header.json @@ -0,0 +1,19 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "senderAgent":"http://example.org", + "modelVersion":"4.1.0", + "issued" : "2021-06-23T17:27:23.566+02:00", + "issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/resources/headers/invalid-token.json b/clearing-house-edc/core/src/test/resources/headers/invalid-token.json new file mode 100644 index 0000000..ea2bbf7 --- /dev/null +++ b/clearing-house-edc/core/src/test/resources/headers/invalid-token.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:LogMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCJ9.hekZoPDjEWaXreQl3l0PUIjBOPQhAl0w2mH4_PdNWuA", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/resources/headers/invalid-type.json b/clearing-house-edc/core/src/test/resources/headers/invalid-type.json new file mode 100644 index 0000000..e96fc8d --- /dev/null +++ b/clearing-house-edc/core/src/test/resources/headers/invalid-type.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:otherMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/test/resources/headers/valid-header.json b/clearing-house-edc/core/src/test/resources/headers/valid-header.json new file mode 100644 index 0000000..85057bb --- /dev/null +++ b/clearing-house-edc/core/src/test/resources/headers/valid-header.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:LogMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/core/src/testFixtures/java/de/truzzt/clearinghouse/edc/tests/BaseTestUtils.java b/clearing-house-edc/core/src/testFixtures/java/de/truzzt/clearinghouse/edc/tests/BaseTestUtils.java new file mode 100644 index 0000000..d4ac055 --- /dev/null +++ b/clearing-house-edc/core/src/testFixtures/java/de/truzzt/clearinghouse/edc/tests/BaseTestUtils.java @@ -0,0 +1,80 @@ +package de.truzzt.clearinghouse.edc.tests; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.edc.spi.EdcException; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; + +public class BaseTestUtils { + + protected static T parseFile(ObjectMapper mapper, Class type, String path) { + + ClassLoader classLoader = BaseTestUtils.class.getClassLoader(); + var jsonResource = classLoader.getResource(path); + + if (jsonResource == null) { + throw new EdcException("Header json file not found: " + path); + } + + URI jsonUrl; + try { + jsonUrl = jsonResource.toURI(); + } catch (URISyntaxException e) { + throw new EdcException("Error finding json file on classpath", e); + } + + Path filePath = Path.of(jsonUrl); + if (!Files.exists(filePath)) { + throw new EdcException("Header json file not found: " + path); + } + + T object; + try { + var jsonContents = Files.readAllBytes(filePath); + object = mapper.readValue(jsonContents, type); + + } catch (IOException e){ + throw new EdcException("Error parsing json file", e); + } + + return object; + } + + protected static Path getFile(String path) { + + ClassLoader classLoader = BaseTestUtils.class.getClassLoader(); + var jsonResource = classLoader.getResource(path); + + if (jsonResource == null) { + throw new EdcException("Header json file not found: " + path); + } + + URI jsonUrl; + try { + jsonUrl = jsonResource.toURI(); + } catch (URISyntaxException e) { + throw new EdcException("Error finding json file on classpath", e); + } + + Path filePath = Path.of(jsonUrl); + if (!Files.exists(filePath)) { + throw new EdcException("Header json file not found: " + path); + } + + return filePath; + } + + protected static String readFile(String path) { + var file = getFile(path); + + try { + return Files.readString(file); + } catch (IOException e) { + throw new EdcException("Error reading file contents", e); + } + } +} diff --git a/clearing-house-edc/extensions/multipart/build.gradle.kts b/clearing-house-edc/extensions/multipart/build.gradle.kts index 00a7a0e..68ed15c 100644 --- a/clearing-house-edc/extensions/multipart/build.gradle.kts +++ b/clearing-house-edc/extensions/multipart/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,12 +8,18 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * Microsoft Corporation - Initial implementation + * truzzt GmbH - Initial implementation * */ plugins { `java-library` + `java-test-fixtures` + jacoco +} + +configurations.all { + exclude(group = "de.fraunhofer.iais.eis.ids.infomodel", module = "java") } dependencies { @@ -26,4 +32,25 @@ dependencies { implementation(edc.api.management.config) implementation(libs.jakarta.rsApi) implementation(libs.jersey.multipart) + + implementation(":infomodel-java-4.1.3") + implementation(":infomodel-util-4.0.4") + + testImplementation(libs.junit.jupiter.api) + testImplementation(libs.mockito.inline) + testImplementation(libs.mockito.inline) + + testImplementation(testFixtures(project(":core"))) + + testRuntimeOnly(libs.junit.jupiter.engine) +} + +tasks.test { + useJUnitPlatform() +} +tasks.jacocoTestReport { + dependsOn(tasks.test) + reports { + xml.required = true + } } diff --git a/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartController.java b/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartController.java index 673f00b..0fdf8a9 100644 --- a/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartController.java +++ b/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartController.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2023 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation + * + */ package de.truzzt.clearinghouse.edc.multipart; import de.fraunhofer.iais.eis.DynamicAttributeTokenBuilder; @@ -7,7 +21,7 @@ import de.truzzt.clearinghouse.edc.types.TypeManagerUtil; import de.truzzt.clearinghouse.edc.types.ids.Message; -import de.truzzt.clearinghouse.edc.types.ids.SecurityToken; +import de.truzzt.clearinghouse.edc.types.ids.RejectionMessage; import de.truzzt.clearinghouse.edc.types.ids.TokenFormat; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.POST; @@ -20,14 +34,15 @@ import org.eclipse.edc.protocol.ids.spi.service.DynamicAttributeTokenService; import org.eclipse.edc.protocol.ids.spi.types.IdsId; import org.eclipse.edc.spi.monitor.Monitor; -import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.eclipse.edc.util.string.StringUtils; import org.glassfish.jersey.media.multipart.FormDataParam; -import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.jetbrains.annotations.NotNull; import java.io.InputStream; import java.util.List; +import static de.truzzt.clearinghouse.edc.util.ResponseUtil.createFormDataMultiPart; +import static de.truzzt.clearinghouse.edc.util.ResponseUtil.createRejectionMessage; import static de.truzzt.clearinghouse.edc.util.ResponseUtil.internalRecipientError; import static de.truzzt.clearinghouse.edc.util.ResponseUtil.malformedMessage; import static de.truzzt.clearinghouse.edc.util.ResponseUtil.messageTypeNotSupported; @@ -71,11 +86,19 @@ public Response request(@PathParam(PID) String pid, @FormDataParam(HEADER) InputStream headerInputStream, @FormDataParam(PAYLOAD) String payload) { + // Check if pid is missing + if (pid == null) { + monitor.severe(LOG_ID + ": PID is missing"); + return Response.status(Response.Status.BAD_REQUEST) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, malformedMessage(null, connectorId))) + .build(); + } + // Check if header is missing if (headerInputStream == null) { monitor.severe(LOG_ID + ": Header is missing"); return Response.status(Response.Status.BAD_REQUEST) - .entity(createFormDataMultiPart(malformedMessage(null, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, malformedMessage(null, connectorId))) .build(); } @@ -86,19 +109,23 @@ public Response request(@PathParam(PID) String pid, } catch (Exception e) { monitor.severe(format(LOG_ID + ": Header parsing failed: %s", e.getMessage())); return Response.status(Response.Status.BAD_REQUEST) - .entity(createFormDataMultiPart(malformedMessage(null, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, malformedMessage(null, connectorId))) .build(); } // Check if any required header field missing if (header.getId() == null - || header.getType() == null - || header.getModelVersion() == null + || (header.getId() != null && StringUtils.isNullOrBlank(header.getId().toString())) + || StringUtils.isNullOrBlank(header.getType()) + || StringUtils.isNullOrBlank(header.getModelVersion()) || header.getIssued() == null || header.getIssuerConnector() == null - || header.getSenderAgent() == null) { + || (header.getIssuerConnector() != null && StringUtils.isNullOrBlank(header.getIssuerConnector().toString())) + || header.getSenderAgent() == null + || (header.getSenderAgent() != null && StringUtils.isNullOrBlank(header.getSenderAgent().toString())) + ) { return Response.status(Response.Status.BAD_REQUEST) - .entity(createFormDataMultiPart(malformedMessage(header, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, malformedMessage(header, connectorId))) .build(); } @@ -107,7 +134,7 @@ public Response request(@PathParam(PID) String pid, if (securityToken == null || securityToken.getTokenValue() == null) { monitor.severe(LOG_ID + ": Token is missing in header"); return Response.status(Response.Status.BAD_REQUEST) - .entity(createFormDataMultiPart(notAuthenticated(header, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, notAuthenticated(header, connectorId))) .build(); } @@ -116,7 +143,7 @@ public Response request(@PathParam(PID) String pid, if (!tokenFormat.equals(TokenFormat.JWT_TOKEN_FORMAT)) { monitor.severe(LOG_ID + ": Invalid security token type: " + tokenFormat); return Response.status(Response.Status.BAD_REQUEST) - .entity(createFormDataMultiPart(malformedMessage(null, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, malformedMessage(null, connectorId))) .build(); } @@ -124,14 +151,14 @@ public Response request(@PathParam(PID) String pid, if (payload == null) { monitor.severe(LOG_ID + ": Payload is missing"); return Response.status(Response.Status.BAD_REQUEST) - .entity(createFormDataMultiPart(malformedMessage(null, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, malformedMessage(null, connectorId))) .build(); } // Validate DAT if (!validateToken(header)) { return Response.status(Response.Status.FORBIDDEN) - .entity(createFormDataMultiPart(notAuthenticated(header, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, notAuthenticated(header, connectorId))) .build(); } @@ -155,21 +182,31 @@ public Response request(@PathParam(PID) String pid, } catch (Exception e) { monitor.severe(LOG_ID + ": Error in message handler processing", e); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .entity(createFormDataMultiPart(internalRecipientError(header, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, internalRecipientError(header, connectorId))) .build(); } // Get the response token if (!getResponseToken(header, handlerResponse)) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .entity(createFormDataMultiPart(internalRecipientError(header, connectorId))) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, internalRecipientError(header, connectorId))) .build(); } // Build the response - return Response.status(Response.Status.CREATED) - .entity(createFormDataMultiPart(handlerResponse.getHeader(), handlerResponse.getPayload())) - .build(); + if (handlerResponse.getHeader() instanceof RejectionMessage) { + var rejectionMessage = (RejectionMessage) handlerResponse.getHeader(); + + return Response.status(Response.Status.INTERNAL_SERVER_ERROR) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, + createRejectionMessage(rejectionMessage.getRejectionReason(), header, connectorId)) + ).build(); + } + else { + return Response.status(Response.Status.CREATED) + .entity(createFormDataMultiPart(typeManagerUtil, HEADER, handlerResponse.getHeader(), PAYLOAD, handlerResponse.getPayload())) + .build(); + } } private boolean validateToken(Message header) { @@ -219,22 +256,4 @@ private boolean getResponseToken(Message header, HandlerResponse handlerResponse }*/ } - private FormDataMultiPart createFormDataMultiPart(Message header, Object payload) { - var multiPart = createFormDataMultiPart(header); - - if (payload != null) { - multiPart.bodyPart(new FormDataBodyPart(PAYLOAD, typeManagerUtil.toJson(payload), MediaType.APPLICATION_JSON_TYPE)); - } - - return multiPart; - } - - private FormDataMultiPart createFormDataMultiPart(Message header) { - var multiPart = new FormDataMultiPart(); - if (header != null) { - multiPart.bodyPart(new FormDataBodyPart(HEADER, typeManagerUtil.toJson(header), MediaType.APPLICATION_JSON_TYPE)); - } - return multiPart; - } - } diff --git a/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartExtension.java b/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartExtension.java index fa3e3cb..59d3cc6 100644 --- a/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartExtension.java +++ b/clearing-house-edc/extensions/multipart/src/main/java/de/truzzt/clearinghouse/edc/multipart/MultipartExtension.java @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2023 Microsoft Corporation + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + * + * Contributors: + * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation + * + */ package de.truzzt.clearinghouse.edc.multipart; import de.truzzt.clearinghouse.edc.handler.Handler; diff --git a/clearing-house-edc/extensions/multipart/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension b/clearing-house-edc/extensions/multipart/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension index ae7a3a9..21d508b 100644 --- a/clearing-house-edc/extensions/multipart/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension +++ b/clearing-house-edc/extensions/multipart/src/main/resources/META-INF/services/org.eclipse.edc.spi.system.ServiceExtension @@ -1,5 +1,5 @@ # -# Copyright (c) 2022 Microsoft Corporation +# Copyright (c) 2023 Microsoft Corporation # # This program and the accompanying materials are made available under the # terms of the Apache License, Version 2.0 which is available at @@ -9,7 +9,7 @@ # # Contributors: # Microsoft Corporation - initial implementation -# +# truzzt GmbH - EDC extension implementation # de.truzzt.clearinghouse.edc.multipart.MultipartExtension \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/java/de/truzzt/clearinghouse/edc/multipart/MultipartControllerTest.java b/clearing-house-edc/extensions/multipart/src/test/java/de/truzzt/clearinghouse/edc/multipart/MultipartControllerTest.java new file mode 100644 index 0000000..3b7861e --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/java/de/truzzt/clearinghouse/edc/multipart/MultipartControllerTest.java @@ -0,0 +1,255 @@ +package de.truzzt.clearinghouse.edc.multipart; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.fraunhofer.iais.eis.DynamicAttributeToken; +import de.truzzt.clearinghouse.edc.dto.HandlerRequest; +import de.truzzt.clearinghouse.edc.dto.HandlerResponse; +import de.truzzt.clearinghouse.edc.dto.LoggingMessageResponse; +import de.truzzt.clearinghouse.edc.handler.Handler; +import de.truzzt.clearinghouse.edc.handler.LogMessageHandler; +import de.truzzt.clearinghouse.edc.multipart.tests.TestUtils; +import de.truzzt.clearinghouse.edc.types.TypeManagerUtil; +import de.truzzt.clearinghouse.edc.types.ids.Message; +import de.truzzt.clearinghouse.edc.types.ids.RejectionMessage; +import de.truzzt.clearinghouse.edc.types.ids.RejectionReason; +import jakarta.ws.rs.core.Response; +import org.eclipse.edc.protocol.ids.spi.service.DynamicAttributeTokenService; +import org.eclipse.edc.protocol.ids.spi.types.IdsId; +import org.eclipse.edc.protocol.ids.spi.types.IdsType; +import org.eclipse.edc.spi.monitor.Monitor; +import org.eclipse.edc.spi.result.Result; +import org.glassfish.jersey.media.multipart.FormDataMultiPart; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.*; +import java.net.URI; +import java.util.List; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; + +public class MultipartControllerTest { + + private static final String IDS_WEBHOOK_ADDRESS = "http://localhost/callback"; + private static final String PAYLOAD = "Hello World"; + + private MultipartController controller; + + private IdsId connectorId; + private TypeManagerUtil typeManagerUtil; + + @Mock + private Monitor monitor; + @Mock + private DynamicAttributeTokenService tokenService; + @Mock + private LogMessageHandler logMessageHandler; + + private final ObjectMapper mapper = new ObjectMapper(); + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + + connectorId = IdsId.Builder.newInstance().type(IdsType.CONNECTOR).value("http://test.connector").build(); + typeManagerUtil = new TypeManagerUtil(new ObjectMapper()); + + List multipartHandlers = List.of(logMessageHandler); + controller = new MultipartController(monitor, connectorId, typeManagerUtil, tokenService, IDS_WEBHOOK_ADDRESS, multipartHandlers); + } + + private T extractHeader(Response response, Class type) { + + assertInstanceOf(FormDataMultiPart.class, response.getEntity()); + FormDataMultiPart multiPartResponse = (FormDataMultiPart) response.getEntity(); + + var header = multiPartResponse.getField("header"); + assertNotNull(header); + + assertInstanceOf(String.class, header.getEntity()); + var entity = (String) header.getEntity(); + return typeManagerUtil.parse(new ByteArrayInputStream(entity.getBytes()), type); + } + + private T extractPayload(Response response, Class type) { + + assertInstanceOf(FormDataMultiPart.class, response.getEntity()); + FormDataMultiPart multiPartResponse = (FormDataMultiPart) response.getEntity(); + + var payload = multiPartResponse.getField("payload"); + assertNotNull(payload); + + assertInstanceOf(String.class, payload.getEntity()); + var entity = (String) payload.getEntity(); + return typeManagerUtil.parse(new ByteArrayInputStream(entity.getBytes()), type); + } + + @Test + public void success() { + var responseHeader = TestUtils.getValidResponseHeader(mapper); + var responsePayload = TestUtils.getValidResponsePayload(mapper); + + doReturn(Result.success()) + .when(tokenService).verifyDynamicAttributeToken(any(DynamicAttributeToken.class), any(URI.class), any(String.class)); + doReturn(true) + .when(logMessageHandler).canHandle(any(HandlerRequest.class)); + doReturn(HandlerResponse.Builder.newInstance().header(responseHeader).payload(responsePayload).build()) + .when(logMessageHandler).handleRequest(any(HandlerRequest.class)); + + var pid = UUID.randomUUID().toString(); + var header = TestUtils.getHeaderInputStream(TestUtils.VALID_HEADER_JSON); + + var response = controller.request(pid, header, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, Message.class); + assertEquals("ids:LogMessage", message.getType()); + + var payload = extractPayload(response, LoggingMessageResponse.class); + assertNotNull(payload.getData()); + } + + @Test + public void missingPIDError() { + var header = TestUtils.getHeaderInputStream(TestUtils.VALID_HEADER_JSON); + + var response = controller.request(null, header, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.MALFORMED_MESSAGE.getId(), message.getRejectionReason().getId()); + } + + @Test + public void missingHeaderError() { + var pid = UUID.randomUUID().toString(); + + var response = controller.request(pid, null, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.MALFORMED_MESSAGE.getId(), message.getRejectionReason().getId()); + } + + @Test + public void invalidHeaderError() { + var pid = UUID.randomUUID().toString(); + var header = TestUtils.getHeaderInputStream(TestUtils.INVALID_HEADER_JSON); + + var response = controller.request(pid, header, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.MALFORMED_MESSAGE.getId(), message.getRejectionReason().getId()); + } + + @Test + public void missingHeaderFieldsError() { + var pid = UUID.randomUUID().toString(); + var header = TestUtils.getHeaderInputStream(TestUtils.MISSING_FIELDS_HEADER_JSON); + + var response = controller.request(pid, header, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.MALFORMED_MESSAGE.getId(), message.getRejectionReason().getId()); + } + + @Test + public void invalidSecurityTokenError() { + doReturn(Result.failure("Invalid token")) + .when(tokenService).verifyDynamicAttributeToken(any(DynamicAttributeToken.class), any(URI.class), any(String.class)); + + var pid = UUID.randomUUID().toString(); + var header = TestUtils.getHeaderInputStream(TestUtils.INVALID_TOKEN_HEADER_JSON); + + var response = controller.request(pid, header, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.FORBIDDEN.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.NOT_AUTHENTICATED.getId(), message.getRejectionReason().getId()); + } + + @Test + public void missingSecurityTokenError() { + var pid = UUID.randomUUID().toString(); + var header = TestUtils.getHeaderInputStream(TestUtils.MISSING_TOKEN_HEADER_JSON); + + var response = controller.request(pid, header, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.NOT_AUTHENTICATED.getId(), message.getRejectionReason().getId()); + } + + @Test + public void missingPayloadError() { + var pid = UUID.randomUUID().toString(); + var header = TestUtils.getHeaderInputStream(TestUtils.VALID_HEADER_JSON); + + var response = controller.request(pid, header, null); + + assertNotNull(response); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.MALFORMED_MESSAGE.getId(), message.getRejectionReason().getId()); + } + + @Test + public void invalidMessageTypeError() { + doReturn(Result.success()) + .when(tokenService).verifyDynamicAttributeToken(any(DynamicAttributeToken.class), any(URI.class), any(String.class)); + doReturn(false) + .when(logMessageHandler).canHandle(any(HandlerRequest.class)); + + var pid = UUID.randomUUID().toString(); + var header = TestUtils.getHeaderInputStream(TestUtils.INVALID_TYPE_HEADER_JSON); + + var response = controller.request(pid, header, PAYLOAD); + + assertNotNull(response); + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus()); + + var message = extractHeader(response, RejectionMessage.class); + + assertNotNull(message.getRejectionReason()); + assertEquals(RejectionReason.MESSAGE_TYPE_NOT_SUPPORTED.getId(), message.getRejectionReason().getId()); + } + +} diff --git a/clearing-house-edc/extensions/multipart/src/test/java/de/truzzt/clearinghouse/edc/multipart/tests/TestUtils.java b/clearing-house-edc/extensions/multipart/src/test/java/de/truzzt/clearinghouse/edc/multipart/tests/TestUtils.java new file mode 100644 index 0000000..4cda33e --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/java/de/truzzt/clearinghouse/edc/multipart/tests/TestUtils.java @@ -0,0 +1,35 @@ +package de.truzzt.clearinghouse.edc.multipart.tests; + +import com.fasterxml.jackson.databind.ObjectMapper; +import de.truzzt.clearinghouse.edc.dto.LoggingMessageResponse; +import de.truzzt.clearinghouse.edc.tests.BaseTestUtils; +import de.truzzt.clearinghouse.edc.types.ids.Message; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +public class TestUtils extends BaseTestUtils { + + public static final String VALID_HEADER_JSON = "headers/valid-header.json"; + public static final String INVALID_HEADER_JSON = "headers/invalid-header.json"; + public static final String INVALID_TYPE_HEADER_JSON = "headers/invalid-type.json"; + public static final String INVALID_TOKEN_HEADER_JSON = "headers/invalid-token.json"; + public static final String MISSING_FIELDS_HEADER_JSON = "headers/missing-fields.json"; + public static final String MISSING_TOKEN_HEADER_JSON = "headers/missing-token.json"; + public static final String VALID_RESPONSE_HEADER_JSON = "headers/valid-response.json"; + + public static final String VALID_RESPONSE_PAYLOAD_JSON = "payloads/valid-response.json"; + + public static InputStream getHeaderInputStream(String path) { + var json = TestUtils.readFile(path); + return new ByteArrayInputStream(json.getBytes()); + } + + public static Message getValidResponseHeader(ObjectMapper mapper) { + return parseFile(mapper, Message.class, VALID_RESPONSE_HEADER_JSON); + } + + public static LoggingMessageResponse getValidResponsePayload(ObjectMapper mapper) { + return parseFile(mapper, LoggingMessageResponse.class, VALID_RESPONSE_PAYLOAD_JSON); + } +} diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-header.json b/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-header.json new file mode 100644 index 0000000..58522c0 --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-header.json @@ -0,0 +1,19 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "senderAgent":"http://example.org", + "modelVersion":"4.1.0", + "issued" : "2021-06-23T17:27:23.566+02:00", + "issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-token.json b/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-token.json new file mode 100644 index 0000000..ea2bbf7 --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-token.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:LogMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCJ9.hekZoPDjEWaXreQl3l0PUIjBOPQhAl0w2mH4_PdNWuA", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-type.json b/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-type.json new file mode 100644 index 0000000..e96fc8d --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/headers/invalid-type.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:otherMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/headers/missing-fields.json b/clearing-house-edc/extensions/multipart/src/test/resources/headers/missing-fields.json new file mode 100644 index 0000000..d1ef397 --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/headers/missing-fields.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:LogMessage", + "@id":"", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/headers/missing-token.json b/clearing-house-edc/extensions/multipart/src/test/resources/headers/missing-token.json new file mode 100644 index 0000000..8c609c9 --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/headers/missing-token.json @@ -0,0 +1,12 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:LogMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/headers/valid-header.json b/clearing-house-edc/extensions/multipart/src/test/resources/headers/valid-header.json new file mode 100644 index 0000000..85057bb --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/headers/valid-header.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:LogMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/headers/valid-response.json b/clearing-house-edc/extensions/multipart/src/test/resources/headers/valid-response.json new file mode 100644 index 0000000..85057bb --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/headers/valid-response.json @@ -0,0 +1,20 @@ +{ + "@context":{ + "ids" : "https://w3id.org/idsa/core/", + "idsc" : "https://w3id.org/idsa/code/" + }, + "@type":"ids:LogMessage", + "@id":"https://w3id.org/idsa/autogen/logMessage/9fdba4ad-f750-4bbc-a7f0-f648ac853508", + "ids:securityToken": { + "@type" : "ids:DynamicAttributeToken", + "@id" : "https://w3id.org/idsa/autogen/dynamicAttributeToken/7bbbd2c1-2d75-4e3d-bd10-c52d0381cab0", + "ids:tokenValue" : "eyJ0eXAiOiJKV1QiLCJraWQiOiJkZWZhdWx0IiwiYWxnIjoiUlMyNTYifQ.eyJzY29wZXMiOlsiaWRzYzpJRFNfQ09OTkVDVE9SX0FUVFJJQlVURVNfQUxMIl0sImF1ZCI6Imlkc2M6SURTX0NPTk5FQ1RPUlNfQUxMIiwiaXNzIjoiaHR0cHM6Ly9kYXBzLmFpc2VjLmZyYXVuaG9mZXIuZGUiLCJuYmYiOjE2MzQ2NTA3MzksImlhdCI6MTYzNDY1MDczOSwianRpIjoiTVRneE9EUXdPVFF6TXpZd05qWXlOVFExTUE9PSIsImV4cCI6MTYzNDY1NDMzOSwic2VjdXJpdHlQcm9maWxlIjoiaWRzYzpCQVNFX1NFQ1VSSVRZX1BST0ZJTEUiLCJyZWZlcnJpbmdDb25uZWN0b3IiOiJodHRwOi8vYnJva2VyLmlkcy5pc3N0LmZyYXVuaG9mZXIuZGUuZGVtbyIsIkB0eXBlIjoiaWRzOkRhdFBheWxvYWQiLCJAY29udGV4dCI6Imh0dHBzOi8vdzNpZC5vcmcvaWRzYS9jb250ZXh0cy9jb250ZXh0Lmpzb25sZCIsInRyYW5zcG9ydENlcnRzU2hhMjU2IjoiOTc0ZTYzMjRmMTJmMTA5MTZmNDZiZmRlYjE4YjhkZDZkYTc4Y2M2YTZhMDU2NjAzMWZhNWYxYTM5ZWM4ZTYwMCIsInN1YiI6IjkyOjE0OkU3OkFDOjEwOjIyOkYyOkNDOjA1OjZFOjJBOjJCOjhEOkRCOjEwOkQ2OjREOkEwOkExOjUzOmtleWlkOkNCOjhDOkM3OkI2Ojg1Ojc5OkE4OjIzOkE2OkNCOjE1OkFCOjE3OjUwOjJGOkU2OjY1OjQzOjVEOkU4In0.Qw3gWMgwnKQyVatbsozcin6qtQbLyXlk6QdaLajGaDmxSYqCKEcAje4kiDp5Fqj04WPmVyF0k8c1BJA3KGnaW3Qcikv4MNxqqoenvKIrSTokXsA7-osqBCfxLhV-s2lSXVTAtV_Q7f71eSoR5j-7nPPX8_nf4Xup4_VzfnwRmnuAbLfHfWThbupxFazC34r3waXCltOTFVa_XDlwEDMpPY7vEPeaqIt2t6ofVGo_HF86UB19liL-UZvp0uSE9z2fhloyxOrx9B_xavGS7pP6oRaumSJEN_x9dfdeDS98HQ_oBSSGBzaI4fM7ik35Yg42KQwmkZesD6P_YSEzVLcJDg", + "ids:tokenFormat" : { + "@id" : "idsc:JWT" + } + }, + "ids:senderAgent":"http://example.org", + "ids:modelVersion":"4.1.0", + "ids:issued" : "2021-06-23T17:27:23.566+02:00", + "ids:issuerConnector" : "https://companyA.com/connector/59a68243-dd96-4c8d-88a9-0f0e03e13b1b" +} \ No newline at end of file diff --git a/clearing-house-edc/extensions/multipart/src/test/resources/payloads/valid-response.json b/clearing-house-edc/extensions/multipart/src/test/resources/payloads/valid-response.json new file mode 100644 index 0000000..ecf63af --- /dev/null +++ b/clearing-house-edc/extensions/multipart/src/test/resources/payloads/valid-response.json @@ -0,0 +1,3 @@ +{ + "data": "eyJhbGciOiJQUzUxMiIsImtpZCI6IlFyYS8vMjlGcnhiajVoaDVBemVmK0czNlNlaU9tOXE3czgrdzh1R0xEMjgifQ.eyJ0cmFuc2FjdGlvbl9pZCI6IjAwMDAwMDAwIiwidGltZXN0YW1wIjoxNjk3NzUxNzUzLCJwcm9jZXNzX2lkIjoiODcyIiwiZG9jdW1lbnRfaWQiOiIyYmMxMGVmNC03NjFjLTQ5NGYtYmQ1YS0xMWVmYTJmMzNmM2EiLCJwYXlsb2FkIjoiSGVsbG8gV29ybGQiLCJjaGFpbl9oYXNoIjoiMCIsImNsaWVudF9pZCI6IjY5OkY1OjlEOkIwOkREOkE2OjlEOjMwOjVGOjU4OkFBOjJEOjIwOjREOkIyOjM5OkYwOjU0OkZDOjNCOmtleWlkOjRGOjY2OjdEOkJEOjA4OkVFOkM2OjRBOkQxOjk2OkQ4OjdDOjZDOkEyOjMyOjhBOkVDOkE2OkFEOjQ5IiwiY2xlYXJpbmdfaG91c2VfdmVyc2lvbiI6IjAuMTAuMCJ9.NhMDSBTRiJJP04NEjBlB1Rt4LlvwDHrOEvNm0qbYRWqe8Vfdza1SSy-OLDCwMnC14hxHmwD5GpWOCbC5iswmuEeWspSMCGcGnGKZr_ra23jr4HV60YKnCAbBhOi5dmiPb6R64DSSJBH9Dw1Cni9zFNLBgUGr8pGEbm_AdijomUfl88fXUiyBWdrP0S-VVtlcygYROZtTusqBz95E_WKSyFU57hf4vOjkFRjfHHkuu92MUrJJwVXwf55YuVa-uLC8Exr2pScqeo2JI-1Y2JBCInOtBtskXmFfocav8ReIZhvL255O1-vHi5ZFsbQppEtstcz2txjP34EHoPCu8NO9s7G-BqJ8hKw5QTMKIV8-N1yrtGb2sK4qXUQCJpCKfJoMPG_BLQo9vHifWJ6gO1z4NZvOvqOXyIWGd89C1wsCWV8cSJcbye-BgAo4SUAdN5KQXTqiyWRc4wrNXC7S7Ajy639xW6k7epXEuya5qIdkP2qh-ZrL0WndA20jExLFzgYmvXVR15WcFsiprgxutFevQ1a-EWOZDsnnTSPhTt5KPFwziKepTzKq73X3cs-IRxAc_4qkEi0-zEy_YIfoWNMxWdkh4EiBj_wpgiN7msskGCGPzq2wslz64n2-AKsQiXqFEPMNv2ihRNhJHxL0PAJKMWYXStauafOffUazfZag0p8" +} \ No newline at end of file diff --git a/clearing-house-edc/launchers/connector-local/build.gradle.kts b/clearing-house-edc/launchers/connector-local/build.gradle.kts index ffe907f..f1ebdcb 100644 --- a/clearing-house-edc/launchers/connector-local/build.gradle.kts +++ b/clearing-house-edc/launchers/connector-local/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,16 +9,20 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ - plugins { `java-library` id("application") id("com.github.johnrengelman.shadow") version "7.1.2" } +configurations.all { + exclude(group = "de.fraunhofer.iais.eis.ids.infomodel", module = "java") +} + dependencies { runtimeOnly(project(":extensions:multipart")) @@ -26,6 +30,9 @@ dependencies { runtimeOnly(edc.config.filesystem) runtimeOnly(edc.vault.filesystem) runtimeOnly(edc.oauth2.core) + + runtimeOnly(":infomodel-java-4.1.3") + runtimeOnly(":infomodel-util-4.0.4") } application { diff --git a/clearing-house-edc/launchers/connector-local/config.properties b/clearing-house-edc/launchers/connector-local/config.properties deleted file mode 100644 index c88ff4d..0000000 --- a/clearing-house-edc/launchers/connector-local/config.properties +++ /dev/null @@ -1,5 +0,0 @@ -edc.truzzt.jwt.audience=1 -edc.truzzt.jwt.issuer=1 -edc.truzzt.jwt.sign.secret=123 -edc.truzzt.jwt.expires.at=60 -edc.truzzt.app.base.url=http://localhost:8000 \ No newline at end of file diff --git a/clearing-house-edc/launchers/connector-prod/build.gradle.kts b/clearing-house-edc/launchers/connector-prod/build.gradle.kts index 1ec96fb..52265b9 100644 --- a/clearing-house-edc/launchers/connector-prod/build.gradle.kts +++ b/clearing-house-edc/launchers/connector-prod/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -9,6 +9,7 @@ * * Contributors: * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ @@ -18,14 +19,19 @@ plugins { id("com.github.johnrengelman.shadow") version "7.1.2" } +configurations.all { + exclude(group = "de.fraunhofer.iais.eis.ids.infomodel", module = "java") +} + dependencies { runtimeOnly(project(":extensions:multipart")) runtimeOnly(edc.bundles.connector) runtimeOnly(edc.oauth2.core) - - // Vault runtimeOnly(edc.vault.filesystem) + + runtimeOnly(":infomodel-java-4.1.3") + runtimeOnly(":infomodel-util-4.0.4") } application { diff --git a/clearing-house-edc/libs/fraunhofer/infomodel-java-4.1.3.jar b/clearing-house-edc/libs/fraunhofer/infomodel-java-4.1.3.jar new file mode 100644 index 0000000..fad447d Binary files /dev/null and b/clearing-house-edc/libs/fraunhofer/infomodel-java-4.1.3.jar differ diff --git a/clearing-house-edc/libs/fraunhofer/infomodel-util-4.0.4.jar b/clearing-house-edc/libs/fraunhofer/infomodel-util-4.0.4.jar new file mode 100644 index 0000000..60a3775 Binary files /dev/null and b/clearing-house-edc/libs/fraunhofer/infomodel-util-4.0.4.jar differ diff --git a/clearing-house-edc/settings.gradle.kts b/clearing-house-edc/settings.gradle.kts index b8d9f44..23350a5 100644 --- a/clearing-house-edc/settings.gradle.kts +++ b/clearing-house-edc/settings.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Microsoft Corporation + * Copyright (c) 2023 Microsoft Corporation * * This program and the accompanying materials are made available under the * terms of the Apache License, Version 2.0 which is available at @@ -8,7 +8,8 @@ * SPDX-License-Identifier: Apache-2.0 * * Contributors: - * Microsoft Corporation - initial implementation + * Microsoft Corporation - Initial implementation + * truzzt GmbH - EDC extension implementation * */ @@ -27,8 +28,8 @@ dependencyResolutionManagement { maven { url = uri("https://oss.sonatype.org/content/repositories/snapshots/") } - maven { - url = uri("https://maven.iais.fraunhofer.de/artifactory/eis-ids-public/") + flatDir { + dirs("libs/fraunhofer") } mavenCentral() mavenLocal() diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 3b06385..b8b4fcf 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -2,6 +2,7 @@ # Admin Guide - [Installation](content/admin-guide/installation.md) +- [Tests](content/admin-guide/tests.md) - [Maintenance](content/admin-guide/maintenance.md) # References diff --git a/docs/content/admin-guide/installation.md b/docs/content/admin-guide/installation.md index 25267fe..62ba90b 100644 --- a/docs/content/admin-guide/installation.md +++ b/docs/content/admin-guide/installation.md @@ -1 +1,27 @@ # Installation + +## Clearinghouse-edc +This module contains the Clearing House Extension that works with the Eclipse Dataspace Connector +allowing logging operations. + +### Configurations +It is required to configure those parameters: + +| Parameter name | Description | Default value | +|----------------------------------------|----------------------------------------------|------------------------| +| `truzzt.clearinghouse.jwt.audience` | Defines the intended recipients of the token | 1 | +| `truzzt.clearinghouse.jwt.issuer` | Person or entity offering the token | 1 | +| `truzzt.clearinghouse.jwt.sign.secret` | Secret key to encode the token | 123 | +| `truzzt.clearinghouse.jwt.expires.at` | Time to token Expiration (in Seconds) | 30 | +| `truzzt.clearinghouse.app.base.url` | Base URL from the clearing house app | http://localhost:8000 | + +### Build +To build the project run the command below: + + ./gradlew build + + +### Running +Local execution: + + java -Dedc.fs.config=launchers/connector-local/resources/config.properties -Dedc.keystore=launchers/connector-local/resources/keystore.jks -Dedc.keystore.password=password -Dedc.vault=launchers/connector-local/resources/vault.properties -jar launchers/connector-local/build/libs/clearing-house-edc.jar diff --git a/docs/content/admin-guide/tests.md b/docs/content/admin-guide/tests.md new file mode 100644 index 0000000..e5ae585 --- /dev/null +++ b/docs/content/admin-guide/tests.md @@ -0,0 +1,22 @@ +# Tests + + +## Clearinghouse-edc + +For the test clearinghouse-edc it uses Junit 5 and Jacoco for the coverage. + +### Running Tests +To run the unit-tests execute the following command: + + ./gradlew test + + +### Test Coverage +To generate the tests coverage execute the following command: + + ./gradlew jacocoTestReport + +The coverage reports will be available in the following folders: + +- [core/build/reports/jacoco/test/html/index.html](./core/build/reports/jacoco/test/html/index.html) +- [extensions/multipart/build/reports/jacoco/test/html/index.html](./extensions/multipart/build/reports/jacoco/test/html/index.html) \ No newline at end of file