Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Update postman and add details check #1001

Merged
merged 3 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docker-compose-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ services:
EDC_WEB_REST_CORS_HEADERS: 'origin,content-type,accept,authorization,X-Api-Key'
EDC_WEB_REST_CORS_ORIGINS: '*'
EDC_AGENT_IDENTITY_KEY: 'client_id' # required for Mock IAM to work

ports:
- '11001:11001'
- '11002:11002'
Expand Down Expand Up @@ -89,6 +90,7 @@ services:
EDC_WEB_REST_CORS_HEADERS: 'origin,content-type,accept,authorization,X-Api-Key'
EDC_WEB_REST_CORS_ORIGINS: '*'
EDC_AGENT_IDENTITY_KEY: 'client_id' # required for Mock IAM to work

ports:
- '22001:11001'
- '22002:11002'
Expand Down
54 changes: 48 additions & 6 deletions docs/api/postman_collection.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"info": {
"_postman_id": "c01dc51f-eb36-43db-b8db-a33ff2f5baa5",
"_postman_id": "a842e697-4b5e-4308-b802-35c446ea6135",
"name": "sovity EDC Community Edition",
"description": "This is the official postman collection for the sovity EDC Community Edition.\n\nThe Management-API is based on core-edc v0.2.1.\n\nsovity EDC Community Edition: [https://github.com/sovity/edc-ce](https://github.com/sovity/edc-ce)\n\nLicense: [https://github.com/sovity/edc-ce/blob/main/LICENSE](https://github.com/sovity/edc-ce/blob/main/LICENSE)",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "31514741"
"_exporter_id": "32949497"
},
"item": [
{
Expand Down Expand Up @@ -84,7 +84,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"id\": \"testname-v1.0\",\r\n \"title\": \"TestName\",\r\n \"language\": \"https://w3id.org/idsa/code/EN\",\r\n \"description\": \"Testdescription\",\r\n \"publisherHomepage\": \"https://www.sovity.de\",\r\n \"licenseUrl\": \"https://www.apache.org/licenses/LICENSE-2.0\",\r\n \"version\": \"v1.0\",\r\n \"keywords\": [\r\n \"keyword1\",\r\n \"keyword2\"\r\n ],\r\n \"mediaType\": \"application/json\",\r\n \"landingPageUrl\": \"https://www.google.com\",\r\n \"dataAddressProperties\": {\r\n \"https://w3id.org/edc/v0.0.1/ns/type\": \"HttpData\",\r\n \"https://w3id.org/edc/v0.0.1/ns/baseUrl\": \"https://www.google.com\",\r\n \"https://w3id.org/edc/v0.0.1/ns/method\": \"GET\",\r\n \"https://w3id.org/edc/v0.0.1/ns/queryParams\": \"\"\r\n }\r\n}",
"raw": "{\r\n \"id\": \"testname-v1.0\",\r\n \"title\": \"TestName\",\r\n \"language\": \"https://w3id.org/idsa/code/EN\",\r\n \"description\": \"Testdescription\",\r\n \"publisherHomepage\": \"https://www.sovity.de\",\r\n \"licenseUrl\": \"https://www.apache.org/licenses/LICENSE-2.0\",\r\n \"version\": \"v1.0\",\r\n \"keywords\": [\r\n \"keyword1\",\r\n \"keyword2\"\r\n ],\r\n \"mediaType\": \"application/json\",\r\n \"landingPageUrl\": \"https://www.google.com\",\r\n \"dataAddressProperties\": {\r\n \"https://w3id.org/edc/v0.0.1/ns/type\": \"HttpData\",\r\n \"https://w3id.org/edc/v0.0.1/ns/baseUrl\": \"https://www.google.com\",\r\n \"https://w3id.org/edc/v0.0.1/ns/method\": \"GET\",\r\n \"https://w3id.org/edc/v0.0.1/ns/queryParams\": \"\"\r\n },\r\n \"dataSource\": {\r\n \"type\": \"HTTP_DATA\",\r\n \"httpData\": {\r\n \"baseUrl\": \"http://example.com/baseUrl/\"\r\n }\r\n }\r\n}",
"options": {
"raw": {
"language": "json"
Expand Down Expand Up @@ -386,7 +386,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"contractDefinitionId\": \"testCD\",\r\n \"contractPolicyId\": \"always-true\",\r\n \"accessPolicyId\": \"always-true\",\r\n \"assetSelector\": [\r\n {\r\n \"operandLeft\": \"https://w3id.org/edc/v0.0.1/ns/id\",\r\n \"operator\": \"IN\",\r\n \"operandRight\": {\r\n \"type\": \"VALUE_LIST\",\r\n \"valueList\": [\r\n \"testparamterization-v1.0\"\r\n ]\r\n }\r\n }\r\n ]\r\n}",
"raw": "{\r\n \"contractDefinitionId\": \"testCD\",\r\n \"contractPolicyId\": \"always-true\",\r\n \"accessPolicyId\": \"always-true\",\r\n \"assetSelector\": [\r\n {\r\n \"operandLeft\": \"https://w3id.org/edc/v0.0.1/ns/id\",\r\n \"operator\": \"IN\",\r\n \"operandRight\": {\r\n \"type\": \"VALUE_LIST\",\r\n \"valueList\": [\r\n \"testname-v1.0\"\r\n ]\r\n }\r\n }\r\n ]\r\n}",
"options": {
"raw": {
"language": "json"
Expand Down Expand Up @@ -476,7 +476,7 @@
"header": [],
"body": {
"mode": "raw",
"raw": "{\r\n \"counterPartyAddress\": \"http://edc:11003/api/dsp\",\r\n \"counterPartyParticipantId\": \"my-edc\",\r\n \"contractOfferId\": \"dGVzdENE:dGVzdHBhcmFtdGVyaXphdGlvbi12MS4w:NTUxNjZiOGMtMzk4My00MWMzLTkxN2UtZTQ1ZGVlNzMyNTlj\",\r\n \"policyJsonLd\": \"{\\\"@id\\\":\\\"f15e4b97-0d99-42f5-8f6a-525daf0b72c6\\\",\\\"@type\\\":\\\"http://www.w3.org/ns/odrl/2/Set\\\",\\\"http://www.w3.org/ns/odrl/2/permission\\\":[{\\\"http://www.w3.org/ns/odrl/2/target\\\":\\\"testparamterization-v1.0\\\",\\\"http://www.w3.org/ns/odrl/2/action\\\":{\\\"http://www.w3.org/ns/odrl/2/type\\\":\\\"USE\\\"},\\\"http://www.w3.org/ns/odrl/2/constraint\\\":[{\\\"http://www.w3.org/ns/odrl/2/leftOperand\\\":{\\\"@value\\\":\\\"ALWAYS_TRUE\\\"},\\\"http://www.w3.org/ns/odrl/2/operator\\\":[{\\\"@id\\\":\\\"http://www.w3.org/ns/odrl/2/eq\\\"}],\\\"http://www.w3.org/ns/odrl/2/rightOperand\\\":{\\\"@value\\\":\\\"true\\\"}}]}],\\\"http://www.w3.org/ns/odrl/2/prohibition\\\":[],\\\"http://www.w3.org/ns/odrl/2/obligation\\\":[],\\\"http://www.w3.org/ns/odrl/2/target\\\":\\\"testparamterization-v1.0\\\"}\",\r\n \"assetId\": \"testparamterization-v1.0\"\r\n}",
"raw": "{\r\n \"counterPartyAddress\": \"http://edc:11003/api/dsp\",\r\n \"counterPartyParticipantId\": \"my-edc\",\r\n \"contractOfferId\": \"{{CONTRACT_OFFER_ID}}\",\r\n \"policyJsonLd\": \"{{POLICY_JSON_LD}}\",\r\n \"assetId\": \"{{ASSET_ID}}\"\r\n}",
"options": {
"raw": {
"language": "json"
Expand Down Expand Up @@ -545,6 +545,48 @@
}
},
"response": []
},
{
"name": "Terminate Contract Agreement",
"event": [
{
"listen": "test",
"script": {
"exec": [
""
],
"type": "text/javascript"
}
}
],
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "raw",
"raw": "{\n \"detail\": \"Some detail between 1 and 1000 chars long\",\n \"reason\": \"Some reason between 1 and 100 chars\"\n}\n",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{PROVIDER_EDC_MANAGEMENT_URL}}/wrapper/ui/pages/content-agreement-page/{{CONTRACT_AGREEMENT_ID}}/terminate",
"host": [
"{{PROVIDER_EDC_MANAGEMENT_URL}}"
],
"path": [
"wrapper",
"ui",
"pages",
"content-agreement-page",
"{{CONTRACT_AGREEMENT_ID}}",
"terminate"
]
}
},
"response": []
}
]
},
Expand Down Expand Up @@ -1960,4 +2002,4 @@
"type": "default"
}
]
}
}
1 change: 1 addition & 0 deletions docs/api/sovity-edc-api-wrapper.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,7 @@ components:
description: "For type PARAMS_ONLY: Required data for starting a Transfer Process"
ContractTerminationRequest:
required:
- detail
- reason
type: object
properties:
Expand Down
50 changes: 50 additions & 0 deletions docs/dev/debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Debugging

## Connect to docker images

### Configure

The images are started with the [docker-entrypoint.sh](../../launchers/docker-entrypoint.sh).

This entry point supports debugging via environment variables.

In `docker-compose-dev`, add the following environment variables in `services.edc.environment`

```yaml
REMOTE_DEBUG: y
REMOTE_DEBUG_BIND: 0.0.0.0:5005
```

If you also want to wait for the debugger to connect before starting the EDC, also add

```yaml
REMOTE_DEBUG_SUSPEND: y
```

Then shutdown and restart the EDC with docker compose.

If you used the `dev` set of files:

```bash
docker compose --env-file .env.dev --file docker-compose-dev.yaml down
docker compose --env-file .env.dev --file docker-compose-dev.yaml up
```

### Connect

Each EDC will start on a different set of ports, but they all bind to the same address mentioned above in docker.

To connect to the EDC, in IJ, do:

* Edit configurations
* Add New Configuration
* Remote JVM debugger
* Debugger mode: attach to remote JVM
* Host: localhost
* Post: it depends on the EDC:
* check the `ports` mapping in the docker compose file where you added the remote debugging options
* look for the entry that is `#####:5005`
* This `#####` port is the port you want to connect to.
* Use module classpath: use sovity-edc-ce

Enjoy! :)
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@
import de.sovity.edc.ext.wrapper.api.ui.model.UiContractNegotiation;
import de.sovity.edc.ext.wrapper.api.ui.model.UiDataOffer;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
package de.sovity.edc.ext.wrapper.api.ui.model;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -35,14 +38,20 @@ public class ContractTerminationRequest {
@Schema(
title = "Termination detail",
description = "A user explanation to detail why the contract was terminated.",
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
requiredMode = Schema.RequiredMode.REQUIRED)
@Size(max = MAX_DETAIL_SIZE)
@NotNull
@NotEmpty
@NotBlank
String detail;

@Schema(
title = "Termination reason",
description = "A short reason why this contract was terminated",
requiredMode = Schema.RequiredMode.REQUIRED)
@Size(max = MAX_REASON_SIZE)
@NotBlank
@NotEmpty
@NotNull
String reason;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@
import org.awaitility.Awaitility;
import org.eclipse.edc.connector.contract.spi.ContractId;
import org.eclipse.edc.connector.transfer.spi.types.TransferProcessStates;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.model.HttpRequest;
import org.mockserver.model.HttpResponse;

import java.time.OffsetDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

Expand All @@ -52,11 +55,11 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.edc.spi.CoreConstants.EDC_NAMESPACE;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;

@ExtendWith(E2eTestExtension.class)
public class ContractTerminationTest {


@Test
void canGetAgreementPageForNonTerminatedContract(
E2eScenario scenario,
Expand Down Expand Up @@ -249,6 +252,44 @@ void limitTheDetailSizeAt1000Chars(
// termination completed == success
}

@TestFactory
List<DynamicTest> theDetailsAreMandatory(
E2eScenario scenario,
@Consumer EdcClient consumerClient,
@Provider EdcClient providerClient
) {
val invalidDetails = List.of(
"",
" ",
" ",
"\t",
"\n"
);

return invalidDetails.stream().map(
detail -> dynamicTest("Can't use '%s' for details".formatted(detail),
() -> {
val assetId = scenario.createAsset();
scenario.createContractDefinition(assetId);
val negotiation = scenario.negotiateAssetAndAwait(assetId);

// act
val reason = "Some reason";

// assert when too big

assertThrows(
ApiException.class,
() -> consumerClient.uiApi().terminateContractAgreement(
negotiation.getContractAgreementId(),
ContractTerminationRequest.builder()
.detail(detail)
.reason(reason)
.build())
);
})).toList();
}

@Test
@SneakyThrows
void canTerminateFromProvider(
Expand Down
Loading