Skip to content
Snippets Groups Projects
Commit 3bff4a67 authored by Martin Vogel's avatar Martin Vogel
Browse files

Merge branch 'feature/566-check-metadata-schema' into 'main'

Validierung des Metadaten Schemas

See merge request !7
parents cc6ace1f 6d21176a
No related branches found
No related tags found
1 merge request!7Validierung des Metadaten Schemas
Showing
with 167 additions and 64 deletions
...@@ -8,6 +8,8 @@ public class ApplicationConfig { ...@@ -8,6 +8,8 @@ public class ApplicationConfig {
private String httpProxyHost = ""; private String httpProxyHost = "";
private Integer httpProxyPort = 0; private Integer httpProxyPort = 0;
private Integer requestTimeoutInSeconds; private Integer requestTimeoutInSeconds;
private String metadataSchemaPath;
private String privateSigningKeyPath;
private Sender sender; private Sender sender;
private Subscriber subscriber; private Subscriber subscriber;
......
...@@ -8,7 +8,5 @@ public class Subscriber { ...@@ -8,7 +8,5 @@ public class Subscriber {
private String clientId; private String clientId;
private String clientSecret; private String clientSecret;
private String privateDecryptionKeyPath; private String privateDecryptionKeyPath;
private String privateSigningKeyPath;
private String metadataSchemaPath;
private String securityEventTokenSchemaPath; private String securityEventTokenSchemaPath;
} }
...@@ -38,6 +38,14 @@ public interface Sender { ...@@ -38,6 +38,14 @@ public interface Sender {
*/ */
ValidationResult validatePublicKey(final RSAKey publicKey); ValidationResult validatePublicKey(final RSAKey publicKey);
/**
* Validates the {@link Metadata} structure against a given JSON-schema to ensure its correctness.
*
* @param metadata the {@link Metadata} object that is validated
* @return a {@link ValidationResult}, contains an error if the {@link Metadata} is invalid or doesn't match the schema
*/
ValidationResult validateMetadata(Metadata metadata, String schema);
/** /**
* Encrypts the submission data payload (json or xml) with JWE (JSON-Web-Encryption). * Encrypts the submission data payload (json or xml) with JWE (JSON-Web-Encryption).
* *
...@@ -115,4 +123,14 @@ public interface Sender { ...@@ -115,4 +123,14 @@ public interface Sender {
* @return the destination * @return the destination
*/ */
Destination getDestination(UUID destinationId); Destination getDestination(UUID destinationId);
/**
* Sends a rejection event if the submission violates any validation rule.
*
* @param submissionId unique identifier of submission
* @param destinationId unique identifier of destination
* @param caseId unique identifier of case
* @see <a href="https://docs.fitko.de/fit-connect/docs/receiving/process-and-acknowledge">Process And Acknowledge</a>
*/
void rejectSubmission(UUID submissionId, UUID destinationId, UUID caseId);
} }
...@@ -45,8 +45,8 @@ public class SenderClient { ...@@ -45,8 +45,8 @@ public class SenderClient {
private SenderClient() { private SenderClient() {
} }
public static WithDestination build(final Sender sender) { public static WithDestination build(final Sender sender, final String metadataSchema) {
return new ClientBuilder(sender); return new ClientBuilder(sender, metadataSchema);
} }
public interface WithDestination { public interface WithDestination {
...@@ -159,10 +159,12 @@ public class SenderClient { ...@@ -159,10 +159,12 @@ public class SenderClient {
private DataPayload dataPayload; private DataPayload dataPayload;
private UUID destinationId; private UUID destinationId;
private ServiceType serviceType; private ServiceType serviceType;
private final String metadataSchema;
private List<File> attachments = new ArrayList<>(); private List<File> attachments = new ArrayList<>();
public ClientBuilder(final Sender sender) { public ClientBuilder(final Sender sender, final String metadataSchema) {
this.sender = sender; this.sender = sender;
this.metadataSchema = metadataSchema;
} }
@Override @Override
...@@ -239,9 +241,16 @@ public class SenderClient { ...@@ -239,9 +241,16 @@ public class SenderClient {
/** Set encrypted metadata with data payload and attachments **/ /** Set encrypted metadata with data payload and attachments **/
logger.info("Adding data payload with mime-type {} to submission", this.dataPayload.mimeType); logger.info("Adding data payload with mime-type {} to submission", this.dataPayload.mimeType);
final DataPayload data = getEncryptedData(this.dataPayload, destination, encryptionKey); final DataPayload dataToSend = getEncryptedData(this.dataPayload, destination, encryptionKey);
submission.setEncryptedData(data.getEncryptedData()); final Metadata metadata = createMetadata(hashedAttachments, dataToSend);
submission.setEncryptedMetadata(getEncryptedMetadata(encryptionKey, data, hashedAttachments)); final ValidationResult validatedMetadata = sender.validateMetadata(metadata, metadataSchema);
if (validatedMetadata.hasError()) {
logger.error("Metadata does not match schema", validatedMetadata.getError());
sender.rejectSubmission(submissionId, destinationId, announcedSubmission.getCaseId());
return Optional.empty();
}
submission.setEncryptedData(dataToSend.getEncryptedData());
submission.setEncryptedMetadata(sender.encryptObject(encryptionKey, metadata));
/** submit submission **/ /** submit submission **/
sender.sendSubmission(submission); sender.sendSubmission(submission);
...@@ -277,11 +286,6 @@ public class SenderClient { ...@@ -277,11 +286,6 @@ public class SenderClient {
.withHashedData(hashedData); .withHashedData(hashedData);
} }
private String getEncryptedMetadata(final RSAKey encryptionKey, final DataPayload dataPayload, final List<Attachment> hashedAttachments) {
final Metadata metadata = createMetadata(hashedAttachments, dataPayload);
return sender.encryptObject(encryptionKey, metadata);
}
private List<Attachment> toHashedAttachments(final List<AttachmentPayload> attachmentPayloads) { private List<Attachment> toHashedAttachments(final List<AttachmentPayload> attachmentPayloads) {
return attachmentPayloads.stream() return attachmentPayloads.stream()
.map(this::toHashedAttachment) .map(this::toHashedAttachment)
......
...@@ -73,7 +73,11 @@ public class ClientFactory { ...@@ -73,7 +73,11 @@ public class ClientFactory {
logger.info(SENDER_BANNER); logger.info(SENDER_BANNER);
logger.info("Initializing sender client ..."); logger.info("Initializing sender client ...");
final Sender sender = getSender(config); final Sender sender = getSender(config);
return SenderClient.build(sender);
logger.info("Reading metadata schema from {} ", config.getMetadataSchemaPath());
final String metadataSchema = readPath(config.getMetadataSchemaPath());
return SenderClient.build(sender, metadataSchema);
} }
...@@ -96,19 +100,18 @@ public class ClientFactory { ...@@ -96,19 +100,18 @@ public class ClientFactory {
logger.info(SUBSCRIBER_BANNER); logger.info(SUBSCRIBER_BANNER);
logger.info("Initializing subscriber client ..."); logger.info("Initializing subscriber client ...");
final Subscriber subscriber = getSubscriber(config); final Subscriber subscriber = getSubscriber(config);
final de.fitko.fitconnect.api.config.Subscriber subscriberConfig = config.getSubscriber(); final var subscriberConfig = config.getSubscriber();
logger.info("Reading private key from {} ", subscriberConfig.getPrivateDecryptionKeyPath()); logger.info("Reading private key from {} ", subscriberConfig.getPrivateDecryptionKeyPath());
final String privateKey = readPath(subscriberConfig.getPrivateDecryptionKeyPath()); final String privateKey = readPath(subscriberConfig.getPrivateDecryptionKeyPath());
logger.info("Reading metadata schema from {} ", subscriberConfig.getMetadataSchemaPath()); logger.info("Reading metadata schema from {} ", config.getMetadataSchemaPath());
final String metadataSchema = readPath(subscriberConfig.getMetadataSchemaPath()); final String metadataSchema = readPath(config.getMetadataSchemaPath());
// TODO read SET-Event Token schema // TODO read SET-Event Token schema
return SubscriberClient.builder(subscriber, privateKey, metadataSchema); return SubscriberClient.builder(subscriber, privateKey, metadataSchema);
} }
private static Subscriber getSubscriber(final ApplicationConfig config) { private static Subscriber getSubscriber(final ApplicationConfig config) {
final CryptoService cryptoService = getCryptoService(); final CryptoService cryptoService = getCryptoService();
final ValidationService validator = getValidatorService(); final ValidationService validator = getValidatorService();
...@@ -124,12 +127,12 @@ public class ClientFactory { ...@@ -124,12 +127,12 @@ public class ClientFactory {
final CryptoService cryptoService = getCryptoService(); final CryptoService cryptoService = getCryptoService();
final ValidationService validator = getValidatorService(); final ValidationService validator = getValidatorService();
final RestTemplate restTemplate = getRestTemplate(config); final RestTemplate restTemplate = getRestTemplate(config);
final OAuthService authService = getSenderConfiguredAuthService(config, restTemplate); final OAuthService authService = getSenderConfiguredAuthService(config, restTemplate);
final EventLogService eventLogService = getEventLogService(config,restTemplate, authService); final EventLogService eventLogService = getEventLogService(config,restTemplate, authService);
final SubmissionService submissionService = getSubmissionService(config,restTemplate, authService); final SubmissionService submissionService = getSubmissionService(config,restTemplate, authService);
final DestinationService destinationService = getDestinationApiService(config,restTemplate, authService); final DestinationService destinationService = getDestinationApiService(config,restTemplate, authService);
return new SubmissionSender(destinationService, submissionService, eventLogService, cryptoService, validator); final SecurityEventService setService = getSecurityEventTokenService(config);
return new SubmissionSender(destinationService, submissionService, eventLogService, cryptoService, validator, setService);
} }
private static OAuthService getSenderConfiguredAuthService(final ApplicationConfig config, final RestTemplate restTemplate) { private static OAuthService getSenderConfiguredAuthService(final ApplicationConfig config, final RestTemplate restTemplate) {
...@@ -176,8 +179,8 @@ public class ClientFactory { ...@@ -176,8 +179,8 @@ public class ClientFactory {
} }
private static SecurityEventTokenService getSecurityEventTokenService(final ApplicationConfig config) { private static SecurityEventTokenService getSecurityEventTokenService(final ApplicationConfig config) {
logger.info("Reading private signing key from {} ", config.getSubscriber().getPrivateSigningKeyPath()); logger.info("Reading private signing key from {} ", config.getPrivateSigningKeyPath());
final String signingKey = readPath(config.getSubscriber().getPrivateSigningKeyPath()); final String signingKey = readPath(config.getPrivateSigningKeyPath());
return new SecurityEventTokenService(signingKey); return new SecurityEventTokenService(signingKey);
} }
......
...@@ -112,8 +112,6 @@ public class ClientIntegrationTest { ...@@ -112,8 +112,6 @@ public class ClientIntegrationTest {
subscriber.setClientId(System.getenv("SUBSCRIBER_CLIENT_ID")); subscriber.setClientId(System.getenv("SUBSCRIBER_CLIENT_ID"));
subscriber.setClientSecret(System.getenv("SUBSCRIBER_CLIENT_SECRET")); subscriber.setClientSecret(System.getenv("SUBSCRIBER_CLIENT_SECRET"));
subscriber.setPrivateDecryptionKeyPath("src/test/resources/private_decryption_test_key.json"); subscriber.setPrivateDecryptionKeyPath("src/test/resources/private_decryption_test_key.json");
subscriber.setPrivateSigningKeyPath("src/test/resources/private_test_signing_key.json");
subscriber.setMetadataSchemaPath("src/test/resources/metadata_schema.json");
final var resourcePaths = new ResourcePaths(); final var resourcePaths = new ResourcePaths();
resourcePaths.setAuthTokenPath("/token"); resourcePaths.setAuthTokenPath("/token");
...@@ -130,6 +128,8 @@ public class ClientIntegrationTest { ...@@ -130,6 +128,8 @@ public class ClientIntegrationTest {
config.setEnvironments(environments); config.setEnvironments(environments);
config.setUsedEnvironment(TEST); config.setUsedEnvironment(TEST);
config.setResourcePaths(resourcePaths); config.setResourcePaths(resourcePaths);
config.setMetadataSchemaPath("src/test/resources/metadata_schema.json");
config.setPrivateSigningKeyPath("src/test/resources/private_test_signing_key.json");
return config; return config;
} }
......
...@@ -11,10 +11,7 @@ import de.fitko.fitconnect.api.domain.model.metadata.data.SubmissionSchema; ...@@ -11,10 +11,7 @@ import de.fitko.fitconnect.api.domain.model.metadata.data.SubmissionSchema;
import de.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup; import de.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
import de.fitko.fitconnect.api.domain.model.submission.SubmitSubmission; import de.fitko.fitconnect.api.domain.model.submission.SubmitSubmission;
import de.fitko.fitconnect.api.domain.validation.ValidationResult; import de.fitko.fitconnect.api.domain.validation.ValidationResult;
import de.fitko.fitconnect.api.exceptions.EncryptionException; import de.fitko.fitconnect.api.exceptions.*;
import de.fitko.fitconnect.api.exceptions.KeyNotRetrievedException;
import de.fitko.fitconnect.api.exceptions.RestApiException;
import de.fitko.fitconnect.api.exceptions.SubmissionNotCreatedException;
import de.fitko.fitconnect.api.services.Sender; import de.fitko.fitconnect.api.services.Sender;
import io.github.netmikey.logunit.api.LogCapturer; import io.github.netmikey.logunit.api.LogCapturer;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
...@@ -23,6 +20,7 @@ import org.junit.jupiter.api.extension.RegisterExtension; ...@@ -23,6 +20,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.Mockito; import org.mockito.Mockito;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
...@@ -44,9 +42,9 @@ public class SenderClientTest { ...@@ -44,9 +42,9 @@ public class SenderClientTest {
private SenderClient.WithDestination underTest; private SenderClient.WithDestination underTest;
@BeforeEach @BeforeEach
public void setup() { public void setup() throws IOException {
senderMock = Mockito.mock(Sender.class); senderMock = Mockito.mock(Sender.class);
underTest = SenderClient.build(senderMock); underTest = SenderClient.build(senderMock, "");
} }
@Test @Test
...@@ -67,6 +65,8 @@ public class SenderClientTest { ...@@ -67,6 +65,8 @@ public class SenderClientTest {
when(senderMock.createSubmission(any())).thenReturn(announcedSubmission); when(senderMock.createSubmission(any())).thenReturn(announcedSubmission);
when(senderMock.validatePublicKey(any())).thenReturn(ValidationResult.ok()); when(senderMock.validatePublicKey(any())).thenReturn(ValidationResult.ok());
when(senderMock.getEncryptionKeyForDestination(any(), any())).thenReturn(publicKey); when(senderMock.getEncryptionKeyForDestination(any(), any())).thenReturn(publicKey);
when(senderMock.validateMetadata(any(), any())).thenReturn(ValidationResult.ok());
// When // When
final var submission = underTest final var submission = underTest
...@@ -100,6 +100,7 @@ public class SenderClientTest { ...@@ -100,6 +100,7 @@ public class SenderClientTest {
when(senderMock.createSubmission(any())).thenReturn(announcedSubmission); when(senderMock.createSubmission(any())).thenReturn(announcedSubmission);
when(senderMock.validatePublicKey(any())).thenReturn(ValidationResult.ok()); when(senderMock.validatePublicKey(any())).thenReturn(ValidationResult.ok());
when(senderMock.getEncryptionKeyForDestination(any(), any())).thenReturn(publicKey); when(senderMock.getEncryptionKeyForDestination(any(), any())).thenReturn(publicKey);
when(senderMock.validateMetadata(any(), any())).thenReturn(ValidationResult.ok());
// When // When
final var submission = underTest final var submission = underTest
...@@ -407,6 +408,24 @@ public class SenderClientTest { ...@@ -407,6 +408,24 @@ public class SenderClientTest {
logs.assertContains("Getting encryption key for destination "+ destinationId+" failed"); logs.assertContains("Getting encryption key for destination "+ destinationId+" failed");
} }
@Test
public void testFailOnInvalidMetadata() throws Exception {
// Given
final var destinationId = setupTestMocks();
when(senderMock.validateMetadata(any(), any())).thenReturn(ValidationResult.error(new ValidationException("invalid metadata")));
// When
final Optional<SubmitSubmission> submission = underTest
.withDestination(destinationId)
.withServiceType("name", "test:key")
.withJsonData("{}")
.submit();
assertTrue(submission.isEmpty());
logs.assertContains("Metadata does not match schema");
}
private UUID setupTestMocks() throws JOSEException { private UUID setupTestMocks() throws JOSEException {
final var destinationId = UUID.randomUUID(); final var destinationId = UUID.randomUUID();
final var destination = getDestination(destinationId); final var destination = getDestination(destinationId);
...@@ -418,6 +437,8 @@ public class SenderClientTest { ...@@ -418,6 +437,8 @@ public class SenderClientTest {
when(senderMock.createSubmission(any())).thenReturn(announcedSubmission); when(senderMock.createSubmission(any())).thenReturn(announcedSubmission);
when(senderMock.validatePublicKey(any())).thenReturn(ValidationResult.ok()); when(senderMock.validatePublicKey(any())).thenReturn(ValidationResult.ok());
when(senderMock.getEncryptionKeyForDestination(any(), any())).thenReturn(publicKey); when(senderMock.getEncryptionKeyForDestination(any(), any())).thenReturn(publicKey);
when(senderMock.validateMetadata(any(), any())).thenReturn(ValidationResult.ok());
return destinationId; return destinationId;
} }
......
...@@ -38,6 +38,8 @@ public class ClientFactoryTest { ...@@ -38,6 +38,8 @@ public class ClientFactoryTest {
senderConfig.setSender(sender); senderConfig.setSender(sender);
senderConfig.setUsedEnvironment(DEV); senderConfig.setUsedEnvironment(DEV);
senderConfig.setResourcePaths(resourcePaths); senderConfig.setResourcePaths(resourcePaths);
senderConfig.setMetadataSchemaPath("src/test/resources/metadata_schema.json");
senderConfig.setPrivateSigningKeyPath("src/test/resources/private_test_signing_key.json");
assertNotNull(ClientFactory.senderClient(senderConfig)); assertNotNull(ClientFactory.senderClient(senderConfig));
} }
...@@ -57,8 +59,6 @@ public class ClientFactoryTest { ...@@ -57,8 +59,6 @@ public class ClientFactoryTest {
subscriber.setClientSecret("123"); subscriber.setClientSecret("123");
subscriber.setClientSecret("abc"); subscriber.setClientSecret("abc");
subscriber.setPrivateDecryptionKeyPath("src/test/resources/private_decryption_test_key.json"); subscriber.setPrivateDecryptionKeyPath("src/test/resources/private_decryption_test_key.json");
subscriber.setPrivateSigningKeyPath("src/test/resources/private_test_signing_key.json");
subscriber.setMetadataSchemaPath("src/test/resources/metadata_schema.json");
final var subscriberConfig = new ApplicationConfig(); final var subscriberConfig = new ApplicationConfig();
subscriberConfig.setHttpProxyHost("https://proxy.fitco.de"); subscriberConfig.setHttpProxyHost("https://proxy.fitco.de");
...@@ -67,6 +67,8 @@ public class ClientFactoryTest { ...@@ -67,6 +67,8 @@ public class ClientFactoryTest {
subscriberConfig.setSubscriber(subscriber); subscriberConfig.setSubscriber(subscriber);
subscriberConfig.setUsedEnvironment(DEV); subscriberConfig.setUsedEnvironment(DEV);
subscriberConfig.setResourcePaths(resourcePaths); subscriberConfig.setResourcePaths(resourcePaths);
subscriberConfig.setMetadataSchemaPath("src/test/resources/metadata_schema.json");
subscriberConfig.setPrivateSigningKeyPath("src/test/resources/private_test_signing_key.json");
assertNotNull(ClientFactory.subscriberClient(subscriberConfig)); assertNotNull(ClientFactory.subscriberClient(subscriberConfig));
} }
......
...@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; ...@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.RSAKey;
import de.fitko.fitconnect.api.domain.model.destination.Destination; import de.fitko.fitconnect.api.domain.model.destination.Destination;
import de.fitko.fitconnect.api.domain.model.jwk.JWK; import de.fitko.fitconnect.api.domain.model.jwk.JWK;
import de.fitko.fitconnect.api.domain.model.metadata.Metadata;
import de.fitko.fitconnect.api.domain.model.submission.CreateSubmission; import de.fitko.fitconnect.api.domain.model.submission.CreateSubmission;
import de.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup; import de.fitko.fitconnect.api.domain.model.submission.SubmissionForPickup;
import de.fitko.fitconnect.api.domain.model.submission.SubmitSubmission; import de.fitko.fitconnect.api.domain.model.submission.SubmitSubmission;
...@@ -17,6 +18,7 @@ import de.fitko.fitconnect.api.services.Sender; ...@@ -17,6 +18,7 @@ import de.fitko.fitconnect.api.services.Sender;
import de.fitko.fitconnect.api.services.crypto.CryptoService; import de.fitko.fitconnect.api.services.crypto.CryptoService;
import de.fitko.fitconnect.api.services.destination.DestinationService; import de.fitko.fitconnect.api.services.destination.DestinationService;
import de.fitko.fitconnect.api.services.events.EventLogService; import de.fitko.fitconnect.api.services.events.EventLogService;
import de.fitko.fitconnect.api.services.events.SecurityEventService;
import de.fitko.fitconnect.api.services.submission.SubmissionService; import de.fitko.fitconnect.api.services.submission.SubmissionService;
import de.fitko.fitconnect.api.services.validation.ValidationService; import de.fitko.fitconnect.api.services.validation.ValidationService;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -33,19 +35,22 @@ public class SubmissionSender implements Sender { ...@@ -33,19 +35,22 @@ public class SubmissionSender implements Sender {
private final CryptoService cryptoService; private final CryptoService cryptoService;
private final DestinationService destinationService; private final DestinationService destinationService;
private final SubmissionService submissionService; private final SubmissionService submissionService;
private final EventLogService evenLogService; private final EventLogService eventLogService;
private final SecurityEventService securityEventService;
public SubmissionSender(final DestinationService destinationService, public SubmissionSender(final DestinationService destinationService,
final SubmissionService submissionService, final SubmissionService submissionService,
final EventLogService eventLogService, final EventLogService eventLogService,
final CryptoService encryptionService, final CryptoService encryptionService,
final ValidationService validationService) { final ValidationService validationService,
final SecurityEventService securityEventService) {
this.destinationService = destinationService; this.destinationService = destinationService;
this.submissionService = submissionService; this.submissionService = submissionService;
this.evenLogService = eventLogService; this.eventLogService = eventLogService;
this.cryptoService = encryptionService; this.cryptoService = encryptionService;
this.validationService = validationService; this.validationService = validationService;
this.securityEventService = securityEventService;
} }
@Override @Override
...@@ -54,6 +59,11 @@ public class SubmissionSender implements Sender { ...@@ -54,6 +59,11 @@ public class SubmissionSender implements Sender {
return validationService.validatePublicKey(publicKey); return validationService.validatePublicKey(publicKey);
} }
@Override
public ValidationResult validateMetadata(final Metadata metadata, final String schema) {
return validationService.validateMetadataSchema(schema, metadata);
}
@Override @Override
public String encryptBytes(final RSAKey publicKey, final byte[] data) { public String encryptBytes(final RSAKey publicKey, final byte[] data) {
logger.info("Encrypting ..."); logger.info("Encrypting ...");
...@@ -110,4 +120,11 @@ public class SubmissionSender implements Sender { ...@@ -110,4 +120,11 @@ public class SubmissionSender implements Sender {
return destinationService.getDestination(destinationId); return destinationService.getDestination(destinationId);
} }
@Override
public void rejectSubmission(final UUID submissionId, final UUID destinationId, final UUID caseId) {
final String rejectSubmissionEvent = securityEventService.createRejectSubmissionEvent(submissionId, destinationId, caseId);
eventLogService.sendEvent(caseId, rejectSubmissionEvent);
logger.info("REJECTED submission {}", submissionId);
}
} }
...@@ -7,26 +7,29 @@ import com.nimbusds.jose.jwk.RSAKey; ...@@ -7,26 +7,29 @@ import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator; import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import de.fitko.fitconnect.api.domain.model.destination.Destination; import de.fitko.fitconnect.api.domain.model.destination.Destination;
import de.fitko.fitconnect.api.domain.model.jwk.JWK; import de.fitko.fitconnect.api.domain.model.jwk.JWK;
import de.fitko.fitconnect.api.domain.model.metadata.ContentStructure;
import de.fitko.fitconnect.api.domain.model.metadata.Metadata; import de.fitko.fitconnect.api.domain.model.metadata.Metadata;
import de.fitko.fitconnect.api.domain.model.metadata.PublicServiceType;
import de.fitko.fitconnect.api.domain.model.metadata.attachment.Attachment;
import de.fitko.fitconnect.api.domain.model.metadata.data.*;
import de.fitko.fitconnect.api.domain.model.submission.*; import de.fitko.fitconnect.api.domain.model.submission.*;
import de.fitko.fitconnect.api.domain.validation.ValidationResult; import de.fitko.fitconnect.api.domain.validation.ValidationResult;
import de.fitko.fitconnect.api.exceptions.EncryptionException; import de.fitko.fitconnect.api.exceptions.*;
import de.fitko.fitconnect.api.exceptions.KeyNotRetrievedException;
import de.fitko.fitconnect.api.exceptions.MetadataNotCreatedException;
import de.fitko.fitconnect.api.exceptions.RestApiException;
import de.fitko.fitconnect.api.services.Sender; import de.fitko.fitconnect.api.services.Sender;
import de.fitko.fitconnect.api.services.crypto.CryptoService; import de.fitko.fitconnect.api.services.crypto.CryptoService;
import de.fitko.fitconnect.api.services.destination.DestinationService; import de.fitko.fitconnect.api.services.destination.DestinationService;
import de.fitko.fitconnect.api.services.events.EventLogService; import de.fitko.fitconnect.api.services.events.EventLogService;
import de.fitko.fitconnect.api.services.submission.SubmissionService; import de.fitko.fitconnect.api.services.submission.SubmissionService;
import de.fitko.fitconnect.api.services.validation.ValidationService; import de.fitko.fitconnect.api.services.validation.ValidationService;
import de.fitko.fitconnect.core.events.SecurityEventTokenService;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.text.ParseException; import java.text.ParseException;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
...@@ -43,24 +46,26 @@ public class SubmissionSenderTest { ...@@ -43,24 +46,26 @@ public class SubmissionSenderTest {
private EventLogService eventLogServiceMock; private EventLogService eventLogServiceMock;
private CryptoService cryptoServiceMock; private CryptoService cryptoServiceMock;
private ValidationService validationServiceMock; private ValidationService validationServiceMock;
private SecurityEventTokenService setEventServiceMock;
private Sender underTest; private Sender underTest;
@BeforeEach @BeforeEach
public void setUp() { public void setUp() {
this.destinationServiceMock = mock(DestinationService.class);
destinationServiceMock = Mockito.mock(DestinationService.class); this.submissionServiceMock = mock(SubmissionService.class);
submissionServiceMock = Mockito.mock(SubmissionService.class); this.eventLogServiceMock = mock(EventLogService.class);
eventLogServiceMock = Mockito.mock(EventLogService.class); this.cryptoServiceMock = mock(CryptoService.class);
cryptoServiceMock = Mockito.mock(CryptoService.class); this.validationServiceMock = mock(ValidationService.class);
validationServiceMock = Mockito.mock(ValidationService.class); this.setEventServiceMock = mock(SecurityEventTokenService.class);
underTest = new SubmissionSender( underTest = new SubmissionSender(
destinationServiceMock, destinationServiceMock,
submissionServiceMock, submissionServiceMock,
eventLogServiceMock, eventLogServiceMock,
cryptoServiceMock, cryptoServiceMock,
validationServiceMock validationServiceMock,
setEventServiceMock
); );
} }
...@@ -169,7 +174,7 @@ public class SubmissionSenderTest { ...@@ -169,7 +174,7 @@ public class SubmissionSenderTest {
final JWK jwk = new ObjectMapper().readValue(publicKeyJson, JWK.class); final JWK jwk = new ObjectMapper().readValue(publicKeyJson, JWK.class);
final RSAKey expectedRSAKey = RSAKey.parse(publicKeyJson); final RSAKey expectedRSAKey = RSAKey.parse(publicKeyJson);
when(destinationServiceMock.getEncryptionKey(any(),any())).thenReturn(jwk); when(destinationServiceMock.getEncryptionKey(any(), any())).thenReturn(jwk);
// When // When
final RSAKey key = underTest.getEncryptionKeyForDestination(submissionId, jwk.getKid()); final RSAKey key = underTest.getEncryptionKeyForDestination(submissionId, jwk.getKid());
...@@ -182,7 +187,7 @@ public class SubmissionSenderTest { ...@@ -182,7 +187,7 @@ public class SubmissionSenderTest {
public void getEncryptionKeyForDestinationFailed() { public void getEncryptionKeyForDestinationFailed() {
// Given // Given
when(destinationServiceMock.getEncryptionKey(any(),any())).thenThrow(RestApiException.class); when(destinationServiceMock.getEncryptionKey(any(), any())).thenThrow(RestApiException.class);
// Then // Then
assertThrows( assertThrows(
...@@ -276,6 +281,37 @@ public class SubmissionSenderTest { ...@@ -276,6 +281,37 @@ public class SubmissionSenderTest {
assertThat(destination, equalTo(expectedDestination)); assertThat(destination, equalTo(expectedDestination));
} }
@Test
public void testValidMetadata() {
// Given
final var metadata = new Metadata();
when(validationServiceMock.validateMetadataSchema(any(), any())).thenReturn(ValidationResult.ok());
// When
final ValidationResult validatedMetadata = underTest.validateMetadata(metadata, "metadataSchema");
// Then
assertTrue(validatedMetadata.isValid());
}
@Test
public void testInvalidMetadata() {
// Given
final var invalidMetadata = new Metadata();
final ValidationResult expectedResult = ValidationResult.error(new ValidationException("invalid metadata"));
when(validationServiceMock.validateMetadataSchema(any(), any())).thenReturn(expectedResult);
// When
final ValidationResult validatedMetadata = underTest.validateMetadata(invalidMetadata, "metadataSchema");
// Then
assertTrue(validatedMetadata.hasError());
assertThat(validatedMetadata.getError().getMessage(), equalTo("invalid metadata"));
}
private String getResourceAsString(final String filename) throws IOException { private String getResourceAsString(final String filename) throws IOException {
return new String(SubmissionSenderTest.class.getResourceAsStream(filename).readAllBytes()); return new String(SubmissionSenderTest.class.getResourceAsStream(filename).readAllBytes());
} }
......
# SKD application properties and global configurations # SKD application properties and global configurations
sdk { sdk {
# Credentials to authenticate via OAuth # Proxy config for http api calls
httpProxyHost: ""
httpProxyPort: 0
requestTimeoutInSeconds: 30
# Path that references the metadata schema
metadataSchemaPath: "path/to/metadata_schema.json"
# Path that references the signing key file
privateSigningKeyPath: "path/to/singning_key.json"
# switch between the active environments DEV, PROD or TEST
usedEnvironment: "DEV"
# Credentials to authenticate via OAuth
sender { sender {
clientId: "SenderClientID" clientId: "SenderClientID"
clientSecret: "SenderSecret" clientSecret: "SenderSecret"
...@@ -14,22 +28,9 @@ sdk { ...@@ -14,22 +28,9 @@ sdk {
# Path that references the private key file # Path that references the private key file
privateDecryptionKeyPath: "path/to/decrpytion_key.json" privateDecryptionKeyPath: "path/to/decrpytion_key.json"
# Path that references the signing key file
privateSigningKeyPath: "path/to/singning_key.json"
# Path that references the metadata schema
metadataSchemaPath: "path/to/metadata_schema.json"
securityEventTokenSchemaPath: "" securityEventTokenSchemaPath: ""
} }
# Proxy config for http api calls
httpProxyHost: ""
httpProxyPort: 0
requestTimeoutInSeconds: 30
# switch between the active environments DEV, PROD or TEST
usedEnvironment: "DEV"
# Configured environments for all api-urls # Configured environments for all api-urls
environments { environments {
dev { dev {
...@@ -46,7 +47,8 @@ sdk { ...@@ -46,7 +47,8 @@ sdk {
} }
} }
resourcePaths { # REST endpoint paths
resourcePaths {
authTokenPath: "/token" authTokenPath: "/token"
destinationPath: "/v1/destinations/{destinationId}" destinationPath: "/v1/destinations/{destinationId}"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment