diff --git a/digiwf-apps/package-lock.json b/digiwf-apps/package-lock.json index 3629c08f8e..7c1155fd4f 100644 --- a/digiwf-apps/package-lock.json +++ b/digiwf-apps/package-lock.json @@ -3451,7 +3451,6 @@ }, "node_modules/ejs": { "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "dependencies": { @@ -11242,7 +11241,6 @@ }, "ejs": { "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "requires": { diff --git a/digiwf-apps/packages/components/digiwf-date-input/package-lock.json b/digiwf-apps/packages/components/digiwf-date-input/package-lock.json index c2e711d983..9fe1971d68 100644 --- a/digiwf-apps/packages/components/digiwf-date-input/package-lock.json +++ b/digiwf-apps/packages/components/digiwf-date-input/package-lock.json @@ -6260,10 +6260,6 @@ "version": "9.0.1", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], "bin": { "uuid": "dist/bin/uuid" } diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/legacy/dms/muc/domain/model/Vorgang.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/legacy/dms/muc/domain/model/Vorgang.java index 47a4343071..cd80ccb6e8 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/legacy/dms/muc/domain/model/Vorgang.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/legacy/dms/muc/domain/model/Vorgang.java @@ -41,6 +41,7 @@ public class Vorgang { * Art des Vortgangs. * Default ist ELEKTRONISCH */ + @Builder.Default private VorgangArt art = VorgangArt.ELEKTRONISCH; public Vorgang(final NeuerVorgang neuerVorgang, final String coo) { diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/config/domain/model/ProcessConfig.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/config/domain/model/ProcessConfig.java index 1ab9769caf..ad5ee5de28 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/config/domain/model/ProcessConfig.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/config/domain/model/ProcessConfig.java @@ -36,6 +36,7 @@ public class ProcessConfig { * Example: "admin@example.com,support@example.com" */ public static final String INCIDENT_NOTIFICATION_ADDRESSES = "app_incident_notification_addresses"; + public static final String APP_FILE_S3_SYNC_CONFIG = "app_file_s3_sync_config"; /** * key of the process config. diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/api/resource/ServiceStartFileRestController.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/api/resource/ServiceStartFileRestController.java index e2d21a4807..9838861427 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/api/resource/ServiceStartFileRestController.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/api/resource/ServiceStartFileRestController.java @@ -5,6 +5,7 @@ package de.muenchen.oss.digiwf.process.definition.api.resource; import de.muenchen.oss.digiwf.process.definition.domain.service.ServiceStartFileService; +import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.shared.file.presignedUrlAdapters.PresignedUrlAction; import de.muenchen.oss.digiwf.shared.security.AppAuthenticationProvider; import io.swagger.v3.oas.annotations.tags.Tag; @@ -39,12 +40,12 @@ public class ServiceStartFileRestController { * @return file names */ @GetMapping("/{definitionKey}") - public ResponseEntity> getFileNames(@PathVariable final String definitionKey, @RequestParam final String filePath) { + public ResponseEntity> getFileNames(@PathVariable final String definitionKey, @RequestParam final String filePath) + throws PropertyNotSetException { final List fileNames = this.serviceStartFileService.getFileNames( definitionKey, filePath, - this.authenticationProvider.getCurrentUserId(), - this.authenticationProvider.getCurrentUserGroups()); + this.authenticationProvider.getCurrentUserId()); return ResponseEntity.ok(fileNames); } @@ -57,14 +58,14 @@ public ResponseEntity> getFileNames(@PathVariable final String defi * @return presignedUrl */ @GetMapping("/{definitionKey}/{fileName}") - public ResponseEntity getPresignedUrlForFileDownload(@PathVariable final String definitionKey, @PathVariable final String fileName, @RequestParam final String filePath) { + public ResponseEntity getPresignedUrlForFileDownload(@PathVariable final String definitionKey, @PathVariable final String fileName, @RequestParam final String filePath) + throws PropertyNotSetException { final String presignedUrl = this.serviceStartFileService.getPresignedUrl( PresignedUrlAction.GET, definitionKey, filePath, fileName, - this.authenticationProvider.getCurrentUserId(), - this.authenticationProvider.getCurrentUserGroups()); + this.authenticationProvider.getCurrentUserId()); return ResponseEntity.ok(presignedUrl); } @@ -77,14 +78,14 @@ public ResponseEntity getPresignedUrlForFileDownload(@PathVariable final * @return presignedUrl */ @PostMapping("/{definitionKey}/{filename}") - public ResponseEntity getPresignedUrlForFileUpload(@PathVariable final String definitionKey, @PathVariable final String filename, @RequestParam final String filePath) { + public ResponseEntity getPresignedUrlForFileUpload(@PathVariable final String definitionKey, @PathVariable final String filename, @RequestParam final String filePath) + throws PropertyNotSetException { final String presignedUrls = this.serviceStartFileService.getPresignedUrl( PresignedUrlAction.POST, definitionKey, filePath, filename, - this.authenticationProvider.getCurrentUserId(), - this.authenticationProvider.getCurrentUserGroups()); + this.authenticationProvider.getCurrentUserId()); return ResponseEntity.ok(presignedUrls); } @@ -98,14 +99,14 @@ public ResponseEntity getPresignedUrlForFileUpload(@PathVariable final S */ //TODO I guess this should be only one url? @DeleteMapping("/{definitionKey}/{filename}") - public ResponseEntity getPresignedUrlForFileDeletion(@PathVariable final String definitionKey, @PathVariable final String filename, @RequestParam final String filePath) { + public ResponseEntity getPresignedUrlForFileDeletion(@PathVariable final String definitionKey, @PathVariable final String filename, @RequestParam final String filePath) + throws PropertyNotSetException { final String presignedUrl = this.serviceStartFileService.getPresignedUrl( PresignedUrlAction.DELETE, definitionKey, filePath, filename, - this.authenticationProvider.getCurrentUserId(), - this.authenticationProvider.getCurrentUserGroups()); + this.authenticationProvider.getCurrentUserId()); return ResponseEntity.ok(presignedUrl); } diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/domain/service/ServiceStartFileService.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/domain/service/ServiceStartFileService.java index 2c4d30ecf6..840826a1e2 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/domain/service/ServiceStartFileService.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/definition/domain/service/ServiceStartFileService.java @@ -6,9 +6,10 @@ import de.muenchen.oss.digiwf.process.config.domain.model.ProcessConfig; import de.muenchen.oss.digiwf.process.config.domain.service.ProcessConfigService; -import de.muenchen.oss.digiwf.process.config.process.ProcessConfigFunctions; import de.muenchen.oss.digiwf.process.definition.domain.model.StartContext; +import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.shared.exception.IllegalResourceAccessException; import de.muenchen.oss.digiwf.shared.exception.NoFileContextException; import de.muenchen.oss.digiwf.shared.file.AbstractFileService; @@ -34,26 +35,30 @@ public class ServiceStartFileService extends AbstractFileService { private final ServiceStartContextService serviceStartContextService; private final ProcessConfigService processConfigService; + private final S3StorageUrlProvider s3StorageUrlProvider; public ServiceStartFileService( final DocumentStorageFolderRepository documentStorageFolderRepository, final ServiceStartContextService serviceStartContextService, final ProcessConfigService processConfigService, final List presignedUrlAdapters, - final ProcessConfigFunctions processConfigFunctions + final S3StorageUrlProvider s3StorageUrlProvider ) { - super(documentStorageFolderRepository, presignedUrlAdapters, processConfigFunctions); + super(documentStorageFolderRepository, presignedUrlAdapters); this.serviceStartContextService = serviceStartContextService; this.processConfigService = processConfigService; + this.s3StorageUrlProvider = s3StorageUrlProvider; } - public List getFileNames(final String definitionKey, final String filePath, final String userId, final List groups) { + @Override + public List getFileNames(final String definitionKey, final String filePath, final String userId) throws PropertyNotSetException { this.checkReadAccess(definitionKey, filePath); final String fileContext = this.getFileContext(userId, definitionKey); - return super.getFileNames(filePath, fileContext, this.getDocumentStorageUrl(definitionKey)); + return super.getFileNames(filePath, fileContext, this.s3StorageUrlProvider.provideS3StorageUrl(definitionKey)); } - public String getPresignedUrl(final PresignedUrlAction action, final String definitionKey, final String filePath, final String fileName, final String userId, final List groups) { + public String getPresignedUrl(final PresignedUrlAction action, final String definitionKey, final String filePath, final String fileName, + final String userId) throws PropertyNotSetException { if (action.equals(PresignedUrlAction.GET)) { this.checkReadAccess(definitionKey, filePath); } else { @@ -61,7 +66,7 @@ public String getPresignedUrl(final PresignedUrlAction action, final String defi } final String fileContext = this.getFileContext(userId, definitionKey); - return super.getPresignedUrl(action, fileContext + "/" + filePath + "/" + fileName, this.getDocumentStorageUrl(definitionKey)); + return super.getPresignedUrl(action, fileContext + "/" + filePath + "/" + fileName, this.s3StorageUrlProvider.provideS3StorageUrl(definitionKey)); } //---------------------------------------- helper methods ---------------------------------------- // diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/api/resource/ServiceInstanceFileRestController.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/api/resource/ServiceInstanceFileRestController.java index 6e755b459a..323a7579a1 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/api/resource/ServiceInstanceFileRestController.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/api/resource/ServiceInstanceFileRestController.java @@ -5,6 +5,7 @@ package de.muenchen.oss.digiwf.process.instance.api.resource; import de.muenchen.oss.digiwf.process.instance.domain.service.ServiceInstanceFileService; +import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.shared.file.presignedUrlAdapters.PresignedUrlAction; import de.muenchen.oss.digiwf.shared.security.AppAuthenticationProvider; import io.swagger.v3.oas.annotations.tags.Tag; @@ -39,7 +40,8 @@ public class ServiceInstanceFileRestController { * @return file names */ @GetMapping("/{instanceId}") - public ResponseEntity> getFileNames(@PathVariable final String instanceId, @RequestParam final String filePath) { + public ResponseEntity> getFileNames(@PathVariable final String instanceId, @RequestParam final String filePath) + throws PropertyNotSetException { final List fileNames = this.serviceInstanceFileService.getFileNames( instanceId, filePath, @@ -56,7 +58,8 @@ public ResponseEntity> getFileNames(@PathVariable final String inst * @return presignedUrl */ @GetMapping("/{instanceId}/{fileName}") - public ResponseEntity getPresignedUrlForFileDownload(@PathVariable final String instanceId, @PathVariable final String fileName, @RequestParam final String filePath) { + public ResponseEntity getPresignedUrlForFileDownload(@PathVariable final String instanceId, @PathVariable final String fileName, @RequestParam final String filePath) + throws PropertyNotSetException { final String presignedUrl = this.serviceInstanceFileService.getPresignedUrl( PresignedUrlAction.GET, instanceId, @@ -75,7 +78,8 @@ public ResponseEntity getPresignedUrlForFileDownload(@PathVariable final * @return presignedUrl */ @PostMapping("/{instanceId}/{filename}") - public ResponseEntity getPresignedUrlForFileUpload(@PathVariable final String instanceId, @PathVariable final String filename, @RequestParam final String filePath) { + public ResponseEntity getPresignedUrlForFileUpload(@PathVariable final String instanceId, @PathVariable final String filename, @RequestParam final String filePath) + throws PropertyNotSetException { final String presignedUrls = this.serviceInstanceFileService.getPresignedUrl( PresignedUrlAction.POST, instanceId, @@ -94,7 +98,8 @@ public ResponseEntity getPresignedUrlForFileUpload(@PathVariable final S * @return presignedUrl */ @DeleteMapping("/{instanceId}/{filename}") - public ResponseEntity getPresignedUrlForFileDeletion(@PathVariable final String instanceId, @PathVariable final String filename, @RequestParam final String filePath) { + public ResponseEntity getPresignedUrlForFileDeletion(@PathVariable final String instanceId, @PathVariable final String filename, @RequestParam final String filePath) + throws PropertyNotSetException { final String presignedUrl = this.serviceInstanceFileService.getPresignedUrl( PresignedUrlAction.DELETE, instanceId, diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/domain/service/ServiceInstanceFileService.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/domain/service/ServiceInstanceFileService.java index b931dddc01..1589211e71 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/domain/service/ServiceInstanceFileService.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/process/instance/domain/service/ServiceInstanceFileService.java @@ -8,7 +8,9 @@ import de.muenchen.oss.digiwf.process.config.domain.service.ProcessConfigService; import de.muenchen.oss.digiwf.process.config.process.ProcessConfigFunctions; import de.muenchen.oss.digiwf.process.instance.domain.model.ServiceInstance; +import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.shared.exception.IllegalResourceAccessException; import de.muenchen.oss.digiwf.shared.file.AbstractFileService; import de.muenchen.oss.digiwf.shared.file.presignedUrlAdapters.PresignedUrlAction; @@ -34,6 +36,7 @@ public class ServiceInstanceFileService extends AbstractFileService { private final ServiceInstanceService serviceInstanceService; private final ServiceInstanceDataService serviceInstanceDataService; private final ServiceInstanceAuthService serviceInstanceAuthService; + private final S3StorageUrlProvider s3StorageUrlProvider; public ServiceInstanceFileService( final DocumentStorageFolderRepository documentStorageFolderRepository, @@ -42,16 +45,17 @@ public ServiceInstanceFileService( final ServiceInstanceDataService serviceInstanceDataService, final ServiceInstanceAuthService serviceInstanceAuthService, final ProcessConfigService processConfigService, - final ProcessConfigFunctions processConfigFunctions + final S3StorageUrlProvider s3StorageUrlProvider ) { - super(documentStorageFolderRepository, presignedUrlAdapters, processConfigFunctions); + super(documentStorageFolderRepository, presignedUrlAdapters); this.serviceInstanceService = serviceInstanceService; this.processConfigService = processConfigService; this.serviceInstanceDataService = serviceInstanceDataService; this.serviceInstanceAuthService = serviceInstanceAuthService; + this.s3StorageUrlProvider = s3StorageUrlProvider; } - public List getFileNames(final String infoId, final String filePath, final String userId) { + public List getFileNames(final String infoId, final String filePath, final String userId) throws PropertyNotSetException { final ServiceInstance processInstance = this.getProcessInstanceId(infoId); final String processInstanceId = processInstance.getInstanceId(); if (!this.serviceInstanceAuthService.hasAccess(processInstanceId, userId)) { @@ -60,10 +64,11 @@ public List getFileNames(final String infoId, final String filePath, fin this.checkReadAccess(processInstanceId, filePath); final String fileContext = this.getFileContext(processInstanceId); - return super.getFileNames(filePath, fileContext, this.getDocumentStorageUrl(processInstance.getDefinitionKey())); + return super.getFileNames(filePath, fileContext, s3StorageUrlProvider.provideS3StorageUrl(processInstance.getDefinitionKey())); } - public String getPresignedUrl(final PresignedUrlAction action, final String infoId, final String filePath, final String fileName, final String userId) { + public String getPresignedUrl(final PresignedUrlAction action, final String infoId, final String filePath, final String fileName, final String userId) + throws PropertyNotSetException { final ServiceInstance processInstance = this.getProcessInstanceId(infoId); final String processInstanceId = processInstance.getInstanceId(); if (!this.serviceInstanceAuthService.hasAccess(processInstanceId, userId)) { @@ -77,7 +82,7 @@ public String getPresignedUrl(final PresignedUrlAction action, final String info } final String fileContext = this.getFileContext(processInstanceId); - return super.getPresignedUrl(action, fileContext + "/" + filePath + "/" + fileName, this.getDocumentStorageUrl(processInstance.getDefinitionKey())); + return super.getPresignedUrl(action, fileContext + "/" + filePath + "/" + fileName, this.s3StorageUrlProvider.provideS3StorageUrl(processInstance.getDefinitionKey())); } //---------------------------------------- helper methods ---------------------------------------- // diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/AbstractFileService.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/AbstractFileService.java index de6f5ff76b..3dc9c03a1b 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/AbstractFileService.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/AbstractFileService.java @@ -1,6 +1,6 @@ package de.muenchen.oss.digiwf.shared.file; -import de.muenchen.oss.digiwf.process.config.process.ProcessConfigFunctions; +import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; import de.muenchen.oss.digiwf.shared.file.presignedUrlAdapters.PresignedUrlAction; import de.muenchen.oss.digiwf.shared.file.presignedUrlAdapters.PresignedUrlAdapter; @@ -11,7 +11,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; /** * General logic for handling file storage. @@ -26,54 +25,42 @@ public abstract class AbstractFileService { protected final DocumentStorageFolderRepository documentStorageFolderRepository; private final List presignedUrlAdapters; - private final ProcessConfigFunctions processConfigFunctions; public AbstractFileService( final DocumentStorageFolderRepository documentStorageFolderRepository, - final List presignedUrlAdapters, - final ProcessConfigFunctions processConfigFunctions + final List presignedUrlAdapters ) { this.documentStorageFolderRepository = documentStorageFolderRepository; this.presignedUrlAdapters = presignedUrlAdapters; - this.processConfigFunctions = processConfigFunctions; } - public List getFileNames(final String filePath, final String fileContext, final Optional documentStorageUrl) { + public List getFileNames(final String filePath, final String fileContext, final String documentStorageUrl) throws PropertyNotSetException { try { final String pathToFolder = fileContext + "/" + filePath; - if (documentStorageUrl.isPresent()) { - return this.extractFilenamesFromFolder(this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, documentStorageUrl.get()).block(), pathToFolder); - } - return this.extractFilenamesFromFolder(this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder).block(), pathToFolder); + return this.extractFilenamesFromFolder( + this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, documentStorageUrl).block(), pathToFolder); } catch (final Exception ex) { log.error("Getting all files of folder {} failed: {}", filePath, ex); throw new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, String.format("Getting all files of folder %s failed", filePath)); } } - protected String getPresignedUrl(final PresignedUrlAction action, final String pathToFile, final Optional documentStorageUrl) { + protected String getPresignedUrl(final PresignedUrlAction action, final String pathToFile, final String documentStorageUrl) { final Optional handler = this.presignedUrlAdapters.stream() .filter(h -> h.isResponsibleForAction(action)) .findAny(); if (handler.isPresent()) { - if (documentStorageUrl.isPresent()) { - return handler.get().getPresignedUrl(documentStorageUrl.get(), pathToFile, 5); - } - return handler.get().getPresignedUrl(pathToFile, 5); + return handler.get().getPresignedUrl(documentStorageUrl, pathToFile, 5); } log.warn("No handler specified for action {}", action); throw new RuntimeException(String.format("No handler specified for action %s", action)); } - protected Optional getDocumentStorageUrl(final String definitionKey) { - return this.processConfigFunctions.get("app_file_s3_sync_config", definitionKey); - } - //---------------------------------------- helper methods ---------------------------------------- // /** - * Extract the filenames from the given file list. Make sure that only filenames for files in the given folder are returned. - * Don't return filenames for files in subfolders. + * Extract the filenames from the given file list. Make sure that only filenames for files in the given folder are returned. Don't return filenames for + * files in subfolders. * * @param fileList * @param pathToFolder diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/S3Configuration.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/S3Configuration.java index b073e877dc..a16e874333 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/S3Configuration.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/S3Configuration.java @@ -1,6 +1,10 @@ package de.muenchen.oss.digiwf.shared.file; +import de.muenchen.oss.digiwf.process.config.domain.model.ProcessConfig; +import de.muenchen.oss.digiwf.process.config.process.ProcessConfigFunctions; import de.muenchen.oss.digiwf.s3.integration.client.ApiClient; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3DomainProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -13,7 +17,7 @@ * @author martin.dietrich */ @Configuration -@ComponentScan(basePackages = {"de.muenchen.oss.digiwf.s3.integration.client"}) +@ComponentScan(basePackages = { "de.muenchen.oss.digiwf.s3.integration.client" }) public class S3Configuration { /** * Provides the {@link RestTemplate} which is used in {@link ApiClient}. @@ -21,6 +25,7 @@ public class S3Configuration { * @return the {@link RestTemplate}. */ @Bean + @ConditionalOnMissingBean public RestTemplate restTemplate() { /* * Add {@link HttpComponentsClientHttpRequestFactory} to rest template to allow @@ -28,4 +33,16 @@ public RestTemplate restTemplate() { */ return new RestTemplate(new HttpComponentsClientHttpRequestFactory()); } + + /** + * Constructs an {@link S3DomainProvider} instance specifically tailored for the engine to retrieve the domain-specific S3 storage URL for a given process + * if its process configuration contains a value for {@link ProcessConfig#APP_FILE_S3_SYNC_CONFIG}. + * + * @param processConfigFunctions {@link ProcessConfigFunctions} offers access to a process configuration for a given process definition id. + * @return S3DomainProvider {@link S3DomainProvider} that retrieves the domain-specific S3 storage url for a process if configured. + */ + @Bean + public S3DomainProvider s3DomainProvider(final ProcessConfigFunctions processConfigFunctions) { + return processDefinitionId -> processConfigFunctions.get(ProcessConfig.APP_FILE_S3_SYNC_CONFIG, processDefinitionId); + } } diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/DeletePresignedUrlAdapter.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/DeletePresignedUrlAdapter.java index ea1692cf03..bdf6dab5cb 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/DeletePresignedUrlAdapter.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/DeletePresignedUrlAdapter.java @@ -1,6 +1,5 @@ package de.muenchen.oss.digiwf.shared.file.presignedUrlAdapters; -import de.muenchen.oss.digiwf.process.instance.process.properties.S3Properties; import de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl.PresignedUrlRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,13 +18,6 @@ public class DeletePresignedUrlAdapter implements PresignedUrlAdapter { private final PresignedUrlRepository presignedUrlRepository; - private final S3Properties s3Properties; - - - @Override - public String getPresignedUrl(final String pathToFile, final int expireInMinutes) throws HttpServerErrorException { - return this.getPresignedUrl(this.s3Properties.getHttpAPI(), pathToFile, expireInMinutes); - } @Override public String getPresignedUrl(final String documentStorageUrl, final String pathToFile, final int expireInMinutes) { diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/GetPresignedUrlAdapter.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/GetPresignedUrlAdapter.java index 646a986721..a1b4eec68a 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/GetPresignedUrlAdapter.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/GetPresignedUrlAdapter.java @@ -19,13 +19,6 @@ public class GetPresignedUrlAdapter implements PresignedUrlAdapter { private final PresignedUrlRepository presignedUrlRepository; - private final S3Properties s3Properties; - - - @Override - public String getPresignedUrl(final String pathToFile, final int expireInMinutes) throws HttpServerErrorException { - return this.getPresignedUrl(this.s3Properties.getHttpAPI(), pathToFile, expireInMinutes); - } @Override public String getPresignedUrl(final String documentStorageUrl, final String pathToFile, final int expireInMinutes) throws HttpServerErrorException { diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PostPresignedUrlAdapter.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PostPresignedUrlAdapter.java index bd05772693..aab9868497 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PostPresignedUrlAdapter.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PostPresignedUrlAdapter.java @@ -20,13 +20,6 @@ public class PostPresignedUrlAdapter implements PresignedUrlAdapter { private final PresignedUrlRepository presignedUrlRepository; - private final S3Properties s3Properties; - - - @Override - public String getPresignedUrl(final String pathToFile, final int expireInMinutes) throws HttpServerErrorException { - return this.getPresignedUrl(this.s3Properties.getHttpAPI(), pathToFile, expireInMinutes); - } @Override public String getPresignedUrl(final String documentStorageUrl, final String pathToFile, final int expireInMinutes) throws HttpServerErrorException { diff --git a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PresignedUrlAdapter.java b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PresignedUrlAdapter.java index 4c3f1ea895..2c677bffde 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PresignedUrlAdapter.java +++ b/digiwf-engine/digiwf-engine-service/src/main/java/de/muenchen/oss/digiwf/shared/file/presignedUrlAdapters/PresignedUrlAdapter.java @@ -9,16 +9,6 @@ */ public interface PresignedUrlAdapter { - /** - * Obtain a presigned url from the default s3 integration service. The default s3 service is specified as property digiwf.s3.url. - * - * @param pathToFile - * @param expireInMinutes specifies how long the presigned url will be valid - * @return - * @throws HttpServerErrorException - */ - String getPresignedUrl(final String pathToFile, final int expireInMinutes) throws HttpServerErrorException; - /** * Obtain a presigned url from the specified s3 integration service * diff --git a/digiwf-engine/digiwf-engine-service/src/main/resources/application.yml b/digiwf-engine/digiwf-engine-service/src/main/resources/application.yml index 2f59456535..4ee916c77d 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/resources/application.yml +++ b/digiwf-engine/digiwf-engine-service/src/main/resources/application.yml @@ -198,7 +198,13 @@ io: digiwf: mail: fromAddress: ${MAIL_USERNAME:digiwf@muenchen.de} - s3: - client: - documentStorageUrl: '${digiwf.s3service.httpAPI}' - securityEnabled: true + +de: + muenchen: + oss: + digiwf: + s3: + client: + document-storage-url: '${digiwf.s3service.httpAPI}' + enable-security: true + diff --git a/digiwf-engine/digiwf-engine-service/src/main/resources/prozesse/example/timer-event/check-timer-form.schema.json b/digiwf-engine/digiwf-engine-service/src/main/resources/prozesse/example/timer-event/check-timer-form.schema.json index 6dd191912a..8a04d4544f 100644 --- a/digiwf-engine/digiwf-engine-service/src/main/resources/prozesse/example/timer-event/check-timer-form.schema.json +++ b/digiwf-engine/digiwf-engine-service/src/main/resources/prozesse/example/timer-event/check-timer-form.schema.json @@ -1,47 +1,48 @@ { - "type": "object", - "x-display": "stepper", - "allOf": [ - { - "key": "sectionKey1", - "title": "Erster Abschnitt", - "type": "object", - "x-options": { - "sectionsTitlesClasses": [ - "d-none" - ] - }, - "allOf": [ - { - "key": "feldgruppe1", - "title": "Erste Gruppe", - "type": "object", - "x-options": { - "childrenClass": "pr-5 pl-0" - }, - "properties": { - "app_process_start_date": { - "fieldType": "text", - "title": "Start-Zeit", - "type": "string", - "key": "app_process_start_date", - "readOnly": true, - "x-options": { - "fieldColProps": { - "cols": 12, - "sm": 12 + "key": "check-timer-form", + "schema": { + "type": "object", + "x-display": " ", + "allOf": [ + { + "key": "sectionKey1", + "title": "Erster Abschnitt", + "type": "object", + "x-options": { + "sectionsTitlesClasses": [ + "d-none" + ] + }, + "allOf": [ + { + "type": "object", + "key": "4ee909e5-9901-4e84-8e2b-0b9fd3142e8e", + "title": "", + "x-options": { + "childrenClass": "pr-5 pl-0" + }, + "properties": { + "message": { + "type": "string", + "title": "Message", + "key": "message", + "x-props": { + "outlined": true, + "dense": true + }, + "x-options": { + "fieldColProps": { + "messages": {} + } }, - "messages": {} - }, - "x-props": { - "outlined": true, - "dense": false - }, - "x-rules": [] + "x-rules": [ + "required" + ] + } } } - } - ] - } - ] -} \ No newline at end of file + ] + } + ] + } +} diff --git a/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-core/src/main/java/de/muenchen/oss/digiwf/cosys/integration/application/port/in/CreateDocumentInPort.java b/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-core/src/main/java/de/muenchen/oss/digiwf/cosys/integration/application/port/in/CreateDocumentInPort.java index 6ab3e58722..d061bca3e2 100644 --- a/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-core/src/main/java/de/muenchen/oss/digiwf/cosys/integration/application/port/in/CreateDocumentInPort.java +++ b/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-core/src/main/java/de/muenchen/oss/digiwf/cosys/integration/application/port/in/CreateDocumentInPort.java @@ -5,6 +5,6 @@ public interface CreateDocumentInPort { - void createDocument(final String processInstanceIde, final String type, final String integrationName, @Valid final GenerateDocument generateDocument); + void createDocument(final String processInstanceId, final String type, final String integrationName, @Valid final GenerateDocument generateDocument); } diff --git a/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-service/src/main/resources/application.yml b/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-service/src/main/resources/application.yml index b81822e5b5..56436df37e 100644 --- a/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-service/src/main/resources/application.yml +++ b/digiwf-integrations/digiwf-cosys-integration/digiwf-cosys-integration-service/src/main/resources/application.yml @@ -14,9 +14,14 @@ io: inputLanguage: Deutsch outputLanguage: Deutsch keepFields: unresolved-ref - s3: - client: - documentStorageUrl: '${DIGIWF_S3_HTTPAPI:http://localhost:8086}' + +de: + muenchen: + oss: + digiwf: + s3: + client: + document-storage-url: '${DIGIWF_S3_HTTPAPI:http://localhost:8086}' management: endpoint: diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/pom.xml b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/pom.xml index e0014d5e21..3f4fab8681 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/pom.xml +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/pom.xml @@ -29,20 +29,13 @@ de.muenchen.oss.digiwf - digiwf-spring-security-starter + digiwf-process-starter ${project.version} - - - - org.apache.tika - tika-core - ${tika.version} - - org.apache.tika - tika-parsers-standard-package - ${tika.version} + de.muenchen.oss.digiwf + digiwf-spring-security-starter + ${project.version} diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessor.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessor.java index 07f648ffc9..5d37d142c4 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessor.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessor.java @@ -97,7 +97,8 @@ public Consumer> createDocument() { createDocumentDto.getUser(), DocumentType.valueOf(createDocumentDto.getType()), createDocumentDto.getFilepathsAsList(), - createDocumentDto.getFileContext() + createDocumentDto.getFileContext(), + message.getHeaders().get(DIGIWF_PROCESS_DEFINITION).toString() ); this.correlateMessage(message.getHeaders().get(DIGIWF_PROCESS_INSTANCE_ID).toString(), @@ -116,7 +117,8 @@ public Consumer> updateDocument() { updateDocumentDto.getUser(), DocumentType.valueOf(updateDocumentDto.getType()), updateDocumentDto.getFilepathsAsList(), - updateDocumentDto.getFileContext() + updateDocumentDto.getFileContext(), + message.getHeaders().get(DIGIWF_PROCESS_DEFINITION).toString() ); this.correlateMessage(message.getHeaders().get(DIGIWF_PROCESS_INSTANCE_ID).toString(), @@ -150,7 +152,8 @@ public Consumer> readContent() { readContentDto.getContentCoos(), readContentDto.getUser(), readContentDto.getFilePath(), - readContentDto.getFileContext() + readContentDto.getFileContext(), + message.getHeaders().get(DIGIWF_PROCESS_DEFINITION).toString() ); this.correlateMessage(message.getHeaders().get(DIGIWF_PROCESS_INSTANCE_ID).toString(), message.getHeaders().get(TYPE).toString(), diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3Adapter.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3Adapter.java index c0eac4753e..6e51467265 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3Adapter.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3Adapter.java @@ -10,89 +10,94 @@ import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFileRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.val; import org.apache.commons.io.FilenameUtils; -import org.apache.tika.Tika; import java.util.ArrayList; import java.util.List; -import java.util.Map; +import java.util.Objects; import java.util.Set; @Slf4j @RequiredArgsConstructor public class S3Adapter implements LoadFileOutPort, TransferContentOutPort { - private final DocumentStorageFileRepository documentStorageFileRepository; + private static final String LOAD_FOLDER_FAILED = "LOAD_FOLDER_FAILED"; + private final DocumentStorageFileRepository documentStorageFileRepository; private final DocumentStorageFolderRepository documentStorageFolderRepository; - - private final Map supportedExtensions; + private final FileExtensionService fileExtensionService; + private final S3StorageUrlProvider s3DomainService; @Override - public List loadFiles(final List filepaths, final String fileContext) { - - List contents = new ArrayList<>(); - + public List loadFiles(final List filepaths, final String fileContext, final String processDefinition) { + final String s3Storage; + try { + s3Storage = s3DomainService.provideS3StorageUrl(processDefinition); + } catch (final PropertyNotSetException e) { + throw new BpmnError(LOAD_FOLDER_FAILED, e.getMessage()); + } + final List contents = new ArrayList<>(); filepaths.forEach(path -> { - String fullPath = fileContext + "/" + path; + final String fullPath = fileContext + "/" + path; if (fullPath.endsWith("/")) { - contents.addAll(getFilesFromFolder(fullPath)); + contents.addAll(getFilesFromFolder(fullPath, s3Storage)); } else { - contents.add(getFile(fullPath)); + contents.add(getFile(fullPath, s3Storage)); } }); - return contents; - } - private List getFilesFromFolder(String folderpath) { + private List getFilesFromFolder(String folderpath, final String domainSpecificS3Storage) { try { - List contents = new ArrayList<>(); - Set filepath = documentStorageFolderRepository.getAllFilesInFolderRecursively(folderpath).block(); - filepath.forEach(file -> { - contents.add(getFile(file)); - }); + final List contents = new ArrayList<>(); + final Set filepath; + filepath = documentStorageFolderRepository.getAllFilesInFolderRecursively(folderpath, domainSpecificS3Storage).block(); + if (Objects.isNull(filepath)) throw new BpmnError(LOAD_FOLDER_FAILED, "An folder could not be loaded from url: " + folderpath); + filepath.forEach(file -> contents.add(getFile(file, domainSpecificS3Storage))); return contents; - } catch (final DocumentStorageException | DocumentStorageServerErrorException | - DocumentStorageClientErrorException | PropertyNotSetException e) { - throw new BpmnError("LOAD_FOLDER_FAILED", "An folder could not be loaded from url: " + folderpath); + } catch (final DocumentStorageException | DocumentStorageServerErrorException | DocumentStorageClientErrorException e) { + throw new BpmnError(LOAD_FOLDER_FAILED, "An folder could not be loaded from url: " + folderpath); } } - private Content getFile(String filepath) { + private Content getFile(String filepath, final String domainSpecificS3Storage) { try { - final Tika tika = new Tika(); - final byte[] bytes = this.documentStorageFileRepository.getFile(filepath, 3); - final String type = tika.detect(bytes); + final byte[] bytes; + bytes = this.documentStorageFileRepository.getFile(filepath, 3, domainSpecificS3Storage); + final String mimeType = fileExtensionService.detectFileType(bytes); final String filename = FilenameUtils.getBaseName(filepath); + // check if mimeType exists + if (!fileExtensionService.isSupported(mimeType)) + throw new BpmnError("FILE_TYPE_NOT_SUPPORTED", "The type of this file is not supported: " + filepath); - final String extension = supportedExtensions.entrySet() - .stream() - .filter(set -> set.getValue().equals(type)) - .findFirst() - .map(Map.Entry::getKey) - .orElseThrow(() -> new BpmnError("FILE_TYPE_NOT_SUPPORTED", "The type of this file is not supported: " + filepath)); - - return new Content(extension, filename, bytes); - - } catch (final DocumentStorageException | DocumentStorageServerErrorException | - DocumentStorageClientErrorException | PropertyNotSetException e) { + return new Content(fileExtensionService.getFileExtension(mimeType), filename, bytes); + } catch (final DocumentStorageException | DocumentStorageServerErrorException | DocumentStorageClientErrorException e) { throw new BpmnError("LOAD_FILE_FAILED", "An file could not be loaded from url: " + filepath); } } @Override - public void transferContent(List content, String filepath, String fileContext) { + public void transferContent(final List content, final String filepath, final String fileContext, final String processDefinitionId) { + final String s3Storage; + try { + s3Storage = s3DomainService.provideS3StorageUrl(processDefinitionId); + } catch (final PropertyNotSetException e) { + throw new BpmnError("SAVE_FILE_FAILED", e.getMessage()); + } + val fullPath = fileContext + "/" + filepath; for (val file : content) { try { - this.documentStorageFileRepository.saveFile(fullPath + "/" + file.getName() + "." + file.getExtension(), file.getContent(), 1, null); + this.documentStorageFileRepository.saveFile(fullPath + "/" + file.getName() + "." + file.getExtension(), file.getContent(), 1, null, + s3Storage); } catch (Exception e) { throw new BpmnError("SAVE_FILE_FAILED", "An file could not be saved to path: " + fullPath); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/CreateDocumentInPort.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/CreateDocumentInPort.java index 47f69de52c..6551c6b43f 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/CreateDocumentInPort.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/CreateDocumentInPort.java @@ -7,6 +7,7 @@ public interface CreateDocumentInPort { - String createDocument(final String procedureCOO, final String title, final LocalDate date, final String user, DocumentType type, final List filepaths, final String fileContext); + String createDocument(final String procedureCOO, final String title, final LocalDate date, final String user, DocumentType type, + final List filepaths, final String fileContext, final String processDefinition); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/ReadContentInPort.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/ReadContentInPort.java index 9eca5adee2..3c6594c569 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/ReadContentInPort.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/ReadContentInPort.java @@ -6,6 +6,7 @@ public interface ReadContentInPort { - void readContent(List fileCoos, @NotBlank String user, @NotBlank String filePath, @NotBlank String fileContext); + void readContent(List fileCoos, @NotBlank String user, @NotBlank String filePath, @NotBlank String fileContext, + @NotBlank String processDefinitionId); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/UpdateDocumentInPort.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/UpdateDocumentInPort.java index 299fba5b1a..44576ba6f5 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/UpdateDocumentInPort.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/in/UpdateDocumentInPort.java @@ -6,6 +6,6 @@ public interface UpdateDocumentInPort { - void updateDocument(final String documentCOO, final String user, DocumentType type, final List filepaths, final String fileContext); + void updateDocument(String documentCOO, String user, DocumentType type, List filepaths, String fileContext, String processDefinition); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/LoadFileOutPort.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/LoadFileOutPort.java index 000e735ab8..c6a1127f1f 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/LoadFileOutPort.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/LoadFileOutPort.java @@ -6,6 +6,6 @@ public interface LoadFileOutPort { - List loadFiles(final List filepaths, final String fileContext); + List loadFiles(List filepaths, String fileContext, String processDefinition); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/TransferContentOutPort.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/TransferContentOutPort.java index 91dc9815f3..efe6e99cf9 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/TransferContentOutPort.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/port/out/TransferContentOutPort.java @@ -6,6 +6,6 @@ public interface TransferContentOutPort { - void transferContent(List content, final String filepath, final String fileContext); + void transferContent(List content, String filepath, String fileContext, String processDefinition); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCase.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCase.java index 1bac508a9a..ca83707ced 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCase.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCase.java @@ -28,10 +28,11 @@ public String createDocument( final String user, final DocumentType type, final List filepaths, - final String fileContext + final String fileContext, + final String processDefinition ) { - final List contents = loadFileOutPort.loadFiles(filepaths, fileContext); + final List contents = loadFileOutPort.loadFiles(filepaths, fileContext, processDefinition); final Document document = new Document(procedureCOO, title, date, type, contents); diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCase.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCase.java index b12d561c14..4520ac5f2c 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCase.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCase.java @@ -22,8 +22,9 @@ public void readContent( final List contentCoos, @NotBlank final String user, @NotBlank final String filePath, - @NotBlank final String fileContext) { + @NotBlank final String fileContext, + @NotBlank final String processDefinitionId) { val content = readContentOutPort.readContent(contentCoos, user); - transferContentOutPort.transferContent(content, filePath, fileContext); + transferContentOutPort.transferContent(content, filePath, fileContext, processDefinitionId); } } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCase.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCase.java index 79dcade178..d0e857de3e 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCase.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/main/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCase.java @@ -24,10 +24,11 @@ public void updateDocument( final String user, final DocumentType type, final List filepaths, - final String fileContext + final String fileContext, + final String processDefinition ) { - final List contents = loadFileOutPort.loadFiles(filepaths, fileContext); + final List contents = loadFileOutPort.loadFiles(filepaths, fileContext, processDefinition); updateDocumentOutPort.updateDocument(documentCOO, type, contents, user); diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/CreateDocumentMessageProcessorTest.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/CreateDocumentMessageProcessorTest.java index 327293e2a5..35cd747cf2 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/CreateDocumentMessageProcessorTest.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/CreateDocumentMessageProcessorTest.java @@ -3,6 +3,7 @@ import de.muenchen.oss.digiwf.dms.integration.domain.DocumentType; import de.muenchen.oss.digiwf.message.process.api.error.IncidentError; import jakarta.validation.ValidationException; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -42,16 +43,19 @@ void setup() { createDocumentDto.getUser(), DocumentType.valueOf(createDocumentDto.getType()), createDocumentDto.getFilepathsAsList(), - createDocumentDto.getFileContext())) + createDocumentDto.getFileContext(), + processDefinitionId)) .thenReturn("documentCOO"); this.message = new Message<>() { + @NotNull @Override public CreateDocumentDto getPayload() { return createDocumentDto; } + @NotNull @Override public MessageHeaders getHeaders() { return messageHeaders; @@ -69,24 +73,26 @@ void testDmsIntegrationCreateDocumentSuccessfully() { createDocumentDto.getUser(), DocumentType.valueOf(createDocumentDto.getType()), createDocumentDto.getFilepathsAsList(), - createDocumentDto.getFileContext()); + createDocumentDto.getFileContext(), + processDefinitionId); } @Test void testDmsIntegrationCreateDocumentHandlesValidationException() { - Mockito.doThrow(new ValidationException("Test ValidationException")).when(createDocumentInPortMock).createDocument(any(), any(), any(), any(), any(), any(), any()); + Mockito.doThrow(new ValidationException("Test ValidationException")).when(createDocumentInPortMock) + .createDocument(any(), any(), any(), any(), any(), any(), any(), any()); messageProcessor.createDocument().accept(this.message); - final ArgumentCaptor messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); + final ArgumentCaptor> messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); verify(errorApiMock, times(1)).handleIncident(messageHeaderArgumentCaptor.capture(), any(IncidentError.class)); Assertions.assertTrue(messageHeaderArgumentCaptor.getValue().containsKey(DIGIWF_PROCESS_INSTANCE_ID)); } - @Test void testDmsCreateDocumentIntegrationHandlesIncidentError() { - Mockito.doThrow(new IncidentError("Error Message")).when(createDocumentInPortMock).createDocument(any(), any(), any(), any(), any(), any(), any()); + Mockito.doThrow(new IncidentError("Error Message")).when(createDocumentInPortMock) + .createDocument(any(), any(), any(), any(), any(), any(), any(), any()); messageProcessor.createDocument().accept(this.message); - final ArgumentCaptor messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); + final ArgumentCaptor> messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); verify(errorApiMock, times(1)).handleIncident(messageHeaderArgumentCaptor.capture(), any(IncidentError.class)); Assertions.assertTrue(messageHeaderArgumentCaptor.getValue().containsKey(DIGIWF_PROCESS_INSTANCE_ID)); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessorTestBase.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessorTestBase.java index 7ebd7c7924..af6f1fa502 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessorTestBase.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/MessageProcessorTestBase.java @@ -23,7 +23,10 @@ class MessageProcessorTestBase { protected final SearchFileInPort searchFileInPort = Mockito.mock(SearchFileInPort.class); protected final SearchSubjectAreaInPort searchSubjectAreaInPort = Mockito.mock(SearchSubjectAreaInPort.class); protected final String processInstanceId = "exampleProcessInstanceId"; - protected final MessageHeaders messageHeaders = new MessageHeaders(Map.of(DIGIWF_PROCESS_INSTANCE_ID, this.processInstanceId, DIGIWF_INTEGRATION_NAME, "dmsIntegration", TYPE, "type")); + protected final String processDefinitionId = "exampleProcessDefinitionId"; + protected final MessageHeaders messageHeaders = new MessageHeaders( + Map.of(DIGIWF_PROCESS_INSTANCE_ID, this.processInstanceId, DIGIWF_INTEGRATION_NAME, "dmsIntegration", TYPE, "type", DIGIWF_PROCESS_DEFINITION, + processDefinitionId)); protected MessageProcessor messageProcessor; protected void setupBase() { @@ -41,4 +44,3 @@ protected void setupBase() { searchSubjectAreaInPort); } } - diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/ReadContentMessageProcessorTest.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/ReadContentMessageProcessorTest.java index ffb924aa6e..f48cb5f449 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/ReadContentMessageProcessorTest.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/ReadContentMessageProcessorTest.java @@ -28,7 +28,8 @@ void setup() { readContentDto.getContentCoos(), readContentDto.getUser(), readContentDto.getFilePath(), - readContentDto.getFileContext()); + readContentDto.getFileContext(), + processDefinitionId); this.message = new Message<>() { @@ -51,7 +52,8 @@ void testDmsIntegrationReadContentSuccessfully() { readContentDto.getContentCoos(), readContentDto.getUser(), readContentDto.getFilePath(), - readContentDto.getFileContext()); + readContentDto.getFileContext(), + processDefinitionId); } } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/UpdateDocumentMessageProcessorTest.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/UpdateDocumentMessageProcessorTest.java index e398407e33..46d5910423 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/UpdateDocumentMessageProcessorTest.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/in/UpdateDocumentMessageProcessorTest.java @@ -3,6 +3,7 @@ import de.muenchen.oss.digiwf.dms.integration.domain.DocumentType; import de.muenchen.oss.digiwf.message.process.api.error.IncidentError; import jakarta.validation.ValidationException; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -37,15 +38,18 @@ void setup() { updateDocumentDto.getUser(), DocumentType.valueOf(updateDocumentDto.getType()), updateDocumentDto.getFilepathsAsList(), - updateDocumentDto.getFileContext()); - + updateDocumentDto.getFileContext(), + processDefinitionId); this.message = new Message<>() { + + @NotNull @Override public UpdateDocumentDto getPayload() { return updateDocumentDto; } + @NotNull @Override public MessageHeaders getHeaders() { return messageHeaders; @@ -61,24 +65,25 @@ void testDmsIntegrationUpdateDocumentSuccessfully() { updateDocumentDto.getUser(), DocumentType.valueOf(updateDocumentDto.getType()), updateDocumentDto.getFilepathsAsList(), - updateDocumentDto.getFileContext()); + updateDocumentDto.getFileContext(), + processDefinitionId); } @Test void testDmsIntegrationUpdateDocumentHandlesValidationException() { - Mockito.doThrow(new ValidationException("Test ValidationException")).when(updateDocumentInPortMock).updateDocument(any(), any(), any(), any(), any()); + Mockito.doThrow(new ValidationException("Test ValidationException")).when(updateDocumentInPortMock) + .updateDocument(any(), any(), any(), any(), any(), any()); messageProcessor.updateDocument().accept(this.message); - final ArgumentCaptor messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); + final ArgumentCaptor> messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); verify(errorApiMock, times(1)).handleIncident(messageHeaderArgumentCaptor.capture(), any(IncidentError.class)); Assertions.assertTrue(messageHeaderArgumentCaptor.getValue().containsKey(DIGIWF_PROCESS_INSTANCE_ID)); } - @Test void testDmsUpdateDocumentIntegrationHandlesIncidentError() { - Mockito.doThrow(new IncidentError("Error Message")).when(updateDocumentInPortMock).updateDocument(any(), any(), any(), any(), any()); + Mockito.doThrow(new IncidentError("Error Message")).when(updateDocumentInPortMock).updateDocument(any(), any(), any(), any(), any(), any()); messageProcessor.updateDocument().accept(this.message); - final ArgumentCaptor messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); + final ArgumentCaptor> messageHeaderArgumentCaptor = ArgumentCaptor.forClass(Map.class); verify(errorApiMock, times(1)).handleIncident(messageHeaderArgumentCaptor.capture(), any(IncidentError.class)); Assertions.assertTrue(messageHeaderArgumentCaptor.getValue().containsKey(DIGIWF_PROCESS_INSTANCE_ID)); } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3AdapterTest.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3AdapterTest.java index 99bed1fdc5..92ba937d46 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3AdapterTest.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/adapter/out/s3/S3AdapterTest.java @@ -2,45 +2,64 @@ import de.muenchen.oss.digiwf.dms.integration.domain.Content; import de.muenchen.oss.digiwf.message.process.api.error.BpmnError; +import de.muenchen.oss.digiwf.process.api.config.api.ProcessConfigApi; +import de.muenchen.oss.digiwf.process.api.config.api.dto.ConfigEntryTO; +import de.muenchen.oss.digiwf.process.api.config.api.dto.ProcessConfigTO; +import de.muenchen.oss.digiwf.process.api.config.impl.ProcessConfigApiImpl; +import de.muenchen.oss.digiwf.process.api.config.impl.ProcessConfigClient; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFileRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3DomainProvider; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.core.io.ClassPathResource; import java.io.IOException; -import java.util.*; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; import static reactor.core.publisher.Mono.just; class S3AdapterTest { + private static final String DEFAULT_S3_URL = "defaultURL"; + private static final String DOMAIN_SPECIFIC_S3_URL = "domainSpecificURL"; + private final DocumentStorageFileRepository documentStorageFileRepository = mock(DocumentStorageFileRepository.class); private final DocumentStorageFolderRepository documentStorageFolderRepository = mock(DocumentStorageFolderRepository.class); + private final ProcessConfigClient processConfigClient = mock(ProcessConfigClient.class); + private final ProcessConfigApi processConfigApi = spy(new ProcessConfigApiImpl(processConfigClient)); + private final S3DomainProvider s3DomainProvider = processConfigApi::getAppFileS3SyncConfig; + private final S3StorageUrlProvider s3StorageUrlProvider = new S3StorageUrlProvider(s3DomainProvider, DEFAULT_S3_URL); + + private final Map supportedExtensions = Map.of("pdf", "application/pdf", + "png", "image/png", + "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); - private Map supportedExtensions = new HashMap<>(); + private final FileExtensionService fileExtensionService = new FileExtensionService(supportedExtensions); + private final String processDefinitionId = "processDefinition"; private S3Adapter s3Adapter; @BeforeEach void setup() { - s3Adapter = new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, supportedExtensions); - supportedExtensions.put("pdf", "application/pdf"); - supportedExtensions.put("png", "image/png"); - supportedExtensions.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + s3Adapter = new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, fileExtensionService, s3StorageUrlProvider); } @Test - void testLoadFileFromFilePath() throws IOException, DocumentStorageException, PropertyNotSetException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + void testLoadFileFromFilePath() + throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pdfPath = "test/test-pdf.pdf"; final String pngPath = "test/digiwf_logo.png"; @@ -54,10 +73,11 @@ void testLoadFileFromFilePath() throws IOException, DocumentStorageException, Pr final byte[] testPdf = new ClassPathResource(fullPdfPath).getInputStream().readAllBytes(); final byte[] testPng = new ClassPathResource(fullPngPath).getInputStream().readAllBytes(); - when(documentStorageFileRepository.getFile(fullPdfPath, 3)).thenReturn(testPdf); - when(documentStorageFileRepository.getFile(fullPngPath, 3)).thenReturn(testPng); + when(documentStorageFileRepository.getFile(fullPdfPath, 3, DEFAULT_S3_URL)).thenReturn(testPdf); + when(documentStorageFileRepository.getFile(fullPngPath, 3, DEFAULT_S3_URL)).thenReturn(testPng); + when(processConfigApi.getProcessConfig(anyString())).thenThrow(new RuntimeException("Process Config does not exist")); - final List contents = this.s3Adapter.loadFiles(filePaths, fileContext); + final List contents = this.s3Adapter.loadFiles(filePaths, fileContext, processDefinitionId); final Content pdfContent = new Content("pdf", "test-pdf", testPdf); final Content pngContent = new Content("png", "digiwf_logo", testPng); @@ -66,9 +86,9 @@ void testLoadFileFromFilePath() throws IOException, DocumentStorageException, Pr assertTrue(contents.contains(pngContent)); } - @Disabled("This test is disabled because the feature domain specific s3 storage url is not implemented yet. See https://github.com/it-at-m/digiwf-core/issues/734") @Test - void testLoadFileFromFilePathWithStorageUrl() throws IOException, DocumentStorageException, PropertyNotSetException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + void testLoadFileFromFilePathWithStorageUrl() + throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pdfPath = "test/test-pdf.pdf"; final String pngPath = "test/digiwf_logo.png"; @@ -82,10 +102,16 @@ void testLoadFileFromFilePathWithStorageUrl() throws IOException, DocumentStorag final byte[] testPdf = new ClassPathResource(fullPdfPath).getInputStream().readAllBytes(); final byte[] testPng = new ClassPathResource(fullPngPath).getInputStream().readAllBytes(); - when(documentStorageFileRepository.getFile(fullPdfPath, 3, "S3Url")).thenReturn(testPdf); - when(documentStorageFileRepository.getFile(fullPngPath, 3, "S3Url")).thenReturn(testPng); + when(documentStorageFileRepository.getFile(fullPdfPath, 3, DOMAIN_SPECIFIC_S3_URL)).thenReturn(testPdf); + when(documentStorageFileRepository.getFile(fullPngPath, 3, DOMAIN_SPECIFIC_S3_URL)).thenReturn(testPng); + when(processConfigApi.getProcessConfig(anyString())).thenReturn(ProcessConfigTO.builder() + .configs(List.of(ConfigEntryTO.builder() + .key("app_file_s3_sync_config") + .value(DOMAIN_SPECIFIC_S3_URL) + .build())) + .build()); - final List contents = this.s3Adapter.loadFiles(filePaths, fileContext); + final List contents = this.s3Adapter.loadFiles(filePaths, fileContext, processDefinitionId); final Content pdfContent = new Content("pdf", "test-pdf", testPdf); final Content pngContent = new Content("png", "digiwf_logo", testPng); @@ -94,9 +120,9 @@ void testLoadFileFromFilePathWithStorageUrl() throws IOException, DocumentStorag assertTrue(contents.contains(pngContent)); } - @Test - void testLoadFileFromFolderPath() throws IOException, DocumentStorageException, PropertyNotSetException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + void testLoadFileFromFolderPath() + throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String folderPath = "test/"; final String fileContext = "files"; @@ -108,19 +134,20 @@ void testLoadFileFromFolderPath() throws IOException, DocumentStorageException, final List paths = List.of(folderPath); - Set filesPaths = new HashSet<>(List.of(fullPdfPath, fullPngPath, fullWordPath)); + final Set filesPaths = new HashSet<>(List.of(fullPdfPath, fullPngPath, fullWordPath)); final byte[] testPdf = new ClassPathResource(fullPdfPath).getInputStream().readAllBytes(); final byte[] testPng = new ClassPathResource(fullPngPath).getInputStream().readAllBytes(); final byte[] testWord = new ClassPathResource(fullWordPath).getInputStream().readAllBytes(); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(fullFolderPath)).thenReturn((just(filesPaths))); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(fullFolderPath, DEFAULT_S3_URL)).thenReturn((just(filesPaths))); - when(documentStorageFileRepository.getFile(fullPdfPath, 3)).thenReturn(testPdf); - when(documentStorageFileRepository.getFile(fullPngPath, 3)).thenReturn(testPng); - when(documentStorageFileRepository.getFile(fullWordPath, 3)).thenReturn(testWord); + when(documentStorageFileRepository.getFile(fullPdfPath, 3, DEFAULT_S3_URL)).thenReturn(testPdf); + when(documentStorageFileRepository.getFile(fullPngPath, 3, DEFAULT_S3_URL)).thenReturn(testPng); + when(documentStorageFileRepository.getFile(fullWordPath, 3, DEFAULT_S3_URL)).thenReturn(testWord); + when(processConfigApi.getProcessConfig(anyString())).thenThrow(new RuntimeException("Process Config does not exist")); - final List contents = this.s3Adapter.loadFiles(paths, fileContext); + final List contents = this.s3Adapter.loadFiles(paths, fileContext, processDefinitionId); final Content pdfContent = new Content("pdf", "test-pdf", testPdf); final Content pngContent = new Content("png", "digiwf_logo", testPng); @@ -131,9 +158,9 @@ void testLoadFileFromFolderPath() throws IOException, DocumentStorageException, assertTrue(contents.contains(wordContent)); } - @Disabled("This test is disabled because the feature domain specific s3 storage url is not implemented yet. See https://github.com/it-at-m/digiwf-core/issues/734") @Test - void testLoadFileFromFolderPathWithStorageUrl() throws IOException, DocumentStorageException, PropertyNotSetException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + void testLoadFileFromFolderPathWithStorageUrl() + throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String folderPath = "test/"; final String fileContext = "files"; @@ -151,13 +178,19 @@ void testLoadFileFromFolderPathWithStorageUrl() throws IOException, DocumentStor final byte[] testPng = new ClassPathResource(fullPngPath).getInputStream().readAllBytes(); final byte[] testWord = new ClassPathResource(fullWordPath).getInputStream().readAllBytes(); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(fullFolderPath, "S3Url")).thenReturn((just(filesPaths))); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(fullFolderPath, DOMAIN_SPECIFIC_S3_URL)).thenReturn((just(filesPaths))); - when(documentStorageFileRepository.getFile(fullPdfPath, 3, "S3Url")).thenReturn(testPdf); - when(documentStorageFileRepository.getFile(fullPngPath, 3, "S3Url")).thenReturn(testPng); - when(documentStorageFileRepository.getFile(fullWordPath, 3, "S3Url")).thenReturn(testWord); + when(documentStorageFileRepository.getFile(fullPdfPath, 3, DOMAIN_SPECIFIC_S3_URL)).thenReturn(testPdf); + when(documentStorageFileRepository.getFile(fullPngPath, 3, DOMAIN_SPECIFIC_S3_URL)).thenReturn(testPng); + when(documentStorageFileRepository.getFile(fullWordPath, 3, DOMAIN_SPECIFIC_S3_URL)).thenReturn(testWord); + when(processConfigApi.getProcessConfig(anyString())).thenReturn(ProcessConfigTO.builder() + .configs(List.of(ConfigEntryTO.builder() + .key("app_file_s3_sync_config") + .value(DOMAIN_SPECIFIC_S3_URL) + .build())) + .build()); - final List contents = this.s3Adapter.loadFiles(paths, fileContext); + final List contents = this.s3Adapter.loadFiles(paths, fileContext, processDefinitionId); final Content pdfContent = new Content("pdf", "test-pdf", testPdf); final Content pngContent = new Content("png", "digiwf_logo", testPng); @@ -169,7 +202,8 @@ void testLoadFileFromFolderPathWithStorageUrl() throws IOException, DocumentStor } @Test - void testLoadFileFromFilePathThrowsDocumentStorageException() throws DocumentStorageException, PropertyNotSetException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + void testLoadFileFromFilePathThrowsDocumentStorageException() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pdfPath = "test/test-pdf.pdf"; final String fileContext = "files"; @@ -178,9 +212,11 @@ void testLoadFileFromFilePathThrowsDocumentStorageException() throws DocumentSto final List filePaths = List.of(pdfPath); - when(documentStorageFileRepository.getFile(fullPdfPath, 3)).thenThrow(new DocumentStorageException("Some error", new RuntimeException("Some error"))); + when(documentStorageFileRepository.getFile(fullPdfPath, 3, DEFAULT_S3_URL)).thenThrow( + new DocumentStorageException("Some error", new RuntimeException("Some error"))); + when(processConfigApi.getProcessConfig(anyString())).thenThrow(new RuntimeException("Process Config does not exist")); - BpmnError bpmnError = assertThrows(BpmnError.class, () -> this.s3Adapter.loadFiles(filePaths, fileContext)); + BpmnError bpmnError = assertThrows(BpmnError.class, () -> this.s3Adapter.loadFiles(filePaths, fileContext, processDefinitionId)); String expectedMessage = "An file could not be loaded from url: " + fullPdfPath; String actualMessage = bpmnError.getErrorMessage(); @@ -191,7 +227,8 @@ void testLoadFileFromFilePathThrowsDocumentStorageException() throws DocumentSto } @Test - void testLoadFileFromFolderPathThrowsDocumentStorageServerErrorException() throws DocumentStorageException, PropertyNotSetException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + void testLoadFileFromFolderPathThrowsDocumentStorageServerErrorException() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String folderPath = "test/"; final String fileContext = "files"; @@ -200,9 +237,11 @@ void testLoadFileFromFolderPathThrowsDocumentStorageServerErrorException() throw final List filePaths = List.of(folderPath); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(fullFolderPath)).thenThrow(new DocumentStorageServerErrorException("Some error", new RuntimeException("Some error"))); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(fullFolderPath, DEFAULT_S3_URL)).thenThrow( + new DocumentStorageServerErrorException("Some error", new RuntimeException("Some error"))); + when(processConfigApi.getProcessConfig(anyString())).thenThrow(new RuntimeException("Process Config does not exist")); - BpmnError bpmnError = assertThrows(BpmnError.class, () -> this.s3Adapter.loadFiles(filePaths, fileContext)); + BpmnError bpmnError = assertThrows(BpmnError.class, () -> this.s3Adapter.loadFiles(filePaths, fileContext, processDefinitionId)); String expectedMessage = "An folder could not be loaded from url: " + fullFolderPath; String actualMessage = bpmnError.getErrorMessage(); @@ -213,7 +252,8 @@ void testLoadFileFromFolderPathThrowsDocumentStorageServerErrorException() throw } @Test - void testLoadFileFromFilePathThrowsUnsupportedFileTypeException() throws DocumentStorageException, PropertyNotSetException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, IOException { + void testLoadFileFromFilePathThrowsUnsupportedFileTypeException() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, IOException { final String htmlPath = "fail/test-html.html"; final String fileContext = "files"; @@ -224,10 +264,11 @@ void testLoadFileFromFilePathThrowsUnsupportedFileTypeException() throws Documen final byte[] testHtml = new ClassPathResource(fullHtmlPath).getInputStream().readAllBytes(); - when(documentStorageFileRepository.getFile(fullHtmlPath, 3)).thenReturn(testHtml); + when(documentStorageFileRepository.getFile(fullHtmlPath, 3, DEFAULT_S3_URL)).thenReturn(testHtml); + when(processConfigApi.getProcessConfig(anyString())).thenThrow(new RuntimeException("Process Config does not exist")); try { - this.s3Adapter.loadFiles(filePaths, fileContext); + this.s3Adapter.loadFiles(filePaths, fileContext, processDefinitionId); } catch (BpmnError bpmnError) { String expectedMessage = "The type of this file is not supported: " + fullHtmlPath; String actualMessage = bpmnError.getErrorMessage(); diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCaseTest.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCaseTest.java index 6b93e069cb..58bfb090c7 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCaseTest.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/CreateDocumentUseCaseTest.java @@ -28,16 +28,18 @@ void createDocument() { List filepaths = List.of("path/content.pdf"); - when(this.loadFileOutPort.loadFiles(any(), any())).thenReturn(List.of(content)); + when(this.loadFileOutPort.loadFiles(any(), any(), any())).thenReturn(List.of(content)); when(this.createDocumentOutPort.createDocument(any(), any())).thenReturn("documentCOO"); LocalDate testDate = LocalDate.parse("2023-12-01"); - createDocumentUseCase.createDocument("procedureCOO", "title", testDate, "user", DocumentType.EINGEHEND, filepaths, "filecontext"); + createDocumentUseCase.createDocument("procedureCOO", "title", testDate, "user", DocumentType.EINGEHEND, filepaths, "filecontext", + "processDefinitionId"); - verify(this.loadFileOutPort, times(1)).loadFiles(filepaths, "filecontext"); + verify(this.loadFileOutPort, times(1)).loadFiles(filepaths, "filecontext", "processDefinitionId"); - verify(this.createDocumentOutPort, times(1)).createDocument(new Document("procedureCOO", "title", testDate, DocumentType.EINGEHEND, List.of(content)), "user"); + verify(this.createDocumentOutPort, times(1)).createDocument(new Document("procedureCOO", "title", testDate, DocumentType.EINGEHEND, List.of(content)), + "user"); } } diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCaseTest.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCaseTest.java index 94e1612c24..f56a371ef9 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCaseTest.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/ReadContentUseCaseTest.java @@ -25,12 +25,12 @@ void readContent() { when(this.readContent.readContent(any(), any())).thenReturn(List.of(content)); - doNothing().when(transferContentOutPort).transferContent(any(), any(), any()); + doNothing().when(transferContentOutPort).transferContent(any(), any(), any(), anyString()); - readContentUseCase.readContent(List.of("fileCoo"), "user", "filepath/", "filecontext/"); + readContentUseCase.readContent(List.of("fileCoo"), "user", "filepath/", "filecontext/", "processDefinitionId"); verify(this.readContent, times(1)).readContent(List.of("fileCoo"), "user"); - verify(this.transferContentOutPort, times(1)).transferContent(List.of(content), "filepath/", "filecontext/"); + verify(this.transferContentOutPort, times(1)).transferContent(List.of(content), "filepath/", "filecontext/", "processDefinitionId"); } } \ No newline at end of file diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCaseTest.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCaseTest.java index 8ebf5efe93..ad8de5eb0a 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCaseTest.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-core/src/test/java/de/muenchen/oss/digiwf/dms/integration/application/usecase/UpdateDocumentUseCaseTest.java @@ -26,16 +26,15 @@ void updateDocument() { List filepaths = List.of("path/content.pdf"); - when(this.loadFileOutPort.loadFiles(any(), any())).thenReturn(List.of(content)); + when(this.loadFileOutPort.loadFiles(any(), any(), any())).thenReturn(List.of(content)); doNothing().when(updateDocumentOutPort).updateDocument(any(), any(), any(), any()); - updateDocumentUseCase.updateDocument("procedureCOO", "user", DocumentType.EINGEHEND, filepaths, "filecontext"); + updateDocumentUseCase.updateDocument("procedureCOO", "user", DocumentType.EINGEHEND, filepaths, "filecontext", "processDefinitionId"); - verify(this.loadFileOutPort, times(1)).loadFiles(filepaths, "filecontext"); + verify(this.loadFileOutPort, times(1)).loadFiles(filepaths, "filecontext", "processDefinitionId"); verify(this.updateDocumentOutPort, times(1)).updateDocument("procedureCOO", DocumentType.EINGEHEND, List.of(content), "user"); - } } \ No newline at end of file diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-service/src/main/resources/application.yml b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-service/src/main/resources/application.yml index dfb0be8ba7..ea383e2cb3 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-service/src/main/resources/application.yml +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-service/src/main/resources/application.yml @@ -63,10 +63,6 @@ digiwf: io: muenchendigital: digiwf: - s3: - client: - document-storage-url: "${DOCUMENT_STORAGE_HOST:http://localhost}:${DOCUMENT_STORAGE_PORT:8080}" - securityEnabled: true message: incidentDestination: "dwf-connector-incident-${DIGIWF_ENV}" bpmnErrorDestination: "dwf-connector-bpmnerror-${DIGIWF_ENV}" @@ -77,8 +73,12 @@ de: muenchen: oss: digiwf: + s3: + client: + document-storage-url: "${DOCUMENT_STORAGE_HOST:http://localhost}:${DOCUMENT_STORAGE_PORT:8080}" + enable-security: true dms: - supportedExtensions: + supported-file-extensions: pdf: "application/pdf" txt: "text/plain" png: "image/png" @@ -92,3 +92,9 @@ de: odp: "application/vnd.oasis.opendocument.presentation" ods: "application/vnd.oasis.opendocument.spreadsheet" odt: "application/vnd.oasis.opendocument.text" + +feign: + client: + config: + digiwf-process-config: + url: ${ENGINE_REST_ENDPOINT_URL} \ No newline at end of file diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-service/src/main/resources/banner.txt b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-service/src/main/resources/banner.txt new file mode 100644 index 0000000000..e35629abb6 --- /dev/null +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-service/src/main/resources/banner.txt @@ -0,0 +1,10 @@ + _____ __ __ _____ _____ _ _ _ _ _ _ _ + | __ \| \/ |/ ____| |_ _| | | | | (_) /\ | (_) | | (_) + | | | | \ / | (___ | | _ __ | |_ ___ __ _ _ __ __ _| |_ _ ___ _ __ / \ _ __ _ __ | |_ ___ __ _| |_ _ ___ _ __ + | | | | |\/| |\___ \ | | | '_ \| __/ _ \/ _` | '__/ _` | __| |/ _ \| '_ \ / /\ \ | '_ \| '_ \| | |/ __/ _` | __| |/ _ \| '_ \ + | |__| | | | |____) | _| |_| | | | || __/ (_| | | | (_| | |_| | (_) | | | | / ____ \| |_) | |_) | | | (_| (_| | |_| | (_) | | | | + |_____/|_| |_|_____/ |_____|_| |_|\__\___|\__, |_| \__,_|\__|_|\___/|_| |_| /_/ \_\ .__/| .__/|_|_|\___\__,_|\__|_|\___/|_| |_| + __/ | | | | | + |___/ |_| |_| + Application Name : ${spring.application.name} + Spring Boot Version : ${spring-boot.formatted-version} diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsAutoConfiguration.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsAutoConfiguration.java index af4c48de34..f03fdcd769 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsAutoConfiguration.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsAutoConfiguration.java @@ -13,8 +13,13 @@ import de.muenchen.oss.digiwf.dms.integration.application.usecase.*; import de.muenchen.oss.digiwf.message.process.api.ErrorApi; import de.muenchen.oss.digiwf.message.process.api.ProcessApi; +import de.muenchen.oss.digiwf.process.api.config.api.ProcessConfigApi; +import de.muenchen.oss.digiwf.s3.integration.client.properties.SupportedFileExtensions; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFileRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3DomainProvider; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.spring.security.authentication.UserAuthenticationProvider; import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -30,27 +35,53 @@ @Configuration @RequiredArgsConstructor @Import(FabasoftClientConfiguration.class) -@EnableConfigurationProperties({FabasoftProperties.class, DmsProperties.class}) +@EnableConfigurationProperties({ FabasoftProperties.class, DmsProperties.class }) public class DmsAutoConfiguration { - private final DmsProperties dmsProperties; - @Bean @ConditionalOnMissingBean - public FabasoftAdapter fabasoftAdapter(final FabasoftProperties dmsProperties, LHMBAI151700GIWSDSoap wsCleint) { - return new FabasoftAdapter(dmsProperties, wsCleint); + public FabasoftAdapter fabasoftAdapter(final FabasoftProperties dmsProperties, final LHMBAI151700GIWSDSoap wsClient) { + return new FabasoftAdapter(dmsProperties, wsClient); } @Bean @ConditionalOnMissingBean - public LHMBAI151700GIWSDSoap wsCleint(final FabasoftClientConfiguration fabasoftClientConfiguration) { + public LHMBAI151700GIWSDSoap wsClient(final FabasoftClientConfiguration fabasoftClientConfiguration) { return fabasoftClientConfiguration.dmsWsClient(); } + /** + * Constructs an {@link S3DomainProvider} instance specifically tailored for this integration to retrieve the domain-specific S3 storage URL for a given + * process if its process configuration contains a value for + * {@link de.muenchen.oss.digiwf.process.api.config.ProcessConfigConstants#APP_FILE_S3_SYNC_CONFIG}. + * + * @param processConfigApi {@link ProcessConfigApi} offers access to a process configuration for a given process definition id. + * @return S3DomainProvider {@link S3DomainProvider} that retrieves the domain-specific S3 storage url for a process if configured. + */ + @Bean + public S3DomainProvider s3DomainProvider(final ProcessConfigApi processConfigApi) { + return processConfigApi::getAppFileS3SyncConfig; + } + @Bean @ConditionalOnMissingBean - public S3Adapter s3Adapter(DocumentStorageFileRepository documentStorageFileRepository, DocumentStorageFolderRepository documentStorageFolderRepository) { - return new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, dmsProperties.getSupportedExtensions()); + public S3Adapter s3Adapter(final DocumentStorageFileRepository documentStorageFileRepository, + final DocumentStorageFolderRepository documentStorageFolderRepository, final FileExtensionService fileExtensionService, + final S3StorageUrlProvider s3StorageUrlProvider) { + return new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, fileExtensionService, s3StorageUrlProvider); + } + + /** + * Offers a {@link java.util.Map} of supported file extensions for this integration in form of a {@link SupportedFileExtensions} object. + * + * @param dmsProperties {@link DmsProperties} contains the supported file extensions. + * @return {@link SupportedFileExtensions} object representing the supported file extensions. + */ + @Bean + public SupportedFileExtensions supportedFileExtensions(final DmsProperties dmsProperties) { + final SupportedFileExtensions supportedFileExtensions = new SupportedFileExtensions(); + supportedFileExtensions.putAll(dmsProperties.getSupportedFileExtensions()); + return supportedFileExtensions; } @Bean diff --git a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsProperties.java b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsProperties.java index e4c687ccf2..443c9e45e6 100644 --- a/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsProperties.java +++ b/digiwf-integrations/digiwf-dms-integration/digiwf-dms-integration-starter/src/main/java/de/muenchen/oss/digiwf/dms/integration/configuration/DmsProperties.java @@ -1,9 +1,9 @@ package de.muenchen.oss.digiwf.dms.integration.configuration; +import jakarta.validation.constraints.NotBlank; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; -import jakarta.validation.constraints.NotBlank; import java.util.Map; @Data @@ -14,6 +14,6 @@ public class DmsProperties { * Supported extensions. */ @NotBlank - private Map supportedExtensions; + private Map supportedFileExtensions; -} +} \ No newline at end of file diff --git a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/pom.xml b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/pom.xml index 44a8a3df9d..ac93db3b6f 100644 --- a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/pom.xml +++ b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/pom.xml @@ -24,16 +24,6 @@ org.springframework spring-web - - org.apache.tika - tika-core - ${tika.version} - - - org.apache.tika - tika-parsers-standard-package - ${tika.version} - org.apache.pdfbox jbig2-imageio diff --git a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/main/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3Adapter.java b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/main/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3Adapter.java index c746646a7b..53668e2333 100644 --- a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/main/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3Adapter.java +++ b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/main/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3Adapter.java @@ -8,27 +8,25 @@ import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; import de.muenchen.oss.digiwf.s3.integration.client.repository.transfer.S3FileTransferRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; import jakarta.mail.util.ByteArrayDataSource; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.apache.tika.Tika; @Slf4j @RequiredArgsConstructor public class S3Adapter implements LoadMailAttachmentOutPort { private final S3FileTransferRepository s3FileTransferRepository; + private final FileExtensionService fileExtensionService; @Override public FileAttachment loadAttachment(final PresignedUrl attachment) throws BpmnError { try { final String fileName = StringUtils.substringAfterLast(attachment.getPath(), "/"); - // Note: Tika throws an IOException that is immediately caught and logged. It may be confusing but the - // IOException that is logged can be ignored. See https://stackoverflow.com/q/66592801 - final Tika tika = new Tika(); final byte[] bytes = this.s3FileTransferRepository.getFile(attachment.getUrl()); - final String type = tika.detect(bytes); + final String type = fileExtensionService.detectFileType(bytes); // Note: Create the ByteArrayDataSource with the bytes and the type to avoid auto type detection by ByteArrayDataSource // https://github.com/it-at-m/digiwf-core/issues/616 final ByteArrayDataSource file = new ByteArrayDataSource(bytes, type); diff --git a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/test/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3AdapterTest.java b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/test/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3AdapterTest.java index fecee1456d..92cac9fa19 100644 --- a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/test/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3AdapterTest.java +++ b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-core/src/test/java/de/muenchen/oss/digiwf/email/integration/adapter/out/S3AdapterTest.java @@ -7,6 +7,7 @@ import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; import de.muenchen.oss.digiwf.s3.integration.client.repository.transfer.S3FileTransferRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -25,12 +26,13 @@ class S3AdapterTest { private final S3FileTransferRepository s3FileTransferRepository = mock(S3FileTransferRepository.class); + private final FileExtensionService fileExtensionService = new FileExtensionService(null); private S3Adapter s3Adapter; @BeforeEach void setup() { - s3Adapter = new S3Adapter(s3FileTransferRepository); + s3Adapter = new S3Adapter(s3FileTransferRepository, fileExtensionService); } @Test diff --git a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-starter/src/main/java/de/muenchen/oss/digiwf/email/integration/configuration/MailAutoConfiguration.java b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-starter/src/main/java/de/muenchen/oss/digiwf/email/integration/configuration/MailAutoConfiguration.java index e39a32ead5..3168a88036 100644 --- a/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-starter/src/main/java/de/muenchen/oss/digiwf/email/integration/configuration/MailAutoConfiguration.java +++ b/digiwf-integrations/digiwf-email-integration/digiwf-email-integration-starter/src/main/java/de/muenchen/oss/digiwf/email/integration/configuration/MailAutoConfiguration.java @@ -16,6 +16,7 @@ import de.muenchen.oss.digiwf.message.process.api.ErrorApi; import de.muenchen.oss.digiwf.message.process.api.ProcessApi; import de.muenchen.oss.digiwf.s3.integration.client.repository.transfer.S3FileTransferRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; import io.micrometer.core.instrument.MeterRegistry; import lombok.RequiredArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -62,8 +63,8 @@ public CorrelateMessageOutPort getCorrelateMessagePort(final ProcessApi processA @Bean @ConditionalOnMissingBean - public LoadMailAttachmentOutPort getLoadMailAttachmentPort(final S3FileTransferRepository s3FileTransferRepository) { - return new S3Adapter(s3FileTransferRepository); + public LoadMailAttachmentOutPort getLoadMailAttachmentPort(final S3FileTransferRepository s3FileTransferRepository, final FileExtensionService fileExtensionService) { + return new S3Adapter(s3FileTransferRepository, fileExtensionService); } @Bean diff --git a/digiwf-integrations/digiwf-integration-parent/pom.xml b/digiwf-integrations/digiwf-integration-parent/pom.xml index 2f10cebce1..5dff718a2b 100644 --- a/digiwf-integrations/digiwf-integration-parent/pom.xml +++ b/digiwf-integrations/digiwf-integration-parent/pom.xml @@ -94,6 +94,16 @@ ${wiremock.version} test + + org.apache.tika + tika-core + ${tika.version} + + + org.apache.tika + tika-parsers-standard-package + ${tika.version} + diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFileUsageController.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFileUsageController.java index 75cf5320f1..c4497a4629 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFileUsageController.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFileUsageController.java @@ -3,8 +3,8 @@ import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFileRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -29,13 +29,16 @@ public class ClientFileUsageController { private static final String PATH_TO_FILE = ClientFolderUsageController.FOLDER + "/" + FILENAME; private final DocumentStorageFileRepository documentStorageFileRepository; + + private final S3StorageUrlProvider s3StorageUrlProvider; @GetMapping @ResponseStatus(HttpStatus.OK) - public void getFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, IOException, PropertyNotSetException { + public void getFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, IOException { final byte[] binaryFile = this.documentStorageFileRepository.getFile( PATH_TO_FILE, - 3 + 3, + s3StorageUrlProvider.getDefaultDocumentStorageUrl() ); final File tmpFile = File.createTempFile("test", ".jpg"); Files.write(tmpFile.toPath(), binaryFile); @@ -44,42 +47,44 @@ public void getFile() throws DocumentStorageException, DocumentStorageClientErro @GetMapping("/inputstream") @ResponseStatus(HttpStatus.OK) - public void getFileInputStream() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, IOException, PropertyNotSetException { + public void getFileInputStream() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, IOException { try (final InputStream fileInputStream = this.documentStorageFileRepository.getFileInputStream( PATH_TO_FILE, - 3 + 3, + s3StorageUrlProvider.getDefaultDocumentStorageUrl() )) { final File tmpFile = File.createTempFile("test-from-inputstream", ".jpg"); Files.write(tmpFile.toPath(), fileInputStream.readAllBytes()); log.info("File InputStream downloaded to {}.", tmpFile.toPath()); } - ; } @PostMapping @ResponseStatus(HttpStatus.OK) - public void saveFile() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + public void saveFile() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final File file = ResourceUtils.getFile("classpath:files/cat.jpg"); final byte[] binaryFile = Files.readAllBytes(file.toPath()); this.documentStorageFileRepository.saveFile( PATH_TO_FILE, binaryFile, 3, - LocalDate.now().plusMonths(1) + LocalDate.now().plusMonths(1), + s3StorageUrlProvider.getDefaultDocumentStorageUrl() ); log.info("File saved."); } @PostMapping("/inputstream") @ResponseStatus(HttpStatus.OK) - public void saveFileInputStream() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + public void saveFileInputStream() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final File file = ResourceUtils.getFile("classpath:files/cat.jpg"); try (final InputStream inputStream = new FileInputStream(file)) { this.documentStorageFileRepository.saveFileInputStream( PATH_TO_FILE, inputStream, 3, - LocalDate.now().plusMonths(1) + LocalDate.now().plusMonths(1), + s3StorageUrlProvider.getDefaultDocumentStorageUrl() ); log.info("File InputStream saved."); } @@ -87,7 +92,7 @@ public void saveFileInputStream() throws IOException, DocumentStorageException, @PutMapping @ResponseStatus(HttpStatus.OK) - public void updateFile() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + public void updateFile() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final File file = ResourceUtils.getFile("classpath:files/sunflower.jpg"); final byte[] binaryFile = Files.readAllBytes(file.toPath()); // Overwrite file on S3 with sunflower.jpg @@ -95,14 +100,15 @@ public void updateFile() throws IOException, DocumentStorageException, DocumentS PATH_TO_FILE, binaryFile, 3, - LocalDate.now().plusMonths(2) + LocalDate.now().plusMonths(2), + s3StorageUrlProvider.getDefaultDocumentStorageUrl() ); log.info("File updated."); } @PutMapping("/inputstream") @ResponseStatus(HttpStatus.OK) - public void updateFileInputStream() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + public void updateFileInputStream() throws IOException, DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final File file = ResourceUtils.getFile("classpath:files/sunflower.jpg"); try (final InputStream inputStream = new FileInputStream(file)) { // Overwrite file on S3 with sunflower.jpg @@ -110,7 +116,8 @@ public void updateFileInputStream() throws IOException, DocumentStorageException PATH_TO_FILE, inputStream, 3, - LocalDate.now().plusMonths(2) + LocalDate.now().plusMonths(2), + s3StorageUrlProvider.getDefaultDocumentStorageUrl() ); log.info("File InputStream updated."); } @@ -118,20 +125,22 @@ public void updateFileInputStream() throws IOException, DocumentStorageException @PatchMapping @ResponseStatus(HttpStatus.OK) - public void updateEndOfLife() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + public void updateEndOfLife() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { this.documentStorageFileRepository.updateEndOfLife( PATH_TO_FILE, - LocalDate.now().plusMonths(999) + LocalDate.now().plusMonths(999), + s3StorageUrlProvider.getDefaultDocumentStorageUrl() ); log.info("End of life for file updated."); } @DeleteMapping @ResponseStatus(HttpStatus.NO_CONTENT) - public void deleteFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + public void deleteFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { this.documentStorageFileRepository.deleteFile( PATH_TO_FILE, - 3 + 3, + s3StorageUrlProvider.getDefaultDocumentStorageUrl() ); log.info("File deleted."); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFolderUsageController.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFolderUsageController.java index 1c9f172180..5ab5cee97c 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFolderUsageController.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/ClientFolderUsageController.java @@ -5,6 +5,7 @@ import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -22,16 +23,18 @@ public class ClientFolderUsageController { private final DocumentStorageFolderRepository documentStorageFolderRepository; + private final S3StorageUrlProvider s3StorageUrlProvider; + @DeleteMapping @ResponseStatus(HttpStatus.NO_CONTENT) public void deleteFolder() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - this.documentStorageFolderRepository.deleteFolder(FOLDER); + this.documentStorageFolderRepository.deleteFolder(FOLDER, s3StorageUrlProvider.getDefaultDocumentStorageUrl()); } @PutMapping @ResponseStatus(HttpStatus.OK) public void getAllFilesInFolderRecursively() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - this.documentStorageFolderRepository.getAllFilesInFolderRecursively(FOLDER).block().forEach(log::info); + this.documentStorageFolderRepository.getAllFilesInFolderRecursively(FOLDER, s3StorageUrlProvider.getDefaultDocumentStorageUrl()).block().forEach(log::info); } } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/PresignedUrlController.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/PresignedUrlController.java index dc127c2663..0ea96b771d 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/PresignedUrlController.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/java/de/muenchen/oss/digiwf/s3/integration/example/client/controller/PresignedUrlController.java @@ -7,6 +7,7 @@ import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl.PresignedUrlRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.transfer.S3FileTransferRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.s3.integration.example.client.controller.dto.FileActionDto; import de.muenchen.oss.digiwf.s3.integration.example.client.controller.dto.PresignedUrlDto; import de.muenchen.oss.digiwf.s3.integration.example.client.streaming.events.CreatePresignedUrlEvent; @@ -37,6 +38,7 @@ public class PresignedUrlController { private final MessageApi messageApi; private final S3FileTransferRepository s3FileTransferRepository; private final PresignedUrlRepository presignedUrlRepository; + private final S3StorageUrlProvider s3StorageUrlProvider; /** * Create a presigned url by sending a {@link CreatePresignedUrlEvent} to the event bus @@ -97,7 +99,7 @@ public void uploadFileSync() throws IOException, DocumentStorageException, Prope final File file = ResourceUtils.getFile("classpath:files/cat.jpg"); final InputStream inputStream = new FileInputStream(file); - final String presignedUrl = this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, 5, null); + final String presignedUrl = this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, 5, null, s3StorageUrlProvider.getDefaultDocumentStorageUrl()); // Example on how to use a custom s3 integration // final String presignedUrl = this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, 5, null, "http://your-s3-integration"); this.s3FileTransferRepository.saveFileInputStream(presignedUrl, inputStream); diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/resources/application.yml b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/resources/application.yml index 5fd29e0a5a..205c3bf83e 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/resources/application.yml +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-example/src/main/resources/application.yml @@ -51,13 +51,18 @@ spring: client-secret: ${SSO_S3_CLIENT_SECRET} scope: email, profile, openid # needed for userInfo endpoint +de: + muenchen: + oss: + digiwf: + s3: + client: + document-storage-url: ${DIGIWF_S3_HTTPAPI:http://localhost:8086} + enable-security: true # security is on and uses the "s3" client + io: muenchendigital: digiwf: - s3: - client: - document-storage-url: ${DIGIWF_S3_HTTPAPI:http://localhost:8086} - securityEnabled: true # security is on and uses the "s3" client streaming: typeMappings: correlatemessagev01: correlatemessagev01 diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/pom.xml b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/pom.xml index d1be52f801..ea6f9f4c10 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/pom.xml +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/pom.xml @@ -47,6 +47,11 @@ spring-boot-starter + + org.apache.httpcomponents.client5 + httpclient5 + + org.springframework.boot diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/configuration/S3IntegrationClientAutoConfiguration.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/configuration/S3IntegrationClientAutoConfiguration.java index 5856772af5..043e66f9a4 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/configuration/S3IntegrationClientAutoConfiguration.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/configuration/S3IntegrationClientAutoConfiguration.java @@ -4,10 +4,16 @@ import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.api.FolderApiApi; import de.muenchen.oss.digiwf.s3.integration.client.properties.S3IntegrationClientProperties; +import de.muenchen.oss.digiwf.s3.integration.client.properties.SupportedFileExtensions; import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3DomainProvider; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; @@ -23,14 +29,13 @@ @Configuration @ComponentScan( basePackages = { - "de.muenchen.oss.digiwf.s3.integration.gen", "de.muenchen.oss.digiwf.s3.integration.client" }, excludeFilters = { @ComponentScan.Filter( type = FilterType.ASSIGNABLE_TYPE, classes = { - /** + /* * Exclude to avoid multiple instantiation of multiple beans with same name. * This class is instantiated in {@link S3IntegrationClientAutoConfiguration} * to give the bean another name. @@ -40,7 +45,8 @@ FolderApiApi.class } ) - }) + } +) @RequiredArgsConstructor @EnableConfigurationProperties(S3IntegrationClientProperties.class) @Slf4j @@ -50,24 +56,23 @@ public class S3IntegrationClientAutoConfiguration { @PostConstruct public void init() { - log.info("[DIGIWF-S3-INTEGRATION-CLIENT]: Staring integration client, security is {}.", s3IntegrationClientProperties.isEnableSecurity() ? "enabled" : "disabled"); + log.info("[DIGIWF-S3-INTEGRATION-CLIENT]: Staring integration client, security is {}.", + s3IntegrationClientProperties.isEnableSecurity() ? "enabled" : "disabled"); } @Bean - @ConditionalOnProperty(prefix = "io.muenchendigital.digiwf.s3.client", name = "securityEnabled", havingValue = "true") + @ConditionalOnProperty(prefix = "de.muenchen.oss.digiwf.s3.client", name = "enable-security", havingValue = "true") public ApiClientFactory securedApiClientFactory(final ClientRegistrationRepository clientRegistrationRepository, - final OAuth2AuthorizedClientService authorizedClientService) { + final OAuth2AuthorizedClientService authorizedClientService) { return new ApiClientFactory( - this.s3IntegrationClientProperties.getDocumentStorageUrl(), this.webClient(clientRegistrationRepository, authorizedClientService) ); } @Bean - @ConditionalOnProperty(prefix = "io.muenchendigital.digiwf.s3.client", name = "securityEnabled", havingValue = "false", matchIfMissing = true) + @ConditionalOnProperty(prefix = "de.muenchen.oss.digiwf.s3.client", name = "enable-security", havingValue = "false", matchIfMissing = true) public ApiClientFactory apiClientFactory() { return new ApiClientFactory( - this.s3IntegrationClientProperties.getDocumentStorageUrl(), WebClient.builder().build() ); } @@ -87,4 +92,45 @@ private WebClient webClient( .build(); } + /** + * Instance of a {@link FileExtensionService} containing externally given supported file extensions. + * + * @param supportedFileExtensions {@link java.util.Map} of supported file extensions. + * @return {@link FileExtensionService} for managing file extensions. + */ + @Bean + @ConditionalOnBean(SupportedFileExtensions.class) + public FileExtensionService fileExtensionValidation(final SupportedFileExtensions supportedFileExtensions) { + return new FileExtensionService(supportedFileExtensions); + } + + /** + * Instance of a {@link FileExtensionService} containing supported file extensions configured within in the 'de.muenchen.oss.digiwf.s3' scope. + * + * @return {@link FileExtensionService} for managing file extensions. + */ + @Bean + @ConditionalOnMissingBean(SupportedFileExtensions.class) + public FileExtensionService fileExtensionValidationFromS3IntegrationClientProperties() { + return new FileExtensionService(this.s3IntegrationClientProperties.getSupportedFileExtensions()); + } + + /** + * Instance of an {@link S3StorageUrlProvider} containing an externally created {@link S3DomainProvider} for retrieving S + * + * @param s3DomainProvider + * @return + */ + @Bean + @ConditionalOnBean(S3DomainProvider.class) + public S3StorageUrlProvider s3StorageUrlProvider(final S3DomainProvider s3DomainProvider) { + return new S3StorageUrlProvider(s3DomainProvider, this.s3IntegrationClientProperties.getDocumentStorageUrl()); + } + + @Bean + @ConditionalOnMissingBean(S3DomainProvider.class) + public S3StorageUrlProvider s3StorageUrlProviderWithoutDomainProvider() { + return new S3StorageUrlProvider(this.s3IntegrationClientProperties.getDocumentStorageUrl()); + } + } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/properties/S3IntegrationClientProperties.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/properties/S3IntegrationClientProperties.java index f528616799..0cdd4ec610 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/properties/S3IntegrationClientProperties.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/properties/S3IntegrationClientProperties.java @@ -1,17 +1,24 @@ package de.muenchen.oss.digiwf.s3.integration.client.properties; +import jakarta.validation.constraints.NotBlank; import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.validation.annotation.Validated; +import java.util.Map; + @Getter @Setter @Validated -@ConfigurationProperties(prefix = "io.muenchendigital.digiwf.s3.client") +@ConfigurationProperties(prefix = "de.muenchen.oss.digiwf.s3.client") public class S3IntegrationClientProperties { - private String documentStorageUrl; - private boolean enableSecurity; + private String documentStorageUrl; + private boolean enableSecurity; + /** + * Supported file extensions. + */ + private Map supportedFileExtensions; } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/properties/SupportedFileExtensions.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/properties/SupportedFileExtensions.java new file mode 100644 index 0000000000..66f0b4873d --- /dev/null +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client-starter/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/properties/SupportedFileExtensions.java @@ -0,0 +1,6 @@ +package de.muenchen.oss.digiwf.s3.integration.client.properties; + +import java.util.HashMap; + +public class SupportedFileExtensions extends HashMap { +} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/pom.xml b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/pom.xml index c7098d3932..65ddfab1a9 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/pom.xml +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/pom.xml @@ -27,6 +27,15 @@ spring-boot-starter-validation + + + org.apache.tika + tika-core + + + org.apache.tika + tika-parsers-standard-package + diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/exception/NoFileTypeException.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/exception/NoFileTypeException.java new file mode 100644 index 0000000000..4e626d0a0f --- /dev/null +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/exception/NoFileTypeException.java @@ -0,0 +1,8 @@ +package de.muenchen.oss.digiwf.s3.integration.client.exception; + +public class NoFileTypeException extends RuntimeException { + + public NoFileTypeException(final String message) { + super(message); + } +} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepository.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepository.java index 5fa4bc03d4..5a3e4f489f 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepository.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepository.java @@ -1,13 +1,12 @@ package de.muenchen.oss.digiwf.s3.integration.client.repository; +import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl.PresignedUrlRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.transfer.S3FileTransferRepository; import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; -import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; @@ -30,25 +29,6 @@ public class DocumentStorageFileRepository { private final ApiClientFactory apiClientFactory; - /** - * Gets the file specified in the parameter from the document storage. - * - * @param pathToFile defines the path to the file. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @return the file. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public byte[] getFile(final String pathToFile, final int expireInMinutes) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - return this.getFile( - pathToFile, - expireInMinutes, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Gets the file specified in the parameter from the document storage. * @@ -60,30 +40,12 @@ public byte[] getFile(final String pathToFile, final int expireInMinutes) throws * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public byte[] getFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + public byte[] getFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final Mono presignedUrl = this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes, documentStorageUrl); return this.s3FileTransferRepository.getFile(presignedUrl.block()); } - /** - * Gets an InputStream for the file specified in the parameter from the document storage. - * - * @param pathToFile defines the path to the file. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @return the InputStream for the file. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public InputStream getFileInputStream(final String pathToFile, final int expireInMinutes) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - return this.getFileInputStream( - pathToFile, - expireInMinutes, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Gets an InputStream for the file specified in the parameter from the document storage. * @@ -95,33 +57,12 @@ public InputStream getFileInputStream(final String pathToFile, final int expireI * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public InputStream getFileInputStream(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + public InputStream getFileInputStream(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final Mono presignedUrl = this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes, documentStorageUrl); return this.s3FileTransferRepository.getFileInputStream(presignedUrl.block()); } - /** - * Saves the file specified in the parameter to the document storage. - * - * @param pathToFile defines the path to the file. - * @param file to save. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @param endOfLifeFolder the end of life of the folder defined in refId. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public void saveFile(final String pathToFile, final byte[] file, final int expireInMinutes, final LocalDate endOfLifeFolder) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - this.saveFile( - pathToFile, - file, - expireInMinutes, - endOfLifeFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Saves the file specified in the parameter to the document storage. * @@ -134,33 +75,12 @@ public void saveFile(final String pathToFile, final byte[] file, final int expir * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public void saveFile(final String pathToFile, final byte[] file, final int expireInMinutes, final LocalDate endOfLifeFolder, final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + public void saveFile(final String pathToFile, final byte[] file, final int expireInMinutes, final LocalDate endOfLifeFolder, + final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String presignedUrl = this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLifeFolder, documentStorageUrl); this.s3FileTransferRepository.saveFile(presignedUrl, file); } - /** - * Saves the file specified in the parameter to the document storage. - * - * @param pathToFile defines the path to the file. - * @param file to save. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @param endOfLifeFolder the end of life of the folder defined in refId. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public void saveFileInputStream(final String pathToFile, final InputStream file, final int expireInMinutes, final LocalDate endOfLifeFolder) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - this.saveFileInputStream( - pathToFile, - file, - expireInMinutes, - endOfLifeFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Saves the file specified in the parameter to the document storage. * @@ -173,33 +93,12 @@ public void saveFileInputStream(final String pathToFile, final InputStream file, * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public void saveFileInputStream(final String pathToFile, final InputStream file, final int expireInMinutes, final LocalDate endOfLifeFolder, final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + public void saveFileInputStream(final String pathToFile, final InputStream file, final int expireInMinutes, final LocalDate endOfLifeFolder, + final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String presignedUrl = this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLifeFolder, documentStorageUrl); this.s3FileTransferRepository.saveFileInputStream(presignedUrl, file); } - /** - * Updates the file specified in the parameter to the document storage. - * - * @param pathToFile defines the path to the file. - * @param file which overwrites the file in the document storage. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @param endOfLifeFolder the end of life of the folder defined in refId. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public void updateFile(final String pathToFile, final byte[] file, final int expireInMinutes, final LocalDate endOfLifeFolder) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - this.updateFile( - pathToFile, - file, - expireInMinutes, - endOfLifeFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Updates the file specified in the parameter to the document storage. * @@ -212,33 +111,12 @@ public void updateFile(final String pathToFile, final byte[] file, final int exp * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public void updateFile(final String pathToFile, final byte[] file, final int expireInMinutes, final LocalDate endOfLifeFolder, final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + public void updateFile(final String pathToFile, final byte[] file, final int expireInMinutes, final LocalDate endOfLifeFolder, + final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String presignedUrl = this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLifeFolder, documentStorageUrl); this.s3FileTransferRepository.updateFile(presignedUrl, file); } - /** - * Updates the file specified in the parameter withinq the document storage. - * - * @param pathToFile defines the path to the file. - * @param file which overwrites the file in the document storage. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @param endOfLifeFolder the end of life of the folder defined in refId. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public void updateFileInputStream(final String pathToFile, final InputStream file, final int expireInMinutes, final LocalDate endOfLifeFolder) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - this.updateFileInputStream( - pathToFile, - file, - expireInMinutes, - endOfLifeFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Updates the file specified in the parameter withinq the document storage. * @@ -251,29 +129,12 @@ public void updateFileInputStream(final String pathToFile, final InputStream fil * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public void updateFileInputStream(final String pathToFile, final InputStream file, final int expireInMinutes, final LocalDate endOfLifeFolder, final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + public void updateFileInputStream(final String pathToFile, final InputStream file, final int expireInMinutes, final LocalDate endOfLifeFolder, + final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String presignedUrl = this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLifeFolder, documentStorageUrl); this.s3FileTransferRepository.updateFileInputStream(presignedUrl, file); } - /** - * Updates the end of life for the file given in the parameter within the document storage. - * - * @param pathToFile defines the path to the file. - * @param endOfLifeFolder the end of life of the folder defined in refId. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public void updateEndOfLife(final String pathToFile, final LocalDate endOfLifeFolder) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException, PropertyNotSetException { - this.updateEndOfLife( - pathToFile, - endOfLifeFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Updates the end of life for the file given in the parameter within the document storage. * @@ -284,43 +145,26 @@ public void updateEndOfLife(final String pathToFile, final LocalDate endOfLifeFo * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public void updateEndOfLife(final String pathToFile, final LocalDate endOfLifeFolder, final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public void updateEndOfLife(final String pathToFile, final LocalDate endOfLifeFolder, final String documentStorageUrl) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { final FileApiApi fileApi = this.apiClientFactory.getFileApiForDocumentStorageUrl(documentStorageUrl); fileApi.updateEndOfLife(pathToFile, endOfLifeFolder); } catch (final HttpClientErrorException exception) { - final String message = String.format("The request to update the end of life for a file failed %s.", exception.getStatusCode()); + final String message = String.format("The request to update the end of life for a file failed %s.", exception.getStatusCode()); log.error(message); throw new DocumentStorageClientErrorException(message, exception); } catch (final HttpServerErrorException exception) { - final String message = String.format("The request to update the end of life for a file failed %s.", exception.getStatusCode()); + final String message = String.format("The request to update the end of life for a file failed %s.", exception.getStatusCode()); log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The request to update the end of life for a file failed."); + final String message = "The request to update the end of life for a file failed."; log.error(message); throw new DocumentStorageException(message, exception); } } - /** - * Deletes the file specified in the parameter from the document storage. - * - * @param pathToFile defines the path to the file. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public void deleteFile(final String pathToFile, final int expireInMinutes) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - this.deleteFile( - pathToFile, - expireInMinutes, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Deletes the file specified in the parameter from the document storage. * @@ -331,7 +175,8 @@ public void deleteFile(final String pathToFile, final int expireInMinutes) throw * @throws DocumentStorageServerErrorException if the problem is with the S3 storage or document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage or the document storage. */ - public void deleteFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + public void deleteFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String presignedUrl = this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes, documentStorageUrl); this.s3FileTransferRepository.deleteFile(presignedUrl); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepository.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepository.java index 5876d429d7..061fe84a09 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepository.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepository.java @@ -1,12 +1,11 @@ package de.muenchen.oss.digiwf.s3.integration.client.repository; +import de.muenchen.oss.digiwf.s3.integration.client.api.FolderApiApi; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; -import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; -import de.muenchen.oss.digiwf.s3.integration.client.api.FolderApiApi; import de.muenchen.oss.digiwf.s3.integration.client.model.FilesInFolderDto; +import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; @@ -24,22 +23,6 @@ public class DocumentStorageFolderRepository { private final ApiClientFactory apiClientFactory; - /** - * Deletes the folder with all containing files on document storage. - * - * @param pathToFolder which defines the folder in the document storage. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the document storage. - * @throws DocumentStorageException if the problem cannot be assigned directly to the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public void deleteFolder(final String pathToFolder) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException, PropertyNotSetException { - this.deleteFolder( - pathToFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Deletes the folder with all containing files on document storage. * @@ -49,7 +32,8 @@ public void deleteFolder(final String pathToFolder) throws DocumentStorageClient * @throws DocumentStorageServerErrorException if the problem is with the document storage. * @throws DocumentStorageException if the problem cannot be assigned directly to the document storage. */ - public void deleteFolder(final String pathToFolder, final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public void deleteFolder(final String pathToFolder, final String documentStorageUrl) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { final FolderApiApi folderApi = this.apiClientFactory.getFolderApiForDocumentStorageUrl(documentStorageUrl); folderApi.delete(pathToFolder); @@ -62,28 +46,12 @@ public void deleteFolder(final String pathToFolder, final String documentStorage log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The request to delete a folder failed."); + final String message = "The request to delete a folder failed."; log.error(message); throw new DocumentStorageException(message, exception); } } - /** - * Returns all files within a folder given in the parameter from document storage. - * - * @param pathToFolder which defines the folder in the document storage. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the document storage. - * @throws DocumentStorageException if the problem cannot be assigned directly to the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public Mono> getAllFilesInFolderRecursively(final String pathToFolder) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException, PropertyNotSetException { - return this.getAllFilesInFolderRecursively( - pathToFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Returns all files within a folder given in the parameter from document storage. * @@ -93,7 +61,8 @@ public Mono> getAllFilesInFolderRecursively(final String pathToFolde * @throws DocumentStorageServerErrorException if the problem is with the document storage. * @throws DocumentStorageException if the problem cannot be assigned directly to the document storage. */ - public Mono> getAllFilesInFolderRecursively(final String pathToFolder, final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public Mono> getAllFilesInFolderRecursively(final String pathToFolder, final String documentStorageUrl) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { final FolderApiApi folderApi = this.apiClientFactory.getFolderApiForDocumentStorageUrl(documentStorageUrl); final Mono filesInFolderDto = folderApi.getAllFilesInFolderRecursively(pathToFolder); @@ -107,7 +76,7 @@ public Mono> getAllFilesInFolderRecursively(final String pathToFolde log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The request to get all files within a folder failed."); + final String message = "The request to get all files within a folder failed."; log.error(message); throw new DocumentStorageException(message, exception); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepository.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepository.java index 3e4d10c685..3caa549a9c 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepository.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepository.java @@ -1,13 +1,12 @@ package de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl; +import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; -import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; -import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; import de.muenchen.oss.digiwf.s3.integration.client.model.FileDataDto; import de.muenchen.oss.digiwf.s3.integration.client.model.PresignedUrlDto; +import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; @@ -25,25 +24,6 @@ public class PresignedUrlRepository { private final ApiClientFactory apiClientFactory; - /** - * Fetches a presignedURL for the file named in the parameter to get a file from the document storage. - * - * @param pathToFile defines the path to the file. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @return the presignedURL. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public Mono getPresignedUrlGetFile(final String pathToFile, final int expireInMinutes) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException, PropertyNotSetException { - return this.getPresignedUrlGetFile( - pathToFile, - expireInMinutes, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Fetches a presignedURL for the file named in the parameter to get a file from the document storage. * @@ -55,7 +35,8 @@ public Mono getPresignedUrlGetFile(final String pathToFile, final int ex * @throws DocumentStorageServerErrorException if the problem is with the document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. */ - public Mono getPresignedUrlGetFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public Mono getPresignedUrlGetFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { final FileApiApi fileApi = this.apiClientFactory.getFileApiForDocumentStorageUrl(documentStorageUrl); final Mono presignedUrlDto = fileApi.get(pathToFile, expireInMinutes); @@ -69,33 +50,12 @@ public Mono getPresignedUrlGetFile(final String pathToFile, final int ex log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The request to create a presigned url to get a file failed."); + final String message = "The request to create a presigned url to get a file failed."; log.error(message); throw new DocumentStorageException(message, exception); } } - /** - * Fetches a presignedURL for the file named in the parameter to store a file in the document storage. - * - * @param pathToFile defines the path to the file. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @param endOfLifeFolder the end of life of the folder defined in refId. May be null. - * @return the presignedURL. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public String getPresignedUrlSaveFile(final String pathToFile, final int expireInMinutes, final LocalDate endOfLifeFolder) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException, PropertyNotSetException { - return this.getPresignedUrlSaveFile( - pathToFile, - expireInMinutes, - endOfLifeFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Fetches a presignedURL for the file named in the parameter to store a file in the document storage. * @@ -108,7 +68,8 @@ public String getPresignedUrlSaveFile(final String pathToFile, final int expireI * @throws DocumentStorageServerErrorException if the problem is with the document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. */ - public String getPresignedUrlSaveFile(final String pathToFile, final int expireInMinutes, final LocalDate endOfLifeFolder, final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public String getPresignedUrlSaveFile(final String pathToFile, final int expireInMinutes, final LocalDate endOfLifeFolder, final String documentStorageUrl) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { final FileApiApi fileApi = this.apiClientFactory.getFileApiForDocumentStorageUrl(documentStorageUrl); final var fileDataDto = new FileDataDto(); @@ -126,33 +87,12 @@ public String getPresignedUrlSaveFile(final String pathToFile, final int expireI log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The request to create a presigned save url failed."); + final String message = "The request to create a presigned save url failed."; log.error(message); throw new DocumentStorageException(message, exception); } } - /** - * Fetches a presignedURL for the file named in the parameter to update a file in the document storage. - * - * @param pathToFile defines the path to the file. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @param endOfLifeFolder the end of life of the folder defined in refId. May be null. - * @return the presignedURL. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public String getPresignedUrlUpdateFile(final String pathToFile, final int expireInMinutes, final LocalDate endOfLifeFolder) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException, PropertyNotSetException { - return this.getPresignedUrlUpdateFile( - pathToFile, - expireInMinutes, - endOfLifeFolder, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Fetches a presignedURL for the file named in the parameter to update a file in the document storage. * @@ -165,7 +105,8 @@ public String getPresignedUrlUpdateFile(final String pathToFile, final int expir * @throws DocumentStorageServerErrorException if the problem is with the document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. */ - public String getPresignedUrlUpdateFile(final String pathToFile, final int expireInMinutes, final LocalDate endOfLifeFolder, final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public String getPresignedUrlUpdateFile(final String pathToFile, final int expireInMinutes, final LocalDate endOfLifeFolder, + final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { final FileApiApi fileApi = this.apiClientFactory.getFileApiForDocumentStorageUrl(documentStorageUrl); final var fileDataDto = new FileDataDto(); @@ -183,31 +124,12 @@ public String getPresignedUrlUpdateFile(final String pathToFile, final int expir log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The request to create a presigned update url failed."); + final String message = "The request to create a presigned update url failed."; log.error(message); throw new DocumentStorageException(message, exception); } } - /** - * Fetches a presignedURL for the file named in the parameter to delete a file from the document storage. - * - * @param pathToFile defines the path to the file. - * @param expireInMinutes the expiration time of the presignedURL in minutes. - * @return the presignedURL. - * @throws DocumentStorageClientErrorException if the problem is with the client. - * @throws DocumentStorageServerErrorException if the problem is with the document storage. - * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. - * @throws PropertyNotSetException if the property "io.muenchendigital.digiwf.s3.client.defaultDocumentStorageUrl" is not set. - */ - public String getPresignedUrlDeleteFile(final String pathToFile, final int expireInMinutes) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException, PropertyNotSetException { - return this.getPresignedUrlDeleteFile( - pathToFile, - expireInMinutes, - this.apiClientFactory.getDefaultDocumentStorageUrl() - ); - } - /** * Fetches a presignedURL for the file named in the parameter to delete a file from the document storage. * @@ -219,7 +141,8 @@ public String getPresignedUrlDeleteFile(final String pathToFile, final int expir * @throws DocumentStorageServerErrorException if the problem is with the document storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the document storage. */ - public String getPresignedUrlDeleteFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public String getPresignedUrlDeleteFile(final String pathToFile, final int expireInMinutes, final String documentStorageUrl) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { final FileApiApi fileApi = this.apiClientFactory.getFileApiForDocumentStorageUrl(documentStorageUrl); final Mono presignedUrlDto = fileApi.delete1(pathToFile, expireInMinutes); @@ -233,7 +156,7 @@ public String getPresignedUrlDeleteFile(final String pathToFile, final int expir log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The request to create a presigned url to delete a file failed."); + final String message = "The request to create a presigned url to delete a file failed."; log.error(message); throw new DocumentStorageException(message, exception); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/transfer/S3FileTransferRepository.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/transfer/S3FileTransferRepository.java index 319d36df60..4535a6a689 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/transfer/S3FileTransferRepository.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/repository/transfer/S3FileTransferRepository.java @@ -5,6 +5,7 @@ import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import lombok.val; import org.springframework.core.io.InputStreamResource; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; @@ -27,6 +28,11 @@ @RequiredArgsConstructor public class S3FileTransferRepository { + private static final String REQUEST_FAILED_WITH_STATUS_CODE = "The presigned url request failed with http status %s."; + private static final String REQUEST_FAILED = "The presigned url request failed."; + + private final RestTemplate restTemplate = new RestTemplate(); + /** * Gets a file from document storage using the presignedURL. * @@ -38,13 +44,13 @@ public class S3FileTransferRepository { */ public byte[] getFile(final String presignedUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { - final var headers = new HttpHeaders(); + val headers = new HttpHeaders(); final HttpEntity httpEntity = new HttpEntity<>(headers); - /** + /* * Using the RestTemplate without any authorization. * The presigned URL contains any authorization against the S3 storage. */ - final ResponseEntity responseEntity = new RestTemplate().exchange( + final ResponseEntity responseEntity = restTemplate.exchange( URI.create(presignedUrl), HttpMethod.GET, httpEntity, @@ -52,15 +58,15 @@ public byte[] getFile(final String presignedUrl) throws DocumentStorageClientErr ); return responseEntity.getBody(); } catch (final HttpClientErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageClientErrorException(message, exception); } catch (final HttpServerErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The presigned url request failed."); + final String message = REQUEST_FAILED; log.error(message); throw new DocumentStorageException(message, exception); } @@ -75,10 +81,10 @@ public byte[] getFile(final String presignedUrl) throws DocumentStorageClientErr */ public InputStream getFileInputStream(final String presignedUrl) throws DocumentStorageException { try { - final var urlResource = new UrlResource(presignedUrl); + val urlResource = new UrlResource(presignedUrl); return urlResource.getInputStream(); } catch (final IOException exception) { - final String message = String.format("The presigned url request failed."); + final String message = REQUEST_FAILED; log.error(message); throw new DocumentStorageException(message, exception); } @@ -93,30 +99,31 @@ public InputStream getFileInputStream(final String presignedUrl) throws Document * @throws DocumentStorageServerErrorException if the problem is with the S3 storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage. */ - public void saveFile(final String presignedUrl, final byte[] file) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public void saveFile(final String presignedUrl, final byte[] file) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { - final var headers = new HttpHeaders(); + val headers = new HttpHeaders(); final HttpEntity fileHttpEntity = new HttpEntity<>(file, headers); - /** + /* * Using the RestTemplate without any authorization. * The presigned URL contains any authorization against the S3 storage. */ - new RestTemplate().exchange( + restTemplate.exchange( URI.create(presignedUrl), HttpMethod.PUT, fileHttpEntity, Void.class ); } catch (final HttpClientErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageClientErrorException(message, exception); } catch (final HttpServerErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The presigned url request failed."); + final String message = REQUEST_FAILED; log.error(message); throw new DocumentStorageException(message, exception); } @@ -131,30 +138,31 @@ public void saveFile(final String presignedUrl, final byte[] file) throws Docume * @throws DocumentStorageServerErrorException if the problem is with the S3 storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage. */ - public void saveFileInputStream(final String presignedUrl, final InputStream file) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public void saveFileInputStream(final String presignedUrl, final InputStream file) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { - final var headers = new HttpHeaders(); + val headers = new HttpHeaders(); final HttpEntity fileHttpEntity = new HttpEntity<>(new InputStreamResource(file), headers); - /** + /* * Using the RestTemplate without any authorization. * The presigned URL contains any authorization against the S3 storage. */ - new RestTemplate().exchange( + restTemplate.exchange( URI.create(presignedUrl), HttpMethod.PUT, fileHttpEntity, Void.class ); } catch (final HttpClientErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageClientErrorException(message, exception); } catch (final HttpServerErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The presigned url request failed."); + final String message = REQUEST_FAILED; log.error(message); throw new DocumentStorageException(message, exception); } @@ -169,33 +177,9 @@ public void saveFileInputStream(final String presignedUrl, final InputStream fil * @throws DocumentStorageServerErrorException if the problem is with the S3 storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage. */ - public void updateFile(final String presignedUrl, final byte[] file) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { - try { - final var headers = new HttpHeaders(); - final HttpEntity fileHttpEntity = new HttpEntity<>(file, headers); - /** - * Using the RestTemplate without any authorization. - * The presigned URL contains any authorization against the S3 storage. - */ - new RestTemplate().exchange( - URI.create(presignedUrl), - HttpMethod.PUT, - fileHttpEntity, - Void.class - ); - } catch (final HttpClientErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); - log.error(message); - throw new DocumentStorageClientErrorException(message, exception); - } catch (final HttpServerErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); - log.error(message); - throw new DocumentStorageServerErrorException(message, exception); - } catch (final RestClientException exception) { - final String message = String.format("The presigned url request failed."); - log.error(message); - throw new DocumentStorageException(message, exception); - } + public void updateFile(final String presignedUrl, final byte[] file) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + saveFile(presignedUrl, file); } /** @@ -207,33 +191,9 @@ public void updateFile(final String presignedUrl, final byte[] file) throws Docu * @throws DocumentStorageServerErrorException if the problem is with the S3 storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage. */ - public void updateFileInputStream(final String presignedUrl, final InputStream file) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { - try { - final var headers = new HttpHeaders(); - final HttpEntity fileHttpEntity = new HttpEntity<>(new InputStreamResource(file), headers); - /** - * Using the RestTemplate without any authorization. - * The presigned URL contains any authorization against the S3 storage. - */ - new RestTemplate().exchange( - URI.create(presignedUrl), - HttpMethod.PUT, - fileHttpEntity, - Void.class - ); - } catch (final HttpClientErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); - log.error(message); - throw new DocumentStorageClientErrorException(message, exception); - } catch (final HttpServerErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); - log.error(message); - throw new DocumentStorageServerErrorException(message, exception); - } catch (final RestClientException exception) { - final String message = String.format("The presigned url request failed."); - log.error(message); - throw new DocumentStorageException(message, exception); - } + public void updateFileInputStream(final String presignedUrl, final InputStream file) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + saveFileInputStream(presignedUrl, file); } /** @@ -244,30 +204,31 @@ public void updateFileInputStream(final String presignedUrl, final InputStream f * @throws DocumentStorageServerErrorException if the problem is with the S3 storage. * @throws DocumentStorageException if the problem cannot be assigned to either the client or the S3 storage. */ - public void deleteFile(final String presignedUrl) throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { + public void deleteFile(final String presignedUrl) + throws DocumentStorageClientErrorException, DocumentStorageServerErrorException, DocumentStorageException { try { - final var headers = new HttpHeaders(); + val headers = new HttpHeaders(); final HttpEntity fileHttpEntity = new HttpEntity<>(headers); - /** + /* * Using the RestTemplate without any authorization. * The presigned URL contains any authorization against the S3 storage. */ - new RestTemplate().exchange( + restTemplate.exchange( URI.create(presignedUrl), HttpMethod.DELETE, fileHttpEntity, Void.class ); } catch (final HttpClientErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageClientErrorException(message, exception); } catch (final HttpServerErrorException exception) { - final String message = String.format("The presigned url request failed with http status %s.", exception.getStatusCode()); + final String message = String.format(REQUEST_FAILED_WITH_STATUS_CODE, exception.getStatusCode()); log.error(message); throw new DocumentStorageServerErrorException(message, exception); } catch (final RestClientException exception) { - final String message = String.format("The presigned url request failed."); + final String message = REQUEST_FAILED; log.error(message); throw new DocumentStorageException(message, exception); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/ApiClientFactory.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/ApiClientFactory.java index 323bab1ae1..a98d2e1360 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/ApiClientFactory.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/ApiClientFactory.java @@ -1,31 +1,18 @@ package de.muenchen.oss.digiwf.s3.integration.client.service; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.ApiClient; import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.api.FolderApiApi; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.springframework.web.reactive.function.client.WebClient; @RequiredArgsConstructor @Slf4j public class ApiClientFactory { - private final String defaultDocumentStorageUrl; - private final WebClient webClient; - public String getDefaultDocumentStorageUrl() throws PropertyNotSetException { - if (StringUtils.isNotBlank(this.defaultDocumentStorageUrl)) { - return this.defaultDocumentStorageUrl; - } - final String message = "Default document storage is not set. Make sure the property io.muenchendigital.digiwf.s3.client.documentStorageUrl is set."; - log.error(message); - throw new PropertyNotSetException(message); - } - public FileApiApi getFileApiForDocumentStorageUrl(final String documentStorageUrl) { return new FileApiApi(this.getApiClientForDocumentStorageUrl(documentStorageUrl)); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/FileExtensionService.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/FileExtensionService.java new file mode 100644 index 0000000000..94bdfbf63f --- /dev/null +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/FileExtensionService.java @@ -0,0 +1,72 @@ +package de.muenchen.oss.digiwf.s3.integration.client.service; + +import de.muenchen.oss.digiwf.s3.integration.client.exception.NoFileTypeException; +import org.apache.tika.Tika; +import org.apache.tika.mime.MimeType; +import org.apache.tika.mime.MimeTypeException; +import org.apache.tika.mime.MimeTypes; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * A service class for managing file extensions and detecting file types. + */ +public class FileExtensionService { + + private static final String NO_FILE_EXTENSION = "No file extension found for %s"; + + /** + * Map stores supported file extensions and their corresponding MIME types. If it is empty, all types are supported. + */ + private final Map supportedFileExtensions; + + public FileExtensionService(final Map supportedFileExtensions) { + this.supportedFileExtensions = Objects.nonNull(supportedFileExtensions) ? supportedFileExtensions : new HashMap<>(); + } + + /** + * Checks if a given file type is supported. + * + * @param type the file type to check. + * @return {@code true} if the file type is supported, {@code false} otherwise. + */ + public boolean isSupported(final String type) { + return supportedFileExtensions.isEmpty() || supportedFileExtensions.containsKey(type) || supportedFileExtensions.containsValue(type); + } + + /** + * Retrieves the file extension for a given MIME type. + * + * @param type the MIME type for which to retrieve the file extension. + * @return the file extension. + * @throws NoFileTypeException if no file extension is found for the given MIME type. + */ + public String getFileExtension(final String type) { + final MimeTypes allMimeTypes = MimeTypes.getDefaultMimeTypes(); + MimeType mimeType; + try { + mimeType = allMimeTypes.forName(type); + } catch (MimeTypeException e) { + throw new NoFileTypeException(NO_FILE_EXTENSION + type); + } + final String extension = mimeType.getExtension(); + final int lastDotIndex = extension.lastIndexOf('.'); + if (lastDotIndex == -1) throw new NoFileTypeException(NO_FILE_EXTENSION + type); + final String fileExtension = extension.substring(lastDotIndex + 1); + if (fileExtension.isEmpty()) throw new NoFileTypeException(NO_FILE_EXTENSION + type); + return fileExtension; + } + + /** + * Detects the file type from a byte array. + * + * @param fileContent the byte array representing the file content. + * @return the detected file type as a MIME type string. + */ + public String detectFileType(final byte[] fileContent) { + final Tika tika = new Tika(); + return tika.detect(fileContent); + } +} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3DomainProvider.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3DomainProvider.java new file mode 100644 index 0000000000..72af131beb --- /dev/null +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3DomainProvider.java @@ -0,0 +1,18 @@ +package de.muenchen.oss.digiwf.s3.integration.client.service; + +import java.util.Optional; + +/** + * Implementors obtain a function that provides an S3 storage URL if it is configured for a given process definition. + */ +@FunctionalInterface +public interface S3DomainProvider { + + /** + * Provides an S3 storage URL if it is configured for a given process definition. + * + * @param processDefinitionId The {@link String} id of a process definition. + * @return An {@link Optional} containing an S3 storage URL if it is configured. + */ + Optional provideDomainSpecificS3StorageUrl(String processDefinitionId); +} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3StorageUrlProvider.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3StorageUrlProvider.java new file mode 100644 index 0000000000..8a00438615 --- /dev/null +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/main/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3StorageUrlProvider.java @@ -0,0 +1,59 @@ +package de.muenchen.oss.digiwf.s3.integration.client.service; + +import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.Optional; + +/** + * Provides the S3 storage URL either configured in a process configuration of a given process definition or the default URL. + */ +@Slf4j +public class S3StorageUrlProvider { + + private final S3DomainProvider s3DomainProvider; + + @Getter + private final String defaultDocumentStorageUrl; + + /** + * Constructor for client users which obtain their own {@link S3DomainProvider}. + * + * @param s3DomainProvider The {@link S3DomainProvider} to use for fetching domain-specific S3 URLs. + * @param defaultDocumentStorageUrl The default S3 storage URL to use if no domain-specific URL is available. + */ + public S3StorageUrlProvider(final S3DomainProvider s3DomainProvider, final String defaultDocumentStorageUrl) { + this.s3DomainProvider = s3DomainProvider; + this.defaultDocumentStorageUrl = defaultDocumentStorageUrl; + } + + /** + * Constructor for client users which do not obtain their own {@link S3DomainProvider}. + * + * @param defaultDocumentStorageUrl The default S3 storage URL to use if no domain-specific URL is available. + */ + public S3StorageUrlProvider(final String defaultDocumentStorageUrl) { + this(processDefinition -> Optional.empty(), defaultDocumentStorageUrl); + } + + /** + * Provides an S3 storage URL either configured in a process configuration of a given process definition or the default URL. + * + * @param processDefinitionId The {@link String} process definition id for which the S3 storage URL will be provided. + * @return The S3 storage URL. + * @throws PropertyNotSetException Thrown if the property 'de.muenchen.oss.digiwf.s3.document-storage-url' is unset. + */ + public String provideS3StorageUrl(final String processDefinitionId) throws PropertyNotSetException { + final Optional domainSpecificStorageUrl = s3DomainProvider.provideDomainSpecificS3StorageUrl(processDefinitionId); + if (domainSpecificStorageUrl.isPresent()) return domainSpecificStorageUrl.get(); + if (StringUtils.isNotBlank(this.defaultDocumentStorageUrl)) { + return this.defaultDocumentStorageUrl; + } + final String message = "Default document storage is not set. Make sure the property de.muenchen.oss.digiwf.s3.document-storage-url is set."; + log.error(message); + throw new PropertyNotSetException(message); + } + +} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepositoryTest.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepositoryTest.java index 2a6262ede9..381129ed43 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepositoryTest.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFileRepositoryTest.java @@ -1,10 +1,9 @@ package de.muenchen.oss.digiwf.s3.integration.client.repository; +import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; -import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl.PresignedUrlRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.transfer.S3FileTransferRepository; import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; @@ -45,104 +44,97 @@ class DocumentStorageFileRepositoryTest { @BeforeEach public void beforeEach() { - this.documentStorageFileRepository = new DocumentStorageFileRepository(this.presignedUrlRepository, this.s3FileTransferRepository, this.apiClientFactory); + this.documentStorageFileRepository = new DocumentStorageFileRepository(this.presignedUrlRepository, this.s3FileTransferRepository, + this.apiClientFactory); Mockito.reset(this.presignedUrlRepository, this.s3FileTransferRepository, this.fileApi, this.apiClientFactory); } @Test - void getFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; final int expireInMinutes = 10; final String presignedUrl = "the_presignedUrl"; - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes, "url")).thenReturn(Mono.just(presignedUrl)); - Mockito.when(this.s3FileTransferRepository.getFile(presignedUrl)).thenReturn(new byte[]{}); - this.documentStorageFileRepository.getFile(pathToFile, expireInMinutes); + Mockito.when(this.s3FileTransferRepository.getFile(presignedUrl)).thenReturn(new byte[] {}); + this.documentStorageFileRepository.getFile(pathToFile, expireInMinutes, "url"); Mockito.verify(this.presignedUrlRepository, Mockito.times(1)).getPresignedUrlGetFile(pathToFile, expireInMinutes, "url"); Mockito.verify(this.s3FileTransferRepository, Mockito.times(1)).getFile(presignedUrl); } @Test - void saveFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void saveFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; - final byte[] file = new byte[]{1, 2, 3, 4, 5, 6, 7}; + final byte[] file = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; final int expireInMinutes = 10; final LocalDate endOfLife = LocalDate.now(); final String presignedUrl = "the_presignedUrl"; - - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife, "url")).thenReturn(presignedUrl); Mockito.doNothing().when(this.s3FileTransferRepository).saveFile(presignedUrl, file); - this.documentStorageFileRepository.saveFile(pathToFile, file, expireInMinutes, endOfLife); + this.documentStorageFileRepository.saveFile(pathToFile, file, expireInMinutes, endOfLife, "url"); Mockito.verify(this.presignedUrlRepository, Mockito.times(1)).getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife, "url"); Mockito.verify(this.s3FileTransferRepository, Mockito.times(1)).saveFile(presignedUrl, file); } @Test - void updateFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void updateFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; - final byte[] file = new byte[]{1, 2, 3, 4, 5, 6, 7}; + final byte[] file = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; final int expireInMinutes = 10; final LocalDate endOfLife = LocalDate.now(); final String presignedUrl = "the_presignedUrl"; - - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife, "url")).thenReturn(presignedUrl); Mockito.doNothing().when(this.s3FileTransferRepository).updateFile(presignedUrl, file); - this.documentStorageFileRepository.updateFile(pathToFile, file, expireInMinutes, endOfLife); + this.documentStorageFileRepository.updateFile(pathToFile, file, expireInMinutes, endOfLife, "url"); Mockito.verify(this.presignedUrlRepository, Mockito.times(1)).getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife, "url"); Mockito.verify(this.s3FileTransferRepository, Mockito.times(1)).updateFile(presignedUrl, file); } @Test - void updateEndOfLife() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void updateEndOfLife() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; final LocalDate endOfLife = LocalDate.now(); Mockito.reset(this.presignedUrlRepository, this.s3FileTransferRepository, this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); - this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife); + this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife, "url"); Mockito.verify(this.fileApi, Mockito.times(1)).updateEndOfLife(pathToFile, endOfLife); Mockito.reset(this.presignedUrlRepository, this.s3FileTransferRepository, this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); Mockito.doThrow(new HttpClientErrorException(HttpStatus.BAD_REQUEST)).when(this.fileApi).updateEndOfLife(pathToFile, endOfLife); - Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife)); + Assertions.assertThrows(DocumentStorageClientErrorException.class, + () -> this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife, "url")); Mockito.verify(this.fileApi, Mockito.times(1)).updateEndOfLife(pathToFile, endOfLife); Mockito.reset(this.presignedUrlRepository, this.s3FileTransferRepository, this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); Mockito.doThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR)).when(this.fileApi).updateEndOfLife(pathToFile, endOfLife); - Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife)); + Assertions.assertThrows(DocumentStorageServerErrorException.class, + () -> this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife, "url")); Mockito.verify(this.fileApi, Mockito.times(1)).updateEndOfLife(pathToFile, endOfLife); Mockito.reset(this.presignedUrlRepository, this.s3FileTransferRepository, this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); Mockito.doThrow(new RestClientException("Something happened")).when(this.fileApi).updateEndOfLife(pathToFile, endOfLife); - Assertions.assertThrows(DocumentStorageException.class, () -> this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife)); + Assertions.assertThrows(DocumentStorageException.class, () -> this.documentStorageFileRepository.updateEndOfLife(pathToFile, endOfLife, "url")); Mockito.verify(this.fileApi, Mockito.times(1)).updateEndOfLife(pathToFile, endOfLife); } @Test - void deleteFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void deleteFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; - final Integer expireInMinutes = 10; + final int expireInMinutes = 10; final String presignedUrl = "the_presignedUrl"; - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes, "url")).thenReturn(presignedUrl); Mockito.doNothing().when(this.s3FileTransferRepository).deleteFile(presignedUrl); - this.documentStorageFileRepository.deleteFile(pathToFile, expireInMinutes); + this.documentStorageFileRepository.deleteFile(pathToFile, expireInMinutes, "url"); Mockito.verify(this.presignedUrlRepository, Mockito.times(1)).getPresignedUrlDeleteFile(pathToFile, expireInMinutes, "url"); Mockito.verify(this.s3FileTransferRepository, Mockito.times(1)).deleteFile(presignedUrl); diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepositoryTest.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepositoryTest.java index 5314007e86..6bdb487ec3 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepositoryTest.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/DocumentStorageFolderRepositoryTest.java @@ -42,71 +42,63 @@ public void beforeEach() { } @Test - void deleteFolder() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void deleteFolder() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFolder = "folder"; Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.when(this.folderApi.delete(pathToFolder)).thenReturn(Mono.empty()); - this.documentStorageFolderRepository.deleteFolder(pathToFolder); + this.documentStorageFolderRepository.deleteFolder(pathToFolder, "url"); Mockito.verify(this.folderApi, Mockito.times(1)).delete(pathToFolder); Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.doThrow(new HttpClientErrorException(HttpStatus.BAD_REQUEST)).when(this.folderApi).delete(pathToFolder); - Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.documentStorageFolderRepository.deleteFolder(pathToFolder)); + Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.documentStorageFolderRepository.deleteFolder(pathToFolder, "url")); Mockito.verify(this.folderApi, Mockito.times(1)).delete(pathToFolder); Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.doThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR)).when(this.folderApi).delete(pathToFolder); - Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.documentStorageFolderRepository.deleteFolder(pathToFolder)); + Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.documentStorageFolderRepository.deleteFolder(pathToFolder, "url")); Mockito.verify(this.folderApi, Mockito.times(1)).delete(pathToFolder); Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.doThrow(new RestClientException("Something happened")).when(this.folderApi).delete(pathToFolder); - Assertions.assertThrows(DocumentStorageException.class, () -> this.documentStorageFolderRepository.deleteFolder(pathToFolder)); + Assertions.assertThrows(DocumentStorageException.class, () -> this.documentStorageFolderRepository.deleteFolder(pathToFolder, "url")); Mockito.verify(this.folderApi, Mockito.times(1)).delete(pathToFolder); } @Test - void getAllFilesInFolderRecursively() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getAllFilesInFolderRecursively() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFolder = "folder"; final FilesInFolderDto filesInFolderDto = new FilesInFolderDto(); filesInFolderDto.setPathToFiles(Set.of("folder/file.txt")); Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.when(this.folderApi.getAllFilesInFolderRecursively(pathToFolder)).thenReturn(Mono.just(filesInFolderDto)); - this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder); + this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, "url"); Mockito.verify(this.folderApi, Mockito.times(1)).getAllFilesInFolderRecursively(pathToFolder); Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.doThrow(new HttpClientErrorException(HttpStatus.BAD_REQUEST)).when(this.folderApi).getAllFilesInFolderRecursively(pathToFolder); - Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder)); + Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, "url")); Mockito.verify(this.folderApi, Mockito.times(1)).getAllFilesInFolderRecursively(pathToFolder); Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.doThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR)).when(this.folderApi).getAllFilesInFolderRecursively(pathToFolder); - Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder)); + Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, "url")); Mockito.verify(this.folderApi, Mockito.times(1)).getAllFilesInFolderRecursively(pathToFolder); Mockito.reset(this.folderApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); Mockito.when(this.apiClientFactory.getFolderApiForDocumentStorageUrl("url")).thenReturn(this.folderApi); Mockito.doThrow(new RestClientException("Something happened")).when(this.folderApi).getAllFilesInFolderRecursively(pathToFolder); - Assertions.assertThrows(DocumentStorageException.class, () -> this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder)); + Assertions.assertThrows(DocumentStorageException.class, () -> this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, "url")); Mockito.verify(this.folderApi, Mockito.times(1)).getAllFilesInFolderRecursively(pathToFolder); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepositoryTest.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepositoryTest.java index a09db689e2..9de9594025 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepositoryTest.java +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/repository/presignedurl/PresignedUrlRepositoryTest.java @@ -1,13 +1,12 @@ package de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl; +import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; -import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; -import de.muenchen.oss.digiwf.s3.integration.client.api.FileApiApi; import de.muenchen.oss.digiwf.s3.integration.client.model.FileDataDto; import de.muenchen.oss.digiwf.s3.integration.client.model.PresignedUrlDto; +import de.muenchen.oss.digiwf.s3.integration.client.service.ApiClientFactory; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,6 +31,8 @@ @MockitoSettings(strictness = Strictness.STRICT_STUBS) class PresignedUrlRepositoryTest { + private static final String DEFAULT_S3_URL = "defaultURL"; + @Mock private ApiClientFactory apiClientFactory; @@ -47,7 +48,8 @@ public void beforeEach() { } @Test - void getPresignedUrlGetFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getPresignedUrlGetFile() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; final Integer expireInMinutes = 10; @@ -55,46 +57,46 @@ void getPresignedUrlGetFile() throws DocumentStorageException, DocumentStorageCl expected.setUrl("the_presignedUrl"); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.get(pathToFile, expireInMinutes)).thenReturn(Mono.just(expected)); - final Mono result = this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes); + final Mono result = this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes, DEFAULT_S3_URL); Mockito.verify(this.fileApi, Mockito.times(1)).get(pathToFile, expireInMinutes); assertThat(result.block(), is(expected.getUrl())); Mockito.reset(this.fileApi); } @Test - void getPresignedUrlGetFileException() throws PropertyNotSetException { + void getPresignedUrlGetFileException() { final String pathToFile = "folder/file.txt"; final Integer expireInMinutes = 10; Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.get(pathToFile, expireInMinutes)).thenThrow(new HttpClientErrorException(HttpStatus.BAD_REQUEST)); - Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes)); + Assertions.assertThrows(DocumentStorageClientErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).get(pathToFile, expireInMinutes); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.get(pathToFile, expireInMinutes)).thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR)); - Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes)); + Assertions.assertThrows(DocumentStorageServerErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).get(pathToFile, expireInMinutes); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.get(pathToFile, expireInMinutes)).thenThrow(new RestClientException("Something happened")); - Assertions.assertThrows(DocumentStorageException.class, () -> this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes)); + Assertions.assertThrows(DocumentStorageException.class, + () -> this.presignedUrlRepository.getPresignedUrlGetFile(pathToFile, expireInMinutes, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).get(pathToFile, expireInMinutes); } @Test - void getPresignedUrlSaveFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getPresignedUrlSaveFile() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; - final Integer expireInMinutes = 10; + final int expireInMinutes = 10; final LocalDate endOfLife = LocalDate.now(); final FileDataDto fileDataDto = new FileDataDto(); @@ -106,19 +108,18 @@ void getPresignedUrlSaveFile() throws DocumentStorageException, DocumentStorageC expected.setUrl("the_presignedUrl"); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.save(fileDataDto)).thenReturn(Mono.just(expected)); - final String result = this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife); + final String result = this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL); Mockito.verify(this.fileApi, Mockito.times(1)).save(fileDataDto); assertThat(result, is(expected.getUrl())); } @Test - void getPresignedUrlSaveFileException() throws PropertyNotSetException { + void getPresignedUrlSaveFileException() { final String pathToFile = "folder/file.txt"; - final Integer expireInMinutes = 10; + final int expireInMinutes = 10; final LocalDate endOfLife = LocalDate.now(); final FileDataDto fileDataDto = new FileDataDto(); @@ -127,31 +128,32 @@ void getPresignedUrlSaveFileException() throws PropertyNotSetException { fileDataDto.setEndOfLife(endOfLife); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.save(fileDataDto)).thenThrow(new HttpClientErrorException(HttpStatus.BAD_REQUEST)); - Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife)); + Assertions.assertThrows(DocumentStorageClientErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).save(fileDataDto); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.save(fileDataDto)).thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR)); - Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife)); + Assertions.assertThrows(DocumentStorageServerErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).save(fileDataDto); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.save(fileDataDto)).thenThrow(new RestClientException("Something happened")); - Assertions.assertThrows(DocumentStorageException.class, () -> this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife)); + Assertions.assertThrows(DocumentStorageException.class, + () -> this.presignedUrlRepository.getPresignedUrlSaveFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).save(fileDataDto); } @Test - void getPresignedUrlUpdateFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getPresignedUrlUpdateFile() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; - final Integer expireInMinutes = 10; + final int expireInMinutes = 10; final LocalDate endOfLife = LocalDate.now(); final FileDataDto fileDataDto = new FileDataDto(); @@ -163,19 +165,18 @@ void getPresignedUrlUpdateFile() throws DocumentStorageException, DocumentStorag expected.setUrl("the_presignedUrl"); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.update(fileDataDto)).thenReturn(Mono.just(expected)); - final String result = this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife); + final String result = this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL); Mockito.verify(this.fileApi, Mockito.times(1)).update(fileDataDto); assertThat(result, is(expected.getUrl())); } @Test - void getPresignedUrlUpdateFileException() throws PropertyNotSetException { + void getPresignedUrlUpdateFileException() { final String pathToFile = "folder/file.txt"; - final Integer expireInMinutes = 10; + final int expireInMinutes = 10; final LocalDate endOfLife = LocalDate.now(); final FileDataDto fileDataDto = new FileDataDto(); @@ -184,69 +185,69 @@ void getPresignedUrlUpdateFileException() throws PropertyNotSetException { fileDataDto.setEndOfLife(endOfLife); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.update(fileDataDto)).thenThrow(new HttpClientErrorException(HttpStatus.BAD_REQUEST)); - Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife)); + Assertions.assertThrows(DocumentStorageClientErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).update(fileDataDto); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.update(fileDataDto)).thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR)); - Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife)); + Assertions.assertThrows(DocumentStorageServerErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).update(fileDataDto); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.update(fileDataDto)).thenThrow(new RestClientException("Something happened")); - Assertions.assertThrows(DocumentStorageException.class, () -> this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife)); + Assertions.assertThrows(DocumentStorageException.class, + () -> this.presignedUrlRepository.getPresignedUrlUpdateFile(pathToFile, expireInMinutes, endOfLife, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).update(fileDataDto); } @Test - void getPresignedUrlDeleteFile() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getPresignedUrlDeleteFile() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final String pathToFile = "folder/file.txt"; - final Integer expireInMinutes = 10; + final int expireInMinutes = 10; final PresignedUrlDto expected = new PresignedUrlDto(); expected.setUrl("the_presignedUrl"); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.delete1(pathToFile, expireInMinutes)).thenReturn(Mono.just(expected)); - final String result = this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes); + final String result = this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes, DEFAULT_S3_URL); Mockito.verify(this.fileApi, Mockito.times(1)).delete1(pathToFile, expireInMinutes); assertThat(result, is(expected.getUrl())); } @Test - void getPresignedUrlDeleteFileException() throws PropertyNotSetException { + void getPresignedUrlDeleteFileException() { final String pathToFile = "folder/file.txt"; - final Integer expireInMinutes = 10; + final int expireInMinutes = 10; Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.delete1(pathToFile, expireInMinutes)).thenThrow(new HttpClientErrorException(HttpStatus.BAD_REQUEST)); - Assertions.assertThrows(DocumentStorageClientErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes)); + Assertions.assertThrows(DocumentStorageClientErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).delete1(pathToFile, expireInMinutes); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.delete1(pathToFile, expireInMinutes)).thenThrow(new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR)); - Assertions.assertThrows(DocumentStorageServerErrorException.class, () -> this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes)); + Assertions.assertThrows(DocumentStorageServerErrorException.class, + () -> this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).delete1(pathToFile, expireInMinutes); Mockito.reset(this.fileApi, this.apiClientFactory); - Mockito.when(this.apiClientFactory.getDefaultDocumentStorageUrl()).thenReturn("url"); - Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl("url")).thenReturn(this.fileApi); + Mockito.when(this.apiClientFactory.getFileApiForDocumentStorageUrl(DEFAULT_S3_URL)).thenReturn(this.fileApi); Mockito.when(this.fileApi.delete1(pathToFile, expireInMinutes)).thenThrow(new RestClientException("Something happened")); - Assertions.assertThrows(DocumentStorageException.class, () -> this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes)); + Assertions.assertThrows(DocumentStorageException.class, + () -> this.presignedUrlRepository.getPresignedUrlDeleteFile(pathToFile, expireInMinutes, DEFAULT_S3_URL)); Mockito.verify(this.fileApi, Mockito.times(1)).delete1(pathToFile, expireInMinutes); } diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/ApiClientFactoryTest.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/ApiClientFactoryTest.java deleted file mode 100644 index fc685351f9..0000000000 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/ApiClientFactoryTest.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.muenchen.oss.digiwf.s3.integration.client.service; - -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -class ApiClientFactoryTest { - - @Test - void getDefaultDocumentStorageUrl() throws PropertyNotSetException { - var apiClientFactory = new ApiClientFactory(null, null); - Assertions.assertThrows(PropertyNotSetException.class, apiClientFactory::getDefaultDocumentStorageUrl); - - apiClientFactory = new ApiClientFactory("url", null); - assertThat(apiClientFactory.getDefaultDocumentStorageUrl(), is("url")); - } - -} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/FileExtensionServiceTest.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/FileExtensionServiceTest.java new file mode 100644 index 0000000000..41795e9fea --- /dev/null +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/FileExtensionServiceTest.java @@ -0,0 +1,52 @@ +package de.muenchen.oss.digiwf.s3.integration.client.service; + +import de.muenchen.oss.digiwf.s3.integration.client.exception.NoFileTypeException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class FileExtensionServiceTest { + + private FileExtensionService service; + + @BeforeEach + void setUp() { + final Map fileExtensions = new HashMap<>(); + fileExtensions.put("pdf", "application/pdf"); + fileExtensions.put("txt", "text/plain"); + service = new FileExtensionService(fileExtensions); + } + + @Test + void testIsSupported() { + assertTrue(service.isSupported("pdf")); + assertFalse(service.isSupported("exe")); + } + + @Test + void testGetFileExtension() { + assertEquals("pdf", service.getFileExtension("application/pdf")); + } + + @Test + void testGetFileExtensionThrowsException() { + assertThrows(NoFileTypeException.class, () -> service.getFileExtension("application/unknown")); + } + + @Test + void testDetectFileType() { + final byte[] fileContent = "Hello, universe!".getBytes(); + assertEquals("text/plain", service.detectFileType(fileContent)); + } + + @Test + void testSupportCheckWithEmptyMap() { + final FileExtensionService emptyService = new FileExtensionService(new HashMap<>()); + assertTrue(emptyService.isSupported("anyType")); + } +} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3StorageUrlProviderTest.java b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3StorageUrlProviderTest.java new file mode 100644 index 0000000000..72a1180f29 --- /dev/null +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-client/src/test/java/de/muenchen/oss/digiwf/s3/integration/client/service/S3StorageUrlProviderTest.java @@ -0,0 +1,58 @@ +package de.muenchen.oss.digiwf.s3.integration.client.service; + +import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +class S3StorageUrlProviderTest { + + private final S3DomainProvider s3DomainProvider = mock(S3DomainProvider.class); + + private static final String DEFAULT_DOCUMENT_STORAGE_URL = "default-storage-url"; + private static final String PROCESS_DEFINITION_ID = "processDefinitionId"; + private static final String DOMAIN_SPECIFIC_STORAGE_URL = "domain-specific-url"; + + private S3StorageUrlProvider s3StorageUrlProviderWithDefault; + private S3StorageUrlProvider s3StorageUrlProviderWithoutDefault; + + @BeforeEach + void setUp() { + s3StorageUrlProviderWithDefault = new S3StorageUrlProvider(s3DomainProvider, DEFAULT_DOCUMENT_STORAGE_URL); + s3StorageUrlProviderWithoutDefault = new S3StorageUrlProvider(s3DomainProvider, null); + } + + @Test + void testProvideS3StorageUrl_DomainSpecificUrl() throws PropertyNotSetException { + when(s3DomainProvider.provideDomainSpecificS3StorageUrl(PROCESS_DEFINITION_ID)) + .thenReturn(Optional.of(DOMAIN_SPECIFIC_STORAGE_URL)); + String result = s3StorageUrlProviderWithDefault.provideS3StorageUrl(PROCESS_DEFINITION_ID); + assertEquals(DOMAIN_SPECIFIC_STORAGE_URL, result); + } + + @Test + void testProvideS3StorageUrl_DefaultUrl() throws PropertyNotSetException { + when(s3DomainProvider.provideDomainSpecificS3StorageUrl(PROCESS_DEFINITION_ID)) + .thenReturn(Optional.empty()); + String result = s3StorageUrlProviderWithDefault.provideS3StorageUrl(PROCESS_DEFINITION_ID); + assertEquals(DEFAULT_DOCUMENT_STORAGE_URL, result); + } + + @Test + void testProvideS3StorageUrl_NoUrls() { + when(s3DomainProvider.provideDomainSpecificS3StorageUrl(PROCESS_DEFINITION_ID)) + .thenReturn(Optional.empty()); + PropertyNotSetException exception = assertThrows(PropertyNotSetException.class, () -> + s3StorageUrlProviderWithoutDefault.provideS3StorageUrl(PROCESS_DEFINITION_ID) + ); + + assertEquals("Default document storage is not set. Make sure the property de.muenchen.oss.digiwf.s3.document-storage-url is set.", + exception.getMessage()); + } +} diff --git a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-service/src/main/resources/application.yml b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-service/src/main/resources/application.yml index 8b692de68c..2312c3f4f8 100644 --- a/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-service/src/main/resources/application.yml +++ b/digiwf-integrations/digiwf-s3-integration/digiwf-s3-integration-service/src/main/resources/application.yml @@ -31,6 +31,16 @@ spring: destination: dwf-s3-${DIGIWF_ENV} sendMessage-out-0: destination: dwf-connector-${DIGIWF_ENV} + +de: + muenchen: + oss: + digiwf: + s3: + client: + document-storage-url: "${DOCUMENT_STORAGE_HOST:http://localhost}:${DOCUMENT_STORAGE_PORT:8080}" + enable-security: false + io: muenchendigital: digiwf: @@ -39,9 +49,6 @@ io: accesskey: ${S3_ACCESSKEY} url: ${S3_URL:http://localhost:9000} secretkey: ${S3_SECRETKEY} - client: - document-storage-url: "${DOCUMENT_STORAGE_HOST:http://localhost}:${DOCUMENT_STORAGE_PORT:8080}" - securityEnabled: false proxyUrl: "${S3_PROXY_HOST}:${S3_PROXY_PORT}" cronjob: cleanup: diff --git a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/pom.xml b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/pom.xml index 784e674184..66bad3fea2 100644 --- a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/pom.xml +++ b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/pom.xml @@ -44,18 +44,6 @@ ${project.version} - - - org.apache.tika - tika-core - ${tika.version} - - - org.apache.tika - tika-parsers-standard-package - ${tika.version} - - de.muenchen.oss.digiwf diff --git a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/main/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3Adapter.java b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/main/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3Adapter.java index 59b9e90be9..c15a1785b9 100644 --- a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/main/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3Adapter.java +++ b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/main/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3Adapter.java @@ -1,41 +1,44 @@ package de.muenchen.oss.digiwf.ticket.integration.adapter.out.s3; import de.muenchen.oss.digiwf.message.process.api.error.BpmnError; -import de.muenchen.oss.digiwf.process.api.config.api.ProcessConfigApi; -import de.muenchen.oss.digiwf.process.api.config.api.dto.ConfigEntryTO; -import de.muenchen.oss.digiwf.process.api.config.api.dto.ProcessConfigTO; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFileRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.ticket.integration.application.port.out.LoadFileOutPort; import de.muenchen.oss.digiwf.ticket.integration.domain.model.FileContent; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; -import org.apache.tika.Tika; import java.util.ArrayList; import java.util.List; -import java.util.Optional; +import java.util.Objects; import java.util.Set; @Slf4j @RequiredArgsConstructor public class S3Adapter implements LoadFileOutPort { + private static final String LOAD_FOLDER_FAILED = "LOAD_FOLDER_FAILED"; + private final DocumentStorageFileRepository documentStorageFileRepository; private final DocumentStorageFolderRepository documentStorageFolderRepository; - private final ProcessConfigApi processConfigApi; - private final List supportedExtensions; - - private final String APP_FILE_S3_SYNC_CONFIG = "app_file_s3_sync_config"; + private final FileExtensionService fileExtensionService; + private final S3StorageUrlProvider s3StorageUrlProvider; @Override public List loadFiles(final List filepaths, final String fileContext, final String processDefinition) { - final String s3Storage = getDomainSpecificS3Storage(processDefinition).orElse(null); + final String s3Storage; + try { + s3Storage = s3StorageUrlProvider.provideS3StorageUrl(processDefinition); + } catch (PropertyNotSetException e) { + throw new BpmnError(LOAD_FOLDER_FAILED, e.getMessage()); + } final List contents = new ArrayList<>(); filepaths.forEach(path -> { final String fullPath = fileContext + "/" + path; @@ -48,60 +51,34 @@ public List loadFiles(final List filepaths, final String fi return contents; } - private List getFilesFromFolder(String folderpath, final String domainSpecificS3Storage) { + private List getFilesFromFolder(String folderPath, final String domainSpecificS3Storage) { try { final List contents = new ArrayList<>(); final Set filepath; - if (domainSpecificS3Storage != null) { - filepath = documentStorageFolderRepository.getAllFilesInFolderRecursively(folderpath, domainSpecificS3Storage).block(); - } else { - filepath = documentStorageFolderRepository.getAllFilesInFolderRecursively(folderpath).block(); - } + filepath = documentStorageFolderRepository.getAllFilesInFolderRecursively(folderPath, domainSpecificS3Storage).block(); + if (Objects.isNull(filepath)) throw new BpmnError(LOAD_FOLDER_FAILED, "An folder could not be loaded from url: " + folderPath); filepath.forEach(file -> contents.add(getFile(file, domainSpecificS3Storage))); return contents; - } catch (final DocumentStorageException | DocumentStorageServerErrorException | - DocumentStorageClientErrorException | PropertyNotSetException e) { - throw new BpmnError("LOAD_FOLDER_FAILED", "An folder could not be loaded from url: " + folderpath); + } catch (final NullPointerException | DocumentStorageException | DocumentStorageServerErrorException | DocumentStorageClientErrorException e) { + throw new BpmnError(LOAD_FOLDER_FAILED, "An folder could not be loaded from url: " + folderPath); } } private FileContent getFile(String filepath, final String domainSpecificS3Storage) { try { - final Tika tika = new Tika(); final byte[] bytes; - if (domainSpecificS3Storage != null) { - bytes = this.documentStorageFileRepository.getFile(filepath, 3, domainSpecificS3Storage); - } else { - bytes = this.documentStorageFileRepository.getFile(filepath, 3); - } - final String mimeType = tika.detect(bytes); + bytes = this.documentStorageFileRepository.getFile(filepath, 3, domainSpecificS3Storage); + final String mimeType = fileExtensionService.detectFileType(bytes); final String filename = FilenameUtils.getName(filepath); // check if mimeType exists - supportedExtensions - .stream() - .filter(extension -> extension.equals(mimeType)) - .findAny() - .orElseThrow(() -> new BpmnError("FILE_TYPE_NOT_SUPPORTED", "The type of this file is not supported: " + filepath)); + if (!fileExtensionService.isSupported(mimeType)) + throw new BpmnError("FILE_TYPE_NOT_SUPPORTED", "The type of this file is not supported: " + filepath); return new FileContent(mimeType, filename, bytes); - } catch (final DocumentStorageException | DocumentStorageServerErrorException | - DocumentStorageClientErrorException | PropertyNotSetException e) { + } catch (final DocumentStorageException | DocumentStorageServerErrorException | DocumentStorageClientErrorException e) { throw new BpmnError("LOAD_FILE_FAILED", "An file could not be loaded from url: " + filepath); } } - private Optional getDomainSpecificS3Storage(final String processDefinition) { - try { - final ProcessConfigTO processConfig = processConfigApi.getProcessConfig(processDefinition); - return processConfig.getConfigs().stream() - .filter(cfg -> cfg.getKey().equals(APP_FILE_S3_SYNC_CONFIG)) - .findAny() - .map(ConfigEntryTO::getValue); - } catch (final Exception e) { - return Optional.empty(); - } - - } - } diff --git a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/test/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3AdapterTest.java b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/test/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3AdapterTest.java index 56ee9c2fd1..0f2cc9acab 100644 --- a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/test/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3AdapterTest.java +++ b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-core/src/test/java/de/muenchen/oss/digiwf/ticket/integration/adapter/out/s3/S3AdapterTest.java @@ -4,34 +4,44 @@ import de.muenchen.oss.digiwf.process.api.config.api.ProcessConfigApi; import de.muenchen.oss.digiwf.process.api.config.api.dto.ConfigEntryTO; import de.muenchen.oss.digiwf.process.api.config.api.dto.ProcessConfigTO; +import de.muenchen.oss.digiwf.process.api.config.impl.ProcessConfigApiImpl; +import de.muenchen.oss.digiwf.process.api.config.impl.ProcessConfigClient; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFileRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3DomainProvider; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.ticket.integration.domain.model.FileContent; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; import java.util.Collections; import java.util.List; +import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; class S3AdapterTest { + private static final String DEFAULT_S3_URL = "defaultURL"; + private static final String DOMAIN_SPECIFIC_S3_URL = "domainSpecificURL"; + private final DocumentStorageFileRepository documentStorageFileRepository = mock(DocumentStorageFileRepository.class); private final DocumentStorageFolderRepository documentStorageFolderRepository = mock(DocumentStorageFolderRepository.class); - private final ProcessConfigApi processConfigApi = mock(ProcessConfigApi.class); - private final List supportedExtensions = List.of("application/pdf", "text/plain"); - - private final S3Adapter s3Adapter = new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, processConfigApi, supportedExtensions); + private final ProcessConfigClient processConfigClient = mock(ProcessConfigClient.class); + private final ProcessConfigApi processConfigApi = spy(new ProcessConfigApiImpl(processConfigClient)); + private final Map supportedExtensions = Map.of("pdf", "application/pdf", "txt", "text/plain"); + private final FileExtensionService fileExtensionService = new FileExtensionService(supportedExtensions); + private final S3DomainProvider s3DomainProvider = processConfigApi::getAppFileS3SyncConfig; + private final S3StorageUrlProvider s3StorageUrlProvider = new S3StorageUrlProvider(s3DomainProvider, DEFAULT_S3_URL); + private final S3Adapter s3Adapter = new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, fileExtensionService, s3StorageUrlProvider); // test data private final List filepaths = List.of("path/to/file.txt"); @@ -39,10 +49,12 @@ class S3AdapterTest { private final String fileContext = "fileContext"; @Test - void test_load_single_file_successfully() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void test_load_single_file_successfully() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { // Set up mock behavior - when(documentStorageFileRepository.getFile(startsWith(fileContext), anyInt())).thenReturn("fileContent".getBytes()); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(startsWith(fileContext), anyString())).thenReturn(Mono.just(Collections.emptySet())); + when(documentStorageFileRepository.getFile(startsWith(fileContext), anyInt(), startsWith(DEFAULT_S3_URL))).thenReturn("fileContent".getBytes()); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(startsWith(fileContext), anyString())).thenReturn( + Mono.just(Collections.emptySet())); when(processConfigApi.getProcessConfig(anyString())).thenThrow(new RuntimeException("Process Config does not exist")); // Invoke the method under test @@ -57,14 +69,16 @@ void test_load_single_file_successfully() throws DocumentStorageException, Docum } @Test - void test_load_single_file_from_domain_specific_s3_successfully() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + void test_load_single_file_from_domain_specific_s3_successfully() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { // Set up mock behavior - when(documentStorageFileRepository.getFile(startsWith(fileContext), anyInt(), anyString())).thenReturn("fileContent".getBytes()); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(startsWith(fileContext), anyString())).thenReturn(Mono.just(Collections.emptySet())); + when(documentStorageFileRepository.getFile(startsWith(fileContext), anyInt(), startsWith(DOMAIN_SPECIFIC_S3_URL))).thenReturn("fileContent".getBytes()); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(startsWith(fileContext), anyString())).thenReturn( + Mono.just(Collections.emptySet())); when(processConfigApi.getProcessConfig(anyString())).thenReturn(ProcessConfigTO.builder() .configs(List.of(ConfigEntryTO.builder() .key("app_file_s3_sync_config") - .value("s3storage") + .value(DOMAIN_SPECIFIC_S3_URL) .build())) .build()); @@ -80,13 +94,16 @@ void test_load_single_file_from_domain_specific_s3_successfully() throws Documen } @Test - void test_load_file_throws_bpmn_error_for_unsupported_types() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void test_load_file_throws_bpmn_error_for_unsupported_types() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { // Set up mock behavior - when(documentStorageFileRepository.getFile(startsWith(fileContext), anyInt())).thenReturn("fileContent".getBytes()); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(startsWith(fileContext))).thenReturn(Mono.just(Collections.emptySet())); + when(documentStorageFileRepository.getFile(startsWith(fileContext), anyInt(), startsWith(DEFAULT_S3_URL))).thenReturn("fileContent".getBytes()); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(startsWith(fileContext), startsWith(DEFAULT_S3_URL))).thenReturn(Mono.just(Collections.emptySet())); when(processConfigApi.getProcessConfig(anyString())).thenThrow(new RuntimeException("Process Config does not exist")); + final Map extensions = Map.of("foo", "baa"); + final FileExtensionService tFileExtensionService = new FileExtensionService(extensions); - final S3Adapter s3Adapter = new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, processConfigApi, List.of("application/pdf")); + final S3Adapter s3Adapter = new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, tFileExtensionService, s3StorageUrlProvider); // Assert the result assertThatThrownBy(() -> s3Adapter.loadFiles(filepaths, fileContext, processDefinition)) @@ -95,5 +112,4 @@ void test_load_file_throws_bpmn_error_for_unsupported_types() throws DocumentSto .containsExactly("FILE_TYPE_NOT_SUPPORTED", "The type of this file is not supported: fileContext/path/to/file.txt"); } - } diff --git a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-service/src/main/resources/application.yml b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-service/src/main/resources/application.yml index a80bffe475..cf227bd23d 100644 --- a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-service/src/main/resources/application.yml +++ b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-service/src/main/resources/application.yml @@ -15,10 +15,6 @@ feign: io: muenchendigital: digiwf: - s3: - client: - document-storage-url: "${DOCUMENT_STORAGE_HOST:http://localhost}:${DOCUMENT_STORAGE_PORT:8080}" - securityEnabled: true message: incidentDestination: "dwf-connector-incident-${DIGIWF_ENV}" bpmnErrorDestination: "dwf-connector-bpmnerror-${DIGIWF_ENV}" @@ -99,18 +95,22 @@ de: muenchen: oss: digiwf: + s3: + client: + document-storage-url: "${DOCUMENT_STORAGE_HOST:http://localhost}:${DOCUMENT_STORAGE_PORT:8080}" + enable-security: true ticketing: - supportedFileExtensions: - - "application/pdf" - - "text/plain" - - "image/png" - - "image/jpeg" - - "application/vnd.openxmlformats-officedocument.wordprocessingml.document" - - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" - - "application/vnd.openxmlformats-officedocument.presentationml.presentation" - - "application/vnd.visio2013" - - "application/vnd.ms-project" - - "application/vnd.oasis.opendocument.formula" - - "application/vnd.oasis.opendocument.presentation" - - "application/vnd.oasis.opendocument.spreadsheet" - - "application/vnd.oasis.opendocument.text" + supported-file-extensions: + pdf: "application/pdf" + txt: "text/plain" + png: "image/png" + jpg: "image/jpeg" + docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation" + vsdx: "application/vnd.visio2013" + mpp: "application/vnd.ms-project" + odf: "application/vnd.oasis.opendocument.formula" + odp: "application/vnd.oasis.opendocument.presentation" + ods: "application/vnd.oasis.opendocument.spreadsheet" + odt: "application/vnd.oasis.opendocument.text" \ No newline at end of file diff --git a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketIntegrationAutoConfiguration.java b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketIntegrationAutoConfiguration.java index ac502a1c6a..fe81b282f7 100644 --- a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketIntegrationAutoConfiguration.java +++ b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketIntegrationAutoConfiguration.java @@ -7,8 +7,12 @@ import de.muenchen.oss.digiwf.message.process.api.ErrorApi; import de.muenchen.oss.digiwf.message.process.api.ProcessApi; import de.muenchen.oss.digiwf.process.api.config.api.ProcessConfigApi; +import de.muenchen.oss.digiwf.s3.integration.client.properties.SupportedFileExtensions; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFileRepository; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3DomainProvider; +import de.muenchen.oss.digiwf.s3.integration.client.service.FileExtensionService; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.ticket.integration.adapter.in.streaming.TicketMessageProcessor; import de.muenchen.oss.digiwf.ticket.integration.adapter.in.streaming.WriteArticleDto; import de.muenchen.oss.digiwf.ticket.integration.adapter.out.s3.S3Adapter; @@ -27,12 +31,10 @@ import java.util.function.Consumer; - @Configuration @RequiredArgsConstructor -@EnableConfigurationProperties({TicketingProperties.class, TicketingProperties.class}) +@EnableConfigurationProperties(TicketingProperties.class) public class TicketIntegrationAutoConfiguration { - private final TicketingProperties ticketingProperties; @Bean public TicketOutPort ticketOutPort(final TicketsApi ticketsApi) { @@ -40,8 +42,10 @@ public TicketOutPort ticketOutPort(final TicketsApi ticketsApi) { } @Bean - public LoadFileOutPort loadFileOutPort(final DocumentStorageFileRepository documentStorageFileRepository, final DocumentStorageFolderRepository documentStorageFolderRepository, final ProcessConfigApi processConfigApi) { - return new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, processConfigApi, ticketingProperties.getSupportedFileExtensions()); + public LoadFileOutPort loadFileOutPort(final DocumentStorageFileRepository documentStorageFileRepository, + final DocumentStorageFolderRepository documentStorageFolderRepository, final FileExtensionService fileExtensionService, + final S3StorageUrlProvider s3StorageUrlProvider) { + return new S3Adapter(documentStorageFileRepository, documentStorageFolderRepository, fileExtensionService, s3StorageUrlProvider); } @Bean @@ -52,8 +56,8 @@ public WriteArticleInPort writeArticleUseCase(final TicketOutPort ticketOutPort, @ConditionalOnMissingBean @Bean public TicketMessageProcessor messageProcessor(final WriteArticleInPort writeArticleInPort, - final ProcessApi processApi, - final ErrorApi errorApi) { + final ProcessApi processApi, + final ErrorApi errorApi) { return new TicketMessageProcessor(writeArticleInPort, processApi, errorApi); } @@ -61,4 +65,29 @@ public TicketMessageProcessor messageProcessor(final WriteArticleInPort writeArt public Consumer> writeArticle(final TicketMessageProcessor messageProcessor) { return messageProcessor.writeArticle(); } + + /** + * Offers a {@link java.util.Map} of supported file extensions for this integration in form of a {@link SupportedFileExtensions} object. + * + * @param ticketingProperties {@link TicketingProperties} contains the supported file extensions. + * @return {@link SupportedFileExtensions} object representing the supported file extensions. + */ + @Bean + public SupportedFileExtensions supportedFileExtensions(final TicketingProperties ticketingProperties) { + final SupportedFileExtensions supportedFileExtensions = new SupportedFileExtensions(); + supportedFileExtensions.putAll(ticketingProperties.getSupportedFileExtensions()); + return supportedFileExtensions; + } + + /** + * {@link S3DomainProvider} instance specifically tailored for this integration to retrieve the domain-specific S3 storage URL for a given process if its + * process configuration contains a value for {@link de.muenchen.oss.digiwf.process.api.config.ProcessConfigConstants#APP_FILE_S3_SYNC_CONFIG}. + * + * @param processConfigApi {@link ProcessConfigApi} offers access to a process configuration for a given process definition id. + * @return S3DomainProvider {@link S3DomainProvider} that retrieves the domain-specific S3 storage url for a process if configured. + */ + @Bean + public S3DomainProvider s3DomainProvider(final ProcessConfigApi processConfigApi) { + return processConfigApi::getAppFileS3SyncConfig; + } } diff --git a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketingProperties.java b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketingProperties.java index 8088311b4c..56c2a6baf1 100644 --- a/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketingProperties.java +++ b/digiwf-integrations/digiwf-ticket-integration/digiwf-ticket-integration-starter/src/main/java/de/muenchen/oss/digiwf/ticket/integration/configuration/TicketingProperties.java @@ -4,13 +4,16 @@ import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; -import java.util.List; +import java.util.Map; @Data @ConfigurationProperties(prefix = "de.muenchen.oss.digiwf.ticketing") public class TicketingProperties { + /** + * Supported extensions. + */ @NotBlank - private List supportedFileExtensions; + private Map supportedFileExtensions; } diff --git a/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/ProcessConfigConstants.java b/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/ProcessConfigConstants.java index 3f60cefaef..06cc1dad5e 100644 --- a/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/ProcessConfigConstants.java +++ b/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/ProcessConfigConstants.java @@ -1,7 +1,10 @@ package de.muenchen.oss.digiwf.process.api.config; +import java.util.Optional; +import java.util.function.Function; + public class ProcessConfigConstants { - public static final String DIGIWF_S3_SYNC_CONFIG = "app_file_s3_sync_config"; + public static final String APP_FILE_S3_SYNC_CONFIG = "app_file_s3_sync_config"; } diff --git a/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/api/ProcessConfigApi.java b/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/api/ProcessConfigApi.java index 2ca6a24901..95f652c23b 100644 --- a/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/api/ProcessConfigApi.java +++ b/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/api/ProcessConfigApi.java @@ -2,17 +2,35 @@ import de.muenchen.oss.digiwf.process.api.config.api.dto.ProcessConfigTO; +import java.util.Optional; + /** * ProcessConfigApi is the api to obtain the process configuration. */ public interface ProcessConfigApi { /** - * Obtain a process configuration for a given process definition id. + * Obtain a process configuration for a given process definition id from digiwf-engine. * * @param processDefinitionId the process definition id * @return the process configuration */ ProcessConfigTO getProcessConfig(final String processDefinitionId); + /** + * Retrieves a configuration value for a given key and process definition ID from the digiwf-engine. + * + * @param key The key of the configuration value to retrieve. + * @param processDefinitionId The ID of the process definition for which the configuration value is sought. + * @return An {@link Optional} containing the configuration value as a {@code String}, or an empty {@link Optional} if no value is found. + */ + Optional getProcessConfigValue(final String key, final String processDefinitionId); + + /** + * Retrieves a domain-specific S3 storage URL for a given process definition id from digiwf-engine. + * + * @param processDefinitionId the process definition id + * @return the domain-specific S3 storage URL if configured + */ + Optional getAppFileS3SyncConfig(String processDefinitionId); } diff --git a/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/impl/ProcessConfigApiImpl.java b/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/impl/ProcessConfigApiImpl.java index 36e71b047e..0900d2c053 100644 --- a/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/impl/ProcessConfigApiImpl.java +++ b/digiwf-libs/digiwf-process/digiwf-process-api/src/main/java/de/muenchen/oss/digiwf/process/api/config/impl/ProcessConfigApiImpl.java @@ -1,27 +1,44 @@ package de.muenchen.oss.digiwf.process.api.config.impl; import de.muenchen.oss.digiwf.process.api.config.api.ProcessConfigApi; +import de.muenchen.oss.digiwf.process.api.config.api.dto.ConfigEntryTO; import de.muenchen.oss.digiwf.process.api.config.api.dto.ProcessConfigTO; import lombok.RequiredArgsConstructor; +import lombok.val; +import java.util.Optional; + +import static de.muenchen.oss.digiwf.process.api.config.ProcessConfigConstants.APP_FILE_S3_SYNC_CONFIG; /** - * ProcessConfigApiImpl is the api to obtain the process configuration. + * ProcessConfigApiImpl is the api to obtain the process configuration and configuration values. */ @RequiredArgsConstructor public class ProcessConfigApiImpl implements ProcessConfigApi { private final ProcessConfigClient processConfigClient; - /** - * Obtain a process configuration for a given process definition id from digiwf-engine. - * - * @param processDefinitionId the process definition id - * @return the process configuration - */ @Override public ProcessConfigTO getProcessConfig(final String processDefinitionId) { return this.processConfigClient.getProcessConfig(processDefinitionId); } + @Override + public Optional getProcessConfigValue(final String key, final String processDefinitionId) { + try { + val processConfigTO = this.getProcessConfig(processDefinitionId); + return processConfigTO.getConfigs().stream() + .filter(cfg -> cfg.getKey().equals(key)) + .findAny() + .map(ConfigEntryTO::getValue); + } catch (final Exception e) { + return Optional.empty(); + } + } + + @Override + public Optional getAppFileS3SyncConfig(final String processDefinitionId) { + return getProcessConfigValue(APP_FILE_S3_SYNC_CONFIG, processDefinitionId); + } + } diff --git a/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/adapter/out/file/PresignedUrlAdapter.java b/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/adapter/out/file/PresignedUrlAdapter.java index 574a42fcbf..b21768ba44 100644 --- a/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/adapter/out/file/PresignedUrlAdapter.java +++ b/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/adapter/out/file/PresignedUrlAdapter.java @@ -1,8 +1,8 @@ package de.muenchen.oss.digiwf.task.service.adapter.out.file; +import de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl.PresignedUrlRepository; import de.muenchen.oss.digiwf.task.service.application.port.out.file.PresignedUrlPort; import de.muenchen.oss.digiwf.task.service.domain.PresignedUrlAction; -import de.muenchen.oss.digiwf.s3.integration.client.repository.presignedurl.PresignedUrlRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -17,7 +17,6 @@ public class PresignedUrlAdapter implements PresignedUrlPort { private final PresignedUrlRepository presignedUrlRepository; private final S3Properties s3Properties; - @Override public String getPresignedUrl(final String pathToFile, final int expireInMinutes, final PresignedUrlAction action) throws HttpServerErrorException { return this.getPresignedUrl(this.s3Properties.getHttpAPI(), pathToFile, expireInMinutes, action); @@ -44,11 +43,11 @@ public String getPresignedUrl(final String documentStorageUrl, final String path throw new RuntimeException(String.format("No handler specified for action %s", action)); } } catch (final Exception ex) { - log.error("Getting presigned url for %s file {} failed: {}", actionString, pathToFile, ex); + log.error("Getting presigned url for {}} file {} failed: {}", actionString, pathToFile, ex); if (action == PresignedUrlAction.POST && ex.getMessage().contains(HttpStatus.CONFLICT.toString())) { - throw new ConflictingResourceException(String.format("Getting presigned url for " + actionString + " file " + pathToFile + " failed")); + throw new ConflictingResourceException(String.format("Getting presigned url for %s file %s failed", actionString, pathToFile)); } - throw new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, String.format("Getting presigned url for " + actionString + " file " + pathToFile +" failed")); + throw new HttpServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR, String.format("Getting presigned url for %s file %s failed", actionString, pathToFile)); } } diff --git a/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCase.java b/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCase.java index f0d90d0c43..469bd85682 100644 --- a/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCase.java +++ b/digiwf-task/digiwf-tasklist-service/src/main/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCase.java @@ -1,7 +1,7 @@ package de.muenchen.oss.digiwf.task.service.application.usecase; -import io.holunda.polyflow.view.Task; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.task.service.application.port.in.WorkOnTaskFile; import de.muenchen.oss.digiwf.task.service.application.port.out.auth.CurrentUserPort; import de.muenchen.oss.digiwf.task.service.application.port.out.file.PresignedUrlPort; @@ -9,10 +9,10 @@ import de.muenchen.oss.digiwf.task.service.application.port.out.polyflow.TaskQueryPort; import de.muenchen.oss.digiwf.task.service.domain.PresignedUrlAction; import de.muenchen.oss.digiwf.task.service.domain.TaskFileConfig; +import io.holunda.polyflow.view.Task; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import lombok.val; -import org.springframework.context.annotation.Lazy; import org.springframework.http.HttpStatus; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; @@ -21,7 +21,6 @@ import java.util.List; import java.util.Set; - @Slf4j @Component @RequiredArgsConstructor @@ -37,6 +36,8 @@ public class WorkOnTaskFileUseCase implements WorkOnTaskFile { private final CurrentUserPort currentUserPort; + private final S3StorageUrlProvider s3StorageUrlProvider; + private TaskFileConfig fileConfig; @NonNull @@ -54,7 +55,8 @@ public List getFileNames(@NonNull final String taskId, @NonNull final St if (documentStorageUrl != null) { allFiles = this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, documentStorageUrl).block(); } else { - allFiles = this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder).block(); + allFiles = this.documentStorageFolderRepository.getAllFilesInFolderRecursively(pathToFolder, + s3StorageUrlProvider.getDefaultDocumentStorageUrl()).block(); } //noinspection DataFlowIssue return extractFilenamesFromFolder(allFiles, pathToFolder); @@ -66,7 +68,8 @@ public List getFileNames(@NonNull final String taskId, @NonNull final St @Override @NonNull - public String getPresignedUrl(final PresignedUrlAction action, @NonNull final String taskId, @NonNull final String filePath, @NonNull final String fileName) { + public String getPresignedUrl(final PresignedUrlAction action, @NonNull final String taskId, @NonNull final String filePath, + @NonNull final String fileName) { this.initializeFileConfig(taskId); @@ -88,10 +91,10 @@ public String getPresignedUrl(final PresignedUrlAction action, @NonNull final St } /** - * Extract the filenames from the given file list. Make sure that only filenames for files in the given folder are returned. - * Don't return filenames for files in subfolders. + * Extract the filenames from the given file list. Make sure that only filenames for files in the given folder are returned. Don't return filenames for + * files in subfolders. * - * @param fileList files. + * @param fileList files. * @param pathToFolder folder prefix, must be part of the filenames. * @return a list of file names without prefix. */ @@ -113,6 +116,4 @@ private Task getTaskForUser(String taskId) { return taskQueryPort.getTaskByIdForCurrentUser(currentUser, taskId); } - - } diff --git a/digiwf-task/digiwf-tasklist-service/src/main/resources/application.yml b/digiwf-task/digiwf-tasklist-service/src/main/resources/application.yml index ad275d59e0..fd5a97491e 100644 --- a/digiwf-task/digiwf-tasklist-service/src/main/resources/application.yml +++ b/digiwf-task/digiwf-tasklist-service/src/main/resources/application.yml @@ -128,13 +128,14 @@ digiwf: url-template: "${MUCS_DMS_URL_TEMPLATE:https://eakte.muenchen.de/fsc/mx/{0}}" label-template: "${MUCS_DMS_LABEL:MUCS DMS {0}}" -io: - muenchendigital: - digiwf: - s3: - client: - documentStorageUrl: '${digiwf.s3service.httpAPI}' - securityEnabled: true +de: + muenchen: + oss: + digiwf: + s3: + client: + document-storage-url: '${digiwf.s3service.httpAPI}' + enable-security: true management: endpoint: diff --git a/digiwf-task/digiwf-tasklist-service/src/test/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCaseTest.java b/digiwf-task/digiwf-tasklist-service/src/test/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCaseTest.java index cb319ef344..0bef71f7c6 100644 --- a/digiwf-task/digiwf-tasklist-service/src/test/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCaseTest.java +++ b/digiwf-task/digiwf-tasklist-service/src/test/java/de/muenchen/oss/digiwf/task/service/application/usecase/WorkOnTaskFileUseCaseTest.java @@ -1,13 +1,11 @@ package de.muenchen.oss.digiwf.task.service.application.usecase; import com.google.common.collect.Sets; -import io.holunda.polyflow.view.Task; -import io.holunda.polyflow.view.auth.User; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageClientErrorException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageException; import de.muenchen.oss.digiwf.s3.integration.client.exception.DocumentStorageServerErrorException; -import de.muenchen.oss.digiwf.s3.integration.client.exception.PropertyNotSetException; import de.muenchen.oss.digiwf.s3.integration.client.repository.DocumentStorageFolderRepository; +import de.muenchen.oss.digiwf.s3.integration.client.service.S3StorageUrlProvider; import de.muenchen.oss.digiwf.task.service.application.port.out.auth.CurrentUserPort; import de.muenchen.oss.digiwf.task.service.application.port.out.file.PresignedUrlPort; import de.muenchen.oss.digiwf.task.service.application.port.out.file.TaskFileConfigResolverPort; @@ -15,6 +13,8 @@ import de.muenchen.oss.digiwf.task.service.domain.IllegalResourceAccessException; import de.muenchen.oss.digiwf.task.service.domain.PresignedUrlAction; import de.muenchen.oss.digiwf.task.service.domain.TaskFileConfig; +import io.holunda.polyflow.view.Task; +import io.holunda.polyflow.view.auth.User; import org.assertj.core.api.Condition; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -32,7 +32,6 @@ import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; -import static org.mockito.Mockito.verifyNoMoreInteractions; class WorkOnTaskFileUseCaseTest { @@ -46,7 +45,10 @@ class WorkOnTaskFileUseCaseTest { private final CurrentUserPort currentUserPort = mock(CurrentUserPort.class); - private final WorkOnTaskFileUseCase useCase = new WorkOnTaskFileUseCase(documentStorageFolderRepository,presignedUrlPort,taskFileConfigResolverPort,taskQueryPort,currentUserPort); + private final S3StorageUrlProvider s3StorageUrlProvider = new S3StorageUrlProvider("defaultS3Url"); + + private final WorkOnTaskFileUseCase useCase = new WorkOnTaskFileUseCase(documentStorageFolderRepository, presignedUrlPort, taskFileConfigResolverPort, + taskQueryPort, currentUserPort, s3StorageUrlProvider); private final User user = new User("0123456789", Sets.newHashSet("group1", "group2")); @@ -63,11 +65,12 @@ void setupMocks() { } @Test - void getFileNamesDocumentWithStorageUrl() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getFileNamesDocumentWithStorageUrl() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final Set filesInS3 = Sets.newHashSet(fileContext + "/able/to/read/file1.txt", fileContext + "/able/to/read/secondfile1.pdf"); - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig",pathsWrite,pathsReadonly)); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString(),anyString())).thenReturn(Mono.just(filesInS3)); + when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig", pathsWrite, pathsReadonly)); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString(), anyString())).thenReturn(Mono.just(filesInS3)); final List listOfNames = useCase.getFileNames("task_0", pathsReadonly.stream().findFirst().orElseThrow()); @@ -75,7 +78,7 @@ void getFileNamesDocumentWithStorageUrl() throws DocumentStorageException, Docum .hasSize(2) .contains("file1.txt", "secondfile1.pdf"); - verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString(),anyString()); + verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString(), anyString()); verifyNoMoreInteractions(documentStorageFolderRepository); verify(taskFileConfigResolverPort).apply(any()); @@ -83,11 +86,12 @@ void getFileNamesDocumentWithStorageUrl() throws DocumentStorageException, Docum } @Test - void getFileNamesDocumentWithoutStorageUrl() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getFileNamesDocumentWithoutStorageUrl() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final Set filesInS3 = Sets.newHashSet(fileContext + "/able/to/read/file1.txt", fileContext + "/able/to/read/secondfile1.pdf"); - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", null,pathsWrite,pathsReadonly)); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString())).thenReturn(Mono.just(filesInS3)); + when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", null, pathsWrite, pathsReadonly)); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString(), anyString())).thenReturn(Mono.just(filesInS3)); final List listOfNames = useCase.getFileNames("task_0", pathsReadonly.stream().findFirst().orElseThrow()); @@ -95,7 +99,7 @@ void getFileNamesDocumentWithoutStorageUrl() throws DocumentStorageException, Do .hasSize(2) .contains("file1.txt", "secondfile1.pdf"); - verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString()); + verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString(), anyString()); verifyNoMoreInteractions(documentStorageFolderRepository); verify(taskFileConfigResolverPort).apply(any()); @@ -103,7 +107,8 @@ void getFileNamesDocumentWithoutStorageUrl() throws DocumentStorageException, Do } @Test - void getFileNames_DoesNotIncludeFilesFromSubdirectories() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { + void getFileNames_DoesNotIncludeFilesFromSubdirectories() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { final Set filesInS3 = Sets.newHashSet( fileContext + "/able/to/read/file1.txt", fileContext + "/able/to/read/secondfile1.pdf", @@ -111,8 +116,8 @@ void getFileNames_DoesNotIncludeFilesFromSubdirectories() throws DocumentStorag fileContext + "/able/to/read/subdir1/file3.txt" ); - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", null,pathsWrite,pathsReadonly)); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString())).thenReturn(Mono.just(filesInS3)); + when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", null, pathsWrite, pathsReadonly)); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString(), anyString())).thenReturn(Mono.just(filesInS3)); final List listOfNames = useCase.getFileNames("task_0", pathsReadonly.stream().findFirst().orElseThrow()); @@ -121,7 +126,7 @@ void getFileNames_DoesNotIncludeFilesFromSubdirectories() throws DocumentStorag .contains("file1.txt", "secondfile1.pdf") .doesNotContain("file2.txt", "file3.txt"); - verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString()); + verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString(), anyString()); verifyNoMoreInteractions(documentStorageFolderRepository); verify(taskFileConfigResolverPort).apply(any()); @@ -129,16 +134,18 @@ void getFileNames_DoesNotIncludeFilesFromSubdirectories() throws DocumentStorag } @Test - void getFileNamesThrowsException() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException, PropertyNotSetException { - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig",pathsWrite,pathsReadonly)); - when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString())).thenThrow(new DocumentStorageException("DocumentStorageException",new Exception())); + void getFileNamesThrowsException() + throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException { + when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig", pathsWrite, pathsReadonly)); + when(documentStorageFolderRepository.getAllFilesInFolderRecursively(anyString(), anyString())).thenThrow( + new DocumentStorageException("DocumentStorageException", new Exception())); - assertThatThrownBy(() -> useCase.getFileNames("task_0","able/to/read")) + assertThatThrownBy(() -> useCase.getFileNames("task_0", "able/to/read")) .isInstanceOf(HttpServerErrorException.class) .hasMessage("500 Getting all files of folder able/to/read failed") .has(new Condition<>(e -> ((HttpServerErrorException) e).getStatusCode().equals(HttpStatus.INTERNAL_SERVER_ERROR), "Status code is 500")); - verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString(),anyString()); + verify(documentStorageFolderRepository).getAllFilesInFolderRecursively(anyString(), anyString()); verifyNoMoreInteractions(documentStorageFolderRepository); verify(taskFileConfigResolverPort).apply(any()); @@ -147,15 +154,15 @@ void getFileNamesThrowsException() throws DocumentStorageException, DocumentStor @Test void getPresignedUrlForGETWithReadAccessAndDocumentStorageUrl() { - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig",pathsWrite,pathsReadonly)); - when(presignedUrlPort.getPresignedUrl(anyString(),anyString(),anyInt(),any())).thenReturn("With DocumentStorageUrl"); - when(presignedUrlPort.getPresignedUrl(anyString(),anyInt(),any())).thenReturn("Without DocumentStorageUrl"); + when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig", pathsWrite, pathsReadonly)); + when(presignedUrlPort.getPresignedUrl(anyString(), anyString(), anyInt(), any())).thenReturn("With DocumentStorageUrl"); + when(presignedUrlPort.getPresignedUrl(anyString(), anyInt(), any())).thenReturn("Without DocumentStorageUrl"); - String presignedUrl = useCase.getPresignedUrl(PresignedUrlAction.GET,"task_0","able/to/read","filename1.txt"); + String presignedUrl = useCase.getPresignedUrl(PresignedUrlAction.GET, "task_0", "able/to/read", "filename1.txt"); assertThat(presignedUrl).isEqualTo("With DocumentStorageUrl"); - verify(presignedUrlPort).getPresignedUrl(anyString(),anyString(),anyInt(),any()); + verify(presignedUrlPort).getPresignedUrl(anyString(), anyString(), anyInt(), any()); verifyNoMoreInteractions(presignedUrlPort); verify(taskFileConfigResolverPort).apply(any()); @@ -164,15 +171,15 @@ void getPresignedUrlForGETWithReadAccessAndDocumentStorageUrl() { @Test void getPresignedUrlForGETWithWriteAccessAndWithoutDocumentStorageUrl() { - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", null,pathsWrite,pathsReadonly)); - when(presignedUrlPort.getPresignedUrl(anyString(),anyString(),anyInt(),any())).thenReturn("With DocumentStorageUrl"); - when(presignedUrlPort.getPresignedUrl(anyString(),anyInt(),any())).thenReturn("Without DocumentStorageUrl"); + when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", null, pathsWrite, pathsReadonly)); + when(presignedUrlPort.getPresignedUrl(anyString(), anyString(), anyInt(), any())).thenReturn("With DocumentStorageUrl"); + when(presignedUrlPort.getPresignedUrl(anyString(), anyInt(), any())).thenReturn("Without DocumentStorageUrl"); - String presignedUrl = useCase.getPresignedUrl(PresignedUrlAction.GET,"task_0","able/to/write","filename1.txt"); + String presignedUrl = useCase.getPresignedUrl(PresignedUrlAction.GET, "task_0", "able/to/write", "filename1.txt"); assertThat(presignedUrl).isEqualTo("Without DocumentStorageUrl"); - verify(presignedUrlPort).getPresignedUrl(anyString(),anyInt(),any()); + verify(presignedUrlPort).getPresignedUrl(anyString(), anyInt(), any()); verifyNoMoreInteractions(presignedUrlPort); verify(taskFileConfigResolverPort).apply(any()); @@ -181,14 +188,14 @@ void getPresignedUrlForGETWithWriteAccessAndWithoutDocumentStorageUrl() { @Test void getPresignedUrlForPUTWithWriteAccess() { - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig",pathsWrite,pathsReadonly)); - when(presignedUrlPort.getPresignedUrl(anyString(),anyString(),anyInt(),any())).thenReturn("With DocumentStorageUrl"); + when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig", pathsWrite, pathsReadonly)); + when(presignedUrlPort.getPresignedUrl(anyString(), anyString(), anyInt(), any())).thenReturn("With DocumentStorageUrl"); - String presignedUrl = useCase.getPresignedUrl(PresignedUrlAction.PUT,"task_0","able/to/write","filename1.txt"); + String presignedUrl = useCase.getPresignedUrl(PresignedUrlAction.PUT, "task_0", "able/to/write", "filename1.txt"); assertThat(presignedUrl).isEqualTo("With DocumentStorageUrl"); - verify(presignedUrlPort).getPresignedUrl(anyString(),anyString(),anyInt(),any()); + verify(presignedUrlPort).getPresignedUrl(anyString(), anyString(), anyInt(), any()); verifyNoMoreInteractions(presignedUrlPort); verify(taskFileConfigResolverPort).apply(any()); @@ -197,10 +204,11 @@ void getPresignedUrlForPUTWithWriteAccess() { @Test void getPresignedUrlForPUTWithReadAccess() { - when(taskFileConfigResolverPort.apply(any())).thenReturn(new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig",pathsWrite,List.of("readonly/path"))); - when(presignedUrlPort.getPresignedUrl(anyString(),anyString(),anyInt(),any())).thenReturn("With DocumentStorageUrl"); + when(taskFileConfigResolverPort.apply(any())).thenReturn( + new TaskFileConfig(this.fileContext, "asyncConfig", "syncConfig", pathsWrite, List.of("readonly/path"))); + when(presignedUrlPort.getPresignedUrl(anyString(), anyString(), anyInt(), any())).thenReturn("With DocumentStorageUrl"); - assertThatThrownBy(() -> useCase.getPresignedUrl(PresignedUrlAction.PUT,"task_0","readonly/path","filename1.txt")) + assertThatThrownBy(() -> useCase.getPresignedUrl(PresignedUrlAction.PUT, "task_0", "readonly/path", "filename1.txt")) .isInstanceOf(IllegalResourceAccessException.class) .hasMessage("No access to defined property"); diff --git a/digiwf-task/digiwf-tasklist-service/src/test/resources/application-itest.yml b/digiwf-task/digiwf-tasklist-service/src/test/resources/application-itest.yml index fe6d7adf3c..950485a75c 100644 --- a/digiwf-task/digiwf-tasklist-service/src/test/resources/application-itest.yml +++ b/digiwf-task/digiwf-tasklist-service/src/test/resources/application-itest.yml @@ -43,7 +43,6 @@ spring: user-info-uri: http://localhost-itest/auth/realms/P82/protocol/openid-connect/userinfo jwk-set-uri: http://localhost-itest/auth/realms/P82/protocol/openid-connect/certs - feign: client: config: @@ -59,12 +58,14 @@ ezldap: port: 8183 url: "http://localhost:${ezldap.client.port}" request: "/test" -io: - muenchendigital: - digiwf: - s3: - client: - securityEnabled: false + +de: + muenchen: + oss: + digiwf: + s3: + client: + enable-security: false digiwf: s3service: