Skip to content
Snippets Groups Projects
Commit cdc8fc10 authored by Jan Zickermann's avatar Jan Zickermann
Browse files

OZG-4097 itcase: Test connection failed error code

parent 96b7c52e
No related branches found
No related tags found
1 merge request!15Ozg 4097 senden und empfangen von anhängen
Pipeline #1730 failed
Showing
with 316 additions and 408 deletions
......@@ -23,8 +23,6 @@
<swagger-parser.version>2.1.23</swagger-parser.version>
<wiremock.version>3.12.0</wiremock.version>
<wiremock-spring-boot.version>3.6.0</wiremock-spring-boot.version>
<wiremock-grpc-extension.version>0.9.0</wiremock-grpc-extension.version>
<grpc.version>1.59.0</grpc.version>
</properties>
<dependencies>
<!-- OZG-Cloud -->
......@@ -56,6 +54,14 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-server-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>net.devh</groupId>
<artifactId>grpc-client-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
......@@ -82,33 +88,12 @@
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-jetty12</artifactId>
<version>${wiremock}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock.integrations</groupId>
<artifactId>wiremock-spring-boot</artifactId>
<version>${wiremock-spring-boot.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-grpc-extension</artifactId>
<version>${wiremock-grpc-extension.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
</dependency>
<!-- commons -->
......@@ -191,23 +176,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<executions>
<execution>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/generated-sources/protobuf</outputDirectory>
<attachDescriptorSet>true</attachDescriptorSet>
<descriptorSetOutputDirectory>${project.basedir}/src/test/resources/grpc/services.dsc</descriptorSetOutputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
......
......@@ -4,6 +4,7 @@ import java.io.IOException;
import jakarta.annotation.Nullable;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClientResponseException;
import de.ozgcloud.nachrichten.postfach.PostfachMessageCode;
......@@ -30,6 +31,9 @@ public class Osi2ExceptionHandler {
if (cause instanceof RestClientResponseException restClientResponseException) {
return deriveMessageCodeFromRestClientResponseException(restClientResponseException);
}
if (cause instanceof ResourceAccessException) {
return PostfachMessageCode.SERVER_CONNECTION_FAILED_MESSAGE_CODE;
}
// TODO KOP-3021 add message code for unsafe upload file
return PostfachMessageCode.PROCESS_FAILED_MESSAGE_CODE;
}
......
package de.ozgcloud.nachrichten.postfach.osiv2.model;
public record BinaryFileUpload(
String name,
String contentType,
long size
) {
}
package de.ozgcloud.nachrichten.postfach.osiv2.storage;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
import de.ozgcloud.apilib.file.OzgCloudFile;
import de.ozgcloud.apilib.file.OzgCloudFileId;
import de.ozgcloud.apilib.file.OzgCloudUploadFile;
import de.ozgcloud.nachrichten.file.AttachmentFile;
import de.ozgcloud.vorgang.grpc.file.GrpcOzgFile;
@Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)
public interface Osi2BinaryFileMapper {
public interface Osi2AttachmentFileMapper {
String ATTACHMENT_FIELD_NAME = "PostfachAttachment";
OzgCloudFile mapToUploadFileMetadata(GrpcOzgFile grpcOzgFile);
default OzgCloudFileId mapToUploadFileId(String fileId) {
return new OzgCloudFileId(fileId);
}
@Mapping(target = "fileName", source = "name")
@Mapping(target = "fieldName", constant = ATTACHMENT_FIELD_NAME)
OzgCloudUploadFile toOzgCloudUploadFile(AttachmentFile attachmentFile);
}
package de.ozgcloud.nachrichten.postfach.osiv2.storage;
import static de.ozgcloud.nachrichten.NachrichtenManagerConfiguration.*;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import java.util.function.Supplier;
import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextAttachingInterceptor;
import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider;
import de.ozgcloud.apilib.file.OzgCloudFile;
import de.ozgcloud.apilib.file.OzgCloudFileService;
import de.ozgcloud.nachrichten.file.AttachmentFile;
import de.ozgcloud.nachrichten.postfach.osiv2.ServiceIfOsi2Enabled;
import de.ozgcloud.nachrichten.postfach.osiv2.exception.Osi2RuntimeException;
import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc;
import de.ozgcloud.vorgang.grpc.binaryFile.GrpcBinaryFilesRequest;
import de.ozgcloud.vorgang.grpc.binaryFile.GrpcGetBinaryFileDataRequest;
......@@ -16,25 +24,45 @@ import net.devh.boot.grpc.client.inject.GrpcClient;
@Log4j2
@ServiceIfOsi2Enabled
@RequiredArgsConstructor
public class Osi2BinaryFileRemoteService {
@GrpcClient("vorgang-manager")
private final BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFileService;
private final Osi2BinaryFileMapper binaryFileMapper;
public class Osi2AttachmentFileService {
@GrpcClient(GRPC_FILE_MANAGER_NAME)
private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub binaryFilServiceStub;
private final Osi2AttachmentFileMapper attachmentFileMapper;
private final OzgCloudFileService ozgCloudFileService;
private final OzgCloudCallContextProvider ozgCloudCallContextProvider;
public List<OzgCloudFile> getFileMetadataOfIds(List<String> fileIds) {
return binaryFileService.findBinaryFilesMetaData(createRequestWithFileIds(fileIds))
try {
return getFileMetadataOfIdsRaw(fileIds);
} catch (RuntimeException e) {
throw new Osi2RuntimeException("getFileMetadataOfIds failed!", e);
}
}
List<OzgCloudFile> getFileMetadataOfIdsRaw(List<String> fileIds) {
return getBinaryFilServiceStub().findBinaryFilesMetaData(createRequestWithFileIds(fileIds))
.getFileList()
.stream()
.map(binaryFileMapper::mapToUploadFileMetadata)
.map(attachmentFileMapper::mapToUploadFileMetadata)
.toList();
}
public String uploadFileAndReturnId(AttachmentFile attachmentFile, Supplier<InputStream> fileInputStream) {
// TODO KOP-3008 use revised (nachrichten-manager) AttachmentFileService
var attachmentFileId = ozgCloudFileService.uploadFile(
attachmentFileMapper.toOzgCloudUploadFile(attachmentFile),
fileInputStream.get()
);
return attachmentFileId.toString();
}
private GrpcBinaryFilesRequest createRequestWithFileIds(List<String> fileIds) {
return GrpcBinaryFilesRequest.newBuilder().addAllFileId(fileIds).build();
}
public InputStream streamFileContent(String fileId) {
var response = binaryFileService.getBinaryFileContent(createRequestWithFileId(fileId));
public InputStream downloadFileContent(String fileId) {
var response = getBinaryFilServiceStub().getBinaryFileContent(createRequestWithFileId(fileId));
return new ConcatInputStream(new Iterator<>() {
@Override
public boolean hasNext() {
......@@ -51,4 +79,8 @@ public class Osi2BinaryFileRemoteService {
private GrpcGetBinaryFileDataRequest createRequestWithFileId(String fileId) {
return GrpcGetBinaryFileDataRequest.newBuilder().setFileId(fileId).build();
}
private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub getBinaryFilServiceStub() {
return binaryFilServiceStub.withInterceptors(new OzgCloudCallContextAttachingInterceptor(ozgCloudCallContextProvider));
}
}
......@@ -19,7 +19,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.ServiceIfOsi2Enabled;
import de.ozgcloud.nachrichten.postfach.osiv2.exception.Osi2RuntimeException;
import de.ozgcloud.nachrichten.postfach.osiv2.model.FileChunkInfo;
import de.ozgcloud.nachrichten.postfach.osiv2.model.Osi2FileUpload;
import de.ozgcloud.nachrichten.postfach.osiv2.storage.Osi2BinaryFileRemoteService;
import de.ozgcloud.nachrichten.postfach.osiv2.storage.Osi2AttachmentFileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
......@@ -28,7 +28,7 @@ import lombok.extern.log4j.Log4j2;
@RequiredArgsConstructor
public class Osi2QuarantineService {
private final PostfachApiFacadeService postfachApiFacadeService;
private final Osi2BinaryFileRemoteService binaryFileService;
private final Osi2AttachmentFileService binaryFileService;
static final Duration POLLING_INTERVAL = Duration.ofSeconds(1);
static final Duration POLLING_TIMEOUT = Duration.ofMinutes(5);
......@@ -48,10 +48,10 @@ public class Osi2QuarantineService {
}
Osi2FileUpload uploadFileToQuarantine(OzgCloudFile file) {
try (var fileInputStream = binaryFileService.streamFileContent(file.getId().toString())) {
try (var fileInputStream = binaryFileService.downloadFileContent(file.getId().toString())) {
return uploadInputStreamToQuarantine(file, fileInputStream);
} catch (IOException e) {
throw new Osi2RuntimeException("Failed to close input stream!", e);
throw new Osi2RuntimeException("Failed to close upload input stream!", e);
}
}
......@@ -82,6 +82,7 @@ public class Osi2QuarantineService {
synchronized boolean checkVirusScanCompleted(List<Osi2FileUpload> osi2FileMetadata) {
// TODO ...
return true;
}
......
......@@ -6,7 +6,6 @@ import java.util.List;
import java.util.UUID;
import org.springframework.core.io.AbstractResource;
import org.springframework.web.client.RestClientResponseException;
import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
import de.ozgcloud.nachrichten.postfach.osiv2.ServiceIfOsi2Enabled;
......@@ -33,7 +32,7 @@ public class PostfachApiFacadeService {
public void sendMessage(PostfachNachricht nachricht, List<Osi2FileUpload> attachments) {
try {
sendMessageRaw(nachricht, attachments);
} catch (RestClientResponseException e) {
} catch (RuntimeException e) {
throw new Osi2RuntimeException("sendMessage failed!", e);
}
}
......@@ -48,7 +47,7 @@ public class PostfachApiFacadeService {
public <T extends AbstractResource> void uploadChunk(FileChunkInfo chunkInfo, T chunkResource) {
try {
uploadChunkRaw(chunkInfo, chunkResource);
} catch (RestClientResponseException e) {
} catch (RuntimeException e) {
throw new Osi2RuntimeException("uploadChunk failed!", e);
}
}
......@@ -65,7 +64,7 @@ public class PostfachApiFacadeService {
public boolean checkUploadSuccessful(final String messageId) {
try {
return checkUploadSuccessfulRaw(messageId);
} catch (RestClientResponseException e) {
} catch (RuntimeException e) {
throw new Osi2RuntimeException("checkUploadSuccessful failed!", e);
}
}
......@@ -79,7 +78,7 @@ public class PostfachApiFacadeService {
public List<String> fetchPendingMessageIds() {
try {
return fetchPendingMessageIdsRaw();
} catch (RestClientResponseException e) {
} catch (RuntimeException e) {
throw new Osi2RuntimeException("fetchPendingMessageIds failed!", e);
}
}
......@@ -93,7 +92,7 @@ public class PostfachApiFacadeService {
public PostfachNachricht fetchMessageById(final String messageId) {
try {
return fetchMessageByIdRaw(messageId);
} catch (RestClientResponseException e) {
} catch (RuntimeException e) {
throw new Osi2RuntimeException("fetchMessageById failed!", e);
}
}
......@@ -106,7 +105,7 @@ public class PostfachApiFacadeService {
public void deleteMessage(final String messageId) {
try {
deleteMessageRaw(messageId);
} catch (RestClientResponseException e) {
} catch (RuntimeException e) {
throw new Osi2RuntimeException("deleteMessage failed!", e);
}
}
......
......@@ -6,6 +6,6 @@ logging:
grpc:
client:
vorgang-manager:
file-manager:
address: static://127.0.0.1:9090
negotiationType: PLAINTEXT
\ No newline at end of file
package de.ozgcloud.nachrichten.postfach.osiv2;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static de.ozgcloud.nachrichten.NachrichtenManagerConfiguration.*;
import static de.ozgcloud.nachrichten.postfach.osiv2.factory.JwtFactory.*;
import static org.assertj.core.api.Assertions.*;
import java.time.OffsetDateTime;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
......@@ -17,14 +19,13 @@ import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.context.TestPropertySource;
import org.wiremock.grpc.dsl.WireMockGrpcService;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
import de.ozgcloud.nachrichten.postfach.PostfachMessageCode;
import de.ozgcloud.nachrichten.postfach.PostfachNachricht;
import de.ozgcloud.nachrichten.postfach.osiv2.exception.Osi2PostfachException;
import de.ozgcloud.nachrichten.postfach.osiv2.extension.AttachmentExampleUploadUtil;
import de.ozgcloud.nachrichten.postfach.osiv2.extension.Jwt;
import de.ozgcloud.nachrichten.postfach.osiv2.extension.OsiMockServerExtension;
import de.ozgcloud.nachrichten.postfach.osiv2.extension.VorgangManagerServerExtension;
......@@ -33,6 +34,7 @@ import de.ozgcloud.nachrichten.postfach.osiv2.factory.MessageExchangeReceiveMess
import de.ozgcloud.nachrichten.postfach.osiv2.factory.MessageExchangeSendMessageResponseTestFactory;
import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory;
import de.ozgcloud.nachrichten.postfach.osiv2.factory.V1ReplyMessageTestFactory;
import de.ozgcloud.nachrichten.postfach.osiv2.storage.Osi2AttachmentFileService;
import lombok.SneakyThrows;
@SpringBootTest(classes = TestApplication.class)
......@@ -48,10 +50,10 @@ class OsiPostfachRemoteServiceITCase {
@RegisterExtension
static final VorgangManagerServerExtension VORGANG_MANAGER_SERVER_EXTENSION = new VorgangManagerServerExtension();
private final PostfachNachricht postfachNachricht = PostfachNachrichtTestFactory.create();
@Autowired
private OsiPostfachRemoteService osiPostfachRemoteService;
@Autowired
private Osi2AttachmentFileService osi2AttachmentFileService;
@DynamicPropertySource
static void dynamicProperties(DynamicPropertyRegistry registry) {
......@@ -60,32 +62,25 @@ class OsiPostfachRemoteServiceITCase {
registry.add("ozgcloud.osiv2.auth.client-id", () -> CLIENT_ID);
registry.add("ozgcloud.osiv2.api.url", OSI_MOCK_SERVER_EXTENSION::getPostfachFacadeUrl);
registry.add("ozgcloud.osiv2.auth.resource", () -> RESOURCE_URN);
registry.add("grpc.client.vorgang-manager.address", VORGANG_MANAGER_SERVER_EXTENSION::getVorgangManagerAddress);
registry.add("grpc.client." + GRPC_FILE_MANAGER_NAME + ".address", VORGANG_MANAGER_SERVER_EXTENSION::getVorgangManagerAddress);
registry.add("grpc.client." + GRPC_FILE_MANAGER_NAME + ".negotiationType", () -> "PLAINTEXT");
}
private WireMockServer postfachFacadeMockServer;
private WireMockGrpcService binaryFileMockService;
@BeforeEach
@SneakyThrows
public void setup() {
postfachFacadeMockServer = OSI_MOCK_SERVER_EXTENSION.getPostfachFacadeMockServer();
binaryFileMockService = VORGANG_MANAGER_SERVER_EXTENSION.getBinaryFileServiceGrpcService();
}
@DisplayName("should send request with jwt")
@Test
@SneakyThrows
void shouldSendRequestWithJwt() {
// Stub message send response (MessageExchangeApi::sendMessage)
postfachFacadeMockServer.stubFor(post(urlPathTemplate("/MessageExchange/v1/Send/{mailboxId}"))
.willReturn(
okJsonObj(
MessageExchangeSendMessageResponseTestFactory.create()
.messageId(UUID.randomUUID())
)
)
);
var postfachNachricht = PostfachNachrichtTestFactory.create();
mockSendResponse();
osiPostfachRemoteService.sendMessage(postfachNachricht);
......@@ -100,6 +95,7 @@ class OsiPostfachRemoteServiceITCase {
@DisplayName("should throw postfach exception with connection error code")
@Test
void shouldThrowPostfachExceptionWithConnectionErrorCode() {
var postfachNachricht = PostfachNachrichtTestFactory.create();
postfachFacadeMockServer.stop();
assertThatThrownBy(() -> osiPostfachRemoteService.sendMessage(postfachNachricht))
......@@ -107,6 +103,37 @@ class OsiPostfachRemoteServiceITCase {
.hasFieldOrPropertyWithValue("messageCode", PostfachMessageCode.SERVER_CONNECTION_FAILED_MESSAGE_CODE);
}
@DisplayName("should send message with attachment")
@Test
void shouldSendMessageWithAttachment() {
var textFileId = AttachmentExampleUploadUtil.uploadTextFile(osi2AttachmentFileService);
// TODO mock quarantine upload requests
var postfachNachrichtWithAttachment = PostfachNachrichtTestFactory.createBuilder()
.attachments(List.of(textFileId))
.build();
mockSendResponse();
osiPostfachRemoteService.sendMessage(postfachNachrichtWithAttachment);
postfachFacadeMockServer.verify(
exactly(1),
postRequestedFor(urlPathTemplate("/MessageExchange/v1/Send/{mailboxId}"))
);
}
private void mockSendResponse() {
// Stub message send response (MessageExchangeApi::sendMessage)
postfachFacadeMockServer.stubFor(post(urlPathTemplate("/MessageExchange/v1/Send/{mailboxId}"))
.willReturn(
okJsonObj(
MessageExchangeSendMessageResponseTestFactory.create()
.messageId(UUID.randomUUID())
)
)
);
}
@DisplayName("should receive one messages")
@Test
@SneakyThrows
......
package de.ozgcloud.nachrichten.postfach.osiv2;
import static de.ozgcloud.nachrichten.NachrichtenManagerConfiguration.*;
import org.mapstruct.factory.Mappers;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import de.ozgcloud.apilib.common.callcontext.CallContext;
import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider;
import de.ozgcloud.apilib.file.OzgCloudFileService;
import de.ozgcloud.apilib.file.grpc.GrpcOzgCloudFileService;
import de.ozgcloud.apilib.file.grpc.OzgCloudFileMapper;
import de.ozgcloud.apilib.vorgang.OzgCloudUserIdMapper;
import de.ozgcloud.nachrichten.common.grpc.NachrichtenCallContextAttachingInterceptor;
import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc;
import net.devh.boot.grpc.client.inject.GrpcClient;
@SpringBootApplication
@AutoConfiguration
public class TestApplication {
@GrpcClient(GRPC_FILE_MANAGER_NAME)
private BinaryFileServiceGrpc.BinaryFileServiceBlockingStub fileServiceBlockingStub;
@GrpcClient(GRPC_FILE_MANAGER_NAME)
private BinaryFileServiceGrpc.BinaryFileServiceStub fileServiceAsyncServiceStub;
@Bean
OzgCloudCallContextProvider ozgCloudCallContextProvider() {
var userIdMapper = Mappers.getMapper(OzgCloudUserIdMapper.class);
return () -> CallContext.builder().clientName(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_CLIENT_NAME)
.userId(userIdMapper.toUserId(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_SENDER_USER_ID)).build();
}
@Bean(OZG_CLOUD_FILE_SERVICE_NAME)
OzgCloudFileService grpcOzgCloudFileService(OzgCloudCallContextProvider contextProvider) {
return new GrpcOzgCloudFileService(fileServiceBlockingStub, fileServiceAsyncServiceStub, contextProvider, Mappers.getMapper(OzgCloudFileMapper.class));
}
}
package de.ozgcloud.nachrichten.postfach.osiv2.extension;
import java.io.ByteArrayInputStream;
import java.util.UUID;
import com.thedeanda.lorem.LoremIpsum;
import de.ozgcloud.nachrichten.file.AttachmentFile;
import de.ozgcloud.nachrichten.postfach.osiv2.storage.Osi2AttachmentFileService;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class AttachmentExampleUploadUtil {
public static String uploadTextFile(Osi2AttachmentFileService remoteService) {
return remoteService.uploadFileAndReturnId(AttachmentFile.builder()
.contentType("test/plain")
.name("test.txt")
.vorgangId(UUID.randomUUID().toString())
.build(), () -> new ByteArrayInputStream(LoremIpsum.getInstance().getParagraphs(5,100).getBytes()));
}
}
package de.ozgcloud.nachrichten.postfach.osiv2.extension;
import java.time.Duration;
import jakarta.validation.constraints.NotNull;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
public class VorgangManagerContainer extends GenericContainer<VorgangManagerContainer> {
private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("docker.ozg-sh.de/vorgang-manager");
private static final String DEFAULT_TAG = "latest";
public static final int PORT = 9090;
public VorgangManagerContainer() {
this(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG));
}
public VorgangManagerContainer(@NotNull DockerImageName dockerImageName) {
super(dockerImageName);
addExposedPort(PORT);
super.withStartupTimeout(Duration.ofMinutes(2));
}
public String getAddress() {
return "%s:%d".formatted(getHost(), getMappedPort(PORT));
}
}
package de.ozgcloud.nachrichten.postfach.osiv2.extension;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.*;
import java.time.Duration;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.wiremock.grpc.GrpcExtensionFactory;
import org.wiremock.grpc.dsl.WireMockGrpcService;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.output.OutputFrame;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import de.ozgcloud.vorgang.grpc.binaryFile.BinaryFileServiceGrpc;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
......@@ -22,42 +21,62 @@ import lombok.extern.log4j.Log4j2;
@RequiredArgsConstructor
public class VorgangManagerServerExtension implements BeforeAllCallback, AfterAllCallback, AfterEachCallback {
private WireMockServer vorgangManagerMockServer;
private WireMockGrpcService binaryFileServiceGrpcService;
static final String VORGANG_MANAGER_NETWORK_ALIAS = "vorgang-manager";
static final String MONGODB_NETWORK_ALIAS = "mongodb";
private VorgangManagerContainer vorgangManagerContainer;
private MongoDBContainer mongoDBContainer;
@Override
public void beforeAll(ExtensionContext context) {
setupVorgangManagerMock();
binaryFileServiceGrpcService = new WireMockGrpcService(
new WireMock(vorgangManagerMockServer),
BinaryFileServiceGrpc.SERVICE_NAME
);
setupVorgangManager();
}
@Override
public void afterEach(ExtensionContext context) {
binaryFileServiceGrpcService.resetAll();
vorgangManagerMockServer.resetAll();
private void setupVorgangManager() {
var network = Network.newNetwork();
mongoDBContainer = new MongoDBContainer("mongo:7.0")
.withStartupTimeout(Duration.ofMinutes(1))
.withNetworkAliases(MONGODB_NETWORK_ALIAS)
.withNetwork(network);
mongoDBContainer.start();
vorgangManagerContainer = new VorgangManagerContainer()
.withEnv(Map.of(
"spring_profiles_active", "local",
"ozgcloud.vorgang-manager.serviceAddress", "%s:%d".formatted(VORGANG_MANAGER_NETWORK_ALIAS, VorgangManagerContainer.PORT),
"spring.data.mongodb.host", MONGODB_NETWORK_ALIAS,
"spring.data.mongodb.port", "27017",
"mongock_enabled", "false"
))
.withNetwork(network)
.withLogConsumer(this::logVorgangManager)
.withStartupTimeout(Duration.ofMinutes(2))
.dependsOn(mongoDBContainer);
vorgangManagerContainer.start();
}
private void logVorgangManager(OutputFrame outputFrame) {
var stream = outputFrame.getType() == OutputFrame.OutputType.STDOUT ? System.out : System.err;
stream.println("[vorgang-manager] " + outputFrame.getUtf8String().stripTrailing());
}
@Override
public void afterAll(ExtensionContext context) {
vorgangManagerMockServer.shutdown();
if (mongoDBContainer != null) {
mongoDBContainer.stop();
}
if (vorgangManagerContainer != null) {
vorgangManagerContainer.stop();
}
private void setupVorgangManagerMock() {
vorgangManagerMockServer = new WireMockServer(
wireMockConfig()
.dynamicPort()
.withRootDirectory("src/test/resources/wiremock")
.extensions(new GrpcExtensionFactory())
);
vorgangManagerMockServer.start();
}
public String getVorgangManagerAddress() {
return "static://127.0.0.1:%d".formatted(vorgangManagerMockServer.port());
return Optional.ofNullable(vorgangManagerContainer)
.map(VorgangManagerContainer::getAddress)
.orElse("missing");
}
@Override
public void afterEach(ExtensionContext context) {
// Consider clearing mongodb (uploaded files)
}
}
......@@ -20,11 +20,10 @@ import org.mockito.Spy;
import de.ozgcloud.apilib.file.OzgCloudFile;
import de.ozgcloud.apilib.file.OzgCloudFileId;
import de.ozgcloud.apilib.file.OzgCloudFileTestFactory;
import de.ozgcloud.nachrichten.postfach.osiv2.exception.Osi2PostfachException;
import de.ozgcloud.nachrichten.postfach.osiv2.exception.Osi2RuntimeException;
import de.ozgcloud.nachrichten.postfach.osiv2.model.FileChunkInfo;
import de.ozgcloud.nachrichten.postfach.osiv2.model.Osi2FileUpload;
import de.ozgcloud.nachrichten.postfach.osiv2.storage.Osi2BinaryFileRemoteService;
import de.ozgcloud.nachrichten.postfach.osiv2.storage.Osi2AttachmentFileService;
import lombok.SneakyThrows;
class Osi2QuarantineServiceTest {
......@@ -37,7 +36,7 @@ class Osi2QuarantineServiceTest {
private PostfachApiFacadeService postfachApiFacadeService;
@Mock
private Osi2BinaryFileRemoteService binaryFileService;
private Osi2AttachmentFileService binaryFileService;
@DisplayName("upload attachments")
@Nested
......@@ -135,7 +134,7 @@ class Osi2QuarantineServiceTest {
@BeforeEach
void mock() {
when(binaryFileService.streamFileContent(any())).thenReturn(fileInputStream);
when(binaryFileService.downloadFileContent(any())).thenReturn(fileInputStream);
doReturn(uploadFile).when(service).uploadInputStreamToQuarantine(any(), any());
}
......@@ -144,7 +143,7 @@ class Osi2QuarantineServiceTest {
void shouldCallStreamFileContent() {
uploadFileToQuarantine();
verify(binaryFileService).streamFileContent(OzgCloudFileTestFactory.ID_STR);
verify(binaryFileService).downloadFileContent(OzgCloudFileTestFactory.ID_STR);
}
@DisplayName("should call uploadInputStreamToQuarantine")
......
......@@ -7,8 +7,9 @@ logging:
org.springframework.http: DEBUG
org.springframework.web.client: DEBUG
spring:
grpc:
client:
vorgang-manager:
file-manager:
address: static://127.0.0.1:9090
negotiationType: PLAINTEXT
\ No newline at end of file
/*
* Copyright (C) 2024 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
syntax = "proto3";
package de.ozgcloud.vorgang.grpc.binaryFile;
import "callcontext.proto";
import "file.model.proto";
option java_multiple_files = true;
option java_package = "de.ozgcloud.vorgang.grpc.binaryFile";
option java_outer_classname = "BinaryFileModelProto";
message GrpcBinaryFilesRequest {
de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
repeated string fileId = 2;
}
message GrpcFindFilesResponse {
repeated de.ozgcloud.vorgang.grpc.file.GrpcOzgFile file = 1;
}
message GrpcBinaryFileDataRequest {
de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
string fileId = 2;
}
message GrpcUploadBinaryFileRequest {
oneof request {
GrpcUploadBinaryFileMetaData metadata = 1;
bytes fileContent = 2;
}
}
message GrpcUploadBinaryFileMetaData {
de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
string vorgangId = 2;
string field = 3;
string fileName = 4;
string contentType = 5;
int64 size = 6 [deprecated = true];
}
message GrpcUploadBinaryFileResponse {
string fileId = 2;
}
message GrpcGetBinaryFileDataRequest {
de.ozgcloud.vorgang.grpc.command.GrpcCallContext context = 1;
string fileId = 2;
}
message GrpcGetBinaryFileDataResponse {
bytes fileContent = 1;
}
message GrpcBinaryFile {
string id = 1;
string name = 2;
int64 size = 3;
string contentType = 4;
}
message GrpcUpdateBinaryFileRequest {
oneof request {
GrpcBinaryFileMetadata metadata = 1;
bytes content = 2;
}
}
message GrpcBinaryFileMetadata {
string fileId = 1;
string fileName = 2;
string contentType = 3;
}
message GrpcUpdateBinaryFileResponse {}
\ No newline at end of file
/*
* Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
syntax = "proto3";
package de.ozgcloud.vorgang.grpc.binaryFile;
import "binaryfile.model.proto";
option java_multiple_files = true;
option java_package = "de.ozgcloud.vorgang.grpc.binaryFile";
option java_outer_classname = "BinaryFileProto";
service BinaryFileService {
rpc UploadBinaryFileAsStream(stream GrpcUploadBinaryFileRequest) returns (GrpcUploadBinaryFileResponse) {
}
rpc GetBinaryFileContent(GrpcGetBinaryFileDataRequest) returns (stream GrpcGetBinaryFileDataResponse) {
}
rpc FindBinaryFilesMetaData(GrpcBinaryFilesRequest) returns (GrpcFindFilesResponse) {
}
rpc UpdateBinaryFile(stream GrpcUpdateBinaryFileRequest) returns (GrpcUpdateBinaryFileResponse) {
}
}
/*
* Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
syntax = "proto3";
package de.ozgcloud.vorgang.grpc.command;
option java_multiple_files = true;
option java_package = "de.ozgcloud.vorgang.grpc.command";
option java_outer_classname = "SharedCommandProto";
message GrpcCallContext {
string client = 1;
GrpcUser user = 2;
string requestId = 3;
}
message GrpcUser {
string id = 1;
string name = 2;
repeated string roles = 3 [deprecated=true];
}
\ No newline at end of file
/*
* Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
syntax = "proto3";
package de.ozgcloud.vorgang.grpc.clientAttribute;
option java_multiple_files = true;
option java_package = "de.ozgcloud.vorgang.grpc.clientAttribute";
message GrpcClientAttribute {
string clientName = 1;
string attributeName = 2;
GrpcAccessPermission access = 3;
GrpcClientAttributeValue value = 4;
}
enum GrpcAccessPermission {
PRIVATE = 0;
READ_ONLY = 1;
READ_WRITE = 2;
}
message GrpcClientAttributeValue {
oneof value {
string stringValue = 1;
int64 intValue = 2;
double doubleValue = 3;
bool boolValue = 4;
}
}
\ No newline at end of file
/*
* Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den
* Ministerpräsidenten des Landes Schleswig-Holstein
* Staatskanzlei
* Abteilung Digitalisierung und zentrales IT-Management der Landesregierung
*
* Lizenziert unter der EUPL, Version 1.2 oder - sobald
* diese von der Europäischen Kommission genehmigt wurden -
* Folgeversionen der EUPL ("Lizenz");
* Sie dürfen dieses Werk ausschließlich gemäß
* dieser Lizenz nutzen.
* Eine Kopie der Lizenz finden Sie hier:
*
* https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Sofern nicht durch anwendbare Rechtsvorschriften
* gefordert oder in schriftlicher Form vereinbart, wird
* die unter der Lizenz verbreitete Software "so wie sie
* ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN -
* ausdrücklich oder stillschweigend - verbreitet.
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
syntax = "proto3";
package de.ozgcloud.vorgang.grpc.clientAttribute;
import "clientattribute.model.proto";
option java_multiple_files = true;
option java_package = "de.ozgcloud.vorgang.grpc.clientAttribute";
service ClientAttributeService {
rpc Set (GrpcSetClientAttributeRequest) returns (GrpcAcknowledgeResponse) {
}
rpc Update (GrpcUpdateClientAttributeRequest) returns (GrpcAcknowledgeResponse) {
}
rpc Delete (GrpcDeleteClientAttributeRequest) returns (GrpcAcknowledgeResponse) {
}
}
message GrpcSetClientAttributeRequest {
string vorgangId = 1;
GrpcClientAttribute attribute = 2;
}
message GrpcUpdateClientAttributeRequest {
string vorgangId = 1;
GrpcClientAttribute attribute = 2;
}
message GrpcDeleteClientAttributeRequest {
string vorgangId = 1;
string clientName = 2;
string attributeName = 3;
}
message GrpcAcknowledgeResponse {
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment