diff --git a/nachrichten-manager-interface/src/main/protobuf/antragraum.model.proto b/nachrichten-manager-interface/src/main/protobuf/antragraum.model.proto index fa1ef06aea7c96255623000b25acb0a1421d138a..34504138fbe034e800a6d2d02eeb90b78bac9f6f 100644 --- a/nachrichten-manager-interface/src/main/protobuf/antragraum.model.proto +++ b/nachrichten-manager-interface/src/main/protobuf/antragraum.model.proto @@ -37,20 +37,36 @@ message GrpcFindRueckfragenRequest { } message GrpcFindRueckfragenResponse { - repeated GrpcRueckfrage rueckfrage = 1; + repeated GrpcRueckfrageHead rueckfrageHead = 1; +} + +message GrpcRueckfrageHead { + string id = 1; + string vorgangId = 2; + string vorgangName = 3; + string vorgangNummer = 4; + string sentAt = 5; + string answeredAt = 6; + string status = 7; + string trustLevel = 8; + bool accessible = 9; } message GrpcRueckfrage { string id = 1; string vorgangId = 2; string vorgangName = 3; - string sentAt = 4; - string answeredAt = 5; - string status = 6; - string text = 7; - repeated string attachmentFileId = 8; - repeated GrpcRueckfrageAnswer answers = 9; - string vorgangNummer = 10; + string vorgangNummer = 4; + string sentAt = 5; + string answeredAt = 6; + string status = 7; + string trustLevel = 8; + bool accessible = 9; + + string text = 10; + + repeated string attachmentFileId = 11; + repeated GrpcRueckfrageAnswer answers = 12; } message GrpcSendRueckfrageAnswerRequest { @@ -67,4 +83,13 @@ message GrpcRueckfrageAnswer { message GrpcSendRueckfrageAnswerResponse { string commandId = 1; +} + +message GrpcGetRueckfrageRequest { + string samlToken = 1; + string id = 2; +} + +message GrpcGetRueckfrageResponse { + GrpcRueckfrage rueckfrage = 1; } \ No newline at end of file diff --git a/nachrichten-manager-interface/src/main/protobuf/antragraum.proto b/nachrichten-manager-interface/src/main/protobuf/antragraum.proto index 5560957878b13267d76a19e2c91ef992bdcca207..e22f3bb0fa2226094b2551d8748c1095f1ded8f5 100644 --- a/nachrichten-manager-interface/src/main/protobuf/antragraum.proto +++ b/nachrichten-manager-interface/src/main/protobuf/antragraum.proto @@ -38,4 +38,7 @@ service AntragraumService { rpc SendRueckfrageAnswer(GrpcSendRueckfrageAnswerRequest) returns (GrpcSendRueckfrageAnswerResponse) { } + + rpc GetRueckfrage(GrpcGetRueckfrageRequest) returns (GrpcGetRueckfrageResponse){ + } } \ No newline at end of file diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java index 3684ce3c2f2c29b5dda1966a5e48bcc4d1ed0cbd..60fb62d6bfa8384eb093780e82411474bec22373 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcService.java @@ -31,6 +31,7 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.nachrichten.common.vorgang.VorgangService; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; import io.grpc.stub.StreamObserver; import lombok.RequiredArgsConstructor; @@ -40,55 +41,76 @@ import net.devh.boot.grpc.server.service.GrpcService; @RequiredArgsConstructor @ConditionalOnProperty(AntragraumProperties.PROPERTY_ANTRAGSRAUM_URL) class AntragraumGrpcService extends AntragraumServiceGrpc.AntragraumServiceImplBase { - private final AntragraumService antragraumService; + private final AntragraumService service; private final AntragraumNachrichtMapper mapper; + private final RueckfrageMapper rueckfrageMapper; + + private final VorgangService vorgangService; @Override public void findRueckfragen(GrpcFindRueckfragenRequest request, StreamObserver<GrpcFindRueckfragenResponse> streamObserver) { - var rueckfragen = antragraumService.findRueckfragen(request.getSamlToken()) - .map(mapper::toGrpc) - .map(rueckfrage -> addAnswers(request.getSamlToken(), rueckfrage)); + var rueckfragen = service.findRueckfragen(request.getSamlToken()).map(mapper::toGrpc); streamObserver.onNext(buildFindRueckfragenResponse(rueckfragen)); streamObserver.onCompleted(); } - private GrpcRueckfrage addAnswers(String samlToken, GrpcRueckfrage rueckfrage) { - return rueckfrage.toBuilder().addAllAnswers(findRueckfrageAnswers(samlToken, rueckfrage.getId())).build(); - } - - List<GrpcRueckfrageAnswer> findRueckfrageAnswers(String samlToken, String rueckfrageId) { - return antragraumService.findAnswers(samlToken, rueckfrageId).map(mapper::toRueckfrageAnswer).toList(); - } - - private GrpcFindRueckfragenResponse buildFindRueckfragenResponse(Stream<GrpcRueckfrage> rueckfragen) { - return GrpcFindRueckfragenResponse.newBuilder().addAllRueckfrage(rueckfragen.toList()).build(); - + private GrpcFindRueckfragenResponse buildFindRueckfragenResponse(Stream<GrpcRueckfrageHead> rueckfragen) { + return GrpcFindRueckfragenResponse.newBuilder().addAllRueckfrageHead(rueckfragen.toList()).build(); } @Override public void sendRueckfrageAnswer(GrpcSendRueckfrageAnswerRequest request, StreamObserver<GrpcSendRueckfrageAnswerResponse> streamObserver) { var answer = mapper.fromRueckfrageAnswer(request.getAnswer()); - answer = enrichRueckfrageAnswer(answer, getRueckfrage(request.getSamlToken(), request.getAnswer().getRueckfrageId())); - var commandId = antragraumService.sendRueckfrageAnswer(request.getSamlToken(), request.getAnswer().getRueckfrageId(), answer); + answer = enrichRueckfrageAnswer(answer, getRueckfrageByNachricht(request.getSamlToken(), request.getAnswer().getRueckfrageId())); + var commandId = service.sendRueckfrageAnswer(request.getSamlToken(), request.getAnswer().getRueckfrageId(), answer); streamObserver.onNext(GrpcSendRueckfrageAnswerResponse.newBuilder().setCommandId(commandId).build()); streamObserver.onCompleted(); } - Rueckfrage getRueckfrage(String samlToken, String postfachNachrichtId) { - return antragraumService.findRueckfragen(samlToken) + RueckfrageHead getRueckfrageByNachricht(String samlToken, String postfachNachrichtId) { + return service.findRueckfragen(samlToken) .filter(rueckfrage -> StringUtils.equals(rueckfrage.getId(), postfachNachrichtId)) .findFirst() .orElseThrow(() -> new TechnicalException(String.format("No rueckfrage found for answer with id %s", postfachNachrichtId))); } - PostfachNachricht enrichRueckfrageAnswer(PostfachNachricht answer, Rueckfrage rueckfrage) { + PostfachNachricht enrichRueckfrageAnswer(PostfachNachricht answer, RueckfrageHead rueckfrage) { return answer.toBuilder() .vorgangId(rueckfrage.getVorgangId()) .postfachAddress(rueckfrage.getPostfachAddress()) .sentAt(ZonedDateTime.now()) .build(); } + + @Override + public void getRueckfrage(GrpcGetRueckfrageRequest request, StreamObserver<GrpcGetRueckfrageResponse> responseObserver) { + var samlToken = request.getSamlToken(); + var rueckfrage = service.getRueckfrage(samlToken, request.getId()); + + var enhancedRueckfrage = enhanceRueckfrage(rueckfrage, samlToken); + + responseObserver.onNext(buildGetRueckfrageResponse(enhancedRueckfrage)); + responseObserver.onCompleted(); + } + + GrpcRueckfrage enhanceRueckfrage(PostfachNachricht rueckfrage, String samlToken) { + var vorgang = vorgangService.getVorgang(rueckfrage.getVorgangId()); + + var answers = service.findAnswers(samlToken, rueckfrage.getId()).toList(); + var firstAnswerSentAt = service.getFirstSentAt(answers.stream()); + + var rueckfrageWithAnswer = addAnswers(rueckfrageMapper.toRueckfrage(firstAnswerSentAt, vorgang, rueckfrage), answers); + return rueckfrageWithAnswer.toBuilder().setAccessible(service.isAccessible(samlToken, vorgang.getTrustLevel())).build(); + } + + GrpcRueckfrage addAnswers(GrpcRueckfrage rueckfrage, List<PostfachNachricht> answers) { + return rueckfrage.toBuilder().addAllAnswers(answers.stream().map(mapper::toRueckfrageAnswer).toList()).build(); + } + + GrpcGetRueckfrageResponse buildGetRueckfrageResponse(GrpcRueckfrage rueckfrage) { + return GrpcGetRueckfrageResponse.newBuilder().setRueckfrage(rueckfrage).build(); + } } diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapper.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapper.java index f0c954007b2aabfa4ed9c3af1e3a3499bb323a04..3c14695971b75f4d1b8543f8f7826a47286a0506 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapper.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapper.java @@ -25,6 +25,7 @@ package de.ozgcloud.nachrichten.antragraum; import java.time.ZonedDateTime; +import java.time.temporal.ChronoField; import org.apache.commons.lang3.StringUtils; import org.mapstruct.CollectionMappingStrategy; @@ -37,27 +38,23 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht; @Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) interface AntragraumNachrichtMapper { + @Mapping(target = "trustLevelBytes", ignore = true) + @Mapping(target = "vorgangNummerBytes", ignore = true) @Mapping(target = "mergeFrom", ignore = true) @Mapping(target = "clearField", ignore = true) @Mapping(target = "clearOneof", ignore = true) @Mapping(target = "mergeUnknownFields", ignore = true) - @Mapping(target = "removeAnswers", ignore = true) @Mapping(target = "answeredAt", ignore = true) @Mapping(target = "answeredAtBytes", ignore = true) @Mapping(target = "idBytes", ignore = true) @Mapping(target = "sentAtBytes", ignore = true) @Mapping(target = "statusBytes", ignore = true) - @Mapping(target = "textBytes", ignore = true) @Mapping(target = "unknownFields", ignore = true) @Mapping(target = "vorgangIdBytes", ignore = true) @Mapping(target = "vorgangNameBytes", ignore = true) @Mapping(target = "allFields", ignore = true) - @Mapping(target = "answersBuilderList", ignore = true) - @Mapping(target = "answersList", ignore = true) - @Mapping(target = "answersOrBuilderList", ignore = true) @Mapping(target = "sentAt", source = "sentAt", dateFormat = "yyyy-MM-dd'T'HH:mm:ss") - @Mapping(target = "attachmentFileIdList", source = "attachments") - GrpcRueckfrage toGrpc(Rueckfrage rueckfrage); + GrpcRueckfrageHead toGrpc(RueckfrageHead rueckfrage); @Mapping(target = "referencedNachricht", ignore = true) @Mapping(target = "mailBody", source = "answerText") @@ -79,7 +76,7 @@ interface AntragraumNachrichtMapper { default ZonedDateTime mapZonedDateTime(String sentAt) { if (StringUtils.isBlank(sentAt)) { - return null; + return ZonedDateTime.now().with(ChronoField.MILLI_OF_SECOND, 0); } return ZonedDateTime.parse(sentAt); } diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java index 3e10f0004cdf6859e59c8dd37927c04a2ede9b08..b7ae839cb454017adc22bd543228b1afe1d1e0da 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/AntragraumService.java @@ -34,6 +34,8 @@ import java.util.stream.Stream; import jakarta.annotation.PostConstruct; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.opensaml.saml.saml2.core.Response; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; @@ -44,6 +46,7 @@ import de.ozgcloud.nachrichten.common.vorgang.Vorgang; import de.ozgcloud.nachrichten.common.vorgang.VorgangService; import de.ozgcloud.nachrichten.postfach.PersistPostfachNachrichtService; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; +import de.ozgcloud.nachrichten.postfach.PostfachNachrichtMapper; import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; @@ -76,6 +79,7 @@ public class AntragraumService { private final RueckfrageMapper rueckfrageMapper; @Qualifier(NachrichtenManagerConfiguration.NACHRICHTEN_VORGANG_SERVICE) private final VorgangService vorgangService; + private final PostfachNachrichtMapper nachrichtMapper; @PostConstruct void init() { @@ -97,16 +101,16 @@ public class AntragraumService { return USER_NOTIFICATION_TEMPLATE.formatted(getAntragsraumUrl()); } - public Stream<Rueckfrage> findRueckfragen(String samlToken) { + public Stream<RueckfrageHead> findRueckfragen(String samlToken) { verifyToken(samlToken); var rueckfragen = postfachNachrichtService.findRueckfragen(BAYERN_ID_SERVICE_KONTO_TYPE, getPostfachId(samlToken)) .map(rueckfrageMapper::fromPostfachNachricht) .map(rueckfrage -> enrichByAnswers(rueckfrage, samlToken)).toList(); - return enrichRueckfragen(rueckfragen); + return enrichRueckfragen(rueckfragen, samlToken); } - Rueckfrage enrichByAnswers(Rueckfrage rueckfrage, String samlToken) { + RueckfrageHead enrichByAnswers(RueckfrageHead rueckfrage, String samlToken) { var rueckfrageBuilder = rueckfrage.toBuilder(); getFirstSentAt(findAnswers(samlToken, rueckfrage.getId())) @@ -119,20 +123,27 @@ public class AntragraumService { return answers.sorted(Comparator.comparing(PostfachNachricht::getSentAt)).map(PostfachNachricht::getSentAt).findFirst(); } - Stream<Rueckfrage> enrichRueckfragen(List<Rueckfrage> rueckfragen) { + Stream<RueckfrageHead> enrichRueckfragen(List<RueckfrageHead> rueckfragen, String samlToken) { if (rueckfragen.isEmpty()) { return Stream.empty(); } - return addVorgangData(rueckfragen, rueckfragen.getFirst().getVorgangId()); + var vorgang = vorgangService.getVorgang(rueckfragen.getFirst().getVorgangId()); + + return rueckfragen.stream() + .map(rueckfrage -> addVorgangData(rueckfrage, vorgang)) + .map(rueckfrage -> addAccessible(rueckfrage, samlToken)); } - Stream<Rueckfrage> addVorgangData(List<Rueckfrage> rueckfragen, String vorgangId) { - var vorgang = vorgangService.getVorgang(vorgangId); - return rueckfragen.stream().map(rueckfrage -> addVorgangData(rueckfrage, vorgang)); + RueckfrageHead addAccessible(RueckfrageHead rueckfrage, String samlToken) { + return rueckfrage.toBuilder().accessible(isAccessible(samlToken, rueckfrage.getTrustLevel())).build(); } - private Rueckfrage addVorgangData(Rueckfrage rueckfrage, Vorgang vorgang) { - return rueckfrage.toBuilder().vorgangName(vorgang.getName()).vorgangNummer(vorgang.getNummer()).build(); + RueckfrageHead addVorgangData(RueckfrageHead rueckfrage, Vorgang vorgang) { + return rueckfrage.toBuilder() + .vorgangName(vorgang.getName()) + .vorgangNummer(vorgang.getNummer()) + .trustLevel(vorgang.getTrustLevel()) + .build(); } public String sendRueckfrageAnswer(String samlToken, String rueckfrageId, PostfachNachricht nachricht) { @@ -147,6 +158,16 @@ public class AntragraumService { return postfachNachrichtService.findAnswers(BAYERN_ID_SERVICE_KONTO_TYPE, getPostfachId(samlToken), rueckfrageId); } + String getPostfachId(String samlToken) { + return decrypter.decryptPostfachId(parser.parse(samlToken)); + } + + public PostfachNachricht getRueckfrage(String samlToken, String id) { + verifyToken(samlToken); + + return nachrichtMapper.fromMapToPostfachMail(postfachNachrichtService.getById(id)); + } + void verifyToken(String token) { var errors = verifier.verify(token); if (CollectionUtils.isNotEmpty(errors)) { @@ -154,7 +175,15 @@ public class AntragraumService { } } - String getPostfachId(String samlToken) { - return decrypter.decryptPostfachId(parser.parse(samlToken)); + public boolean isAccessible(String samlToken, String trustLevel) { + return StringUtils.equals(getTrustLevel(samlToken), trustLevel); + } + + String getTrustLevel(String samlToken) { + return decrypter.decryptTrustLevel(parseSamlToken(samlToken)); + } + + Response parseSamlToken(String samlToken) { + return parser.parse(samlToken); } -} +} \ No newline at end of file diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/Rueckfrage.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/RueckfrageHead.java similarity index 74% rename from nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/Rueckfrage.java rename to nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/RueckfrageHead.java index acc18d8093e83d95447a6f8d63fa95e8b24ab1e9..8d7e25b27bd41c144bc3b107e3cf46a444228236 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/Rueckfrage.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/RueckfrageHead.java @@ -1,8 +1,6 @@ package de.ozgcloud.nachrichten.antragraum; import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.List; import de.ozgcloud.nachrichten.postfach.PostfachAddress; import lombok.Builder; @@ -10,7 +8,7 @@ import lombok.Getter; @Getter @Builder(toBuilder = true) -class Rueckfrage { +class RueckfrageHead { private String id; private String vorgangId; @@ -23,9 +21,7 @@ class Rueckfrage { @Builder.Default private RueckfrageStatus status = RueckfrageStatus.NEW; - private String text; - - @Builder.Default - private List<String> attachments = Collections.emptyList(); + private String trustLevel; + private boolean accessible; } \ No newline at end of file diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapper.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapper.java index 439961c766b90a6952961e916a0117210115dc63..b2a7ffddae6b391fab7c684b808f68d2b9972250 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapper.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapper.java @@ -1,11 +1,17 @@ package de.ozgcloud.nachrichten.antragraum; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; import org.mapstruct.CollectionMappingStrategy; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.NullValueCheckStrategy; import org.mapstruct.ReportingPolicy; +import de.ozgcloud.nachrichten.common.vorgang.Vorgang; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; @Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, // @@ -13,10 +19,56 @@ import de.ozgcloud.nachrichten.postfach.PostfachNachricht; nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) interface RueckfrageMapper { + final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssX"); + + @Mapping(target = "accessible", ignore = true) + @Mapping(target = "trustLevel", ignore = true) + @Mapping(target = "vorgangNummer", ignore = true) @Mapping(target = "answeredAt", ignore = true) @Mapping(target = "status", ignore = true) - @Mapping(target = "text", source = "mailBody") @Mapping(target = "vorgangName", ignore = true) - Rueckfrage fromPostfachNachricht(PostfachNachricht postfachNachricht); + RueckfrageHead fromPostfachNachricht(PostfachNachricht postfachNachricht); + + @Mapping(target = "mergeFrom", ignore = true) + @Mapping(target = "clearField", ignore = true) + @Mapping(target = "clearOneof", ignore = true) + @Mapping(target = "mergeUnknownFields", ignore = true) + @Mapping(target = "removeAnswers", ignore = true) + @Mapping(target = "answeredAt", expression = "java(setAnsweredAt(firstAnswerSentAt))") + @Mapping(target = "answeredAtBytes", ignore = true) + @Mapping(target = "idBytes", ignore = true) + @Mapping(target = "sentAtBytes", ignore = true) + @Mapping(target = "statusBytes", ignore = true) + @Mapping(target = "trustLevelBytes", ignore = true) + @Mapping(target = "vorgangIdBytes", ignore = true) + @Mapping(target = "vorgangNummerBytes", ignore = true) + @Mapping(target = "accessible", ignore = true) + @Mapping(target = "status", expression = "java(setStatus(firstAnswerSentAt))") + @Mapping(target = "textBytes", ignore = true) + @Mapping(target = "trustLevel", source = "vorgang.trustLevel") + @Mapping(target = "unknownFields", ignore = true) + @Mapping(target = "vorgangName", source = "vorgang.name") + @Mapping(target = "vorgangNameBytes", ignore = true) + @Mapping(target = "vorgangNummer", source = "vorgang.nummer") + @Mapping(target = "allFields", ignore = true) + @Mapping(target = "answersBuilderList", ignore = true) + @Mapping(target = "answersList", ignore = true) + @Mapping(target = "answersOrBuilderList", ignore = true) + @Mapping(target = "attachmentFileIdList", source = "rueckfrage.attachments") + @Mapping(target = "sentAt", source = "rueckfrage.sentAt", dateFormat = "yyyy-MM-dd'T'HH:mm:ss") + @Mapping(target = "id", source = "rueckfrage.id") + @Mapping(target = "text", source = "rueckfrage.mailBody") + GrpcRueckfrage toRueckfrage(Optional<ZonedDateTime> firstAnswerSentAt, Vorgang vorgang, PostfachNachricht rueckfrage); + + default String setVorgangName(Vorgang vorgang) { + return vorgang.getName(); + } + + default String setAnsweredAt(Optional<ZonedDateTime> firstAnswerSentAt) { + return firstAnswerSentAt.map(formatter::format).orElseGet(() -> StringUtils.EMPTY); + } + default String setStatus(Optional<ZonedDateTime> firstAnswerSentAt) { + return firstAnswerSentAt.map(answeredAt -> RueckfrageStatus.ANSWERED.name()).orElseGet(RueckfrageStatus.NEW::name); + } } \ No newline at end of file diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/Saml2Decrypter.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/Saml2Decrypter.java index 0501ba08ed694b67b30face9998ed31faecb0e9c..eb4f7eea2ad94a4cbc9946e46c4fe7d55fe21dbb 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/Saml2Decrypter.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/antragraum/Saml2Decrypter.java @@ -25,11 +25,13 @@ package de.ozgcloud.nachrichten.antragraum; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; +import java.util.List; import jakarta.annotation.PostConstruct; import org.opensaml.core.xml.schema.XSString; +import org.opensaml.saml.saml2.core.Assertion; +import org.opensaml.saml.saml2.core.Attribute; import org.opensaml.saml.saml2.core.AttributeStatement; import org.opensaml.saml.saml2.core.EncryptedAssertion; import org.opensaml.saml.saml2.core.Response; @@ -41,7 +43,6 @@ import org.opensaml.xmlsec.encryption.support.ChainingEncryptedKeyResolver; import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver; import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver; import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver; -import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver; import org.opensaml.xmlsec.keyinfo.impl.CollectionKeyInfoCredentialResolver; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.security.saml2.Saml2Exception; @@ -56,49 +57,75 @@ class Saml2Decrypter { private final BayernIdSamlConfiguration configuration; public static final String LEGACY_POSTKORB_HANDLE_KEY = "urn:oid:2.5.4.18"; + public static final String TRUST_LEVEL_KEY = "urn:oid:1.2.40.0.10.2.1.1.261.94"; + private Decrypter decrypter; private static final EncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver( - Arrays.asList(new InlineEncryptedKeyResolver(), new EncryptedElementTypeEncryptedKeyResolver(), - new SimpleRetrievalMethodEncryptedKeyResolver())); + Arrays.asList(new InlineEncryptedKeyResolver(), new EncryptedElementTypeEncryptedKeyResolver(), + new SimpleRetrievalMethodEncryptedKeyResolver())); @PostConstruct void init() { - Collection<Credential> credentials = new ArrayList<>(); + var credentials = new ArrayList<Credential>(); var decryptionX509Credential = configuration.getDecryptionCredential(); - Credential cred = CredentialSupport.getSimpleCredential(decryptionX509Credential.getCertificate(), decryptionX509Credential.getPrivateKey()); + var cred = CredentialSupport.getSimpleCredential(decryptionX509Credential.getCertificate(), decryptionX509Credential.getPrivateKey()); credentials.add(cred); - KeyInfoCredentialResolver resolver = new CollectionKeyInfoCredentialResolver(credentials); + var resolver = new CollectionKeyInfoCredentialResolver(credentials); var setupDecrypter = new Decrypter(null, resolver, encryptedKeyResolver); setupDecrypter.setRootInNewDocument(true); decrypter = setupDecrypter; } + public String decryptPostfachId(Response response) { + decryptResponseElements(response); + + var postfachIdAttribute = getAttributes(response).stream().filter(this::isPostfachId).findFirst(); + + return postfachIdAttribute.map(this::getStringValue).orElseThrow(); + } + + boolean isPostfachId(Attribute attribute) { + return LEGACY_POSTKORB_HANDLE_KEY.equals(attribute.getName()); + } + + public String decryptTrustLevel(Response response) { + decryptResponseElements(response); + + var trustLevelAttribute = getAttributes(response).stream().filter(this::isTrustLevel).findFirst(); + + return trustLevelAttribute.map(this::getStringValue).orElseThrow(); + } + void decryptResponseElements(Response response) { - for (EncryptedAssertion encryptedAssertion : response.getEncryptedAssertions()) { - try { - var assertion = decrypter.decrypt(encryptedAssertion); - response.getAssertions().add(assertion); - } catch (Exception ex) { - throw new Saml2Exception(ex); - } + response.getEncryptedAssertions().stream() + .map(this::decryptAssertion) + .forEach(assertion -> response.getAssertions().add(assertion)); + } + + private Assertion decryptAssertion(EncryptedAssertion assertion) { + try { + return decrypter.decrypt(assertion); + } catch (Exception ex) { + throw new Saml2Exception(ex); } } - String decryptPostfachId(Response response) { - decryptResponseElements(response); + private List<Attribute> getAttributes(Response response) { + return getAttributeStatement(response).getAttributes(); + } - var samlAssertion = response.getAssertions().getFirst(); - var statements = (AttributeStatement) samlAssertion.getStatements().get(1); - var attributes = statements.getAttributes(); - var postfachIdOptional = attributes.stream().filter(attribute -> LEGACY_POSTKORB_HANDLE_KEY.equals(attribute.getName())).findFirst(); + private AttributeStatement getAttributeStatement(Response response) { + return (AttributeStatement) response.getAssertions().getFirst().getStatements().get(1); + } - return postfachIdOptional.map(postfachIdAttribute -> { - var values = postfachIdAttribute.getAttributeValues(); - return ((XSString) values.getFirst()).getValue(); - }).orElseThrow(); + boolean isTrustLevel(Attribute attribute) { + return TRUST_LEVEL_KEY.equals(attribute.getName()); + } + private String getStringValue(Attribute attribute) { + return ((XSString) attribute.getAttributeValues().getFirst()).getValue(); } -} +} \ No newline at end of file diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/NachrichtenVorgangMapper.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/NachrichtenVorgangMapper.java index 621101d3933b4f6f0414ee307e4682315ef06f2f..087b161af912abd75372e845e51e8b546e620937 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/NachrichtenVorgangMapper.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/NachrichtenVorgangMapper.java @@ -1,6 +1,7 @@ package de.ozgcloud.nachrichten.common.vorgang; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang; @@ -8,5 +9,6 @@ import de.ozgcloud.vorgang.vorgang.GrpcVorgangWithEingang; @Mapper(unmappedTargetPolicy = ReportingPolicy.WARN) interface NachrichtenVorgangMapper { + @Mapping(target = "trustLevel", source = "vorgangWithEingang.header.serviceKonto.trustLevel") Vorgang fromVorgangWithEingang(GrpcVorgangWithEingang vorgangWithEingang); } diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/Vorgang.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/Vorgang.java index 6e3df04528c6d10ceddb2832d712dea41a3f2bf1..713f4da191b6a75fa690f42ce20984c2811dd5b3 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/Vorgang.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/vorgang/Vorgang.java @@ -10,4 +10,6 @@ public class Vorgang { private String id; private String name; private String nummer; + + private String trustLevel; } \ No newline at end of file diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapper.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapper.java index 7c9ce56fee998de321c44bb1b0ee9348a33466cc..f0b40d4b0da955f55c627a4edaa19ad7eb6e132e 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapper.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/postfach/PostfachNachrichtMapper.java @@ -126,7 +126,7 @@ public abstract class PostfachNachrichtMapper { return fromMapToPostfachMail(grpcObjectMapper.mapFromGrpc(grpcVorgangAttachedItem.getItem())); } - PostfachNachricht fromMapToPostfachMail(Map<String, Object> mailMap) { + public PostfachNachricht fromMapToPostfachMail(Map<String, Object> mailMap) { var postfachMailBuilder = PostfachNachricht.builder() .id(MapUtils.getString(mailMap, PostfachNachricht.FIELD_ID)) .vorgangId(MapUtils.getString(mailMap, (PostfachNachricht.FIELD_VORGANG_ID))) diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java index 6b96cc3be43f4a2797608efb1350768c1c50f502..a3815062085899da5db72cba9430d03f317a8c93 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumGrpcServiceTest.java @@ -26,6 +26,8 @@ import static org.mockito.Mockito.*; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; +import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.stream.Stream; @@ -33,16 +35,24 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import de.ozgcloud.common.errorhandling.TechnicalException; +import de.ozgcloud.nachrichten.common.vorgang.GrpcServiceKontoTestFactory; +import de.ozgcloud.nachrichten.common.vorgang.Vorgang; +import de.ozgcloud.nachrichten.common.vorgang.VorgangService; +import de.ozgcloud.nachrichten.common.vorgang.VorgangTestFactory; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; +import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory; import io.grpc.stub.StreamObserver; class AntragraumGrpcServiceTest { + @Spy @InjectMocks private AntragraumGrpcService grpcService; @@ -50,31 +60,44 @@ class AntragraumGrpcServiceTest { private AntragraumService service; @Mock private AntragraumNachrichtMapper nachrichtMapper; + @Mock + private RueckfrageMapper rueckfrageMapper; + @Mock + private VorgangService vorgangService; + + @DisplayName("Find rueckfragen") @Nested class TestFindRueckfragen { + @Captor + private ArgumentCaptor<GrpcFindRueckfragenResponse> responseCaptor; @Mock private StreamObserver<GrpcFindRueckfragenResponse> streamObserver; + private final RueckfrageHead rueckfrage = RueckfrageHeadTestFactory.create(); + + private final GrpcRueckfrageHead grpcRueckfrageHead = GrpcRueckfrageHeadTestFactory.create(); + @BeforeEach void setup() { - when(service.findRueckfragen(any())).thenReturn(Stream.of(RueckfrageTestFactory.create())); - when(nachrichtMapper.toGrpc(any(Rueckfrage.class))).thenReturn(GrpcRueckfrageTestFactory.create()); + when(service.findRueckfragen(any())).thenReturn(Stream.of(rueckfrage)); + when(nachrichtMapper.toGrpc(any())).thenReturn(grpcRueckfrageHead); } @Test void shouldCallMapper() { grpcService.findRueckfragen(GrpcFindRueckfrageRequestTestFactory.create(), streamObserver); - verify(nachrichtMapper).toGrpc(any(Rueckfrage.class)); + verify(nachrichtMapper).toGrpc(rueckfrage); } @Test void shouldCallOnNext() { grpcService.findRueckfragen(GrpcFindRueckfrageRequestTestFactory.create(), streamObserver); - verify(streamObserver).onNext(any(GrpcFindRueckfragenResponse.class)); + verify(streamObserver).onNext(responseCaptor.capture()); + assertThat(responseCaptor.getValue().getRueckfrageHeadList()).containsExactly(grpcRueckfrageHead); } @Test @@ -83,13 +106,6 @@ class AntragraumGrpcServiceTest { verify(streamObserver).onCompleted(); } - - @Test - void shouldLoadAnswers() { - grpcService.findRueckfragen(GrpcFindRueckfrageRequestTestFactory.create(), streamObserver); - - verify(service).findAnswers(GrpcFindRueckfrageRequestTestFactory.SAML_TOKEN, GrpcRueckfrageTestFactory.ID); - } } @DisplayName("Send rueckfrage answer") @@ -98,7 +114,7 @@ class AntragraumGrpcServiceTest { @Mock private StreamObserver<GrpcSendRueckfrageAnswerResponse> streamObserver; private PostfachNachricht postfachNachricht = PostfachNachrichtTestFactory.create(); - private Rueckfrage rueckfrage = RueckfrageTestFactory.create(); + private RueckfrageHead rueckfrage = RueckfrageHeadTestFactory.create(); @BeforeEach void setup() { @@ -106,7 +122,7 @@ class AntragraumGrpcServiceTest { when(service.sendRueckfrageAnswer(anyString(), anyString(), any(PostfachNachricht.class))) .thenReturn(UUID.randomUUID().toString()); doReturn(postfachNachricht).when(grpcService).enrichRueckfrageAnswer(any(), any()); - doReturn(rueckfrage).when(grpcService).getRueckfrage(any(), any()); + doReturn(rueckfrage).when(grpcService).getRueckfrageByNachricht(anyString(), anyString()); } @Test @@ -120,7 +136,7 @@ class AntragraumGrpcServiceTest { void shouldGetRueckfrage() { sendRueckfrageAnswer(); - verify(grpcService).getRueckfrage(GrpcSendRueckfrageAnswerRequestTestFactory.SAML_TOKEN, + verify(grpcService).getRueckfrageByNachricht(GrpcSendRueckfrageAnswerRequestTestFactory.SAML_TOKEN, GrpcRueckfrageAnswerTestFactory.RUECKFRAGE_ID); } @@ -157,13 +173,13 @@ class AntragraumGrpcServiceTest { } } - @DisplayName("Get rueckfrage") + @DisplayName("Get rueckfrage by nachricht") @Nested - class TestGetRueckfrage { + class TestGetRueckfrageByNachricht { - private final Rueckfrage matchingRueckfrage = RueckfrageTestFactory.createBuilder().id(GrpcRueckfrageAnswerTestFactory.RUECKFRAGE_ID) + private final RueckfrageHead matchingRueckfrage = RueckfrageHeadTestFactory.createBuilder().id(GrpcRueckfrageAnswerTestFactory.RUECKFRAGE_ID) .build(); - private final Rueckfrage rueckfrage = RueckfrageTestFactory.create(); + private final RueckfrageHead rueckfrage = RueckfrageHeadTestFactory.create(); @BeforeEach void mock() { @@ -191,8 +207,8 @@ class AntragraumGrpcServiceTest { assertThatThrownBy(() -> getRueckfrage()).isInstanceOf(TechnicalException.class); } - private Rueckfrage getRueckfrage() { - return grpcService.getRueckfrage(GrpcSendRueckfrageAnswerRequestTestFactory.SAML_TOKEN, + private RueckfrageHead getRueckfrage() { + return grpcService.getRueckfrageByNachricht(GrpcSendRueckfrageAnswerRequestTestFactory.SAML_TOKEN, GrpcRueckfrageAnswerTestFactory.RUECKFRAGE_ID); } } @@ -207,7 +223,7 @@ class AntragraumGrpcServiceTest { .sentAt(null) .build(); - private final Rueckfrage postfachNachrichtRueckfrage = RueckfrageTestFactory.create(); + private final RueckfrageHead postfachNachrichtRueckfrage = RueckfrageHeadTestFactory.create(); @Test void shouldSetVorgangId() { @@ -230,4 +246,206 @@ class AntragraumGrpcServiceTest { assertThat(enrichedPostfachNachricht.getSentAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); } } + + @DisplayName("Get rueckfrage") + @Nested + class TestGetRueckfrage { + + @Mock + private StreamObserver<GrpcGetRueckfrageResponse> streamObserver; + + private final GrpcGetRueckfrageRequest request = GrpcGetRueckfrageRequestTestFactory.create(); + + private final PostfachNachricht rueckfrage = PostfachNachrichtTestFactory.create(); + + private final GrpcGetRueckfrageResponse getRueckfrageResponse = GrpcGetRueckfrageResponseTestFactory.create(); + + private final GrpcRueckfrage grpcRueckfrage = GrpcRueckfrageTestFactory.create(); + + @BeforeEach + void mock() { + when(service.getRueckfrage(any(), any())).thenReturn(rueckfrage); + + doReturn(getRueckfrageResponse).when(grpcService).buildGetRueckfrageResponse(any()); + doReturn(grpcRueckfrage).when(grpcService).enhanceRueckfrage(any(), any()); + } + + @Test + void shouldCallServiceToGetRueckfrage() { + getRueckfrage(); + + verify(service).getRueckfrage(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN, PostfachNachrichtTestFactory.ID); + } + + @Test + void shouldEnhanceRueckfrage() { + getRueckfrage(); + + verify(grpcService).enhanceRueckfrage(rueckfrage, GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + } + + @Test + void shouldCallBuildRueckfrageResponse() { + getRueckfrage(); + + verify(grpcService).buildGetRueckfrageResponse(grpcRueckfrage); + } + + @Test + void shouldCallOnNext() { + getRueckfrage(); + + verify(streamObserver).onNext(getRueckfrageResponse); + } + + @Test + void shouldCallOnCompleted() { + getRueckfrage(); + + verify(streamObserver).onCompleted(); + } + + private void getRueckfrage() { + grpcService.getRueckfrage(request, streamObserver); + } + } + + @DisplayName("Enhance rueckfrage") + @Nested + class TestEnhanceRueckfrage { + + @Captor + private ArgumentCaptor<Stream<PostfachNachricht>> answersStreamCaptor; + + @Captor + private ArgumentCaptor<List<PostfachNachricht>> answersListCaptor; + + private final PostfachNachricht rueckfrage = PostfachNachrichtTestFactory.create(); + + private final PostfachNachricht answer = PostfachNachrichtTestFactory.create(); + + private final ZonedDateTime now = ZonedDateTime.now(); + private final Optional<ZonedDateTime> sentAt = Optional.of(now); + + private final Vorgang vorgang = VorgangTestFactory.create(); + + private final GrpcRueckfrage grpcRueckfrage = GrpcRueckfrageTestFactory.create(); + + @BeforeEach + void mock() { + when(service.findAnswers(any(), any())).thenReturn(Stream.of(answer)); + when(service.getFirstSentAt(any())).thenReturn(sentAt); + when(vorgangService.getVorgang(any())).thenReturn(vorgang); + when(rueckfrageMapper.toRueckfrage(any(), any(), any())).thenReturn(grpcRueckfrage); + when(service.isAccessible(any(), any())).thenReturn(true); + + doReturn(grpcRueckfrage).when(grpcService).addAnswers(any(), any()); + } + + @Test + void shouldCallVorgangService() { + enhanceRueckfrage(); + + verify(vorgangService).getVorgang(MessageTestFactory.VORGANG_ID); + } + + @Test + void shouldCallServiceToGetAnswers() { + enhanceRueckfrage(); + + verify(service).findAnswers(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN, PostfachNachrichtTestFactory.ID); + } + + @Test + void shouldCallServiceToGetFirstSentAt() { + enhanceRueckfrage(); + + verify(service).getFirstSentAt(answersStreamCaptor.capture()); + assertThat(answersStreamCaptor.getValue().toList().get(0)).isEqualTo(answer); + } + + @Test + void shouldCallMapper() { + enhanceRueckfrage(); + + verify(rueckfrageMapper).toRueckfrage(sentAt, vorgang, rueckfrage); + } + + @Test + void shouldCallAddAnswers() { + enhanceRueckfrage(); + + verify(grpcService).addAnswers(eq(grpcRueckfrage), answersListCaptor.capture()); + assertThat(answersListCaptor.getValue().get(0)).isEqualTo(answer); + } + + @Test + void shouldCallIsAccessable() { + enhanceRueckfrage(); + + verify(service).isAccessible(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN, GrpcServiceKontoTestFactory.TRUST_LEVEL); + } + + @Test + void shouldSetAccessible() { + var rueckfrage = enhanceRueckfrage(); + + assertThat(rueckfrage.getAccessible()).isTrue(); + } + + @Test + void shouldReturnRueckfrage() { + var buildedRueckfrage = enhanceRueckfrage(); + + assertThat(buildedRueckfrage).isEqualTo(grpcRueckfrage); + } + + private GrpcRueckfrage enhanceRueckfrage() { + return grpcService.enhanceRueckfrage(rueckfrage, GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + } + } + + @DisplayName("Add answers") + @Nested + class TestAddAnswers { + + private final PostfachNachricht answer = PostfachNachrichtTestFactory.create(); + + private final GrpcRueckfrage grpcRueckfrage = GrpcRueckfrageTestFactory.create(); + + private final GrpcRueckfrageAnswer grpcRueckfrageAnwswer = GrpcRueckfrageAnswerTestFactory.create(); + + @BeforeEach + void mock() { + when(nachrichtMapper.toRueckfrageAnswer(any())).thenReturn(grpcRueckfrageAnwswer); + } + + @Test + void shouldCallMapper() { + grpcService.addAnswers(grpcRueckfrage, List.of(answer)); + + verify(nachrichtMapper).toRueckfrageAnswer(answer); + } + + @Test + void shouldReturnRueckfrageWithAnswers() { + var enhancedRueckfrage = grpcService.addAnswers(grpcRueckfrage, List.of(answer)); + + assertThat(enhancedRueckfrage.getAnswersList().get(0)).isEqualTo(grpcRueckfrageAnwswer); + } + } + + @DisplayName("Build get rueckfrage response") + @Nested + class TestBuildGetRueckfrageResponse { + + private final GrpcRueckfrage grpcRueckfrage = GrpcRueckfrageTestFactory.create(); + + @Test + void shouldReturnResponseIncludingRueckfrage() { + var rueckfrageResponse = grpcService.buildGetRueckfrageResponse(grpcRueckfrage); + + assertThat(rueckfrageResponse.getRueckfrage()).isEqualTo(grpcRueckfrage); + } + } } \ No newline at end of file diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapperTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapperTest.java index 528286a86d01a664d7d17aa19e87503bbf680c95..f09c76ce759f8b873260173d524c85093f832847 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapperTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumNachrichtMapperTest.java @@ -24,9 +24,11 @@ import static org.assertj.core.api.Assertions.*; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoField; import java.time.temporal.ChronoUnit; import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; @@ -45,55 +47,41 @@ class AntragraumNachrichtMapperTest { @Test void shouldMapVorgangId() { - var result = map(); + var result = toGrpc(); - assertThat(result.getVorgangId()).isEqualTo(RueckfrageTestFactory.VORGANG_ID); + assertThat(result.getVorgangId()).isEqualTo(RueckfrageHeadTestFactory.VORGANG_ID); } @Test void shouldMapId() { - var result = map(); + var result = toGrpc(); - assertThat(result.getId()).isEqualTo(RueckfrageTestFactory.ID); + assertThat(result.getId()).isEqualTo(RueckfrageHeadTestFactory.ID); } @Test void shouldMapVorgangName() { - var result = map(); + var result = toGrpc(); - assertThat(result.getVorgangName()).isEqualTo(RueckfrageTestFactory.VORGANG_NAME); + assertThat(result.getVorgangName()).isEqualTo(RueckfrageHeadTestFactory.VORGANG_NAME); } @Test void shouldMapStatus() { - var result = map(); + var result = toGrpc(); assertThat(result.getStatus()).isEqualTo(RueckfrageStatus.NEW.name()); } @Test void shouldMapSentAt() { - var result = map(); + var result = toGrpc(); assertThat(result.getSentAt()).isEqualTo(PostfachNachrichtTestFactory.SENT_AT.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); } - @Test - void shouldMapText() { - var result = map(); - - assertThat(result.getText()).isEqualTo(PostfachNachrichtTestFactory.MAIL_BODY); - } - - @Test - void shouldMapAttachments() { - var result = map(); - - assertThat(result.getAttachmentFileIdList()).hasSize(1).first().isEqualTo(PostfachNachrichtTestFactory.ATTACHMENTS.get(0)); - } - - private GrpcRueckfrage map() { - return mapper.toGrpc(RueckfrageTestFactory.create()); + private GrpcRueckfrageHead toGrpc() { + return mapper.toGrpc(RueckfrageHeadTestFactory.create()); } } @@ -102,63 +90,65 @@ class AntragraumNachrichtMapperTest { class TestMapAnswerToPostfachNachricht { @Test void shouldMapText() { - var result = map(); + var result = fromRueckfrageAnswer(); assertThat(result.getMailBody()).isEqualTo(GrpcRueckfrageAnswerTestFactory.TEXT); } @Test void shouldMapMessageId() { - var result = map(); + var result = fromRueckfrageAnswer(); assertThat(result.getMessageId()).isEqualTo(GrpcRueckfrageAnswerTestFactory.RUECKFRAGE_ID); } @Test void shouldMapAttachmentIds() { - var result = map(); + var result = fromRueckfrageAnswer(); assertThat(result.getAttachments()).isEqualTo(GrpcRueckfrageAnswerTestFactory.ATTACHMENT_ID_LIST); } @Test void shouldSetDirection() { - var result = map(); + var result = fromRueckfrageAnswer(); assertThat(result.getDirection()).isEqualTo(Direction.IN); } @Test void shouldSetReplyOption() { - var result = map(); + var result = fromRueckfrageAnswer(); assertThat(result.getReplyOption()).isEqualTo(ReplyOption.FORBIDDEN); } @Test void shouldSetCreateAt() { - var result = map(); + var result = fromRueckfrageAnswer(); assertThat(result.getCreatedAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); } @Test void shouldSetSentAt() { - var result = map(); + var result = fromRueckfrageAnswer(); assertThat(result.getSentAt()).isCloseTo(PostfachNachrichtTestFactory.SENT_AT, within(2, ChronoUnit.SECONDS)); } + @DisplayName("should set sentAt to now without milliseconds if value is missing") @Test - void shouldHandleEmptySentAt() { + void shouldSetSentAtIfMissing() { var rueckfrage = GrpcRueckfrageAnswerTestFactory.createBuilder().setSentAt(StringUtils.EMPTY).build(); var result = mapper.fromRueckfrageAnswer(rueckfrage); - assertThat(result.getSentAt()).isNull(); + assertThat(result.getSentAt()).isCloseTo(ZonedDateTime.now(), within(2, ChronoUnit.SECONDS)); + assertThat(result.getSentAt().get(ChronoField.MILLI_OF_SECOND)).isZero(); } - private PostfachNachricht map() { + private PostfachNachricht fromRueckfrageAnswer() { return mapper.fromRueckfrageAnswer(GrpcRueckfrageAnswerTestFactory.create()); } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumServiceTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumServiceTest.java index 36523ddfe28228a5b7276c294dffcd500b2cea46..1b0bd3f3c2168126a21ebdb75a118626394eaf99 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumServiceTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/AntragraumServiceTest.java @@ -7,6 +7,7 @@ import static org.mockito.Mockito.*; import java.time.ZonedDateTime; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.UUID; import java.util.stream.Stream; @@ -21,10 +22,13 @@ import org.mockito.Spy; import org.opensaml.saml.saml2.core.Response; import de.ozgcloud.nachrichten.NachrichtenManagerProperties; +import de.ozgcloud.nachrichten.common.vorgang.GrpcServiceKontoTestFactory; +import de.ozgcloud.nachrichten.common.vorgang.Vorgang; import de.ozgcloud.nachrichten.common.vorgang.VorgangService; import de.ozgcloud.nachrichten.common.vorgang.VorgangTestFactory; import de.ozgcloud.nachrichten.postfach.PersistPostfachNachrichtService; import de.ozgcloud.nachrichten.postfach.PostfachNachricht; +import de.ozgcloud.nachrichten.postfach.PostfachNachrichtMapper; import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; class AntragraumServiceTest { @@ -49,6 +53,8 @@ class AntragraumServiceTest { private RueckfrageMapper rueckfrageMapper; @Mock private VorgangService vorgangService; + @Mock + private PostfachNachrichtMapper nachrichtMapper; @Nested class TestGetAntragsraumUrl { @@ -75,7 +81,7 @@ class AntragraumServiceTest { private static final String SAML_TOKEN = "TOKEN"; private static final String POSTFACH_ID = "dummyPostfachId"; - private final Rueckfrage rueckfrage = RueckfrageTestFactory.create(); + private final RueckfrageHead rueckfrage = RueckfrageHeadTestFactory.create(); private final PostfachNachricht postfachNachricht = PostfachNachrichtTestFactory.create(); @BeforeEach @@ -84,65 +90,64 @@ class AntragraumServiceTest { when(rueckfrageMapper.fromPostfachNachricht(any())).thenReturn(rueckfrage); doReturn(rueckfrage).when(service).enrichByAnswers(any(), any()); - doReturn(Stream.of(rueckfrage)).when(service).enrichRueckfragen(any()); + doReturn(Stream.of(rueckfrage)).when(service).enrichRueckfragen(any(), any()); doReturn(POSTFACH_ID).when(service).getPostfachId(any()); + + doNothing().when(service).verifyToken(any()); } @Test void shouldCallVerify() { - service.findRueckfragen(SAML_TOKEN).toList(); + findRueckfragen(); verify(service).verifyToken(SAML_TOKEN); } - @Test - void shouldCallVerifier() { - service.findRueckfragen(SAML_TOKEN).toList(); - - verify(verifier).verify(anyString()); - } - @Test void shouldGetPostfachId() { - service.findRueckfragen(SAML_TOKEN).toList(); + findRueckfragen(); verify(service).getPostfachId(SAML_TOKEN); } @Test void shouldCallPostfachService() { - service.findRueckfragen(SAML_TOKEN).toList(); + findRueckfragen(); verify(postfachNachrichtService).findRueckfragen(AntragraumService.BAYERN_ID_SERVICE_KONTO_TYPE, POSTFACH_ID); } @Test void shouldCallMapper() { - service.findRueckfragen(SAML_TOKEN).toList(); + findRueckfragen(); verify(rueckfrageMapper).fromPostfachNachricht(postfachNachricht); } @Test void shouldCallEnrichByAnswers() { - service.findRueckfragen(SAML_TOKEN).toList(); + findRueckfragen(); verify(service).enrichByAnswers(rueckfrage, SAML_TOKEN); } @Test void shouldCallEnrichRueckfragen() { - service.findRueckfragen(SAML_TOKEN).toList(); + findRueckfragen(); - verify(service).enrichRueckfragen(any()); + verify(service).enrichRueckfragen(any(), eq(SAML_TOKEN)); } @Test void shouldReturnFullFilledValue() { - var rueckfragen = service.findRueckfragen(SAML_TOKEN).toList(); + var rueckfragen = findRueckfragen(); assertThat(rueckfragen).containsExactly(rueckfrage); } + + private List<RueckfrageHead> findRueckfragen() { + return service.findRueckfragen(SAML_TOKEN).toList(); + } } @DisplayName("Enrich by answers") @@ -150,7 +155,7 @@ class AntragraumServiceTest { class TestEnrichByAnswers { private static final String SAML_TOKEN = "TOKEN"; - private final Rueckfrage rueckfrage = RueckfrageTestFactory.create(); + private final RueckfrageHead rueckfrage = RueckfrageHeadTestFactory.create(); private final PostfachNachricht postfachNachricht = PostfachNachrichtTestFactory.create(); private final Stream<PostfachNachricht> answers = Stream.of(postfachNachricht); @@ -164,7 +169,7 @@ class AntragraumServiceTest { void shouldCallFindAnswers() { enrichByAnswer(); - verify(service).findAnswers(SAML_TOKEN, RueckfrageTestFactory.ID); + verify(service).findAnswers(SAML_TOKEN, RueckfrageHeadTestFactory.ID); } @Test @@ -189,74 +194,127 @@ class AntragraumServiceTest { .isEqualTo(rueckfrage); } - private Rueckfrage enrichByAnswer() { + private RueckfrageHead enrichByAnswer() { return service.enrichByAnswers(rueckfrage, SAML_TOKEN); } } - @DisplayName("Enrich rueckfrage") + @DisplayName("Enrich rueckfragen") @Nested - class TestEnrichRueckgabe { + class TestEnrichRueckfragen { - private final Rueckfrage rueckfrageWithoutVorgangName = RueckfrageTestFactory.createBuilder().vorgangName(null).build(); - private final List<Rueckfrage> rueckfragen = Collections.singletonList(rueckfrageWithoutVorgangName); + private final RueckfrageHead rueckfrageHead = RueckfrageHeadTestFactory.create(); + private final List<RueckfrageHead> rueckfragen = Collections.singletonList(rueckfrageHead); - @BeforeEach - void mock() { - doReturn(Stream.of(RueckfrageTestFactory.create())).when(service).addVorgangData(any(), any()); - } + private final Vorgang vorgang = VorgangTestFactory.create(); + @DisplayName("should return an empty stream is no rueckfragen exists") @Test - void shouldCallAddVorgangDataIfRueckfragenExists() { - service.enrichRueckfragen(rueckfragen); + void shouldReturnEmptyStream() { + var rueckfragen = service.enrichRueckfragen(Collections.emptyList(), GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN).toList(); - verify(service).addVorgangData(Collections.singletonList(rueckfrageWithoutVorgangName), RueckfrageTestFactory.VORGANG_ID); + assertThat(rueckfragen).isEmpty(); } - @Test - void shouldReturnValue() { - var enrichedRueckfragen = service.enrichRueckfragen(rueckfragen); + @DisplayName("on existing rueckfragen") + @Nested + class TestOnExistingRueckfragen { + + @BeforeEach + void mock() { + when(vorgangService.getVorgang(any())).thenReturn(vorgang); + + doReturn(rueckfrageHead).when(service).addVorgangData(any(), any()); + doReturn(rueckfrageHead).when(service).addAccessible(any(), any()); + } + + @Test + void shouldCallVorgangService() { + enrichRueckfragen(); + + verify(vorgangService).getVorgang(RueckfrageHeadTestFactory.VORGANG_ID); + } + + @Test + void shouldAddVorgangData() { + enrichRueckfragen(); - assertThat(enrichedRueckfragen.findFirst()).get().extracting(Rueckfrage::getVorgangName).isEqualTo(RueckfrageTestFactory.VORGANG_NAME); + verify(service).addVorgangData(rueckfrageHead, vorgang); + } + + @Test + void shouldAddAccessible() { + enrichRueckfragen(); + + verify(service).addAccessible(rueckfrageHead, GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + } + + @Test + void shouldReturnEnrichedRueckfragen() { + var enrichedRueckfragen = enrichRueckfragen(); + + assertThat(enrichedRueckfragen).containsExactly(rueckfrageHead); + } + } + + private List<RueckfrageHead> enrichRueckfragen() { + return service.enrichRueckfragen(rueckfragen, GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN).toList(); } } - @DisplayName("Add vorgang data") + @DisplayName("Add accessible") @Nested - class TestAddVorgangData { + class TestAddAccessible { - private final Rueckfrage rueckfrage = RueckfrageTestFactory.createBuilder() - .vorgangName(null) - .build(); + private final RueckfrageHead rueckfrageHead = RueckfrageHeadTestFactory.createBuilder().accessible(false).build(); @BeforeEach void mock() { - when(vorgangService.getVorgang(any())).thenReturn(VorgangTestFactory.create()); + doReturn(true).when(service).isAccessible(any(), any()); } @Test - void shouldCallGetVorgang() { - addVorgangData().toList(); + void shouldCallIsAccessible() { + service.addAccessible(rueckfrageHead, GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); - verify(vorgangService).getVorgang(RueckfrageTestFactory.VORGANG_ID); + verify(service).isAccessible(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN, GrpcServiceKontoTestFactory.TRUST_LEVEL); } + @Test + void shouldSetAccessible() { + var rueckfrageWithAccessible = service.addAccessible(rueckfrageHead, GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + + assertThat(rueckfrageWithAccessible.isAccessible()).isTrue(); + } + } + + @DisplayName("Add vorgang data") + @Nested + class TestAddVorgangData { + @Test void shouldSetVorgangName() { - var rueckfragenWithVorgangData = addVorgangData().toList(); + var rueckfragenWithVorgangData = addVorgangData(); - assertThat(rueckfragenWithVorgangData.getFirst().getVorgangName()).isEqualTo(VorgangTestFactory.NAME); + assertThat(rueckfragenWithVorgangData.getVorgangName()).isEqualTo(VorgangTestFactory.NAME); } @Test void shouldSetVorgangNummer() { - var rueckfragenWithVorgangData = addVorgangData().toList(); + var rueckfragenWithVorgangData = addVorgangData(); + + assertThat(rueckfragenWithVorgangData.getVorgangNummer()).isEqualTo(VorgangTestFactory.NUMMER); + } + + @Test + void shouldSetTrustLevel() { + var rueckfragenWithVorgangData = addVorgangData(); - assertThat(rueckfragenWithVorgangData.getFirst().getVorgangNummer()).isEqualTo(VorgangTestFactory.NUMMER); + assertThat(rueckfragenWithVorgangData.getTrustLevel()).isEqualTo(GrpcServiceKontoTestFactory.TRUST_LEVEL); } - private Stream<Rueckfrage> addVorgangData() { - return service.addVorgangData(Collections.singletonList(rueckfrage), RueckfrageTestFactory.VORGANG_ID); + private RueckfrageHead addVorgangData() { + return service.addVorgangData(RueckfrageHead.builder().build(), VorgangTestFactory.create()); } } @@ -278,31 +336,30 @@ class AntragraumServiceTest { } } + @DisplayName("Send rueckfragen answers") @Nested class TestSendRueckfragenAnswers { static final String SAML_TOKEN = "TOKEN"; static final String RUECKFRAGE_ID = UUID.randomUUID().toString(); static final PostfachNachricht NACHRICHT = PostfachNachrichtTestFactory.create(); - @Test - void shouldCallVerify() { - service.sendRueckfrageAnswer(SAML_TOKEN, RUECKFRAGE_ID, NACHRICHT); - - verify(service).verifyToken(SAML_TOKEN); + @BeforeEach + void mock() { + doNothing().when(service).verifyToken(any()); } @Test - void shouldCallVerifier() { - service.findRueckfragen(SAML_TOKEN); + void shouldCallVerifyToken() { + service.sendRueckfrageAnswer(SAML_TOKEN, RUECKFRAGE_ID, NACHRICHT); - verify(verifier).verify(anyString()); + verify(service).verifyToken(SAML_TOKEN); } @Test void shouldCallPostfachService() { service.sendRueckfrageAnswer(SAML_TOKEN, RUECKFRAGE_ID, NACHRICHT); - verify(postfachNachrichtService).persistAnswer(eq(RUECKFRAGE_ID), any(PostfachNachricht.class)); + verify(postfachNachrichtService).persistAnswer(RUECKFRAGE_ID, NACHRICHT); } } @@ -362,4 +419,147 @@ class AntragraumServiceTest { verify(decrypter).decryptPostfachId(response); } } + + @DisplayName("Get rueckfrage") + @Nested + class TestGetRueckfrage { + + private final String samlToken = "DummySamlToken"; + + private final Map<String, Object> nachrichtAsMap = PostfachNachrichtTestFactory.asMap(); + private final PostfachNachricht nachricht = PostfachNachrichtTestFactory.create(); + + @BeforeEach + void mock() { + when(postfachNachrichtService.getById(any())).thenReturn(nachrichtAsMap); + when(nachrichtMapper.fromMapToPostfachMail(any())).thenReturn(nachricht); + + doNothing().when(service).verifyToken(any()); + } + + @Test + void shouldVerifySamlToken() { + getRueckfrage(); + + verify(service).verifyToken(samlToken); + } + + @Test + void shouldCallPersistPostfachNachrichtService() { + getRueckfrage(); + + verify(postfachNachrichtService).getById(RueckfrageHeadTestFactory.ID); + } + + @Test + void shouldCallNachrichtMapper() { + getRueckfrage(); + + verify(nachrichtMapper).fromMapToPostfachMail(nachrichtAsMap); + } + + @Test + void shouldReturnValue() { + var rueckfrage = getRueckfrage(); + + assertThat(rueckfrage).isEqualTo(nachricht); + } + + private PostfachNachricht getRueckfrage() { + return service.getRueckfrage(samlToken, RueckfrageHeadTestFactory.ID); + } + } + + @DisplayName("Is accessible") + @Nested + class TestIsAccessible { + + @Test + void shouldCallGetTrustLevel() { + service.isAccessible(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN, GrpcServiceKontoTestFactory.TRUST_LEVEL); + + verify(service).getTrustLevel(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + } + + @Test + void shouldReturnTrueIfTrustLevelMatches() { + doReturn(GrpcServiceKontoTestFactory.TRUST_LEVEL).when(service).getTrustLevel(any()); + + var trustLevel = service.isAccessible(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN, GrpcServiceKontoTestFactory.TRUST_LEVEL); + + assertThat(trustLevel).isTrue(); + } + + @Test + void shouldReturnFalseIfTrustLevelNotMatches() { + doReturn("qutasch").when(service).getTrustLevel(any()); + + var trustLevel = service.isAccessible(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN, GrpcServiceKontoTestFactory.TRUST_LEVEL); + + assertThat(trustLevel).isFalse(); + } + } + + @DisplayName("Get trustLevel") + @Nested + class TestGetTrustLevel { + + @Mock + private Response response; + + @BeforeEach + void mock() { + doReturn(response).when(service).parseSamlToken(any()); + + when(decrypter.decryptTrustLevel(any())).thenReturn(GrpcServiceKontoTestFactory.TRUST_LEVEL); + } + + @Test + void shouldCallParseSamlToken() { + service.getTrustLevel(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + + verify(service).parseSamlToken(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + } + + @Test + void shouldCallDecrypter() { + service.getTrustLevel(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + + verify(decrypter).decryptTrustLevel(response); + } + + @Test + void shouldReturnValue() { + var trustLevel = service.getTrustLevel(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + + assertThat(trustLevel).isEqualTo(GrpcServiceKontoTestFactory.TRUST_LEVEL); + } + } + + @DisplayName("Parse saml token") + @Nested + class TestParseSamlToken { + + @Mock + private Response response; + + @BeforeEach + void mock() { + when(parser.parse(any())).thenReturn(response); + } + + @Test + void shouldCallParser() { + service.parseSamlToken(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + + verify(parser).parse(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + } + + @Test + void shouldReturnValue() { + var parseResponse = service.parseSamlToken(GrpcGetRueckfrageRequestTestFactory.SAML_TOKEN); + + assertThat(parseResponse).isEqualTo(response); + } + } } \ No newline at end of file diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcFindRueckfragenResponseTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcFindRueckfragenResponseTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..053337a10a324e2efd0500f3dd0a0b2a5a8b59a7 --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcFindRueckfragenResponseTestFactory.java @@ -0,0 +1,12 @@ +package de.ozgcloud.nachrichten.antragraum; + +public class GrpcFindRueckfragenResponseTestFactory { + + public static GrpcFindRueckfragenResponse create() { + return createBuilder().build(); + } + + public static GrpcFindRueckfragenResponse.Builder createBuilder() { + return GrpcFindRueckfragenResponse.newBuilder(); + } +} diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcGetRueckfrageRequestTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcGetRueckfrageRequestTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..96962e7bb8d6122aff28342476fa9132a30a5716 --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcGetRueckfrageRequestTestFactory.java @@ -0,0 +1,18 @@ +package de.ozgcloud.nachrichten.antragraum; + +import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; + +public class GrpcGetRueckfrageRequestTestFactory { + + public final static String SAML_TOKEN = "DUMMY_SAML_TOKEN"; + + public static GrpcGetRueckfrageRequest create() { + return createBuilder().build(); + } + + public static GrpcGetRueckfrageRequest.Builder createBuilder() { + return GrpcGetRueckfrageRequest.newBuilder() + .setSamlToken(SAML_TOKEN) + .setId(PostfachNachrichtTestFactory.ID); + } +} diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcGetRueckfrageResponseTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcGetRueckfrageResponseTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..53e38d91e5d9b82cdd31c99c4a0d601b32b5de5b --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcGetRueckfrageResponseTestFactory.java @@ -0,0 +1,13 @@ +package de.ozgcloud.nachrichten.antragraum; + +public class GrpcGetRueckfrageResponseTestFactory { + + public static GrpcGetRueckfrageResponse create() { + return createBuilder().build(); + } + + public static GrpcGetRueckfrageResponse.Builder createBuilder() { + return GrpcGetRueckfrageResponse.newBuilder() + .setRueckfrage(GrpcRueckfrageTestFactory.create()); + } +} \ No newline at end of file diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcRueckfrageHeadTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcRueckfrageHeadTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..68e54b548d44e9dfa21282c69fc42dd0640164f0 --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcRueckfrageHeadTestFactory.java @@ -0,0 +1,12 @@ +package de.ozgcloud.nachrichten.antragraum; + +public class GrpcRueckfrageHeadTestFactory { + + public static GrpcRueckfrageHead create() { + return createBuilder().build(); + } + + public static GrpcRueckfrageHead.Builder createBuilder() { + return GrpcRueckfrageHead.newBuilder(); + } +} \ No newline at end of file diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcRueckfrageTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcRueckfrageTestFactory.java index 248e5abc56da8018fd832afef80ea32039aa2c07..f053390345d713197a6f201900253f689cdfb3f3 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcRueckfrageTestFactory.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/GrpcRueckfrageTestFactory.java @@ -1,10 +1,10 @@ package de.ozgcloud.nachrichten.antragraum; -import java.util.UUID; +import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; public class GrpcRueckfrageTestFactory { - public static final String ID = UUID.randomUUID().toString(); + private final static boolean ACCESSIBLE = true; public static GrpcRueckfrage create() { return createBuilder().build(); @@ -12,7 +12,11 @@ public class GrpcRueckfrageTestFactory { public static GrpcRueckfrage.Builder createBuilder() { return GrpcRueckfrage.newBuilder() - .setId(ID); + .setId(PostfachNachrichtTestFactory.ID) + .setText(PostfachNachrichtTestFactory.MAIL_BODY) + .setSentAt(PostfachNachrichtTestFactory.SENT_AT_STR) + .addAllAttachmentFileId(PostfachNachrichtTestFactory.ATTACHMENTS) + .setAccessible(ACCESSIBLE); } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageHeadTestFactory.java similarity index 68% rename from nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageTestFactory.java rename to nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageHeadTestFactory.java index 3a60a8a4d1f15b5ebe814c10197a92afc8afe8f0..e9405169cae3b2ee605ae346e7b212f14f0294ea 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageTestFactory.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageHeadTestFactory.java @@ -4,27 +4,27 @@ import java.util.UUID; import com.thedeanda.lorem.LoremIpsum; +import de.ozgcloud.nachrichten.common.vorgang.GrpcServiceKontoTestFactory; import de.ozgcloud.nachrichten.postfach.PostfachAddressTestFactory; import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; -public class RueckfrageTestFactory { +public class RueckfrageHeadTestFactory { public static final String ID = UUID.randomUUID().toString(); public static final String VORGANG_ID = UUID.randomUUID().toString(); public static final String VORGANG_NAME = LoremIpsum.getInstance().getName(); - public static Rueckfrage create() { + public static RueckfrageHead create() { return createBuilder().build(); } - public static Rueckfrage.RueckfrageBuilder createBuilder() { - return Rueckfrage.builder() + public static RueckfrageHead.RueckfrageHeadBuilder createBuilder() { + return RueckfrageHead.builder() .id(ID) .vorgangId(VORGANG_ID) .vorgangName(VORGANG_NAME) .postfachAddress(PostfachAddressTestFactory.create()) .sentAt(PostfachNachrichtTestFactory.SENT_AT) - .text(PostfachNachrichtTestFactory.MAIL_BODY) - .attachments(PostfachNachrichtTestFactory.ATTACHMENTS); + .trustLevel(GrpcServiceKontoTestFactory.TRUST_LEVEL); } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapperTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapperTest.java index 5c7e80e7db967c35727133fdac1d42cbc51cd3d3..7fc8bf3676f32b4c24aeb8795e43ee06193bcb86 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapperTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/RueckfrageMapperTest.java @@ -2,12 +2,19 @@ package de.ozgcloud.nachrichten.antragraum; import static org.assertj.core.api.Assertions.*; +import java.time.ZonedDateTime; +import java.util.Optional; + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mapstruct.factory.Mappers; +import de.ozgcloud.nachrichten.common.vorgang.GrpcServiceKontoTestFactory; +import de.ozgcloud.nachrichten.common.vorgang.Vorgang; +import de.ozgcloud.nachrichten.common.vorgang.VorgangTestFactory; import de.ozgcloud.nachrichten.postfach.PostfachAddressTestFactory; +import de.ozgcloud.nachrichten.postfach.PostfachNachricht; import de.ozgcloud.nachrichten.postfach.PostfachNachrichtTestFactory; import de.ozgcloud.nachrichten.postfach.osi.MessageTestFactory; @@ -48,28 +55,86 @@ class RueckfrageMapperTest { } @Test - void shouldMapText() { + void shouldHaveDefaultStatus() { var mapped = mapFromPostfachNachricht(); - assertThat(mapped.getText()).isEqualTo(PostfachNachrichtTestFactory.MAIL_BODY); + assertThat(mapped.getStatus()).isEqualTo(RueckfrageStatus.NEW); + } + + private RueckfrageHead mapFromPostfachNachricht() { + return mapper.fromPostfachNachricht(PostfachNachrichtTestFactory.create()); + } + } + + @DisplayName("To rueckfrage") + @Nested + class TestToRueckfrage { + + private final Vorgang vorgang = VorgangTestFactory.create(); + private final PostfachNachricht rueckfrageNachricht = PostfachNachrichtTestFactory.create(); + + public static final String ANSWERED_AT_STR = "2020-04-01T11:30:10Z"; + public static final ZonedDateTime ANSWERED_AT_AT = ZonedDateTime.parse(ANSWERED_AT_STR); + private final Optional<ZonedDateTime> firstSentAt = Optional.of(ANSWERED_AT_AT); + + @Test + void shouldMapId() { + var rueckfrage = toRueckfrage(); + + assertThat(rueckfrage.getId()).isEqualTo(PostfachNachrichtTestFactory.ID); + } + + @Test + void shouldMapText() { + var rueckfrage = toRueckfrage(); + + assertThat(rueckfrage.getText()).isEqualTo(PostfachNachrichtTestFactory.MAIL_BODY); } @Test void shouldMapAttachments() { - var mapped = mapFromPostfachNachricht(); + var rueckfrage = toRueckfrage(); - assertThat(mapped.getAttachments()).isEqualTo(PostfachNachrichtTestFactory.ATTACHMENTS); + assertThat(rueckfrage.getAttachmentFileIdList()).containsExactly(PostfachNachrichtTestFactory.ATTACHMENT_FILE_ID); } @Test - void shouldHaveDefaultStatus() { - var mapped = mapFromPostfachNachricht(); + void shouldMapVorgangName() { + var rueckfrage = toRueckfrage(); - assertThat(mapped.getStatus()).isEqualTo(RueckfrageStatus.NEW); + assertThat(rueckfrage.getVorgangName()).isEqualTo(VorgangTestFactory.NAME); } - private Rueckfrage mapFromPostfachNachricht() { - return mapper.fromPostfachNachricht(PostfachNachrichtTestFactory.create()); + @Test + void shouldMapVorgangNummer() { + var rueckfrage = toRueckfrage(); + + assertThat(rueckfrage.getVorgangNummer()).isEqualTo(VorgangTestFactory.NUMMER); + } + + @Test + void shouldMapTrustLevel() { + var rueckfrage = toRueckfrage(); + + assertThat(rueckfrage.getTrustLevel()).isEqualTo(GrpcServiceKontoTestFactory.TRUST_LEVEL); + } + + @Test + void shouldMapAnsweredAt() { + var rueckfrage = toRueckfrage(); + + assertThat(rueckfrage.getAnsweredAt()).isEqualTo(ANSWERED_AT_STR); + } + + @Test + void shouldMapStatus() { + var rueckfrage = toRueckfrage(); + + assertThat(rueckfrage.getStatus()).isEqualTo(RueckfrageStatus.ANSWERED.name()); + } + + private GrpcRueckfrage toRueckfrage() { + return mapper.toRueckfrage(firstSentAt, vorgang, rueckfrageNachricht); } } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/Saml2DecrypterTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/Saml2DecrypterTest.java index 1dd94cea3e8ef54e5b7d62ac936921ed583d748b..d36c6c4365259ddf6bf7c500ae614597cb69abaf 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/Saml2DecrypterTest.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/antragraum/Saml2DecrypterTest.java @@ -21,13 +21,18 @@ package de.ozgcloud.nachrichten.antragraum; import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.NoSuchElementException; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.Mock; -import org.opensaml.saml.saml2.core.Attribute; +import org.mockito.Mockito; import org.opensaml.saml.saml2.core.AttributeStatement; import org.opensaml.saml.saml2.core.Response; import org.springframework.core.io.InputStreamResource; @@ -59,7 +64,7 @@ class Saml2DecrypterTest { var parser = new Saml2Parser(configuration); samlResponse = parser.parse(samlResponseString); - decrypter = new Saml2Decrypter(configuration); + decrypter = Mockito.spy(new Saml2Decrypter(configuration)); decrypter.init(); } @@ -107,20 +112,41 @@ class Saml2DecrypterTest { assertThat(attributes).hasSize(7); } - @Test - void shouldHavePostfachId() { - decrypter.decryptResponseElements(samlResponse); - var samlAssertion = samlResponse.getAssertions().get(0); - var statements = (AttributeStatement) samlAssertion.getStatements().get(1); - var attributes = statements.getAttributes(); - var postfachIdOptional = attributes.stream().filter(attribute -> "legacyPostkorbHandle".equals(attribute.getFriendlyName())).findFirst(); - assertThat(postfachIdOptional).map(Attribute::getAttributeValues).isNotNull(); + @DisplayName("Decrypt postfachId") + @Nested + class TestDecryptPostfachId { + + @Test + void shouldReturnPostfachIdIfExists() { + var postfachId = decrypter.decryptPostfachId(samlResponse); + + assertThat(postfachId).isEqualTo("28721c6f-b78f-4d5c-a048-19fd2fc429d2"); + } + + @Test + void shouldThrowExceptionIfMissing() { + doReturn(false).when(decrypter).isPostfachId(any()); + + assertThatThrownBy(() -> decrypter.decryptPostfachId(samlResponse)).isInstanceOf(NoSuchElementException.class); + } } - @Test - void shouldGetPostfachId() { - var postfachId = decrypter.decryptPostfachId(samlResponse); + @DisplayName("Decrypt trustLevel") + @Nested + class TestDecryptTrustLevel { + + @Test + void shouldReturnTrustLevelIfExists() { + var trustLevel = decrypter.decryptTrustLevel(samlResponse); + + assertThat(trustLevel).isEqualTo("STORK-QAA-Level-1"); + } + + @Test + void shouldThrowExceptionIfMissing() { + doReturn(false).when(decrypter).isTrustLevel(any()); - assertThat(postfachId).isEqualTo("28721c6f-b78f-4d5c-a048-19fd2fc429d2"); + assertThatThrownBy(() -> decrypter.decryptTrustLevel(samlResponse)).isInstanceOf(NoSuchElementException.class); + } } } \ No newline at end of file diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcServiceKontoTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcServiceKontoTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..1b2291608de848908807d38f83051e942be47ae4 --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcServiceKontoTestFactory.java @@ -0,0 +1,19 @@ +package de.ozgcloud.nachrichten.common.vorgang; + +import com.thedeanda.lorem.LoremIpsum; + +import de.ozgcloud.vorgang.vorgang.GrpcServiceKonto; + +public class GrpcServiceKontoTestFactory { + + public final static String TRUST_LEVEL = LoremIpsum.getInstance().getWords(1); + + public static GrpcServiceKonto create() { + return createBuilder().build(); + } + + public static GrpcServiceKonto.Builder createBuilder() { + return GrpcServiceKonto.newBuilder() + .setTrustLevel(TRUST_LEVEL); + } +} diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcVorgangHeadTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcVorgangHeadTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..f1ccd6f4418409556357aa0f9478fb57204c40e1 --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcVorgangHeadTestFactory.java @@ -0,0 +1,15 @@ +package de.ozgcloud.nachrichten.common.vorgang; + +import de.ozgcloud.vorgang.vorgang.GrpcVorgangHead; + +public class GrpcVorgangHeadTestFactory { + + public static GrpcVorgangHead create() { + return createBuilder().build(); + } + + public static GrpcVorgangHead.Builder createBuilder() { + return GrpcVorgangHead.newBuilder() + .setServiceKonto(GrpcServiceKontoTestFactory.create()); + } +} diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcVorgangWithEingangTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcVorgangWithEingangTestFactory.java index cd089671dd93144c8833bbb133e7f41e6453ea39..5c2edee1d5d205a075c05b55bc0b2dc3199e0d57 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcVorgangWithEingangTestFactory.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/GrpcVorgangWithEingangTestFactory.java @@ -12,6 +12,7 @@ public class GrpcVorgangWithEingangTestFactory { return GrpcVorgangWithEingang.newBuilder() .setId(VorgangTestFactory.ID) .setName(VorgangTestFactory.NAME) - .setNummer(VorgangTestFactory.NUMMER); + .setNummer(VorgangTestFactory.NUMMER) + .setHeader(GrpcVorgangHeadTestFactory.create()); } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/VorgangTestFactory.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/VorgangTestFactory.java index 48ef6e441a5be6163176a1d3c34496268053b0d1..087fe08faa89ec0ea7ae6cfeda68744eeb727592 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/VorgangTestFactory.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/vorgang/VorgangTestFactory.java @@ -18,6 +18,7 @@ public class VorgangTestFactory { return Vorgang.builder() .id(ID) .name(NAME) - .nummer(NUMMER); + .nummer(NUMMER) + .trustLevel(GrpcServiceKontoTestFactory.TRUST_LEVEL); } }