Skip to content

Commit

Permalink
VKT(Backend) Viestintäpalvelu attachment proof of concept implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jrkkp committed Feb 21, 2025
1 parent c893500 commit be19dd5
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 14 deletions.
25 changes: 24 additions & 1 deletion backend/vkt/src/main/java/fi/oph/vkt/api/PublicController.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package fi.oph.vkt.api;

import static fi.oph.vkt.util.LocalisationUtil.localeFI;
import com.fasterxml.jackson.core.JsonProcessingException;
import fi.oph.vkt.api.dto.PublicEducationDTO;
import fi.oph.vkt.api.dto.PublicEnrollmentCreateDTO;
Expand All @@ -16,16 +17,21 @@
import fi.oph.vkt.model.type.EnrollmentType;
import fi.oph.vkt.model.type.ExamLevel;
import fi.oph.vkt.model.type.FreeEnrollmentType;
import fi.oph.vkt.repository.EnrollmentRepository;
import fi.oph.vkt.service.FeatureFlagService;
import fi.oph.vkt.service.PaymentService;
import fi.oph.vkt.service.PublicAuthService;
import fi.oph.vkt.service.PublicEnrollmentService;
import fi.oph.vkt.service.PublicExamEventService;
import fi.oph.vkt.service.PublicPersonService;
import fi.oph.vkt.service.PublicReservationService;
import fi.oph.vkt.service.email.EmailAttachmentData;
import fi.oph.vkt.service.email.EmailData;
import fi.oph.vkt.service.email.sender.EmailSenderViestintapalveluNew;
import fi.oph.vkt.service.koski.KoskiService;
import fi.oph.vkt.service.receipt.ReceiptData;
import fi.oph.vkt.service.receipt.ReceiptRenderer;
import fi.oph.vkt.util.LocalisationUtil;
import fi.oph.vkt.util.SessionUtil;
import fi.oph.vkt.util.UIRouteUtil;
import fi.oph.vkt.util.exception.APIException;
Expand All @@ -39,6 +45,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
Expand Down Expand Up @@ -95,6 +102,12 @@ public class PublicController {
@Resource
private CasClient casClient;

@Resource
private EnrollmentRepository enrollmentRepository;

@Resource
private ReceiptRenderer receiptRenderer;

@GetMapping(path = "/examEvent")
public List<PublicExamEventDTO> list() {
return publicExamEventService.listExamEvents(ExamLevel.EXCELLENT);
Expand Down Expand Up @@ -339,6 +352,16 @@ public void paymentSuccess(
public void email(
) throws IOException, ExecutionException, InterruptedException {
final EmailSenderViestintapalveluNew emailSenderViestintapalveluNew = new EmailSenderViestintapalveluNew(casClient, Constants.SERVICENAME, Constants.EMAIL_SENDER_NAME);

final byte[] receiptBytes = "test".getBytes();

final EmailAttachmentData emailAttachmentData = EmailAttachmentData
.builder()
.name("test.txt")
.contentType("text/plain")
.data(receiptBytes)
.build();

emailSenderViestintapalveluNew.sendEmail(
EmailData
.builder()
Expand All @@ -347,7 +370,7 @@ public void email(
.recipientAddress("[email protected]")
.recipientName("Test")
.body("This is a test")
.attachments(List.of())
.attachments(List.of(emailAttachmentData))
.build()
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
import org.asynchttpclient.Request;
import org.asynchttpclient.RequestBuilder;
import org.asynchttpclient.Response;
import org.asynchttpclient.request.body.multipart.ByteArrayPart;
import org.asynchttpclient.util.HttpConstants;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;

@RequiredArgsConstructor
public class EmailSenderViestintapalveluNew implements EmailSender {
Expand All @@ -36,14 +35,15 @@ public class EmailSenderViestintapalveluNew implements EmailSender {
@Override
public String sendEmail(final EmailData emailData) throws JsonProcessingException, ExecutionException, InterruptedException {
final ObjectMapper objectMapper = new ObjectMapper();
final Map<String, Object> postData = createPostData(emailData);
final List<String> attachments = createAndPostAttachments(emailData.attachments());
final Map<String, Object> postData = createPostData(emailData, attachments);
final String body = objectMapper.writeValueAsString(postData);

final Request request = new RequestBuilder()
.setUrl("https://viestinvalitys.testiopintopolku.fi/lahetys/v1/viestit")
.setMethod("POST")
.setBody(body)
.setRequestTimeout(Duration.ofMillis(10000))
.setRequestTimeout(Duration.ofSeconds(10))
.addHeader("Caller-Id", callerId)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
Expand All @@ -53,7 +53,7 @@ public String sendEmail(final EmailData emailData) throws JsonProcessingExceptio
final Response response = casClient.executeAndRetryWithCleanSessionOnStatusCodes(request, Set.of(401)).get();

if (response.getStatusCode() == HttpConstants.ResponseStatusCodes.OK_200) {
return parseExternalId(response.getResponseBody());
return parseExternalId(response.getResponseBody(), "lahetysTunniste");
}
} catch (Exception e) {
throw e;
Expand All @@ -62,7 +62,7 @@ public String sendEmail(final EmailData emailData) throws JsonProcessingExceptio
return null;
}

private Map<String, Object> createPostData(final EmailData emailData) {
private Map<String, Object> createPostData(final EmailData emailData, final List<String> attachments) {
final Map<String, Object> senderFields = Map.of("nimi", sender, "sahkopostiOsoite", "[email protected]");
// Allowed characters: a-z, A-Z, 0-9 ja -_.
final String emailKeyPrefix = "vkt-email-";
Expand Down Expand Up @@ -90,26 +90,62 @@ private Map<String, Object> createPostData(final EmailData emailData) {
"sailytysaika",
expirationDays,
"idempotencyKey",
emailKeyPrefix + emailData.id()
//"attachments",
//createAttachments(emailData.attachments())
emailKeyPrefix + emailData.id(),
"liitteidenTunnisteet",
attachments
);
}

private List<Map<String, Object>> createAttachments(final List<EmailAttachmentData> attachments) {
private String postAttachment(final EmailAttachmentData attachment) throws ExecutionException, InterruptedException, JsonProcessingException {
final Request request = new RequestBuilder()
.setUrl("https://viestinvalitys.testiopintopolku.fi/lahetys/v1/liitteet")
.setMethod("POST")
.addBodyPart(new ByteArrayPart("liite", attachment.data(), attachment.contentType(), null, attachment.name()))
.setRequestTimeout(Duration.ofSeconds(10))
.addHeader("Caller-Id", callerId)
.addHeader("Content-Type", "multipart/form-data")
.addHeader("Accept", "application/json")
.build();

try {
final Response response = casClient.executeAndRetryWithCleanSessionOnStatusCodes(request, Set.of(401)).get();

if (response.getStatusCode() == HttpConstants.ResponseStatusCodes.OK_200) {
final String id = parseExternalId(response.getResponseBody(), "liiteTunniste");

if (id == null) {
throw new RuntimeException("");
}

return id;
} else {
throw new RuntimeException("");
}
} catch (Exception e) {
throw e;
}
}

private List<String> createAndPostAttachments(final List<EmailAttachmentData> attachments) {
return Optional
.ofNullable(attachments)
.map(nonNullAttachments ->
nonNullAttachments
.stream()
.map(a -> Map.<String, Object>of("data", a.data(), "name", a.name(), "contentType", a.contentType()))
.map(attachment -> {
try {
return postAttachment(attachment);
} catch (final Exception e) {
throw new RuntimeException(e);
}
})
.toList()
)
.orElse(List.of());
}

private String parseExternalId(final String result) throws JsonProcessingException {
private String parseExternalId(final String result, final String key) throws JsonProcessingException {
final Map<String, String> map = OBJECT_MAPPER.readValue(result, new TypeReference<>() {});
return map.get("id");
return map.get(key);
}
}

0 comments on commit be19dd5

Please sign in to comment.