diff --git a/server/pom.xml b/server/pom.xml index a5aaeb77ff6884f1b9323aa1674bd409671234ef..29efbf14a3624e8da3ac7d95a110b992d0d9373a 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -341,6 +341,12 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <systemPropertyVariables> + <user.language>en</user.language> + <user.country>US</user.country> + </systemPropertyVariables> + </configuration> </plugin> <plugin> diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileController.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileController.java index 969fc3f7b52c5dc201105755ddbb99fc196e5e06..850d16c480a8d57553c3109da01fc9bd2598d1d3 100644 --- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileController.java +++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileController.java @@ -62,18 +62,27 @@ public class FileController { private final @NonNull FileValidator fileValidator; @Operation(summary = "Download file content") - @GetMapping(value = "{nachrichtEventId}/{fileId}", produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE, "images/*" }) + @GetMapping(value = "{nachrichtEventId}/{nachrichtId}/{fileId}", produces = { MediaType.APPLICATION_OCTET_STREAM_VALUE, "images/*" }) public ResponseEntity<StreamingResponseBody> getFileData( @Parameter(description = "The id of the NachrichtEvent in the InfoManager the file belongs to", example = "60af924b4f1a2560298b4567") @PathVariable String nachrichtEventId, + @Parameter(description = "The id of the Nachricht the file belongs to", example = "60af924b4f1a2560298b4567") @PathVariable String nachrichtId, @Parameter(description = "The id of the file", example = "6358fd0bee7a051389cdd788") @PathVariable String fileId) { - var ozgFile = getFile(fileId, nachrichtEventId); + var fileIdentificationData = buildFileIdentificationData(fileId, nachrichtId, nachrichtEventId); - return buildResponseEntity(ozgFile, createDownloadStreamingBody(fileId, nachrichtEventId)); + return buildResponseEntity(getFile(fileIdentificationData), createDownloadStreamingBody(fileIdentificationData)); } - OzgFile getFile(String fileId, String nachrichtEventId) { - return fileService.getFile(fileId, nachrichtEventId); + private FileIdentificationData buildFileIdentificationData(String fileId, String nachrichtId, String nachrichtEventId) { + return FileIdentificationData.builder() + .fileId(fileId) + .nachrichtId(nachrichtId) + .nachrichtEventId(nachrichtEventId) + .build(); + } + + OzgFile getFile(FileIdentificationData fileIdentificationData) { + return fileService.getFile(fileIdentificationData); } private ResponseEntity<StreamingResponseBody> buildResponseEntity(OzgFile ozgFile, StreamingResponseBody responseBody) { @@ -88,8 +97,8 @@ public class FileController { } } - private StreamingResponseBody createDownloadStreamingBody(String fileId, String nachrichtEventId) { - return out -> fileService.downloadFileContent(fileId, out, nachrichtEventId); + private StreamingResponseBody createDownloadStreamingBody(FileIdentificationData fileIdentificationData) { + return out -> fileService.downloadFileContent(fileIdentificationData, out); } @Operation(summary = "Upload file content", diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileIdentificationData.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileIdentificationData.java new file mode 100644 index 0000000000000000000000000000000000000000..f7a44c19cd3a0fae91e5d34ae353929c39b1f5b5 --- /dev/null +++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileIdentificationData.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023-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. + */ + +package de.ozgcloud.antragsraum.attachments; + +import lombok.Builder; + +@Builder +public record FileIdentificationData( + String fileId, + String nachrichtId, + String nachrichtEventId) { +} diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java index 10a61627f53b935530131af711003edd33186c7c..387b57e63d78e5fe377a49e310fce26848e3ac2a 100644 --- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java +++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRemoteService.java @@ -35,22 +35,17 @@ import lombok.extern.log4j.Log4j2; @RequiredArgsConstructor class FileRemoteService { private final @NonNull FileRestClient restClient; + private final @NonNull OzgFileMapper ozgFileMapper; - OzgFile getFile(String fileId, String address) { - var grpcFileMetadata = restClient.findBinaryFilesMetaData(fileId, address); + OzgFile getFile(FileIdentificationData fileIdentificationData, String address) { + var grpcFileMetadata = restClient.getFileMetadata(fileIdentificationData, address); - if (Objects.isNull(grpcFileMetadata.getFile())) { - LOG.warn("Received file id {} from {}, but findBinaryFilesMetaData returned empty file list", fileId, address); + if (Objects.isNull(grpcFileMetadata.getFileMetadata())) { + LOG.warn("Received file id {} from {}, but getFileMetadata returned empty ", fileIdentificationData.fileId(), address); return null; } - if (!grpcFileMetadata.getFile().isEmpty()) { - return OzgFileMapper.fromRestFile(grpcFileMetadata.getFile().getFirst()); - } - - LOG.warn("Received file id {} from {}, but findBinaryFilesMetaData returned empty file list", fileId, address); - - return null; + return ozgFileMapper.fromGrpcFileMetadata(grpcFileMetadata.getFileMetadata(), fileIdentificationData.fileId()); } CompletableFuture<String> uploadFile(OzgUploadFile uploadFile, String address) { @@ -60,7 +55,7 @@ class FileRemoteService { return fileIdFuture; } - void downloadFileContent(String fileId, OutputStream out, String address) { - restClient.downloadFileContent(fileId, out, address); + void downloadFileContent(FileIdentificationData fileIdentificationData, String address, OutputStream out) { + restClient.downloadFileContent(fileIdentificationData, address, out); } } diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java index bfde3830060e9a10f1123032e12ce9898e28f2e7..9f9eb98599cefa037b2ce5623706d6164aecb9ce 100644 --- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java +++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileRestClient.java @@ -38,18 +38,22 @@ import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestClientException; import de.ozgcloud.antragsraum.WebConfiguration; import de.ozgcloud.antragsraum.common.RestClientUtils; import de.ozgcloud.antragsraum.common.TechnicalException; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcFindFilesResponse; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcGetAttachmentContentRequest; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcGetAttachmentMetadataRequest; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcGetAttachmentMetadataResponse; +import de.ozgcloud.antragsraum.security.AuthenticationHelper; import lombok.extern.log4j.Log4j2; @Log4j2 @Component class FileRestClient { - static final String FIND_FILE_METADATA_API = "/api/v1/file/metadata/{fileId}"; - static final String GET_FILE_CONTENT_API = "/api/v1/file/content/{fileId}"; + static final String FIND_FILE_METADATA_API = "/api/v1/file/metadata"; + static final String GET_FILE_CONTENT_API = "/api/v1/file/content"; static final String UPLOAD_FILE_API = "/api/v1/file"; public static final String FILE_KEY = "file"; public static final String VORGANG_ID_KEY = "vorgangId"; @@ -61,14 +65,26 @@ class FileRestClient { this.restClient = restClient; } - AntragraumproxyGrpcFindFilesResponse findBinaryFilesMetaData(String fileId, final String address) { - return restClient - .get() - .uri(FIND_FILE_METADATA_API, fileId) - .accept(MediaType.APPLICATION_JSON) - .header(X_GRPC_ADDRESS, RestClientUtils.sanitizeAddress(address)) - .retrieve() - .toEntity(AntragraumproxyGrpcFindFilesResponse.class).getBody(); + AntragraumGrpcGetAttachmentMetadataResponse getFileMetadata(FileIdentificationData fileIdentificationData, final String address) { + var request = new AntragraumGrpcGetAttachmentMetadataRequest(); + request.setFileId(fileIdentificationData.fileId()); + request.setNachrichtId(fileIdentificationData.nachrichtId()); + request.setSamlToken(AuthenticationHelper.getSamlToken()); + + try { + return restClient + .post() + .uri(FIND_FILE_METADATA_API) + .header(X_GRPC_ADDRESS, RestClientUtils.sanitizeAddress(address)) + .contentType(MediaType.APPLICATION_JSON) + .body(request) + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .toEntity(AntragraumGrpcGetAttachmentMetadataResponse.class).getBody(); + } catch (RestClientException e) { + LOG.error("Error loading file metadata. {}", e.getMessage(), e); + throw e; + } } void uploadFile(final OzgUploadFile uploadFile, final String address, final CompletableFuture<String> fileIdFuture) { @@ -98,15 +114,27 @@ class FileRestClient { .retrieve().toEntity(String.class).getBody(); } - void downloadFileContent(final String fileId, final OutputStream out, final String address) { - var fileContent = Optional.ofNullable(restClient - .get() - .uri(GET_FILE_CONTENT_API, fileId) - .header(X_GRPC_ADDRESS, RestClientUtils.sanitizeAddress(address)) - .accept(MediaType.APPLICATION_OCTET_STREAM) - .retrieve().toEntity(Resource.class).getBody()); + void downloadFileContent(FileIdentificationData fileIdentificationData, final String address, final OutputStream out) { + var request = new AntragraumGrpcGetAttachmentContentRequest(); + request.setFileId(fileIdentificationData.fileId()); + request.setNachrichtId(fileIdentificationData.nachrichtId()); + request.setSamlToken(AuthenticationHelper.getSamlToken()); + + try { + var fileContent = Optional.ofNullable(restClient + .post() + .uri(GET_FILE_CONTENT_API, fileIdentificationData.fileId()) + .header(X_GRPC_ADDRESS, RestClientUtils.sanitizeAddress(address)) + .contentType(MediaType.APPLICATION_JSON) + .body(request) + .accept(MediaType.APPLICATION_OCTET_STREAM) + .retrieve().toEntity(Resource.class).getBody()); - fileContent.ifPresent(file -> processFile(out, file)); + fileContent.ifPresent(file -> processFile(out, file)); + } catch (RestClientException e) { + LOG.error("Error downloading file. {}", e.getMessage(), e); + throw e; + } } private static void processFile(final OutputStream out, Resource fileContent) { diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java index 99041ce9e5862efcd444b2baf613fcc1949f4886..f1c616aceebd4325dcb2f8c5ff1743e3d5d9b828 100644 --- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java +++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/FileService.java @@ -40,16 +40,16 @@ public class FileService { private final @NonNull VirusScannerClient scanner; private final @NonNull NachrichtEventService nachrichtEventService; - public OzgFile getFile(String fileId, String nachrichtEventId) { - var nachrichtEvent = nachrichtEventService.getNachrichtEventById(nachrichtEventId); + public OzgFile getFile(FileIdentificationData fileIdentificationData) { + var nachrichtEvent = nachrichtEventService.getNachrichtEventById(fileIdentificationData.nachrichtEventId()); - return fileRemoteService.getFile(fileId, nachrichtEvent.address()); + return fileRemoteService.getFile(fileIdentificationData, nachrichtEvent.address()); } - void downloadFileContent(String fileId, OutputStream out, String nachrichtEventId) { - var nachrichtEvent = nachrichtEventService.getNachrichtEventById(nachrichtEventId); + void downloadFileContent(FileIdentificationData fileIdentificationData, OutputStream out) { + var nachrichtEvent = nachrichtEventService.getNachrichtEventById(fileIdentificationData.nachrichtEventId()); - fileRemoteService.downloadFileContent(fileId, out, nachrichtEvent.address()); + fileRemoteService.downloadFileContent(fileIdentificationData, nachrichtEvent.address(), out); } CompletableFuture<String> upload(String vorgangId, String nachrichtEventId, MultipartFile file) { diff --git a/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java b/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java index 341e10bc55ba104157b9f035bae43d3629e3a4af..83c813973c3e5587ee2d07dd1c44319a32e66fce 100644 --- a/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java +++ b/server/src/main/java/de/ozgcloud/antragsraum/attachments/OzgFileMapper.java @@ -20,20 +20,18 @@ package de.ozgcloud.antragsraum.attachments; -import java.util.Objects; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcFileMetadata; + +@Mapper +interface OzgFileMapper { + + @Mapping(target = "id", source = "fileId") + @Mapping(target = "fileName", source = "grpcFile.name") + @Mapping(target = "contentType", source = "grpcFile.contentType") + @Mapping(target = "fileSize", expression = "java(grpcFile.getSize() != null ? Long.parseLong(grpcFile.getSize()) : -1L)") + OzgFile fromGrpcFileMetadata(AntragraumGrpcFileMetadata grpcFile, String fileId); -@NoArgsConstructor(access = AccessLevel.PRIVATE) -class OzgFileMapper { - static OzgFile fromRestFile(AntragraumproxyGrpcOzgFile grpcFile) { - return OzgFile.builder() - .id(grpcFile.getId()) - .fileName(grpcFile.getName()) - .contentType(grpcFile.getContentType()) - .fileSize(Objects.nonNull(grpcFile.getSize()) ? Long.parseLong(grpcFile.getSize()) : -1L) - .build(); - } } diff --git a/server/src/main/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapper.java b/server/src/main/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapper.java index a118da2f45e0537d03bf6173cf7e869c72a7db43..325197b8f0da465b9ebb0a40399d705f17c93cdf 100644 --- a/server/src/main/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapper.java +++ b/server/src/main/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapper.java @@ -29,6 +29,7 @@ import java.util.Objects; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import de.ozgcloud.antragsraum.attachments.FileIdentificationData; import de.ozgcloud.antragsraum.attachments.FileService; import de.ozgcloud.antragsraum.attachments.OzgFile; import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcRueckfrage; @@ -43,28 +44,23 @@ import lombok.extern.log4j.Log4j2; class NachrichtMapper { private final @NonNull FileService fileService; - private List<OzgFile> getAttachments(List<String> fileIds, String nachrichtEventId) { + private List<OzgFile> getAttachments(List<String> fileIds, String nachrichtId, String nachrichtEventId) { if (Objects.isNull(fileIds)) { return List.of(); } - return fileIds.stream().filter(StringUtils::isNotEmpty).map(fileId -> fileService.getFile(fileId, nachrichtEventId)) + return fileIds.stream().filter(StringUtils::isNotEmpty).map(fileId -> getFile(fileId, nachrichtId, nachrichtEventId)) .filter(Objects::nonNull).toList(); } - long toMillisecondsTimestamp(String dateString) { - long timestamp = 0; - try { - timestamp = LocalDateTime.parse(dateString).toEpochSecond(ZoneOffset.UTC) * 1000; - } catch (DateTimeException e) { - if (StringUtils.isEmpty(dateString)) { - LOG.debug("Empty date received for Nachricht. Setting it to 0 (=1970-01-01)"); - } else { - LOG.warn("Invalid date [{}] received for Nachricht. Setting it to 0 (=1970-01-01)", dateString); - } - } + private OzgFile getFile(String fileId, String nachrichtId, String nachrichtEventId) { + var fileIdentificationData = FileIdentificationData.builder() + .fileId(fileId) + .nachrichtId(nachrichtId) + .nachrichtEventId(nachrichtEventId) + .build(); - return timestamp; + return fileService.getFile(fileIdentificationData); } public Nachricht fromRestRueckfrage(final AntragraumproxyGrpcRueckfrage rueckfrage, final String id) { @@ -77,7 +73,7 @@ class NachrichtMapper { .replyNachrichten(fromRestRueckfrageAnswer(rueckfrage, id)) .answeredAt(toMillisecondsTimestamp(rueckfrage.getAnsweredAt())) .sendAt(toMillisecondsTimestamp(rueckfrage.getSentAt())) - .attachments(getAttachments(rueckfrage.getAttachmentFileId(), id)) + .attachments(getAttachments(rueckfrage.getAttachmentFileId(), rueckfrage.getId(), id)) .accessible(Boolean.TRUE.equals(rueckfrage.getAccessible())) .trustLevel(TrustLevelMapper.map(rueckfrage.getTrustLevel())) .status(rueckfrage.getStatus()); @@ -85,6 +81,21 @@ class NachrichtMapper { return builder.build(); } + private long toMillisecondsTimestamp(String dateString) { + long timestamp = 0; + try { + timestamp = LocalDateTime.parse(dateString).toEpochSecond(ZoneOffset.UTC) * 1000; + } catch (DateTimeException e) { + if (StringUtils.isEmpty(dateString)) { + LOG.debug("Empty date received for Nachricht. Setting it to 0 (=1970-01-01)"); + } else { + LOG.warn("Invalid date [{}] received for Nachricht. Setting it to 0 (=1970-01-01)", dateString); + } + } + + return timestamp; + } + private List<ReplyNachricht> fromRestRueckfrageAnswer(final AntragraumproxyGrpcRueckfrage rueckfrage, final String id) { if (Objects.isNull(rueckfrage.getAnswers())) { return List.of(); @@ -95,7 +106,7 @@ class NachrichtMapper { .id(rueckfrage.getId()) .nachrichtEventId(id) .message(answer.getAnswerText()) - .attachments(getAttachments(answer.getAttachmentFileId(), id)); + .attachments(getAttachments(answer.getAttachmentFileId(), rueckfrage.getId(), id)); return builder.build(); }).toList(); } diff --git a/server/src/main/resources/openapi/swagger.json b/server/src/main/resources/openapi/swagger.json index cd1bb83e704b6bb9ae8d5872498e460400a1824c..28e3dd8a362901cbb434e35528aeb3f4edc98e4d 100644 --- a/server/src/main/resources/openapi/swagger.json +++ b/server/src/main/resources/openapi/swagger.json @@ -12,6 +12,18 @@ { "name": "AntragraumService", "description": "Service to proxy between Antragraum Backend and NachrichtenManager in OZG-Cloud" + }, + { + "name": "BinaryFileService", + "description": "Service to proxy between Antragraum Backend and VorgangManager File Api in OZG-Cloud" + }, + { + "name": "CommandService", + "description": "Service to proxy between Antragraum Backend and VorgangManager Command Api in OZG-Cloud" + }, + { + "name": "InformationService", + "description": "Service to proxy between Antragraum Backend and InfoManager in OZG-Cloud" } ], "schemes": [ @@ -163,153 +175,18 @@ ] } }, - "/api/v1/file": { + "/api/v1/file/metadata": { "post": { - "operationId": "BinaryFileService_UploadBinaryFileAsStream", - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "$ref": "#/definitions/antragraumproxyGrpcUploadBinaryFileResponse" - } - }, - "403": { - "description": "Returned when the user does not have permission to access the resource.", - "schema": {} - }, - "404": { - "description": "Returned when the resource does not exist.", - "schema": { - "type": "string", - "format": "string" - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, - "parameters": [ - { - "name": "body", - "description": " (streaming inputs)", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/antragraumproxyGrpcUploadBinaryFileRequest" - } - } - ], - "tags": [ - "BinaryFileService" - ] - } - }, - "/api/v1/file/content/{fileId}": { - "get": { - "summary": "Summary: GetBinaryFileContent rpc", - "description": "Get the content of a file", - "operationId": "BinaryFileService_GetBinaryFileContent", - "responses": { - "200": { - "description": "Returns file content as binary stream.", - "schema": { - "type": "object", - "properties": { - "result": { - "$ref": "#/definitions/antragraumproxyGrpcGetBinaryFileDataResponse" - }, - "error": { - "$ref": "#/definitions/rpcStatus" - } - }, - "title": "Stream result of antragraumproxyGrpcGetBinaryFileDataResponse" - } - }, - "403": { - "description": "Returned when the user does not have permission to access the resource.", - "schema": {} - }, - "404": { - "description": "Returned when the resource does not exist.", - "schema": {} - }, - "503": { - "description": "Returned when the resource is temporarily unavailable.", - "schema": {} - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, - "parameters": [ - { - "name": "fileId", - "in": "path", - "required": true, - "type": "string" - }, - { - "name": "context.client", - "in": "query", - "required": false, - "type": "string" - }, - { - "name": "context.user.id", - "in": "query", - "required": false, - "type": "string" - }, - { - "name": "context.user.name", - "in": "query", - "required": false, - "type": "string" - }, - { - "name": "context.user.roles", - "in": "query", - "required": false, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "multi" - }, - { - "name": "context.requestId", - "in": "query", - "required": false, - "type": "string" - } - ], - "tags": [ - "BinaryFileService" - ] - } - }, - "/api/v1/file/metadata/{fileId}": { - "get": { - "summary": "Summary: FindBinaryFilesMetaData rpc", + "summary": "Summary: GetAttachmentMetadata rpc", "description": "Get the metadata of a file", - "operationId": "BinaryFileService_FindBinaryFilesMetaData", + "operationId": "AntragraumService_GetAttachmentMetadata", "responses": { "200": { "description": "Returns file metadata as json.", "schema": { - "$ref": "#/definitions/antragraumproxyGrpcFindFilesResponse" + "$ref": "#/definitions/antragraumGrpcGetAttachmentMetadataResponse" } }, - "403": { - "description": "Returned when the user does not have permission to access the resource.", - "schema": {} - }, "404": { "description": "Returned when the resource does not exist.", "schema": {} @@ -327,53 +204,16 @@ }, "parameters": [ { - "name": "fileId", - "in": "path", + "name": "body", + "in": "body", "required": true, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "csv", - "minItems": 1 - }, - { - "name": "context.client", - "in": "query", - "required": false, - "type": "string" - }, - { - "name": "context.user.id", - "in": "query", - "required": false, - "type": "string" - }, - { - "name": "context.user.name", - "in": "query", - "required": false, - "type": "string" - }, - { - "name": "context.user.roles", - "in": "query", - "required": false, - "type": "array", - "items": { - "type": "string" - }, - "collectionFormat": "multi" - }, - { - "name": "context.requestId", - "in": "query", - "required": false, - "type": "string" + "schema": { + "$ref": "#/definitions/antragraumGrpcGetAttachmentMetadataRequest" + } } ], "tags": [ - "BinaryFileService" + "AntragraumService" ] } }, @@ -695,6 +535,57 @@ } } }, + "antragraumGrpcFileMetadata": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "size": { + "type": "string", + "format": "int64" + }, + "contentType": { + "type": "string" + } + } + }, + "antragraumGrpcGetAttachmentMetadataResponse": { + "type": "object", + "properties": { + "fileMetadata": { + "$ref": "#/definitions/antragraumGrpcFileMetadata" + } + } + }, + "antragraumGrpcGetAttachmentMetadataRequest": { + "type": "object", + "properties": { + "samlToken": { + "type": "string" + }, + "nachrichtId": { + "type": "string" + }, + "fileId": { + "type": "string" + } + } + }, + "antragraumGrpcGetAttachmentContentRequest": { + "type": "object", + "properties": { + "samlToken": { + "type": "string" + }, + "nachrichtId": { + "type": "string" + }, + "fileId": { + "type": "string" + } + } + }, "protobufAny": { "type": "object", "properties": { @@ -737,18 +628,6 @@ } } }, - "antragraumproxyGrpcFindFilesResponse": { - "type": "object", - "properties": { - "file": { - "type": "array", - "items": { - "type": "object", - "$ref": "#/definitions/antragraumproxyGrpcOzgFile" - } - } - } - }, "antragraumproxyGrpcGetAttachmentsResponse": { "type": "object", "properties": { @@ -761,15 +640,6 @@ } } }, - "antragraumproxyGrpcGetBinaryFileDataResponse": { - "type": "object", - "properties": { - "fileContent": { - "type": "string", - "format": "byte" - } - } - }, "antragraumproxyGrpcGetRepresentationsResponse": { "type": "object", "properties": { @@ -800,50 +670,6 @@ } } }, - "antragraumproxyGrpcUploadBinaryFileMetaData": { - "type": "object", - "properties": { - "context": { - "$ref": "#/definitions/antragraumproxyGrpcCallContext" - }, - "vorgangId": { - "type": "string" - }, - "field": { - "type": "string" - }, - "fileName": { - "type": "string" - }, - "contentType": { - "type": "string" - }, - "size": { - "type": "string", - "format": "int64" - } - } - }, - "antragraumproxyGrpcUploadBinaryFileRequest": { - "type": "object", - "properties": { - "metadata": { - "$ref": "#/definitions/antragraumproxyGrpcUploadBinaryFileMetaData" - }, - "fileContent": { - "type": "string", - "format": "byte" - } - } - }, - "antragraumproxyGrpcUploadBinaryFileResponse": { - "type": "object", - "properties": { - "fileId": { - "type": "string" - } - } - }, "antragraumproxyGrpcUser": { "type": "object", "properties": { diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumproxyGrpcOzgFileTestFactory.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumGrpcFileMetadataTestFactory.java similarity index 81% rename from server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumproxyGrpcOzgFileTestFactory.java rename to server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumGrpcFileMetadataTestFactory.java index 59966bfd22ee61ef176772a8c3e1550fac6a36e3..4506cc650b89cb9b2ca6c0c34b9f31145824736f 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumproxyGrpcOzgFileTestFactory.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumGrpcFileMetadataTestFactory.java @@ -22,12 +22,11 @@ package de.ozgcloud.antragsraum.attachments; import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcFileMetadata; -public class AntragraumproxyGrpcOzgFileTestFactory { - static AntragraumproxyGrpcOzgFile create() { - var file = new AntragraumproxyGrpcOzgFile(); - file.setId(FILE_ID); +public class AntragraumGrpcFileMetadataTestFactory { + static AntragraumGrpcFileMetadata create() { + var file = new AntragraumGrpcFileMetadata(); file.setContentType(CONTENT_TYPE); file.setSize(FILE_SIZE_STRING); file.setName(FILE_NAME); diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumproxyGrpcFindFilesResponseTestFactory.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumGrpcGetAttachmentMetadataResponseTestFactory.java similarity index 76% rename from server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumproxyGrpcFindFilesResponseTestFactory.java rename to server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumGrpcGetAttachmentMetadataResponseTestFactory.java index 9bc0f654a2cbd1a755b3232b3fb73b860beae816..784fa6e1fb2e74ff1a730a3d1cee59f67fbeff23 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumproxyGrpcFindFilesResponseTestFactory.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/AntragraumGrpcGetAttachmentMetadataResponseTestFactory.java @@ -22,17 +22,15 @@ package de.ozgcloud.antragsraum.attachments; -import java.util.List; - -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcFindFilesResponse; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcGetAttachmentMetadataResponse; import lombok.AccessLevel; import lombok.NoArgsConstructor; @NoArgsConstructor(access = AccessLevel.PRIVATE) -class AntragraumproxyGrpcFindFilesResponseTestFactory { - static AntragraumproxyGrpcFindFilesResponse create() { - var response = new AntragraumproxyGrpcFindFilesResponse(); - response.setFile(List.of(AntragraumproxyGrpcOzgFileTestFactory.create())); +class AntragraumGrpcGetAttachmentMetadataResponseTestFactory { + static AntragraumGrpcGetAttachmentMetadataResponse create() { + var response = new AntragraumGrpcGetAttachmentMetadataResponse(); + response.setFileMetadata(AntragraumGrpcFileMetadataTestFactory.create()); return response; } } diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java index 9b349040187947528344a5c5109c8c99fc4593c6..5be8c6bce51110148ce61c128b48762bac4fc825 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerITCase.java @@ -56,7 +56,6 @@ import org.springframework.web.client.RestTemplate; import de.ozgcloud.antragsraum.common.NotFoundException; import de.ozgcloud.antragsraum.common.TechnicalException; import de.ozgcloud.antragsraum.common.VirusFoundException; -import de.ozgcloud.antragsraum.nachricht.NachrichtTestFactory; @AutoConfigureMockMvc @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) @@ -85,7 +84,7 @@ public class FileControllerITCase { class TestDownloadingFileContent { @BeforeEach void init() { - when(fileService.getFile(anyString(), anyString())).thenReturn(OzgFileTestFactory.create()); + when(fileService.getFile(any(FileIdentificationData.class))).thenReturn(OzgFileTestFactory.create()); } @Test @@ -99,7 +98,7 @@ public class FileControllerITCase { class TestFileNotFoundError { @BeforeEach void init() { - doThrow(NotFoundException.class).when(fileService).getFile(anyString(), anyString()); + doThrow(NotFoundException.class).when(fileService).getFile(any(FileIdentificationData.class)); } @Test @@ -114,7 +113,7 @@ public class FileControllerITCase { @Test @WithMockUser void shouldReturn500ByTechnicalException() throws Exception { - doThrow(TechnicalException.class).when(fileService).getFile(anyString(), anyString()); + doThrow(TechnicalException.class).when(fileService).getFile(any(FileIdentificationData.class)); performRequest().andExpect(status().isInternalServerError()); } @@ -122,7 +121,7 @@ public class FileControllerITCase { @Test @WithMockUser void shouldReturn500ByRuntimeException() throws Exception { - doThrow(RuntimeException.class).when(fileService).getFile(anyString(), anyString()); + doThrow(RuntimeException.class).when(fileService).getFile(any(FileIdentificationData.class)); performRequest().andExpect(status().isInternalServerError()); } @@ -132,8 +131,7 @@ public class FileControllerITCase { class TestNotAcceptable { @BeforeEach void init() { - when(fileService.getFile(anyString(), any())).thenReturn(OzgFileTestFactory.create()); - doThrow(VirusFoundException.class).when(fileService).getFile(anyString(), any()); + doThrow(VirusFoundException.class).when(fileService).getFile(any(FileIdentificationData.class)); } @Test @@ -145,7 +143,7 @@ public class FileControllerITCase { ResultActions performRequest() throws Exception { return mockMvc.perform( - get(PATH + NachrichtTestFactory.NACHRICHT_EVENT_ID + "/" + FILE_ID) + get(PATH + NACHRICHT_EVENT_ID + "/" + NACHRICHT_ID + "/" + FILE_ID) .with(csrf().asHeader()) .accept(MediaType.APPLICATION_OCTET_STREAM_VALUE)); } diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerTest.java index 6a18a3cf6b0c84a6adb8a775cd3eb1b2774d0da2..7fea74c9db5808ae1514c66bd67118290a541748 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerTest.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileControllerTest.java @@ -20,10 +20,7 @@ package de.ozgcloud.antragsraum.attachments; -import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.NACHRICHT_EVENT_ID; -import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.VORGANG_ID; import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*; -import static de.ozgcloud.antragsraum.nachricht.NachrichtTestFactory.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -62,56 +59,54 @@ class FileControllerTest { class TestGetFileContent { @BeforeEach void init() { - when(fileService.getFile(anyString(), anyString())).thenReturn(OzgFileTestFactory.create()); + lenient().when(fileService.getFile(any(FileIdentificationData.class))).thenReturn(OzgFileTestFactory.create()); } @Test void shouldCallGetFile() { - fileController.getFileData( - Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), FILE_ID); + fileController.getFileData(Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), NACHRICHT_ID, FILE_ID); - verify(fileService).getFile(anyString(), anyString()); + verify(fileService).getFile(any(FileIdentificationData.class)); } @Test void shouldHaveStatusOk() { - var response = fileController.getFileData( - Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), FILE_ID); + var response = fileController.getFileData(Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), + NACHRICHT_ID, FILE_ID); assertThat(response.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(HttpStatus.OK.value())); } @Test void shouldHaveContentLength() { - var response = fileController.getFileData( - Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), FILE_ID); + var response = fileController.getFileData(Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), + NACHRICHT_ID, FILE_ID); assertThat(response.getHeaders().getContentLength()).isEqualTo(FILE_SIZE); } @Test void shouldHaveContentType() { - var response = fileController.getFileData( - Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), FILE_ID); + var response = fileController.getFileData(Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), + NACHRICHT_ID, FILE_ID); assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.parseMediaType(CONTENT_TYPE)); } @Test void shouldHandleNullFile() { - when(fileService.getFile(anyString(), anyString())).thenReturn(null); + when(fileService.getFile(any(FileIdentificationData.class))).thenReturn(null); - var response = fileController.getFileData( - Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), FILE_ID); + var response = fileController.getFileData(Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), + NACHRICHT_ID, FILE_ID); assertThat(response.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(404)); } @Test void shouldHaveContentDispositionHeader() { - var contentDisposition = fileController.getFileData( - Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), FILE_ID) - .getHeaders().getContentDisposition(); + var contentDisposition = fileController.getFileData(Base64.getEncoder().encodeToString(CHANNEL_ADDRESS.getBytes(StandardCharsets.UTF_8)), + NACHRICHT_ID, FILE_ID).getHeaders().getContentDisposition(); assertThat(contentDisposition).hasToString("attachment; filename=\"" + FILE_NAME + "\""); } @@ -119,11 +114,13 @@ class FileControllerTest { @Nested class TestGetFile { + private static final FileIdentificationData FILE_IDENTIFICATION_DATA = FileIdentificationDataTestFactory.create(); + @Test void shouldCallService() { - fileController.getFile(FILE_ID, REPLY_TO_NACHRICHT_ID); + fileController.getFile(FILE_IDENTIFICATION_DATA); - verify(fileService).getFile(any(), anyString()); + verify(fileService).getFile(FILE_IDENTIFICATION_DATA); } } diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileIdentificationDataTestFactory.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileIdentificationDataTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..4d4266da59ea7d729df11bb46296a071708afb1c --- /dev/null +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileIdentificationDataTestFactory.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023-2024. + * 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. + */ + +package de.ozgcloud.antragsraum.attachments; + +import static de.ozgcloud.antragsraum.attachments.OzgFileTestFactory.*; + +public class FileIdentificationDataTestFactory { + + public static FileIdentificationData create() { + return createBuilder().build(); + } + + public static FileIdentificationData.FileIdentificationDataBuilder createBuilder() { + return FileIdentificationData.builder() + .fileId(FILE_ID) + .nachrichtId(NACHRICHT_ID) + .nachrichtEventId(NACHRICHT_EVENT_ID); + } + +} diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceITCase.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceITCase.java index 092a6414e9f2c5608221d6d54d2f92364b9edb00..4f8bbbf0b30bda4191a595694ac68b9b090e130b 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceITCase.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceITCase.java @@ -42,6 +42,7 @@ import lombok.extern.log4j.Log4j2; @SpringJUnitConfig(classes = { FileRemoteServiceTestConfiguration.class }) @Log4j2 public class FileRemoteServiceITCase { + private static final FileIdentificationData FILE_IDENTIFICATION_DATA = FileIdentificationDataTestFactory.create(); private static final String ADDRESS = "http://localhost:8088"; @SpyBean @@ -65,10 +66,11 @@ public class FileRemoteServiceITCase { @Nested class TestGetFile { + @Test @DirtiesContext void shouldGetFile() { - var file = fileRemoteService.getFile(FILE_ID, ADDRESS); + var file = fileRemoteService.getFile(FILE_IDENTIFICATION_DATA, ADDRESS); assertThat(file).isNotNull(); } @@ -76,7 +78,7 @@ public class FileRemoteServiceITCase { @Test @DirtiesContext void shouldHaveFileMetaData() { - var file = fileRemoteService.getFile(FILE_ID, ADDRESS); + var file = fileRemoteService.getFile(FILE_IDENTIFICATION_DATA, ADDRESS); assertThat(file).isEqualTo(OzgFileTestFactory.create()); } @@ -84,11 +86,12 @@ public class FileRemoteServiceITCase { @Nested class TestGetFileContent { + @Test @DirtiesContext void shouldGetFileContent() { var out = new ByteArrayOutputStream(); - fileRemoteService.downloadFileContent(FILE_ID, out, ADDRESS); + fileRemoteService.downloadFileContent(FILE_IDENTIFICATION_DATA, ADDRESS, out); assertThat(out.size()).isEqualTo(DATA.length); } diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java index cb33df3d0cb5bd83bbaaa0242210f60ca862cba1..a519703c1c6ee78029865dbf8aecadc4525e50b9 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTest.java @@ -30,7 +30,6 @@ import static org.mockito.Mockito.*; import java.io.ByteArrayOutputStream; import java.io.OutputStream; -import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -41,11 +40,12 @@ import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcFindFilesResponse; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcFileMetadata; @ExtendWith(MockitoExtension.class) class FileRemoteServiceTest { + private static final FileIdentificationData FILE_IDENTIFICATION_DATA = FileIdentificationDataTestFactory.create(); + @Spy @InjectMocks private FileRemoteService remoteService; @@ -53,61 +53,62 @@ class FileRemoteServiceTest { @Mock private FileRestClient restClient; + @Mock + private OzgFileMapper ozgFileMapper; + @Nested class TestLoadingFile { @BeforeEach void init() { - var response = new AntragraumproxyGrpcFindFilesResponse(); - var file = new AntragraumproxyGrpcOzgFile(); - file.setName(FILE_NAME); - file.setSize(FILE_SIZE_STRING); - file.setContentType(CONTENT_TYPE); - file.setId(FILE_ID); - response.setFile(List.of(file)); - when(restClient.findBinaryFilesMetaData(any(), any())).thenReturn(response); + lenient().when(restClient.getFileMetadata(any(FileIdentificationData.class), anyString())).thenReturn( + AntragraumGrpcGetAttachmentMetadataResponseTestFactory.create()); + lenient().when(ozgFileMapper.fromGrpcFileMetadata(any(AntragraumGrpcFileMetadata.class), anyString())) + .thenReturn(OzgFileTestFactory.create()); } @Test void shouldLoadFileMetadata() { - var file = remoteService.getFile(FILE_ID, CHANNEL_ADDRESS); + var file = remoteService.getFile(FILE_IDENTIFICATION_DATA, CHANNEL_ADDRESS); assertThat(file).isNotNull(); } @Test void shouldHaveFileName() { - var file = remoteService.getFile(FILE_ID, CHANNEL_ADDRESS); + var file = remoteService.getFile(FILE_IDENTIFICATION_DATA, CHANNEL_ADDRESS); assertThat(file.fileName()).isEqualTo(FILE_NAME); } @Test void shouldHaveFileSize() { - var file = remoteService.getFile(FILE_ID, CHANNEL_ADDRESS); + var file = remoteService.getFile(FILE_IDENTIFICATION_DATA, CHANNEL_ADDRESS); assertThat(file.fileSize()).isEqualTo(FILE_SIZE); } @Test void shouldHaveContentType() { - var file = remoteService.getFile(FILE_ID, CHANNEL_ADDRESS); + var file = remoteService.getFile(FILE_IDENTIFICATION_DATA, CHANNEL_ADDRESS); assertThat(file.contentType()).isEqualTo(CONTENT_TYPE); } @Test void shouldHaveFileId() { - var file = remoteService.getFile(FILE_ID, CHANNEL_ADDRESS); + var file = remoteService.getFile(FILE_IDENTIFICATION_DATA, CHANNEL_ADDRESS); assertThat(file.id()).isEqualTo(FILE_ID); } @Test void shouldHandleEmpty() { - var response = new AntragraumproxyGrpcFindFilesResponse(); - when(restClient.findBinaryFilesMetaData(any(), any())).thenReturn(response); + var response = AntragraumGrpcGetAttachmentMetadataResponseTestFactory.create(); + response.setFileMetadata(null); + + when(restClient.getFileMetadata(any(FileIdentificationData.class), anyString())).thenReturn(response); - var file = remoteService.getFile(FILE_ID, CHANNEL_ADDRESS); + var file = remoteService.getFile(FILE_IDENTIFICATION_DATA, CHANNEL_ADDRESS); assertThat(file).isNull(); } @@ -119,9 +120,9 @@ class FileRemoteServiceTest { @Test void shouldCallDownloadFileObserver() { - remoteService.downloadFileContent(FILE_ID, output, CHANNEL_ADDRESS); + remoteService.downloadFileContent(FILE_IDENTIFICATION_DATA, CHANNEL_ADDRESS, output); - verify(restClient).downloadFileContent(eq(FILE_ID), any(OutputStream.class), eq(CHANNEL_ADDRESS)); + verify(restClient).downloadFileContent(eq(FILE_IDENTIFICATION_DATA), eq(CHANNEL_ADDRESS), any(OutputStream.class)); } } diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTestConfiguration.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTestConfiguration.java index 532bc9f603d52860ceab5392bd79cb7ec5b74c34..abbf945050ddad9e86310c2b1525351c4de070a7 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTestConfiguration.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRemoteServiceTestConfiguration.java @@ -22,6 +22,7 @@ package de.ozgcloud.antragsraum.attachments; +import org.mapstruct.factory.Mappers; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; @@ -42,9 +43,14 @@ public class FileRemoteServiceTestConfiguration { return new StubFileRestClient(); } + @Bean + OzgFileMapper ozgFileMapper() { + return Mappers.getMapper(OzgFileMapper.class); + } + @Bean FileRemoteService fileRemoteService() { - return new FileRemoteService(fileRestClient()); + return new FileRemoteService(fileRestClient(), ozgFileMapper()); } @Bean diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRestClientTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRestClientTest.java index 45af2c4e9e4efcae7fded3f6becc5cfe972ca858..dc60cc51bac544490fae72ff1bdd86fdfdf46573 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRestClientTest.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileRestClientTest.java @@ -39,22 +39,26 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; import org.springframework.boot.test.web.client.MockServerRestClientCustomizer; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.web.client.RestClient; +import org.springframework.web.client.RestClientException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import de.ozgcloud.antragsraum.common.TechnicalException; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcFindFilesResponse; +import de.ozgcloud.antragsraum.security.AuthenticationHelper; +import de.ozgcloud.antragsraum.security.UserTestFactory; @SpringJUnitConfig(classes = { FileRestClientTestConfiguration.class }) @RestClientTest(FileRestClient.class) class FileRestClientTest { - final static String ADDRESS = "http://localhost:8382"; - public static final String FILE_ID = "test"; + private static final FileIdentificationData FILE_IDENTIFICATION_DATA = FileIdentificationDataTestFactory.create(); + static final String ADDRESS = "http://localhost:8382"; + private FileRestClient fileRestClient; @Autowired @@ -75,24 +79,33 @@ class FileRestClientTest { } @Nested - class TestLoadingFileMetadata { - private final String fileFileUri = ADDRESS + FIND_FILE_METADATA_API.replace("{fileId}", FILE_ID); + class TestGetFileMetadata { - @BeforeEach - void setup() throws JsonProcessingException { - server.expect(requestTo(fileFileUri)) - .andRespond(withSuccess(objectMapper.writeValueAsString(createFindFileMetadataResponse()), MediaType.APPLICATION_JSON)); - } + private static final String FILE_METADATA_URI = ADDRESS + FIND_FILE_METADATA_API; + + @Test + void shouldLoadFileMetadata() throws JsonProcessingException { + try (var authenticationHelper = mockStatic(AuthenticationHelper.class)) { + authenticationHelper.when(AuthenticationHelper::getSamlToken).thenReturn(UserTestFactory.SAML_TOKEN); + server.expect(requestTo(FILE_METADATA_URI)).andRespond( + withSuccess(objectMapper.writeValueAsString(AntragraumGrpcGetAttachmentMetadataResponseTestFactory.create()), + MediaType.APPLICATION_JSON)); + + var fileMetadata = fileRestClient.getFileMetadata(FILE_IDENTIFICATION_DATA, ADDRESS + FIND_FILE_METADATA_API); - private AntragraumproxyGrpcFindFilesResponse createFindFileMetadataResponse() { - return AntragraumproxyGrpcFindFilesResponseTestFactory.create(); + assertThat(fileMetadata).isNotNull(); + } } @Test - void shouldFindFileMetadata() { - var fileMetadata = fileRestClient.findBinaryFilesMetaData(FILE_ID, ADDRESS + FIND_FILE_METADATA_API); - - assertThat(fileMetadata).isNotNull(); + void shouldThrowRestClientException() { + try (var authenticationHelper = mockStatic(AuthenticationHelper.class)) { + authenticationHelper.when(AuthenticationHelper::getSamlToken).thenReturn(UserTestFactory.SAML_TOKEN); + server.expect(requestTo(FILE_METADATA_URI)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); + + assertThatExceptionOfType(RestClientException.class).isThrownBy( + () -> fileRestClient.getFileMetadata(FILE_IDENTIFICATION_DATA, ADDRESS + GET_FILE_CONTENT_API)); + } } } @@ -124,30 +137,49 @@ class FileRestClientTest { @Nested class TestDownloadFileContent { - private final String fileContentUri = ADDRESS + GET_FILE_CONTENT_API.replace("{fileId}", FILE_ID); - @BeforeEach - void setup() throws IOException { - server.expect(requestTo(fileContentUri)) - .andRespond(withSuccess(OzgUploadFileTestFactory.MULTIPART_FILE.getBytes(), MediaType.APPLICATION_OCTET_STREAM)); - } + private static final String FILE_CONTENT_URI = ADDRESS + GET_FILE_CONTENT_API; @Test void shouldDownloadFileContent() throws IOException { - var out = new ByteArrayOutputStream(); - fileRestClient.downloadFileContent(FILE_ID, out, ADDRESS + GET_FILE_CONTENT_API); - var res = out.toByteArray(); + try (var authenticationHelper = mockStatic(AuthenticationHelper.class)) { + authenticationHelper.when(AuthenticationHelper::getSamlToken).thenReturn(UserTestFactory.SAML_TOKEN); + server.expect(requestTo(FILE_CONTENT_URI)) + .andRespond(withSuccess(OzgUploadFileTestFactory.MULTIPART_FILE.getBytes(), MediaType.APPLICATION_OCTET_STREAM)); + + var out = new ByteArrayOutputStream(); + fileRestClient.downloadFileContent(FILE_IDENTIFICATION_DATA, ADDRESS + GET_FILE_CONTENT_API, out); + var res = out.toByteArray(); - assertThat(res).isEqualTo(OzgUploadFileTestFactory.MULTIPART_FILE.getBytes()); + assertThat(res).isEqualTo(OzgUploadFileTestFactory.MULTIPART_FILE.getBytes()); + } } @Test - void shouldDownloadFileContentIoException() { - var out = mock(ByteArrayOutputStream.class); - doThrow(IOException.class).when(out).write(any(byte[].class), anyInt(), anyInt()); + void shouldThrowTechnicalException() throws IOException { + try (var authenticationHelper = mockStatic(AuthenticationHelper.class)) { + authenticationHelper.when(AuthenticationHelper::getSamlToken).thenReturn(UserTestFactory.SAML_TOKEN); + server.expect(requestTo(FILE_CONTENT_URI)) + .andRespond(withSuccess(OzgUploadFileTestFactory.MULTIPART_FILE.getBytes(), MediaType.APPLICATION_OCTET_STREAM)); + + var out = mock(ByteArrayOutputStream.class); + doThrow(IOException.class).when(out).write(any(byte[].class), anyInt(), anyInt()); + + assertThatExceptionOfType(TechnicalException.class).isThrownBy( + () -> fileRestClient.downloadFileContent(FILE_IDENTIFICATION_DATA, ADDRESS + GET_FILE_CONTENT_API, out)); + } + } - assertThatExceptionOfType(TechnicalException.class).isThrownBy( - () -> fileRestClient.downloadFileContent(FILE_ID, out, ADDRESS + GET_FILE_CONTENT_API)); + @Test + void shouldThrowRestClientException() { + try (var authenticationHelper = mockStatic(AuthenticationHelper.class)) { + authenticationHelper.when(AuthenticationHelper::getSamlToken).thenReturn(UserTestFactory.SAML_TOKEN); + server.expect(requestTo(FILE_CONTENT_URI)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR)); + + assertThatExceptionOfType(RestClientException.class).isThrownBy( + () -> fileRestClient.downloadFileContent(FILE_IDENTIFICATION_DATA, ADDRESS + GET_FILE_CONTENT_API, + mock(ByteArrayOutputStream.class))); + } } } } \ No newline at end of file diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java index e0b3260d71a1f8e1e5d49b4973c13d6364fb39be..7abb90873e0ec47906f26a79f3b012e3499cb057 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/FileServiceTest.java @@ -47,6 +47,8 @@ import de.ozgcloud.antragsraum.events.NachrichtEventService; import de.ozgcloud.antragsraum.events.NachrichtEventTestFactory; class FileServiceTest { + private static final FileIdentificationData FILE_IDENTIFICATION_DATA = FileIdentificationDataTestFactory.create(); + @Spy @InjectMocks private FileService fileService; @@ -111,13 +113,13 @@ class FileServiceTest { class TestLoadingFile { @BeforeEach void init() { - when(remoteService.getFile(anyString(), anyString())).thenReturn(OzgFileTestFactory.create()); + when(remoteService.getFile(any(FileIdentificationData.class), anyString())).thenReturn(OzgFileTestFactory.create()); when(nachrichtEventService.getNachrichtEventById(NACHRICHT_EVENT_ID)).thenReturn(NachrichtEventTestFactory.createNachrichtEvent()); } @Test void shouldGetFile() { - var file = fileService.getFile(FILE_ID, NACHRICHT_EVENT_ID); + var file = fileService.getFile(FILE_IDENTIFICATION_DATA); assertThat(file).isNotNull(); } @@ -132,9 +134,9 @@ class FileServiceTest { @Test void shouldCallRemoteService() { - fileService.downloadFileContent(FILE_ID, new ByteArrayOutputStream(), NACHRICHT_EVENT_ID); + fileService.downloadFileContent(FILE_IDENTIFICATION_DATA, new ByteArrayOutputStream()); - verify(remoteService).downloadFileContent(anyString(), any(OutputStream.class), anyString()); + verify(remoteService).downloadFileContent(any(FileIdentificationData.class), anyString(), any(OutputStream.class)); } } diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java index 3b5fe232aacaf64dc1bf70a2d92dc4908b4480e8..0bf371ff7788306ad627870860cc620d1de8e438 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileMapperTest.java @@ -27,40 +27,45 @@ import static org.assertj.core.api.Assertions.*; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcOzgFile; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcFileMetadata; class OzgFileMapperTest { + + private final OzgFileMapper mapper = Mappers.getMapper(OzgFileMapper.class); + @Nested class TestMappingGrpcOzgFile { - private final AntragraumproxyGrpcOzgFile grpcOzgFile = AntragraumproxyGrpcOzgFileTestFactory.create(); + private final AntragraumGrpcFileMetadata grpcOzgFile = AntragraumGrpcFileMetadataTestFactory.create(); @Test void shouldHaveFileName() { - var file = OzgFileMapper.fromRestFile(grpcOzgFile); + var file = mapper.fromGrpcFileMetadata(grpcOzgFile, FILE_ID); assertThat(file.fileName()).isEqualTo(FILE_NAME); } @Test void shouldHaveFileSize() { - var file = OzgFileMapper.fromRestFile(grpcOzgFile); + var file = mapper.fromGrpcFileMetadata(grpcOzgFile, FILE_ID); assertThat(file.fileSize()).isEqualTo(FILE_SIZE); } @Test void shouldHaveContentType() { - var file = OzgFileMapper.fromRestFile(grpcOzgFile); + var file = mapper.fromGrpcFileMetadata(grpcOzgFile, FILE_ID); assertThat(file.contentType()).isEqualTo(CONTENT_TYPE); } @Test void shouldHaveFileId() { - var file = OzgFileMapper.fromRestFile(grpcOzgFile); + var file = mapper.fromGrpcFileMetadata(grpcOzgFile, FILE_ID); assertThat(file.id()).isEqualTo(FILE_ID); } } + } \ No newline at end of file diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java index ffc89411660cadd3dc794c55980f0d9cac486f94..97c8a98d5f72da9a2e5c11f5f2fdafaee13cfb35 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/OzgFileTestFactory.java @@ -33,6 +33,7 @@ public class OzgFileTestFactory { static final String FILE_SIZE_STRING = String.valueOf(FILE_SIZE); static final String FILE_NAME = "Testfile.pdf"; static final String NACHRICHT_EVENT_ID = UUID.randomUUID().toString(); + static final String NACHRICHT_ID = UUID.randomUUID().toString(); static final String CHANNEL_ADDRESS = "static://localhost:9090"; static final byte[] DATA = "juhu, ein bild".getBytes(); diff --git a/server/src/test/java/de/ozgcloud/antragsraum/attachments/StubFileRestClient.java b/server/src/test/java/de/ozgcloud/antragsraum/attachments/StubFileRestClient.java index 5aafe992b948413218b9507f3b2830e74ff7d3b6..46a80b56b36b90c082fbe3948e98668bb4eeb0c4 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/attachments/StubFileRestClient.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/attachments/StubFileRestClient.java @@ -28,22 +28,22 @@ import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.CompletableFuture; -import de.ozgcloud.antragsraum.proxy.AntragraumproxyGrpcFindFilesResponse; +import de.ozgcloud.antragsraum.proxy.AntragraumGrpcGetAttachmentMetadataResponse; class StubFileRestClient extends FileRestClient { public StubFileRestClient() { super(null); } - public AntragraumproxyGrpcFindFilesResponse findBinaryFilesMetaData(String fileId, final String address) { - return AntragraumproxyGrpcFindFilesResponseTestFactory.create(); + public AntragraumGrpcGetAttachmentMetadataResponse getFileMetadata(FileIdentificationData fileIdentificationData, final String address) { + return AntragraumGrpcGetAttachmentMetadataResponseTestFactory.create(); } public void uploadFile(final OzgUploadFile uploadFile, final String address, final CompletableFuture<String> fileIdFuture) { fileIdFuture.complete(FILE_ID); } - public void downloadFileContent(final String fileId, final OutputStream out, final String address) { + public void downloadFileContent(FileIdentificationData fileIdentificationData, final String address, final OutputStream out) { try { out.write(OzgUploadFileTestFactory.MULTIPART_FILE.getBytes()); } catch (IOException e) { diff --git a/server/src/test/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapperTest.java b/server/src/test/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapperTest.java index 882721adbbcb05259680c8735c5f092b4624cec0..6b8a2aa6499b97fbf63eec72a15540f5dde22739 100644 --- a/server/src/test/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapperTest.java +++ b/server/src/test/java/de/ozgcloud/antragsraum/nachricht/NachrichtMapperTest.java @@ -35,6 +35,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import de.ozgcloud.antragsraum.attachments.FileIdentificationData; import de.ozgcloud.antragsraum.attachments.FileService; import de.ozgcloud.antragsraum.attachments.OzgFile; import de.ozgcloud.antragsraum.attachments.OzgFileTestFactory; @@ -64,7 +65,7 @@ class NachrichtMapperTest { @BeforeEach void setup() { - when(fileService.getFile(anyString(), anyString())).thenReturn(OzgFileTestFactory.create()); + lenient().when(fileService.getFile(any(FileIdentificationData.class))).thenReturn(OzgFileTestFactory.create()); } @Test @@ -148,7 +149,7 @@ class NachrichtMapperTest { @Test void shouldMapEmptyAttachments() { - when(fileService.getFile(anyString(), anyString())).thenReturn(null); + when(fileService.getFile(any(FileIdentificationData.class))).thenReturn(null); var nachricht = mapper.fromRestRueckfrage(AntragraumproxyGrpcRueckfrageTestFactory.createRueckfrage(), NachrichtTestFactory.NACHRICHT_EVENT_ID);