Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • fit-connect/sdk-java
1 result
Show changes
Commits on Source (23)
Showing
with 371 additions and 98 deletions
...@@ -26,19 +26,19 @@ reuse: ...@@ -26,19 +26,19 @@ reuse:
DOCKER_REGISTRY_READ: $DOCKER_PULL_REGISTRY DOCKER_REGISTRY_READ: $DOCKER_PULL_REGISTRY
build: build:
image: maven:latest image: eclipse-temurin:11.0.18_10-jdk
stage: build stage: build
script: script:
- ./mvnw $MAVEN_CLI_OPTS clean install -DskipTests --no-transfer-progress -T2 - ./mvnw $MAVEN_CLI_OPTS clean install -DskipTests --no-transfer-progress -T2
test: test:
image: maven:latest image: eclipse-temurin:11.0.18_10-jdk
stage: test stage: test
script: script:
- ./mvnw $MAVEN_CLI_OPTS test --no-transfer-progress -T2 - ./mvnw $MAVEN_CLI_OPTS verify --no-transfer-progress -T2
package: package:
image: maven:latest image: eclipse-temurin:11.0.18_10-jdk
stage: package stage: package
before_script: &gpg-setup before_script: &gpg-setup
- apt-get update - apt-get update
...@@ -50,14 +50,15 @@ package: ...@@ -50,14 +50,15 @@ package:
- ./mvnw $MAVEN_CLI_OPTS package -DskipTests - ./mvnw $MAVEN_CLI_OPTS package -DskipTests
artifacts: artifacts:
paths: paths:
- client/target/*.jar
- core/target/*.jar
- api/target/*.jar - api/target/*.jar
- core/target/*.jar
- client/target/*.jar
- integration-tests/target/*.jar
expire_in: 1 day expire_in: 1 day
when: manual when: manual
deploy: deploy:
image: maven:latest image: eclipse-temurin:11.0.18_10-jdk
stage: deploy stage: deploy
before_script: *gpg-setup before_script: *gpg-setup
script: script:
......
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Files: api/src/* client/src/* core/src/* Files: api/src/* client/src/* core/src/* integration-tests/src/*
api/README.md client/README.md core/README.md api/README.md client/README.md core/README.md
README.md CHANGELOG.md SECURITY.md README.md CHANGELOG.md SECURITY.md
Copyright: 2022 FIT-Connect contributors Copyright: 2022 FIT-Connect contributors
...@@ -10,7 +10,7 @@ Files: .mvn/wrapper/* mvnw mvnw.cmd ...@@ -10,7 +10,7 @@ Files: .mvn/wrapper/* mvnw mvnw.cmd
Copyright: 2013-2022 The Apache Software Foundation Copyright: 2013-2022 The Apache Software Foundation
License: Apache-2.0 License: Apache-2.0
Files: pom.xml api/pom.xml core/pom.xml client/pom.xml open-api/pom.xml Files: pom.xml api/pom.xml core/pom.xml client/pom.xml integration-tests/pom.xml
.gitlab-ci.yml .gitignore .m2/release.xml .gitlab-ci.yml .gitignore .m2/release.xml
renovate.json checkstyle.xml checkstyle-suppressions.xml config.yml renovate.json checkstyle.xml checkstyle-suppressions.xml config.yml
Copyright: 2022 FIT-Connect contributors Copyright: 2022 FIT-Connect contributors
......
...@@ -106,11 +106,18 @@ _The following steps show how to get the SDK running_ ...@@ -106,11 +106,18 @@ _The following steps show how to get the SDK running_
- add reference to private signature key (JWK) to *SUBSCRIBER* section - add reference to private signature key (JWK) to *SUBSCRIBER* section
6. Provide config via environment variable ``FIT_CONNECT_CONFIG`` or load the config with 6. Load a configuration via:
````java ````java
final var config = ApplicationConfigLoader.loadConfig("absolute/path/to/config.yml"); final ApplicationConfig config = ApplicationConfigLoader.loadConfigFromPath(Path.of("path/to/config.yml"));
final var senderClient = ClientFactory.senderClient(config);
```` ````
7. Afterwards the config is used to initialize clients with the `ClientFactory` that offer clients for sender, subscriber and routing:
````java
final SenderClient senderClient = ClientFactory.getSenderClient(config);
//
final SubscriberClient subscriberClient = ClientFactory.getSubscriberClient(config);
//
final RoutingClient routingClient = ClientFactory.getRoutingClient(config);
````
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
...@@ -126,7 +133,7 @@ A typical workflow using the `RoutingClient` and `SenderClient` would be: ...@@ -126,7 +133,7 @@ A typical workflow using the `RoutingClient` and `SenderClient` would be:
Areas can be searched with one or more search criteria: Areas can be searched with one or more search criteria:
```java ```java
final RoutingClient routingClient = ClientFactory.routingClient(config); final RoutingClient routingClient = ClientFactory.getRoutingClient(config);
final var citySearchCriterion = "Leip*"; final var citySearchCriterion = "Leip*";
final var zipCodeSearchCriterion = "04229"; final var zipCodeSearchCriterion = "04229";
...@@ -156,7 +163,7 @@ __Note:__ Both, the `leikaKey` service-identifier and the region keys `ars/ags`c ...@@ -156,7 +163,7 @@ __Note:__ Both, the `leikaKey` service-identifier and the region keys `ars/ags`c
#### Find destination by service identifier and *areaId* #### Find destination by service identifier and *areaId*
```java ```java
final RoutingClient routingClient = ClientFactory.routingClient(config); final RoutingClient routingClient = ClientFactory.getRoutingClient(config);
final DestinationSearch search = DestinationSearch.Builder() final DestinationSearch search = DestinationSearch.Builder()
.withLeikaKey("99123456760610") .withLeikaKey("99123456760610")
...@@ -178,7 +185,7 @@ for (final Route route : routes){ ...@@ -178,7 +185,7 @@ for (final Route route : routes){
Besides the areaId another search criterion for the area/region can be used as well: Besides the areaId another search criterion for the area/region can be used as well:
```java ```java
final RoutingClient routingClient = ClientFactory.routingClient(config); final RoutingClient routingClient = ClientFactory.getRoutingClient(config);
final DestinationSearch search = DestinationSearch.Builder() final DestinationSearch search = DestinationSearch.Builder()
.withLeikaKey("99123456760610") .withLeikaKey("99123456760610")
...@@ -212,12 +219,12 @@ If all data, metadata and attachments are encrypted outside the SDK the sender c ...@@ -212,12 +219,12 @@ If all data, metadata and attachments are encrypted outside the SDK the sender c
```java ```java
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final Optional<String> publicJwk = ClientFactory.senderClient(config).getPublicKey(destinationId); final String publicJwkAsJsonString = ClientFactory.getSenderClient(config).getPublicKey(destinationId);
``` ```
#### 2. Send encrypted data #### 2. Send encrypted data
To send an encrypted submission the builder `EncryptedSubmissionBuilder` is needed to construct an `EncryptedSubmissionPayload` object. To send an encrypted submission the builder `EncryptedSubmissionBuilder` is needed to construct an `SendableEncryptedSubmission` object.
The payload can be submitted as shown below via the `ClientFactory`. The payload can be submitted as shown below via the `ClientFactory`.
If optional attachments are added, the UUID needs to be provided for each attachment to be able to announce them before the submission is actually sent. If optional attachments are added, the UUID needs to be provided for each attachment to be able to announce them before the submission is actually sent.
...@@ -225,17 +232,17 @@ This is necessary because the SDK does not have access to the already encrypted ...@@ -225,17 +232,17 @@ This is necessary because the SDK does not have access to the already encrypted
```java ```java
// The constructed client can be reused to send multiple submissions // The constructed client can be reused to send multiple submissions
final SenderClient senderClient = ClientFactory.senderClient(config); final SenderClient senderClient = ClientFactory.getSenderClient(config);
final EncryptedSubmissionPayload frontendEncryptedPayload = EncryptedSubmissionBuilder.Builder() final SendableEncryptedSubmission encryptedSubmission = SendableEncryptedSubmission.Builder()
.withEncryptedAttachment(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"), "$encrpyt€ed @tt@chment") // optional .setDestination(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"))
.withEncryptedData("{$encrpyt€ed json}") .setServiceType("urn:de:fim:leika:leistung:99400048079000", "Führerscheinummeldung")
.withEncryptedMetadata("$encrpyt€ed metadata") .setEncryptedMetadata("$encrpyt€ed metadata")
.withDestination(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14")) .setEncryptedData("{$encrpyt€ed json}")
.withServiceType("Führerscheinummeldung", "urn:de:fim:leika:leistung:99400048079000") .addEncryptedAttachment(new EncryptedAttachment(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"), "$encrpyt€ed @tt@chment")) // optional
.build(); .build();
final SentSubmission sentSubmission = senderClient.submit(frontendEncryptedPayload); final SentSubmission sentSubmission = senderClient.send(encryptedSubmission);
``` ```
| **Important** | | **Important** |
...@@ -249,21 +256,23 @@ If all data, metadata and attachments are encrypted in the sender using the SDK, ...@@ -249,21 +256,23 @@ If all data, metadata and attachments are encrypted in the sender using the SDK,
Be aware that this example is not end-2-end encrypted, see [FIT-Connect documentation](https://docs.fitko.de/fit-connect/docs/getting-started/encryption) for details. Be aware that this example is not end-2-end encrypted, see [FIT-Connect documentation](https://docs.fitko.de/fit-connect/docs/getting-started/encryption) for details.
To send a submission the builder `SubmissionBuilder` is needed to construct a `SubmissionPayload` object. To send a submission the builder `SubmissionBuilder` is needed to construct a `SendableSubmission` object.
The payload can be submitted as shown below via the `ClientFactory`. The payload can be submitted as shown below via the `ClientFactory`.
```java ```java
// The constructed client can be reused to send multiple submissions // The constructed client can be reused to send multiple submissions
final SenderClient senderClient = ClientFactory.senderClient(config); final SenderClient senderClient = ClientFactory.getSenderClient(config);
final SubmissionPayload submissionPayload = SubmissionBuilder.Builder() final SendableSubmission sendableSubmission = SendableSubmission.Builder()
.withAttachment(Path.of("path/to/attachment.txt").toFile()) // optional .setDestination(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"))
.withJsonData("{ \"foo\" : \"bar\"}") .setServiceType("urn:de:fim:leika:leistung:99400048079000", "Führerscheinummeldung")
.withDestination(UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14")) .setJsonData("{ \"foo\" : \"bar\"}")
.withServiceType("Führerscheinummeldung", "urn:de:fim:leika:leistung:99400048079000") // optional properties
.addAttachment(Attachment.fromPath(Path.of("path/to/attachment.txt"), "text/plain"))
.setReplyChannel(ReplyChannel.fromEmail("test@mail.org"))
.build(); .build();
final SentSubmission sentSubmission = senderClient.submit(submissionPayload); final SentSubmission sentSubmission = senderClient.send(sendableSubmission);
``` ```
...@@ -273,7 +282,7 @@ To read the event-log, destinationId and caseId are needed. ...@@ -273,7 +282,7 @@ To read the event-log, destinationId and caseId are needed.
final var caseId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var caseId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final List<EventLogEntry> eventLog = ClientFactory.senderClient(config).getEventLog(caseId, destinationId); final List<EventLogEntry> eventLog = ClientFactory.getSenderClient(config).getEventLog(caseId, destinationId);
for(EventLogEntry logEntry: eventLog) { for(EventLogEntry logEntry: eventLog) {
LOGGER.info("Event: {}", logEntry.getEvent()); LOGGER.info("Event: {}", logEntry.getEvent());
...@@ -303,9 +312,9 @@ Instead of the entire log, the latest status for a submission can be retrieved a ...@@ -303,9 +312,9 @@ Instead of the entire log, the latest status for a submission can be retrieved a
```java ```java
final SentSubmission sentSubmission = ... // persisted sent submission by sender client final SentSubmission sentSubmission = ... // persisted sent submission by sender client
final EventStatus eventStatus = ClientFactory.senderClient(config).getStatusForSubmission(sentSubmission); final EventStatus submissionStatus = ClientFactory.getSenderClient(config).getStatusForSubmission(sentSubmission);
LOGGER.info("Current status for submission {} => {}", sentSubmission.getSubmissionId(), eventStatus.getStatus()); LOGGER.info("Current status for submission {} => {}", sentSubmission.getSubmissionId(), submissionStatus.getStatus());
``` ```
The example output shows the current state of the submission after being created, following the transitions in the diagram below: The example output shows the current state of the submission after being created, following the transitions in the diagram below:
...@@ -326,7 +335,7 @@ More details on how this method works can be found here: ...@@ -326,7 +335,7 @@ More details on how this method works can be found here:
The Java SDK provides a convenient method for validating callbacks, its usage could look like this: The Java SDK provides a convenient method for validating callbacks, its usage could look like this:
```java ```java
final SenderClient senderClient = ClientFactory.senderClient(config); final SenderClient senderClient = ClientFactory.getSenderClient(config);
final ValidationResult validationResult = senderClient.validateCallback("hmac", 0L, "body", "secret"); final ValidationResult validationResult = senderClient.validateCallback("hmac", 0L, "body", "secret");
...@@ -342,45 +351,62 @@ Submissions can be fetched by id or as a list of submissions for a specific case ...@@ -342,45 +351,62 @@ Submissions can be fetched by id or as a list of submissions for a specific case
#### List with pagination #### List with pagination
Limit and offset parameters allow to page through the result. Limit and offset parameters allow to page through the result.
```java ```java
final var subscriberClient = ClientFactory.getSubscriberClient(config);
final int offset = 0; final int offset = 0;
final int limit = 100; final int limit = 100;
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final Set<SubmissionForPickup> firstOneHundredSubmissions = ClientFactory.subscriberClient(config).getAvailableSubmissions(destinationId), limit, offset);
final Set<SubmissionForPickup> firstOneHundredSubmissions = subscriberClient.getAvailableSubmissionsforDestination(destinationId), limit, offset);
``` ```
#### List without pagination #### List without pagination
Listing available submissions without pagination pulls the first 500 entries. Listing available submissions without pagination pulls the first 500 entries.
```java ```java
final var subscriberClient = ClientFactory.getSubscriberClient(config);
final var destinationId= UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var destinationId= UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final Set<SubmissionForPickup> submissions = ClientFactory.subscriberClient(config).getAvailableSubmissions(destinationId);
final Set<SubmissionForPickup> submissions = subscriberClient.getAvailableSubmissionsForDestination(destinationId);
``` ```
#### Receive single submission #### Receive single submission
```java ```java
final submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); // by id
final ReceivedSubmission receivedSubmission = ClientFactory.subscriberClient(config).requestSubmission(submissionId); final var submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final ReceivedSubmission receivedSubmission = ClientFactory.getSubscriberClient(config).requestSubmission(submissionId);
``` ```
```java
// by object
final SubmissionForPickup submissionForPickup = // code for sending submission;
final ReceivedSubmission receivedSubmission = ClientFactory.getSubscriberClient(config).requestSubmission(submissionForPickup);
```
Now, the received submission allows access to the decrypted data, attachments, metadata and ids Now, the received submission allows access to the decrypted data, attachments, metadata and ids
```java ```java
// access data // access data
final String data = receivedData.getData(); final String data = receivedSubmission.getDataAsString();
final URI dataSchemaUri = receivedData.getDataSchemaUri(); final URI dataSchemaUri = receivedSubmission.getDataSchemaUri();
final MimeType mimeType = receivedData.getDataMimeType(); final String mimeType = receivedSubmission.getDataMimeType();
// access metadata // access metadata
final Metadata = receivedData.getSubmissionMetdata(); final Metadata metadata = receivedSubmission.getSubmissionMetdata();
// access reply channel
final ReplyChannel replyChannel = metadata.getReplyChannel();
// access attachments // access attachments
for(final ReceivedAttachment attachment : receivedSubmission.getAttachments()){ for(final Attachment attachment : receivedSubmission.getAttachments()){
final byte[] attachmentRawData = attachment.getData();
final String originalFilename = attachment.getFilename(); final String originalFilename = attachment.getFilename();
final UUID attachmentId = attachment.getAttachmentId(); final String attachmentMimeType = attachment.getMimeType();
// different formats to retrieve the attachment content
final byte[] attachmentDataAsBytes = attachment.getDataAsBytes();
final String attachmentDataAsString = attachment.getDataAString(StandardCharsets.UTF_8);
} }
// access further ids of submission // access further ids of submission
final UUID caseId = receivedData.getCaseId(); final UUID caseId = receivedSubmission.getCaseId();
final UUID submissionId = receivedData.getSubmissionId(); final UUID submissionId = receivedSubmission.getSubmissionId();
final UUID destinationId = receivedData.getDestinationId(); final UUID destinationId = receivedSubmission.getDestinationId();
``` ```
### Sending events to the event-log ### Sending events to the event-log
...@@ -389,13 +415,20 @@ In order to accept or reject a submission, the subscriber client can send events ...@@ -389,13 +415,20 @@ In order to accept or reject a submission, the subscriber client can send events
For more details please see the documentation on [events](https://docs.fitko.de/fit-connect/docs/getting-started/event-log/overview) and the creation of [set-events](https://docs.fitko.de/fit-connect/docs/getting-started/event-log/set-creation). For more details please see the documentation on [events](https://docs.fitko.de/fit-connect/docs/getting-started/event-log/overview) and the creation of [set-events](https://docs.fitko.de/fit-connect/docs/getting-started/event-log/set-creation).
#### Accepting a submission #### Accepting a submission
If the functional review by the subscriber was positive, the submission can be accepted with an `accept-submission` event. If the functional review by the subscriber was positive, the submission can be accepted with an `accept-submission` event.
For this event a list of optional problems can be sent, the submission is still accepted but with remarks.
```java ```java
final var submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
ClientFactory.subscriberClient(config) ClientFactory.getSubscriberClient(config)
.requestSubmission(submissionId) .requestSubmission(submissionId);
.acceptSubmission(); .acceptSubmission();
// OR accept with an optional list of problems
ClientFactory.getSubscriberClient(config)
.requestSubmission(submissionId);
.acceptSubmission(List.of(new MyCustomProblem()));
``` ```
After the accept event was sent the submission transitions into the state `deleted` and is removed. After the accept event was sent the submission transitions into the state `deleted` and is removed.
#### Rejecting a submission #### Rejecting a submission
...@@ -405,11 +438,9 @@ See the Fit-Connect documentation for more details on [available (technical) pro ...@@ -405,11 +438,9 @@ See the Fit-Connect documentation for more details on [available (technical) pro
```java ```java
final var submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var submissionId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final var rejectionProblems = List.of(new DataSchemaViolation()); ClientFactory.getSubscriberClient(config)
.requestSubmission(submissionId);
ClientFactory.subscriberClient(config) .rejectSubmission(List.of(new DataSchemaViolation()));
.requestSubmission(submissionId)
.rejectSubmission(rejectionProblems);
``` ```
After the rejection event was sent the submission transitions into the state `deleted` and is removed. After the rejection event was sent the submission transitions into the state `deleted` and is removed.
...@@ -419,7 +450,7 @@ To read the event-log, destinationId and caseId are needed. ...@@ -419,7 +450,7 @@ To read the event-log, destinationId and caseId are needed.
final var caseId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var caseId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14"); final var destinationId = UUID.fromString("d2d43892-9d9c-4630-980a-5af341179b14");
final List<EventLogEntry> eventLog = ClientFactory.subscriberClient(config).getEventLog(caseId, destinationId); final List<EventLogEntry> eventLog = ClientFactory.getSubscriberClient(config).getEventLog(caseId, destinationId);
for(EventLogEntry logEntry: eventLog) { for(EventLogEntry logEntry: eventLog) {
LOGGER.info("Event: {}", logEntry.getEvent()); LOGGER.info("Event: {}", logEntry.getEvent());
...@@ -450,7 +481,7 @@ For more details please see the [event-log documentation](https://docs.fitko.de/ ...@@ -450,7 +481,7 @@ For more details please see the [event-log documentation](https://docs.fitko.de/
The validation of callbacks works similar to the sender side (see [Sender Callback Validation](#validating-callbacks)), but instead of the `SenderClient`, we use the `SubscriberClient`: The validation of callbacks works similar to the sender side (see [Sender Callback Validation](#validating-callbacks)), but instead of the `SenderClient`, we use the `SubscriberClient`:
```java ```java
final SubscriberClient subscriberClient = ClientFactory.subscriberClient(config); final SubscriberClient subscriberClient = ClientFactory.getSubscriberClient(config);
final ValidationResult validationResult = subscriberClient.validateCallback("hmac", 0L, "body", "secret"); final ValidationResult validationResult = subscriberClient.validateCallback("hmac", 0L, "body", "secret");
...@@ -461,8 +492,8 @@ if(validationResult.hasError()){ ...@@ -461,8 +492,8 @@ if(validationResult.hasError()){
## Integration Tests ## Integration Tests
Integration tests in `dev.fitko.fitconnect.client.ClientIntegrationTest` run only on the CI-Server and are ignored by default locally. Integration tests do not run per default with `mvn test`, but they can be executed with the maven profile `IntegrationTests` via `mvn -PIntegrationTests test`.
To run them on a local machine the following environment variables have to be set in the run-configuration of the IDE: They expect the following environment variables to be set in the rn configuration of the IDE or on the local terminal:
* SENDER_CLIENT_ID * SENDER_CLIENT_ID
* SENDER_CLIENT_SECRET * SENDER_CLIENT_SECRET
...@@ -483,7 +514,7 @@ var submissionBaseUrl = "https://submission-api-testing.fit-connect.fitko.dev"; ...@@ -483,7 +514,7 @@ var submissionBaseUrl = "https://submission-api-testing.fit-connect.fitko.dev";
## Roadmap ## Roadmap
- [ ] Add auto-reject on technical errors - [ ] Add auto-reject on technical errors
- [ ] Maven central release of 1.0.0 - [ ] Maven central release of 1.0.0-beta
See the [open issues](https://git.fitko.de/fit-connect/planning/-/boards/44?search=SDK) for a full list of proposed features (and known issues). See the [open issues](https://git.fitko.de/fit-connect/planning/-/boards/44?search=SDK) for a full list of proposed features (and known issues).
...@@ -506,6 +537,6 @@ Hierfür kann das SDK in die anzubindenden Software integriert werden. ...@@ -506,6 +537,6 @@ Hierfür kann das SDK in die anzubindenden Software integriert werden.
Erfolgt die Integration des SDK in unveränderter Form, liegt keine Bearbeitung im Sinne der EUPL bzw. des deutschen Urheberrechts vor. Erfolgt die Integration des SDK in unveränderter Form, liegt keine Bearbeitung im Sinne der EUPL bzw. des deutschen Urheberrechts vor.
Die Art und Weise der Verlinkung des SDK führt insbesondere nicht zur Schaffung eines abgeleiteten Werkes. Die Art und Weise der Verlinkung des SDK führt insbesondere nicht zur Schaffung eines abgeleiteten Werkes.
Die unveränderte Übernahme des SDK in eine anzubindende Software führt damit nicht dazu, dass die anzubindende Software unter den Bedingungen der EUPL zu lizenzieren ist. Die unveränderte Übernahme des SDK in eine anzubindende Software führt damit nicht dazu, dass die anzubindende Software unter den Bedingungen der EUPL zu lizenzieren ist.
Für die Weitergabe des SDK selbst - in unveränderter oder bearbeiteter Form, als Quellcode oder ausführbares Programm - gelten die Lizenzbedingungen der EUPL in unverände*rter Weise. Für die Weitergabe des SDK selbst - in unveränderter oder bearbeiteter Form, als Quellcode oder ausführbares Programm - gelten die Lizenzbedingungen der EUPL in unveränderter Weise.*
<p align="right">(<a href="#top">back to top</a>)</p> <p align="right">(<a href="#top">back to top</a>)</p>
...@@ -5,6 +5,8 @@ import lombok.Builder; ...@@ -5,6 +5,8 @@ import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.List;
@Data @Data
@Builder @Builder
@AllArgsConstructor @AllArgsConstructor
...@@ -12,6 +14,6 @@ import lombok.NoArgsConstructor; ...@@ -12,6 +14,6 @@ import lombok.NoArgsConstructor;
public class SubscriberConfig { public class SubscriberConfig {
private String clientId; private String clientId;
private String clientSecret; private String clientSecret;
private String privateDecryptionKeyPath; private List<String> privateDecryptionKeyPaths;
private String privateSigningKeyPath; private String privateSigningKeyPath;
} }
...@@ -2,6 +2,7 @@ package dev.fitko.fitconnect.api.domain.model.destination; ...@@ -2,6 +2,7 @@ package dev.fitko.fitconnect.api.domain.model.destination;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import dev.fitko.fitconnect.api.domain.model.replychannel.ReplyChannel;
import dev.fitko.fitconnect.api.domain.model.submission.Callback; import dev.fitko.fitconnect.api.domain.model.submission.Callback;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
......
package dev.fitko.fitconnect.api.domain.model.destination; package dev.fitko.fitconnect.api.domain.model.destination;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import dev.fitko.fitconnect.api.domain.model.replychannel.ReplyChannel;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
......
...@@ -100,12 +100,12 @@ public enum Event { ...@@ -100,12 +100,12 @@ public enum Event {
@Override @Override
public SubmissionState getState() { public SubmissionState getState() {
return SubmissionState.SUBMITTED; return SubmissionState.NOTIFIED;
} }
@Override @Override
public Set<Event> allowedNextEvents() { public Set<Event> allowedNextEvents() {
return Set.of(SUBMIT); return Set.of(ACCEPT, REJECT, FORWARD);
} }
}, },
......
...@@ -2,43 +2,72 @@ package dev.fitko.fitconnect.api.domain.model.event; ...@@ -2,43 +2,72 @@ package dev.fitko.fitconnect.api.domain.model.event;
import dev.fitko.fitconnect.api.domain.model.event.problems.Problem; import dev.fitko.fitconnect.api.domain.model.event.problems.Problem;
import dev.fitko.fitconnect.api.domain.model.submission.Submission; import dev.fitko.fitconnect.api.domain.model.submission.Submission;
import dev.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@Data @Data
@Builder
@AllArgsConstructor
public class EventPayload { public class EventPayload {
private UUID submissionId; private UUID submissionId;
private UUID destinationId; private UUID destinationId;
private UUID caseId; private UUID caseId;
// used for auth-tag validation
private String encryptedMetadata; private String encryptedMetadata;
private String encryptedData; private String encryptedData;
private Map<UUID, String> encryptedAttachments; private Map<UUID, String> encryptedAttachments;
private List<Problem> problems; private List<Problem> problems;
public EventPayload(final Submission submission, final Map<UUID, String> encryptedAttachments, final List<Problem> problems) { public static EventPayload forRejectEvent(final SubmissionForPickup submission, final List<Problem> problems){
submissionId = submission.getSubmissionId(); return EventPayload.builder()
destinationId = submission.getDestinationId(); .submissionId(submission.getSubmissionId())
caseId = submission.getCaseId(); .destinationId(submission.getDestinationId())
encryptedData = submission.getEncryptedData(); .caseId(submission.getCaseId())
encryptedMetadata = submission.getEncryptedMetadata(); .problems(problems)
this.encryptedAttachments = encryptedAttachments; .build();
this.problems = problems;
} }
public EventPayload(final Submission submission, final Map<UUID, String> encryptedAttachments) { public static EventPayload forRejectEvent(final Submission submission, final List<Problem> problems){
this(submission, encryptedAttachments, Collections.emptyList()); return EventPayload.builder()
.submissionId(submission.getSubmissionId())
.destinationId(submission.getDestinationId())
.caseId(submission.getCaseId())
.problems(problems)
.build();
} }
public EventPayload(final Submission submission, final List<Problem> problems) { public static EventPayload forAcceptEvent(final Submission submission, final Problem... problems){
this(submission, Collections.emptyMap(), problems); return EventPayload.builder()
.submissionId(submission.getSubmissionId())
.destinationId(submission.getDestinationId())
.caseId(submission.getCaseId())
.encryptedData(submission.getEncryptedData())
.encryptedMetadata(submission.getEncryptedMetadata())
.encryptedAttachments(Collections.emptyMap())
.problems(Arrays.asList(problems))
.build();
} }
public EventPayload(final Submission submission) { public static EventPayload forAcceptEventWithAttachments(final Submission submission, final Map<UUID, String> encryptedAttachments, final Problem... problems){
this(submission, Collections.emptyMap(), Collections.emptyList()); return EventPayload.builder()
.submissionId(submission.getSubmissionId())
.destinationId(submission.getDestinationId())
.caseId(submission.getCaseId())
.encryptedData(submission.getEncryptedData())
.encryptedMetadata(submission.getEncryptedMetadata())
.encryptedAttachments(encryptedAttachments)
.problems(Arrays.asList(problems))
.build();
} }
} }
...@@ -7,7 +7,8 @@ public enum SubmissionState { ...@@ -7,7 +7,8 @@ public enum SubmissionState {
ACCEPTED("accepted"), ACCEPTED("accepted"),
REJECTED("rejected"), REJECTED("rejected"),
DELETED("deleted"), DELETED("deleted"),
FORWARDED("forwarded"); FORWARDED("forwarded"),
NOTIFIED("notified");
private final String name; private final String name;
......
...@@ -10,7 +10,7 @@ import java.util.List; ...@@ -10,7 +10,7 @@ import java.util.List;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class EventStatus { public class SubmissionStatus {
SubmissionState status; SubmissionState status;
List<Problem> problems; List<Problem> problems;
} }
...@@ -2,9 +2,13 @@ package dev.fitko.fitconnect.api.domain.model.metadata; ...@@ -2,9 +2,13 @@ package dev.fitko.fitconnect.api.domain.model.metadata;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
@Data @Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class AdditionalReferenceInfo { public class AdditionalReferenceInfo {
...@@ -13,6 +17,29 @@ public class AdditionalReferenceInfo { ...@@ -13,6 +17,29 @@ public class AdditionalReferenceInfo {
@JsonProperty("applicationDate") @JsonProperty("applicationDate")
private String applicationDate; private String applicationDate;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String senderReference;
private String applicationDate;
public Builder withSenderReference(final String senderReference) {
this.senderReference = senderReference;
return this;
}
public Builder withApplicationDate(final String applicationDate) {
this.applicationDate = applicationDate;
return this;
}
public AdditionalReferenceInfo build() {
return new AdditionalReferenceInfo(senderReference, applicationDate);
}
}
} }
package dev.fitko.fitconnect.api.domain.model.metadata; package dev.fitko.fitconnect.api.domain.model.metadata;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
@Data @Data
@NoArgsConstructor @AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AuthenticationInformation { public class AuthenticationInformation {
@JsonProperty("type") @JsonProperty("type")
...@@ -16,4 +18,32 @@ public class AuthenticationInformation { ...@@ -16,4 +18,32 @@ public class AuthenticationInformation {
@JsonProperty("content") @JsonProperty("content")
private String content; private String content;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String type;
private String version;
private String content;
public Builder withType(final String type) {
this.type = type;
return this;
}
public Builder withVersion(final String version) {
this.version = version;
return this;
}
public Builder withContent(final String content) {
this.content = content;
return this;
}
public AuthenticationInformation build() {
return new AuthenticationInformation(type, version, content);
}
}
} }
...@@ -2,7 +2,7 @@ package dev.fitko.fitconnect.api.domain.model.metadata; ...@@ -2,7 +2,7 @@ package dev.fitko.fitconnect.api.domain.model.metadata;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import dev.fitko.fitconnect.api.domain.model.metadata.attachment.Attachment; import dev.fitko.fitconnect.api.domain.model.metadata.attachment.ApiAttachment;
import dev.fitko.fitconnect.api.domain.model.metadata.data.Data; import dev.fitko.fitconnect.api.domain.model.metadata.data.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
...@@ -17,5 +17,5 @@ public class ContentStructure { ...@@ -17,5 +17,5 @@ public class ContentStructure {
private Data data; private Data data;
@JsonProperty("attachments") @JsonProperty("attachments")
private List<Attachment> attachments; private List<ApiAttachment> attachments;
} }
...@@ -2,28 +2,41 @@ package dev.fitko.fitconnect.api.domain.model.metadata; ...@@ -2,28 +2,41 @@ package dev.fitko.fitconnect.api.domain.model.metadata;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data; import dev.fitko.fitconnect.api.domain.model.metadata.payment.PaymentInformation;
import dev.fitko.fitconnect.api.domain.model.replychannel.ReplyChannel;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List; import java.util.List;
@Data @Setter
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class Metadata { public class Metadata {
@Getter
@JsonProperty("$schema") @JsonProperty("$schema")
private String schema; private String schema;
@JsonProperty("contentStructure") @Getter
private ContentStructure contentStructure; private ContentStructure contentStructure;
@JsonProperty("publicServiceType")
private PublicServiceType publicServiceType; private PublicServiceType publicServiceType;
@JsonProperty("authenticationInformation") @Getter
private List<AuthenticationInformation> authenticationInformation; private List<AuthenticationInformation> authenticationInformation;
@JsonProperty("additionalReferenceInfo") @Getter
private PaymentInformation paymentInformation;
@Getter
private ReplyChannel replyChannel;
@Getter
private AdditionalReferenceInfo additionalReferenceInfo; private AdditionalReferenceInfo additionalReferenceInfo;
} }
...@@ -12,7 +12,7 @@ import java.util.UUID; ...@@ -12,7 +12,7 @@ import java.util.UUID;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class Attachment { public class ApiAttachment {
@JsonProperty("hash") @JsonProperty("hash")
private Hash hash; private Hash hash;
......
package dev.fitko.fitconnect.api.domain.model.metadata.payment;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import java.net.URI;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PaymentInformation {
private URI transactionUrl;
private String transactionId;
private String transactionReference;
private Date transactionTimestamp;
private PaymentMethod paymentMethod;
private String paymentMethodDetail;
private PaymentStatus status;
private double grossAmount;
public static Builder builder() {
return new Builder();
}
public static class Builder {
private URI transactionUrl;
private @NonNull String transactionId;
private @NonNull String transactionReference;
private @NonNull Date transactionTimestamp;
private @NonNull PaymentMethod paymentMethod;
private String paymentMethodDetail;
private @NonNull PaymentStatus status;
private double grossAmount;
public Builder withTransactionUrl(final URI transactionUrl) {
this.transactionUrl = transactionUrl;
return this;
}
public Builder withTransactionId(final String transactionId) {
this.transactionId = transactionId;
return this;
}
public Builder withTransactionReference(final String transactionReference) {
this.transactionReference = transactionReference;
return this;
}
public Builder withTransactionTimestamp(final Date transactionTimestamp) {
this.transactionTimestamp = transactionTimestamp;
return this;
}
public Builder withPaymentMethod(final PaymentMethod paymentMethod) {
this.paymentMethod = paymentMethod;
return this;
}
public Builder withPaymentMethodDetail(final String paymentMethodDetail) {
this.paymentMethodDetail = paymentMethodDetail;
return this;
}
public Builder withStatus(final PaymentStatus status) {
this.status = status;
return this;
}
public Builder withGrossAmount(final double grossAmount) {
this.grossAmount = grossAmount;
return this;
}
public PaymentInformation build() {
return new PaymentInformation(transactionUrl, transactionId, transactionReference, transactionTimestamp, paymentMethod, paymentMethodDetail, status, grossAmount);
}
}
}
package dev.fitko.fitconnect.api.domain.model.metadata.payment;
public enum PaymentMethod {
GIROPAY, PAYDIRECT, CREDITCARD, PAYPAL, INVOICE, OTHER
}
package dev.fitko.fitconnect.api.domain.model.metadata.payment;
public enum PaymentStatus {
INITIAL, BOOKED, FAILED, CANCELED
}
package dev.fitko.fitconnect.api.domain.model.destination; package dev.fitko.fitconnect.api.domain.model.replychannel;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@Data @Data
@NoArgsConstructor @NoArgsConstructor
public class ReplyChannel { @AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class DeMail {
@JsonProperty("deMail") @JsonProperty("address")
private Object deMail; private String address;
@JsonProperty("elster")
private Object elster;
@JsonProperty("eMail")
private ReplyChannelEMail eMail;
@JsonProperty("fink")
private Object fink;
} }
package dev.fitko.fitconnect.api.domain.model.replychannel;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Elster {
@JsonProperty("accountId")
private String accountId;
@JsonProperty("lieferTicket")
private String deliveryTicket;
@JsonProperty("geschaeftszeichen")
private String reference;
}