diff --git a/README.md b/README.md index fc4316db8d736573a12de87b2da76a596d7668cf..9e2d81a9d779ab9b7ea0397ce5850415a1ea9998 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Anbindung des OSIv2-Postfachs für die OZG-Cloud. Die Client-Authentifizierung beim Authentication-Server (Servicekonto) erfolgt über den OAuth2-Client-Credentials-Flow (siehe [RFC 6749, Sec. 1.3.4](https://www.rfc-editor.org/rfc/rfc6749#section-1.3.4)) mit `client_id` und `client_secret` in Verbindung mit einem Resource-URI-Parameter (siehe [RFC 8707](https://datatracker.ietf.org/doc/html/rfc8707)), der den Zugriff des Clients auf den Resource-Server (Postfach-Facade) einschränkt. -Der Resource-Server liest die Resource-URI aus dem `aud`-Claim (siehe [RFC 9068, Sec. 3](https://datatracker.ietf.org/doc/html/rfc9068#section-3)). +Der Resource-Server liest die Resource-URI aus dem `aud`-Claim (siehe [RFC 9068, Sec. 3](https://datatracker.ietf.org/doc/html/rfc9068#section-3) und [ServicePortal-Dokumentation](https://idp.serviceportal-stage.hamburg.de/doc/external/articles/OIDC/OIDC-Protokoll.html)). ### Beispiel: diff --git a/spec/postfach-api-facade.yaml b/spec/postfach-api-facade.yaml index 708f7e16cc9e82ecf771d1401179bf40739c14ff..f9730377d06df25d100193431405c9ab1ab5031a 100644 --- a/spec/postfach-api-facade.yaml +++ b/spec/postfach-api-facade.yaml @@ -2466,11 +2466,9 @@ components: type: string description: "Die fachliche Vorgangsnummer.<br/><br/>\n Zu einem Vorgang\ \ kann es mehrere Nachrichten geben. (max. 256 Zeichen)\n " - nullable: true subject: type: string description: "Betreff der Nachricht<br/><br/>\n (max. 255 Zeichen)\n " - nullable: true body: type: string description: "Nachrichtentext<br/><br/>\n Dies ist entweder ein einfacher\ diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapper.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapper.java index d199e5109946eaf485a636c7adb6bce20babed26..91a9d58c3a5880cadb70bf5706aafb98e8faa49f 100644 --- a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapper.java +++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapper.java @@ -1,5 +1,7 @@ package de.ozgcloud.nachrichten.postfach.osiv2.transfer; +import java.util.Collections; +import java.util.List; import java.util.Optional; import org.mapstruct.Mapper; @@ -9,30 +11,51 @@ import org.mapstruct.ReportingPolicy; import de.ozgcloud.nachrichten.postfach.PostfachAddress; import de.ozgcloud.nachrichten.postfach.PostfachAddressIdentifier; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; +import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.MessageExchangeFiles; import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.OutSendMessageRequestV2; +import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1References; +import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior; @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR) public interface RequestMapper { - @Mapping(target = "sequencenumber", ignore = true) + String ORIGIN_SENDER = "OZG-Cloud"; + + @Mapping(target = "sequencenumber", source = "vorgangId") @Mapping(target = "body", source = "mailBody") - @Mapping(target = "displayName", ignore = true) - @Mapping(target = "originSender", ignore = true) - @Mapping(target = "replyAction", constant = "REPLYPOSSIBLE") - @Mapping(target = "eidasLevel", constant = "MEDIUM") + @Mapping(target = "displayName", source = "createdBy") + @Mapping(target = "originSender", constant = ORIGIN_SENDER) + @Mapping(target = "replyAction", source = "replyOption") + @Mapping(target = "eidasLevel", constant = "LOW") @Mapping(target = "isObligatory", expression = "java( false )") @Mapping(target = "isHtml", expression = "java( true )") - @Mapping(target = "files", ignore = true) - @Mapping(target = "references", ignore = true) + @Mapping(target = "files", expression = "java( mapMessageExchangeFiles() )") + @Mapping(target = "references", expression = "java( mapReferences() )") OutSendMessageRequestV2 mapOutSendMessageRequestV2(PostfachNachricht nachricht); + default List<MessageExchangeFiles> mapMessageExchangeFiles() { + return Collections.emptyList(); + } + + default List<V1References> mapReferences() { + return Collections.emptyList(); + } + + default V1ReplyBehavior mapReplyAction(PostfachNachricht.ReplyOption replyOption) { + return switch (replyOption) { + case FORBIDDEN -> V1ReplyBehavior.REPLYFORBIDDEN; + case POSSIBLE -> V1ReplyBehavior.REPLYPOSSIBLE; + case MANDATORY -> V1ReplyBehavior.REPLYMANDATORY; + }; + } default String mapMailboxId(PostfachNachricht nachricht) { return Optional.ofNullable(nachricht.getPostfachAddress()) .map(PostfachAddress::getIdentifier) .filter(PostfachAddressIdentifier::isStringBasedIdentifier) .map(Object::toString) - .orElseThrow(() -> new IllegalArgumentException("Missing MailboxId! Expect MailboxId to be a string-based PostfachAddress of PostfachNachricht.")); + .orElseThrow(() -> new IllegalArgumentException( + "Missing MailboxId! Expect MailboxId to be a string-based PostfachAddress of PostfachNachricht.")); } } diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java index 78c6a2f4e5e0384195bf93c99957aef281af2077..5cca4d39ca591f10b9612b24ba2abc8075070e3c 100644 --- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java +++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/OsiPostfachRemoteServiceRemoteITCase.java @@ -15,6 +15,11 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; +import de.ozgcloud.nachrichten.postfach.PostfachNachricht; +import de.ozgcloud.nachrichten.postfach.osiv2.factory.DummyStringBasedIdentifier; +import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory; +import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory; + @SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) @ActiveProfiles("itcase") @EnabledIfEnvironmentVariable(named = "SH_STAGE_CLIENT_SECRET", matches = ".+") @@ -23,6 +28,14 @@ public class OsiPostfachRemoteServiceRemoteITCase { @Autowired private OsiPostfachRemoteService osiPostfachRemoteService; + private final PostfachNachricht nachricht = PostfachNachrichtTestFactory.createBuilder() + .postfachAddress(PostfachAddressTestFactory.createBuilder() + .identifier(DummyStringBasedIdentifier.builder() + .mailboxId("sh/sh/60e319ae-4fe7-4f47-c7c8-08dca563280a") + .build()) + .build()) + .build(); + @DynamicPropertySource static void dynamicProperties(DynamicPropertyRegistry registry) { registry.add( @@ -54,7 +67,7 @@ public class OsiPostfachRemoteServiceRemoteITCase { @DisplayName("should not fail") @Test void shouldNotFail() { - assertThatCode(() -> osiPostfachRemoteService.getAllMessages()) + assertThatCode(() -> osiPostfachRemoteService.sendMessage(nachricht)) .doesNotThrowAnyException(); } diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachNachrichtTestFactory.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachNachrichtTestFactory.java index c57b2aafc06fbd8ded48cea7bf624f42fb8d1d72..e24b966431f23e9de36aac29539323a0c456a25b 100644 --- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachNachrichtTestFactory.java +++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/factory/PostfachNachrichtTestFactory.java @@ -7,6 +7,8 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht; public class PostfachNachrichtTestFactory { public static final String MAIL_BODY = "mail body"; public static final String MAIL_SUBJECT = "mail subject"; + public static final String VORGANG_ID = "test-vorgang-id"; + public static final String USER_ID = "test-user-id"; public static PostfachNachricht create() { @@ -17,8 +19,10 @@ public class PostfachNachrichtTestFactory { return PostfachNachricht.builder() .mailBody(MAIL_BODY) .subject(MAIL_SUBJECT) + .replyOption(PostfachNachricht.ReplyOption.FORBIDDEN) .createdAt(ZonedDateTime.now()) - .vorgangId("test-vorgang-id") + .createdBy(USER_ID) + .vorgangId(VORGANG_ID) .postfachAddress(PostfachAddressTestFactory.create()); } } diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapperTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapperTest.java index 5ac7fea93436ca8b2637288039b238829fef5084..957d440acaadcb07690857899f081c151bbadb6b 100644 --- a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapperTest.java +++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/transfer/RequestMapperTest.java @@ -2,6 +2,7 @@ package de.ozgcloud.nachrichten.postfach.osiv2.transfer; import static de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory.*; import static de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory.*; +import static de.ozgcloud.nachrichten.postfach.osiv2.transfer.RequestMapper.*; import static org.assertj.core.api.Assertions.*; import java.util.stream.Stream; @@ -16,10 +17,12 @@ import org.mapstruct.factory.Mappers; import de.ozgcloud.nachrichten.postfach.PostfachAddress; import de.ozgcloud.nachrichten.postfach.PostfachAddressIdentifier; +import de.ozgcloud.nachrichten.postfach.PostfachNachricht; import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachAddressTestFactory; import de.ozgcloud.nachrichten.postfach.osiv2.factory.PostfachNachrichtTestFactory; import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.OutSendMessageRequestV2; import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1EidasLevel; +import de.ozgcloud.nachrichten.postfach.osiv2.gen.model.V1ReplyBehavior; class RequestMapperTest { @@ -67,6 +70,16 @@ class RequestMapperTest { @DisplayName("map OutSendMessageRequestV2") @Nested class TestMapOutSendMessageRequestV2 { + + @DisplayName("should map sequence number") + @Test + void shouldMapSequenceNumber() { + var result = doMapping(); + + assertThat(result.getSequencenumber()).isEqualTo(VORGANG_ID); + } + + @DisplayName("should map subject") @Test void shouldMapSubject() { @@ -83,12 +96,60 @@ class RequestMapperTest { assertThat(result.getBody()).isEqualTo(MAIL_BODY); } + @DisplayName("should map display name") + @Test + void shouldMapDisplayName() { + var result = doMapping(); + + assertThat(result.getDisplayName()).isEqualTo(USER_ID); + } + + @DisplayName("should map origin sender") + @Test + void shouldMapOriginSender() { + var result = doMapping(); + + assertThat(result.getOriginSender()).isEqualTo(ORIGIN_SENDER); + } + + @DisplayName("should map forbidden reply action") + @Test + void shouldMapForbiddenReplyAction() { + var result = doMapping(); + + assertThat(result.getReplyAction()).isEqualTo(V1ReplyBehavior.REPLYFORBIDDEN); + } + + @DisplayName("should map possible reply action") + @Test + void shouldMapPossibleReplyAction() { + var nachricht = PostfachNachrichtTestFactory.createBuilder() + .replyOption(PostfachNachricht.ReplyOption.POSSIBLE) + .build(); + + var result = mapper.mapOutSendMessageRequestV2(nachricht); + + assertThat(result.getReplyAction()).isEqualTo(V1ReplyBehavior.REPLYPOSSIBLE); + } + + @DisplayName("should map mandatory reply action") + @Test + void shouldMapMandatoryReplyAction() { + var nachricht = PostfachNachrichtTestFactory.createBuilder() + .replyOption(PostfachNachricht.ReplyOption.MANDATORY) + .build(); + + var result = mapper.mapOutSendMessageRequestV2(nachricht); + + assertThat(result.getReplyAction()).isEqualTo(V1ReplyBehavior.REPLYMANDATORY); + } + @DisplayName("should set eidasLevel") @Test void shouldSetEidasLevel() { var result = doMapping(); - assertThat(result.getEidasLevel()).isEqualTo(V1EidasLevel.MEDIUM); + assertThat(result.getEidasLevel()).isEqualTo(V1EidasLevel.LOW); } @DisplayName("should set isObligatory") @@ -99,6 +160,30 @@ class RequestMapperTest { assertThat(result.getIsObligatory()).isFalse(); } + @DisplayName("should set isHtml") + @Test + void shouldSetIsHtml() { + var result = doMapping(); + + assertThat(result.getIsHtml()).isTrue(); + } + + @DisplayName("should map files") + @Test + void shouldMapFiles() { + var result = doMapping(); + + assertThat(result.getFiles()).isEmpty(); + } + + @DisplayName("should map references") + @Test + void shouldMapReferences() { + var result = doMapping(); + + assertThat(result.getFiles()).isEmpty(); + } + private OutSendMessageRequestV2 doMapping() { return mapper.mapOutSendMessageRequestV2(PostfachNachrichtTestFactory.create()); }