Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix(#616): email integration for release #626

Merged
merged 4 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
import de.muenchen.oss.digiwf.email.integration.model.FileAttachment;
import de.muenchen.oss.digiwf.email.integration.model.PresignedUrl;
import de.muenchen.oss.digiwf.message.process.api.error.BpmnError;
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.repository.transfer.S3FileTransferRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tika.Tika;

import javax.mail.util.ByteArrayDataSource;
import java.io.IOException;
import java.io.InputStream;

@Slf4j
@RequiredArgsConstructor
Expand All @@ -28,15 +28,16 @@ public FileAttachment loadAttachment(final PresignedUrl attachment) throws BpmnE
// 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 InputStream inputStream = this.s3FileTransferRepository.getFileInputStream(attachment.getUrl());
final ByteArrayDataSource file = new ByteArrayDataSource(inputStream, tika.detect(inputStream));
final byte[] bytes = this.s3FileTransferRepository.getFile(attachment.getUrl());
final String type = tika.detect(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);
file.setName(fileName);
return new FileAttachment(fileName, file);
} catch (final DocumentStorageException e) {
} catch (final DocumentStorageException | DocumentStorageServerErrorException | DocumentStorageClientErrorException e) {
log.error("An attachment could not be loaded from presigned url: {}", attachment);
throw new BpmnError("LOAD_FILE_FAILED", "An attachment could not be loaded from presigned url: " + attachment);
} catch (final IOException e) {
log.error("File type not supported of the attachment: {}", attachment);
throw new BpmnError("FILE_TYPE_NOT_SUPPORTED", "File type not supported of the attachment: " + attachment);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,25 @@
import de.muenchen.oss.digiwf.email.integration.model.FileAttachment;
import de.muenchen.oss.digiwf.email.integration.model.PresignedUrl;
import de.muenchen.oss.digiwf.message.process.api.error.BpmnError;
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.repository.transfer.S3FileTransferRepository;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@Slf4j
class S3AdapterTest {

private final S3FileTransferRepository s3FileTransferRepository = mock(S3FileTransferRepository.class);
Expand All @@ -29,29 +34,42 @@ void setup() {
}

@Test
void testLoadAttachment_Success() throws IOException, BpmnError, DocumentStorageException {
void testLoadAttachment_DocumentStorageException() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException {
final String url = "http://localhost:3000/some-file.txt";
final String fileContent = "This is the content of the file.";
final PresignedUrl presignedUrl = new PresignedUrl(url, "/path/to/some-file.txt", "GET");

final InputStream inputStream = new ByteArrayInputStream(fileContent.getBytes(StandardCharsets.UTF_8));
when(s3FileTransferRepository.getFileInputStream(url)).thenReturn(inputStream);

final FileAttachment result = s3Adapter.loadAttachment(presignedUrl);

Assertions.assertEquals("some-file.txt", result.getFileName());
Assertions.assertEquals(fileContent, new String(result.getFile().getInputStream().readAllBytes(), StandardCharsets.UTF_8));
// DocumentStorageException
when(s3FileTransferRepository.getFile(url))
.thenThrow(new DocumentStorageException("Some error", new RuntimeException("Some error")));
Assertions.assertThrows(BpmnError.class, () -> s3Adapter.loadAttachment(presignedUrl));
}

@Test
void testLoadAttachment_DocumentStorageException() throws DocumentStorageException {
final String url = "http://localhost:3000/some-file.txt";
final PresignedUrl presignedUrl = new PresignedUrl(url, "/path/to/some-file.txt", "GET");
void testLoadAttachment_Success() throws DocumentStorageException, DocumentStorageClientErrorException, DocumentStorageServerErrorException {
final Map<String, String> files = Map.of(
"digiwf_logo.png", "image/png",
"test-pdf.pdf", "application/pdf",
"test-word.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
);

when(s3FileTransferRepository.getFileInputStream(url))
.thenThrow(new DocumentStorageException("Some error", new RuntimeException("Some error")));
for (final Map.Entry<String, String> file : files.entrySet()) {
try {
final String path = "files/" + file.getKey();
final byte[] testFile = new ClassPathResource(path).getInputStream().readAllBytes();
when(s3FileTransferRepository.getFile(anyString())).thenReturn(testFile);

Assertions.assertThrows(BpmnError.class, () -> s3Adapter.loadAttachment(presignedUrl));
final FileAttachment fileAttachment = this.s3Adapter.loadAttachment(
new PresignedUrl("http://localhost:9000/" + file, path, "GET")
);

Assertions.assertTrue(Arrays.equals(testFile, fileAttachment.getFile().getInputStream().readAllBytes()));
Assertions.assertEquals(file.getKey(), fileAttachment.getFileName());
Assertions.assertEquals(file.getValue(), fileAttachment.getFile().getContentType());
} catch (final IOException e) {
log.warn("Could not read file: {}", file);
Assertions.fail(e);
}
}
}

}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<dependencies>
<dependency>
<groupId>de.muenchen.oss.digiwf</groupId>
<artifactId>digiwf-email-integration-starter</artifactId>
<artifactId>digiwf-message-starter</artifactId>
<version>${project.version}</version>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package de.muenchen.oss.digiwf.email.integration.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.List;

/**
* Object contains all the information needed to send a mail.
*/
@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class Mail {

/**
* Receiver addresses of the mail, comma separated.
*/
@NotBlank(message = "No receivers given")
private String receivers;

/**
* CC-Receiver addresses of the mail, comma separated.
*/
private String receiversCc;

/**
* BCC-Receiver addresses of the mail, comma separated.
*/
private String receiversBcc;

/**
* Subject of the mail.
*/
@NotBlank(message = "No subject given")
private String subject;

/**
* Body of the mail.
*/
@NotBlank(message = "No body given")
private String body;

/**
* Reply to address
*/
private String replyTo;

@Valid
private List<PresignedUrl> attachments;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package de.muenchen.oss.digiwf.email.integration.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;

/**
* Attachment File you want to get from the S3 storage.
*/
@Data
@RequiredArgsConstructor
@AllArgsConstructor
public class PresignedUrl {

/**
* Url to the s3 service.
*/
@NotBlank(message = "Presigned Url is mandatory")
private String url;

/**
* Path to the file inside in the S3 storage.
*/
@NotBlank(message = "Path is mandatory")
private String path;

/**
* Proper Http Method (Post, Put, Get, Delete) to interact with S3.
* Note: Only GET is supported. The mail integration is not intended to modify files!
*/
@NotBlank(message = "Action is mandatory")
@Pattern(regexp = "GET", message = "Only action GET is supported")
private String action;

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@ server:
spring:
cloud:
function:
definition: functionRouter;sendMessage;
definition: sendMessage;
stream:
function:
routing:
enabled: 'true'
bindings:
functionRouter-in-0:
group: "dwf-email-service"
destination: "dwf-email-${DIGIWF_ENV}"
sendMessage-out-0:
destination: "dwf-connector-${DIGIWF_ENV}"
destination: "dwf-email-${DIGIWF_ENV}"
kafka:
binder:
configuration:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ Content-Type: application/json
{
"receivers": "[email protected]",
"subject": "Testing Email Integration",
"body": "This is a test email. You can delete it safely"
"body": "This is a test email. You can delete it safely",
"attachments": [
{
"url": "http://127.0.0.1:9000/test/email-attachment-test/Workshop-LHM-%28MPDZ%29-20-07-2023.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=JCXDR004T558IUPC9VIX%2F20230828%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230828T070615Z&X-Amz-Expires=604800&X-Amz-Security-Token=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJKQ1hEUjAwNFQ1NThJVVBDOVZJWCIsImV4cCI6MTY5MzI0OTM3OSwicGFyZW50IjoibWluaW8ifQ.JMuUDc84vfXQOd191fcixiqeNApyMGsY2H3kBG-DGxu63HUFthwHTX7z6u1Esm0wyAjLodrNJvVQhE3rjPCVlw&X-Amz-SignedHeaders=host&versionId=null&X-Amz-Signature=4aaeab93df6fa39589752e4e691e06750c432610babc3e1edbfd7a49b3f34262",
"path": "/test/email-attachment-test/Workshop-LHM-%28MPDZ%29-20-07-2023.pdf",
"action": "GET"
}
]
}

### testEventBus should fail
Expand Down
Loading