diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeService.java index 3920a077b01adce74965354f6bac185112d3fc3c..109c3cc16ff77ccd10019a80caf011c3cb1fbb7a 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeService.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeService.java @@ -37,4 +37,7 @@ public class ClientAttributeService { remoteService.setBooleanReadOnlyClientAttribute(vorgangId, ClientAttribute.HAS_NEW_POSTFACH_NACHRICHT, false); } + public void setHasNewPostfachNachricht(String vorgangId) { + remoteService.setBooleanReadOnlyClientAttribute(vorgangId, ClientAttribute.HAS_NEW_POSTFACH_NACHRICHT, true); + } } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java index 94f0209dfd9324b206466fe52e0ae806d26fbb16..74c0bcb2df4a2abeae92823d91b7c51a1c15ebb5 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java @@ -25,6 +25,7 @@ package de.ozgcloud.alfa.common.command; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; +import java.util.List; import java.util.function.Predicate; import java.util.stream.Stream; @@ -41,10 +42,11 @@ import de.ozgcloud.alfa.bescheid.DocumentController; import de.ozgcloud.alfa.collaboration.CollaborationController.CollaborationByVorgangController; import de.ozgcloud.alfa.forwarding.ForwardingController; import de.ozgcloud.alfa.kommentar.KommentarController; -import de.ozgcloud.alfa.postfach.PostfachMailController; import de.ozgcloud.alfa.vorgang.VorgangController; import de.ozgcloud.alfa.wiedervorlage.WiedervorlageController; +import lombok.RequiredArgsConstructor; +@RequiredArgsConstructor @Component class CommandModelAssembler implements RepresentationModelAssembler<Command, EntityModel<Command>> { @@ -57,14 +59,29 @@ class CommandModelAssembler implements RepresentationModelAssembler<Command, Ent static final Predicate<Command> HAS_KNOWN_COMMAND_ORDER = command -> command.getCommandOrder() != CommandOrder.UNBEKANNT; + private static final List<CommandOrder> ORDER_PROCESSED_SEPERATELY = List.of( + CommandOrder.RECEIVE_POSTFACH_NACHRICHT, + CommandOrder.RESEND_POSTFACH_MAIL, + CommandOrder.SEND_POSTFACH_MAIL, + CommandOrder.SEND_POSTFACH_NACHRICHT); + + static final Predicate<Command> IS_PROCESSABLE_ORDER = command -> !ORDER_PROCESSED_SEPERATELY.contains(command.getCommandOrder()); + + private final List<CommandProcessor> processors; + @Override public EntityModel<Command> toModel(Command command) { - return EntityModel.of(command) + var entityModel = EntityModel.of(command) .add(linkTo(CommandController.class).slash(command.getId()).withSelfRel()) - .addIf(CommandHelper.IS_DONE.and(HAS_KNOWN_COMMAND_ORDER).test(command), () -> effectedResourceLinkByOrderType(command)) + .addIf(CommandHelper.IS_DONE.and(HAS_KNOWN_COMMAND_ORDER).and(IS_PROCESSABLE_ORDER).test(command), + () -> effectedResourceLinkByOrderType(command)) .addIf(CommandHelper.IS_PENDING.test(command), () -> linkTo(CommandController.class).slash(command.getId()).withRel(REL_UPDATE)) .addIf(IS_NOT_LOESCH_ANFORDERUNG_AND_REVOKEABLE.test(command), () -> linkTo(methodOn(CommandController.class).revoke(command.getId(), null)).withRel(REL_REVOKE)); + + processors.forEach(processor -> processor.process(entityModel)); + + return entityModel; } Link effectedResourceLinkByOrderType(Command entity) { @@ -73,14 +90,13 @@ class CommandModelAssembler implements RepresentationModelAssembler<Command, Ent WebMvcLinkBuilder linkBuilder = switch (type) { case FORWARDING -> linkTo(methodOn(ForwardingController.class).findByVorgangId(entity.getVorgangId())); case KOMMENTAR -> linkTo(KommentarController.class).slash(entity.getRelationId()); - case POSTFACH -> linkTo(methodOn(PostfachMailController.class).getAll(entity.getVorgangId())); case VORGANG -> linkTo(VorgangController.class).slash(entity.getRelationId()); case VORGANG_LIST -> linkTo(VorgangController.class); case WIEDERVORLAGE -> linkTo(WiedervorlageController.class).slash(entity.getRelationId()); case BESCHEID -> linkTo(methodOn(BescheidController.class).getDraft(entity.getVorgangId())); case DOCUMENT -> linkTo(DocumentController.class).slash(entity.getCreatedResource()); case COLLABORATION -> linkTo(methodOn(CollaborationByVorgangController.class).getAllByVorgangId(entity.getVorgangId())); - case NONE -> throw new IllegalArgumentException("Unknown CommandOrder: " + entity.getOrder()); + default -> throw new IllegalArgumentException("Unknown CommandOrder: " + entity.getOrder()); }; return linkBuilder.withRel(REL_EFFECTED_RESOURCE); diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..77d8d40bf056a8936f15b04788e1d3ec33354a4c --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/common/command/CommandProcessor.java @@ -0,0 +1,34 @@ +package de.ozgcloud.alfa.common.command; + +import java.util.Objects; + +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.LinkRelation; +import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; + +public abstract class CommandProcessor { + + static final LinkRelation REL_EFFECTED_RESOURCE = LinkRelation.of("effected_resource"); + static final LinkRelation REL_RELATED_RESOURCE = LinkRelation.of("related_resource"); + + public void process(EntityModel<Command> model) { + var command = model.getContent(); + + if (Objects.isNull(command)) { + return; + } + + model.addIf(CommandHelper.IS_DONE.test(command) && isResponsibleForEffectedResource(command.getCommandOrder()), + () -> createEffectedResourceLinkBuilder(command).withRel(REL_EFFECTED_RESOURCE)); + model.addIf(isResponsibleForRelatedResource(command.getCommandOrder()), + () -> createRelatedResourceLinkBuilder(command).withRel(REL_RELATED_RESOURCE)); + } + + public abstract boolean isResponsibleForEffectedResource(CommandOrder order); + + public abstract WebMvcLinkBuilder createEffectedResourceLinkBuilder(Command command); + + public abstract boolean isResponsibleForRelatedResource(CommandOrder order); + + public abstract WebMvcLinkBuilder createRelatedResourceLinkBuilder(Command command); +} \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssembler.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssembler.java index d1f3b17742b04f08c6f30d4dac6ef11159425724..792d90d96a1f927864324971cf58871a3fb3f60f 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssembler.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssembler.java @@ -58,6 +58,7 @@ class PostfachMailModelAssembler implements RepresentationModelAssembler<Postfac public static final String REL_SEND = "send"; public static final String REL_RESEND_POSTFACH_MAIL = "resendPostfachMail"; public static final String REL_RESET_NEW_POSTFACH_MAIL = "resetHasNewPostfachNachricht"; + public static final String REL_SET_HAS_NEW_POSTFACH_MAIL = "setHasNewPostfachNachricht"; public static final String REL_ATTACHMENTS = "attachments"; public static final String REL_EDIT = "edit"; static final String REL_UPLOAD_ATTACHMENT = "uploadAttachment"; @@ -116,9 +117,8 @@ class PostfachMailModelAssembler implements RepresentationModelAssembler<Postfac model.add(linkTo(BinaryFileController.class).slash(vorgangId).slash(POSTFACH_NACHRICHT_ATTACHMENT_FIELD).slash(FILE_PATH) .withRel(REL_UPLOAD_ATTACHMENT)); - if (vorgang.isHasNewPostfachNachricht()) { - model.add(linkTo(VorgangController.class).slash(vorgangId).slash(HAS_NEW_POSTFACH_NACHRICHT_FIELD).withRel(REL_RESET_NEW_POSTFACH_MAIL)); - } + model.add(linkTo(VorgangController.class).slash(vorgangId).slash(HAS_NEW_POSTFACH_NACHRICHT_FIELD) + .withRel(vorgang.isHasNewPostfachNachricht() ? REL_RESET_NEW_POSTFACH_MAIL : REL_SET_HAS_NEW_POSTFACH_MAIL)); } @Override diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachNachrichtCommandProcessor.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachNachrichtCommandProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..358f358b4726a24daab1a0917e8a5e4ed58ce21d --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachNachrichtCommandProcessor.java @@ -0,0 +1,46 @@ +package de.ozgcloud.alfa.postfach; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; + +import java.util.List; + +import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; +import org.springframework.stereotype.Component; + +import de.ozgcloud.alfa.common.command.Command; +import de.ozgcloud.alfa.common.command.CommandOrder; +import de.ozgcloud.alfa.common.command.CommandProcessor; + +@Component +public class PostfachNachrichtCommandProcessor extends CommandProcessor { + + private static final List<CommandOrder> RESPONSIBLE_ORDER = List.of( + CommandOrder.RECEIVE_POSTFACH_NACHRICHT, + CommandOrder.RESEND_POSTFACH_MAIL); + + private static final List<CommandOrder> RESPONSIBLE_EFFECTED_RESOURCE_ORDER = List.of( + CommandOrder.SEND_POSTFACH_MAIL, + CommandOrder.SEND_POSTFACH_NACHRICHT, + CommandOrder.RESEND_POSTFACH_MAIL, + CommandOrder.RECEIVE_POSTFACH_NACHRICHT); + + @Override + public boolean isResponsibleForRelatedResource(CommandOrder order) { + return RESPONSIBLE_ORDER.contains(order); + } + + @Override + public WebMvcLinkBuilder createRelatedResourceLinkBuilder(Command command) { + return linkTo(PostfachMailController.class).slash(command.getRelationId()); + } + + @Override + public boolean isResponsibleForEffectedResource(CommandOrder order) { + return RESPONSIBLE_EFFECTED_RESOURCE_ORDER.contains(order); + } + + @Override + public WebMvcLinkBuilder createEffectedResourceLinkBuilder(Command command) { + return linkTo(methodOn(PostfachMailController.class).getAll(command.getVorgangId())); + } +} \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/ResetNewPostfachNachrichtBody.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/SetNewPostfachNachrichtBody.java similarity index 96% rename from alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/ResetNewPostfachNachrichtBody.java rename to alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/SetNewPostfachNachrichtBody.java index 70ec293220e4217bec94d7da43727e48306bad85..15f2a5c2a15dd5d3ed9935a269a98e19ac4d8035 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/ResetNewPostfachNachrichtBody.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/SetNewPostfachNachrichtBody.java @@ -28,7 +28,7 @@ import lombok.Setter; @Getter @Setter -class ResetNewPostfachNachrichtBody { +public class SetNewPostfachNachrichtBody { private boolean hasNewPostfachNachricht; } diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java index 8e348daeeaf3edca0114fa607d300cbd962524e7..f6d8eecb375133ea747023446cdacc3aa4655acc 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/vorgang/VorgangController.java @@ -25,8 +25,6 @@ package de.ozgcloud.alfa.vorgang; import java.util.Optional; -import jakarta.servlet.http.HttpServletResponse; - import org.apache.commons.lang3.StringUtils; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.RepresentationModel; @@ -46,6 +44,7 @@ import de.ozgcloud.alfa.common.user.UserId; import de.ozgcloud.alfa.statistic.StatisticController; import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; import io.micrometer.core.annotation.Timed; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @RestController @@ -187,14 +186,13 @@ public class VorgangController { } @PutMapping(path = "/{vorgangId}/hasNewPostfachNachricht", consumes = MediaType.APPLICATION_JSON_VALUE) - public void resetNewPostfachNachricht(@PathVariable String vorgangId, @RequestBody ResetNewPostfachNachrichtBody body, + public void setNewPostfachNachricht(@PathVariable String vorgangId, @RequestBody SetNewPostfachNachrichtBody body, HttpServletResponse response) { if (body.isHasNewPostfachNachricht()) { - response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value()); - return; + clientAttributeService.setHasNewPostfachNachricht(vorgangId); + } else { + clientAttributeService.resetPostfachNachricht(vorgangId); } - - clientAttributeService.resetPostfachNachricht(vorgangId); response.setStatus(HttpStatus.NO_CONTENT.value()); } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeServiceTest.java index 59bd03ddbb440d66be7e8fb1c262cdaa0976692d..25866dae17d71b3b5c68a9c1f71485efffe1df87 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/clientattribute/ClientAttributeServiceTest.java @@ -42,13 +42,23 @@ class ClientAttributeServiceTest { @Nested class TestResetNewPostfachNachricht { - private final ClientAttribute clientAttribute = ClientAttribute.HAS_NEW_POSTFACH_NACHRICHT; @Test void shouldCallRemoteService() { service.resetPostfachNachricht(VorgangHeaderTestFactory.ID); - verify(remoteService).setBooleanReadOnlyClientAttribute(VorgangHeaderTestFactory.ID, clientAttribute, false); + verify(remoteService).setBooleanReadOnlyClientAttribute(VorgangHeaderTestFactory.ID, ClientAttribute.HAS_NEW_POSTFACH_NACHRICHT, false); + } + } + + @Nested + class TestSetHasNewPostfachNachricht { + + @Test + void shouldCallRemoteService() { + service.setHasNewPostfachNachricht(VorgangHeaderTestFactory.ID); + + verify(remoteService).setBooleanReadOnlyClientAttribute(VorgangHeaderTestFactory.ID, ClientAttribute.HAS_NEW_POSTFACH_NACHRICHT, true); } } } diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java index bd98a6b0274afd52ed736ae3a742674401ff45ca..cfaba07c471a901ee5a18863c7555b6fc362f53b 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java @@ -27,7 +27,12 @@ import static de.ozgcloud.alfa.common.command.CommandModelAssembler.*; import static de.ozgcloud.alfa.common.command.CommandTestFactory.*; import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import java.util.ArrayList; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -35,7 +40,11 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.EnumSource.Mode; import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; @@ -49,6 +58,19 @@ class CommandModelAssemblerTest { @InjectMocks private CommandModelAssembler modelAssembler; + @Spy + private List<CommandProcessor> processors = new ArrayList<>(); + @Mock + private CommandProcessor processor; + + @Captor + private ArgumentCaptor<EntityModel<Command>> commandEntityModelCaptor; + + @BeforeEach + void setProcessorMocks() { + processors.add(processor); + } + @Test void shouldHaveSelfLink() { var model = modelAssembler.toModel(CommandTestFactory.create()); @@ -56,6 +78,16 @@ class CommandModelAssemblerTest { assertThat(model.getLink(IanaLinkRelations.SELF)).isPresent().get().extracting(Link::getHref).isEqualTo(COMMAND_SINGLE_PATH); } + @Test + void shouldCallProcessor() { + var command = CommandTestFactory.create(); + + modelAssembler.toModel(command); + + verify(processor).process(commandEntityModelCaptor.capture()); + assertThat(commandEntityModelCaptor.getValue().getContent()).isEqualTo(command); + } + @Nested @DisplayName("Link to effected Resource") class TestEffectedResourceLink { @@ -103,22 +135,6 @@ class CommandModelAssemblerTest { } } - @DisplayName("on postfach") - @Nested - class TestOnPostfach { - - private static final String POSTFACH_URL = "/api/postfachMails?vorgangId=" + VorgangHeaderTestFactory.ID; - - @ParameterizedTest - @ValueSource(strings = { "SEND_POSTFACH_MAIL" }) - void shouldHaveLinkToPostfach(String order) { - var model = toModelWithOrder(order); - - assertThat(model.getLink(CommandModelAssembler.REL_EFFECTED_RESOURCE)).isPresent().get() - .extracting(Link::getHref).isEqualTo(POSTFACH_URL); - } - } - @DisplayName("on bescheid") @Nested class TestOnBescheid { @@ -196,7 +212,8 @@ class CommandModelAssemblerTest { } @ParameterizedTest - @EnumSource(mode = Mode.EXCLUDE, names = { "UNBEKANNT" }) + @EnumSource(mode = Mode.EXCLUDE, names = { "UNBEKANNT", "SEND_POSTFACH_MAIL", "SEND_POSTFACH_NACHRICHT", "RESEND_POSTFACH_MAIL", + "RECEIVE_POSTFACH_NACHRICHT" }) void shouldBeAbleToBuildLinkForEveryOrder(CommandOrder order) { var link = modelAssembler.effectedResourceLinkByOrderType(CommandTestFactory.createBuilder().order(order.name()).build()); diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandProcessorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..edc832bafccb29ef6053a64fefda68e44955ec6a --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/common/command/CommandProcessorTest.java @@ -0,0 +1,146 @@ +package de.ozgcloud.alfa.common.command; + +import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.Spy; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; + +class CommandProcessorTest { + + @Spy + private CommandProcessor processor; + + @DisplayName("Process") + @Nested + class TestProcess { + + private final Command command = CommandTestFactory.create(); + private final EntityModel<Command> model = EntityModel.of(command); + + private final WebMvcLinkBuilder linkBuilder = WebMvcLinkBuilder.linkTo(CommandController.class).slash("id"); + + @Test + void shouldNotThrowExceptionsOnNullContent() { + EntityModel<Command> entityModel = when(mock(EntityModel.class).getContent()).thenReturn(null).getMock(); + + assertDoesNotThrow(() -> processor.process(entityModel)); + } + + @DisplayName("effected resource") + @Nested + class TestEffectedResource { + + @DisplayName("should verify if responsibility is related to the order") + @Test + void shouldCallIsResponsibleForEffectedResource() { + processor.process(model); + + verify(processor).isResponsibleForEffectedResource(CommandOrder.fromOrder(CommandTestFactory.ORDER)); + } + + @DisplayName("should NOT create link builder for related resource if the responsibility matches") + @Test + void shouldNOTCallCreateEffectedResourceLinkBuilder() { + when(processor.isResponsibleForEffectedResource(any())).thenReturn(false); + + processor.process(model); + + verify(processor, never()).createEffectedResourceLinkBuilder(command); + } + + @DisplayName("should create link builder for effected resource if the responsibility matches") + @Test + void shouldCallCreateEffectedResourceLinkBuilder() { + when(processor.isResponsibleForEffectedResource(any())).thenReturn(true); + doReturn(linkBuilder).when(processor).createEffectedResourceLinkBuilder(any()); + + processor.process(model); + + verify(processor).createEffectedResourceLinkBuilder(command); + } + + @DisplayName("link") + @Nested + class TestEffectedResourceLink { + + @Test + void shouldBeAddedIfResponsible() { + doReturn(true).when(processor).isResponsibleForEffectedResource(any()); + doReturn(linkBuilder).when(processor).createEffectedResourceLinkBuilder(any()); + var finishedCommand = CommandTestFactory.createBuilder().status(CommandStatus.FINISHED).build(); + var entityModel = EntityModel.of(finishedCommand); + + processor.process(entityModel); + + assertThat(entityModel.getLink(CommandProcessor.REL_EFFECTED_RESOURCE).get().getHref()).isEqualTo("/api/commands/id"); + } + + @Test + void shouldNotBeAddedIfCommandNotDone() { + var pendingCommand = CommandTestFactory.createBuilder().status(CommandStatus.PENDING).build(); + var entityModel = EntityModel.of(pendingCommand); + + processor.process(entityModel); + + assertThat(entityModel.getLink(CommandProcessor.REL_EFFECTED_RESOURCE)).isNotPresent(); + } + } + } + + @DisplayName("related resource") + @Nested + class TestRelatedResource { + + @DisplayName("should verify if responsibility is related to the order") + @Test + void shouldCallIsResponsibleForRelatedResource() { + processor.process(model); + + verify(processor).isResponsibleForRelatedResource(CommandOrder.fromOrder(CommandTestFactory.ORDER)); + } + + @DisplayName("should create link builder for related resource if the responsibility matches") + @Test + void shouldCallCreateRelatedResourceLinkBuilder() { + when(processor.isResponsibleForRelatedResource(any())).thenReturn(true); + doReturn(linkBuilder).when(processor).createRelatedResourceLinkBuilder(any()); + + processor.process(model); + + verify(processor).createRelatedResourceLinkBuilder(command); + } + + @DisplayName("should NOT create link builder for related resource if the responsibility matches") + @Test + void shouldNOTCallCreateRelatedResourceLinkBuilder() { + when(processor.isResponsibleForRelatedResource(any())).thenReturn(false); + + processor.process(model); + + verify(processor, never()).createRelatedResourceLinkBuilder(command); + } + + @DisplayName("link") + @Nested + class TestRelatedResourceLink { + + @Test + void shouldBeAddedIfResponsible() { + doReturn(true).when(processor).isResponsibleForRelatedResource(any()); + doReturn(linkBuilder).when(processor).createRelatedResourceLinkBuilder(any()); + + processor.process(model); + + assertThat(model.getLink(CommandProcessor.REL_RELATED_RESOURCE).get().getHref()).isEqualTo("/api/commands/id"); + } + } + } + } +} \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssemblerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssemblerTest.java index 091797403adabd9734b63866c28185033da4e0b7..01b02c1d5fd666420cefb40d3b80a070cabe65b8 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssemblerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailModelAssemblerTest.java @@ -449,6 +449,7 @@ class PostfachMailModelAssemblerTest { @Nested class ResetNewPostfachNachrichtLink { + @Test void shouldBePresent() { callModelAssembler(VorgangWithEingangTestFactory.create()); @@ -469,6 +470,29 @@ class PostfachMailModelAssemblerTest { } } + @Nested + class SetHasNewPostfachNachrichtLink { + + @Test + void shouldBePresent() { + callModelAssembler(VorgangWithEingangTestFactory.createBuilder().hasNewPostfachNachricht(false).build()); + + var link = model.getLink(PostfachMailModelAssembler.REL_SET_HAS_NEW_POSTFACH_MAIL); + assertThat(link).isPresent().get().extracting(Link::getHref) + .isEqualTo(UriComponentsBuilder.fromUriString("/api/vorgangs") + .pathSegment(VorgangHeaderTestFactory.ID, "hasNewPostfachNachricht") + .build().toString()); + } + + @Test + void shouldNotBePresent() { + callModelAssembler(VorgangWithEingangTestFactory.create()); + + var link = model.getLink(PostfachMailModelAssembler.REL_SET_HAS_NEW_POSTFACH_MAIL); + assertThat(link).isNotPresent(); + } + } + @DisplayName("send postfach mail") @Nested class SendPostfachMailLink { diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachNachrichtCommandProcessorTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachNachrichtCommandProcessorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5b2cbca51b4b6d9a2373c7ef399aa513e5eb5bb4 --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachNachrichtCommandProcessorTest.java @@ -0,0 +1,88 @@ +package de.ozgcloud.alfa.postfach; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.EnumSource.Mode; +import org.mockito.Spy; + +import de.ozgcloud.alfa.common.command.CommandOrder; +import de.ozgcloud.alfa.common.command.CommandTestFactory; + +class PostfachNachrichtCommandProcessorTest { + + @Spy + private PostfachNachrichtCommandProcessor processor; + + @DisplayName("Related resource") + @Nested + class TestRelatedResource { + + @DisplayName("is responsible") + @Nested + class TestIsResponsible { + + @EnumSource(mode = Mode.INCLUDE, names = { "RECEIVE_POSTFACH_NACHRICHT", "RESEND_POSTFACH_MAIL" }) + @ParameterizedTest(name = "{0}") + void shouldReturnTrueOnOrder(CommandOrder order) { + var isResponsible = processor.isResponsibleForRelatedResource(order); + + assertThat(isResponsible).isTrue(); + } + + @EnumSource(mode = Mode.EXCLUDE, names = { "RECEIVE_POSTFACH_NACHRICHT", "RESEND_POSTFACH_MAIL" }) + @ParameterizedTest(name = "{0}") + void shouldReturnFalseOnOrder(CommandOrder order) { + var isResponsible = processor.isResponsibleForRelatedResource(order); + + assertThat(isResponsible).isFalse(); + } + } + + @Test + void shouldCreateLinkBuilder() { + var linkBuilder = processor.createRelatedResourceLinkBuilder(CommandTestFactory.create()); + + assertThat(linkBuilder).hasToString(PostfachMailController.PATH + "/" + CommandTestFactory.RELATION_ID); + } + } + + @DisplayName("Effected resource") + @Nested + class TestEffectedResource { + + @DisplayName("is responsible") + @Nested + class TestIsResponsible { + + @EnumSource(mode = Mode.INCLUDE, names = { "SEND_POSTFACH_MAIL", "SEND_POSTFACH_NACHRICHT", "RESEND_POSTFACH_MAIL", + "RECEIVE_POSTFACH_NACHRICHT" }) + @ParameterizedTest(name = "{0}") + void shouldReturnTrueOnOrder(CommandOrder order) { + var isResponsible = processor.isResponsibleForEffectedResource(order); + + assertThat(isResponsible).isTrue(); + } + + @EnumSource(mode = Mode.EXCLUDE, names = { "SEND_POSTFACH_MAIL", "SEND_POSTFACH_NACHRICHT", "RESEND_POSTFACH_MAIL", + "RECEIVE_POSTFACH_NACHRICHT" }) + @ParameterizedTest(name = "{0}") + void shouldReturnFalseOnOrder(CommandOrder order) { + var isResponsible = processor.isResponsibleForEffectedResource(order); + + assertThat(isResponsible).isFalse(); + } + } + + @Test + void shouldCreateLinkBuilder() { + var linkBuilder = processor.createEffectedResourceLinkBuilder(CommandTestFactory.create()); + + assertThat(linkBuilder).hasToString(PostfachMailController.PATH + "?vorgangId=" + CommandTestFactory.VORGANG_ID); + } + } +} \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java index 257f019b7ffc2ba3f4a0b10f74139f3ed49cc4b5..36d0bc99fb051803fe2996fed0ffab28355bf81c 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java @@ -39,6 +39,8 @@ 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.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; @@ -281,24 +283,16 @@ class VorgangControllerITCase { @Nested class TestClientAttribute { - @Test - void shouldReturnNoContent() throws Exception { - var content = VorgangHeaderTestFactory.createHasNewPostfachNachrichtContent(false); + @ParameterizedTest + @ValueSource(booleans = {true, false}) + void shouldReturnNoContent(boolean hasNewPostfachNachricht) throws Exception { + var content = VorgangHeaderTestFactory.createHasNewPostfachNachrichtContent(hasNewPostfachNachricht); var response = doRequest(content); response.andExpect(status().isNoContent()); } - @Test - void shouldReturnUnprocessableEntity() throws Exception { - var content = VorgangHeaderTestFactory.createHasNewPostfachNachrichtContent(true); - - var response = doRequest(content); - - response.andExpect(status().isUnprocessableEntity()); - } - private ResultActions doRequest(String content) throws Exception { return mockMvc.perform(put("/api/vorgangs/{0}/hasNewPostfachNachricht", VorgangHeaderTestFactory.ID).with(csrf()) .contentType(MediaType.APPLICATION_JSON) diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java index 609ea5ccf1b83f33ecb2db97b2f4ff90652d2470..5f641cbf4302f0b27e863bf82f0634379a8cda6b 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerTest.java @@ -869,22 +869,21 @@ class VorgangControllerTest { } } - @DisplayName("Reset new postfachNachricht") @Nested - class TestResetNewPostfachNachricht { + class TestSetNewPostfachNachricht { @Test - void resetNewPostfachNachricht() { + void shouldResetNewPostfachNachricht() { performRequest("{\"hasNewPostfachNachricht\":false}").assertThat().hasStatus(HttpStatus.NO_CONTENT); verify(clientAttributeService).resetPostfachNachricht(VorgangHeaderTestFactory.ID); } @Test - void shouldReturnUnprocessableEntity() { - performRequest("{\"hasNewPostfachNachricht\":true}").assertThat().hasStatus(HttpStatus.UNPROCESSABLE_ENTITY); + void shouldSetHasNewPostfachNachricht() { + performRequest("{\"hasNewPostfachNachricht\":true}").assertThat().hasStatus(HttpStatus.NO_CONTENT); - verify(clientAttributeService, never()).resetPostfachNachricht(VorgangHeaderTestFactory.ID); + verify(clientAttributeService).setHasNewPostfachNachricht(VorgangHeaderTestFactory.ID); } private MockMvcRequestBuilder performRequest(String body) { diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml index ca99396fb145aef959cab90037aa14d0df91b5ed..a0c14d08bdd36bd36cdf19a84c36ffb31281e8ef 100644 --- a/src/main/helm/templates/deployment.yaml +++ b/src/main/helm/templates/deployment.yaml @@ -100,6 +100,14 @@ spec: - name: ozgcloud_user-assistance_documentation_url value: {{ .Values.ozgcloud.user_assistance.documentation.url }} {{- end }} + {{- if (((.Values.ozgcloud).upload).maxFileSize).postfachNachrichtAttachment }} + - name: ozgcloud_upload_maxFileSize_postfachNachrichtAttachment + value: {{ .Values.ozgcloud.upload.maxFileSize.postfachNachrichtAttachment }} + {{- end }} + {{- if (((.Values.ozgcloud).upload).contentTypes).postfachNachrichtAttachment }} + - name: ozgcloud_upload_contentTypes_postfachNachrichtAttachment + value: {{ .Values.ozgcloud.upload.contentTypes.postfachNachrichtAttachment }} + {{- end }} {{- with include "app.getCustomList" . }} {{ . | indent 8 }} {{- end }} diff --git a/src/test/helm/deployment_63_char_test.yaml b/src/test/helm/deployment_63_char_test.yaml index 28fa4858c874ef7f6a783a6d5ecadb9666ab797a..e4f54aa4043f30d2e29d3b0bd43af18ce39491b7 100644 --- a/src/test/helm/deployment_63_char_test.yaml +++ b/src/test/helm/deployment_63_char_test.yaml @@ -44,21 +44,21 @@ set: imagePullSecret: image-pull-secret tests: + - it: should not fail on .Release.Namespace length less than 63 characters + asserts: + - notFailedTemplate: { } - it: should fail on .Release.Namespace length longer than 63 characters release: namespace: test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 asserts: - failedTemplate: errorMessage: .Release.Namespace test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 ist zu lang (max. 63 Zeichen) - - it: should not fail on .Release.Namespace length less than 63 characters + - it: should not fail on .Chart.Name-.Chart.Version length less than 63 characters asserts: - - notFailedTemplate: {} + - notFailedTemplate: { } - it: should fail on .Chart.Name-.Chart.Version length longer than 63 characters chart: version: 1.0-test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 asserts: - failedTemplate: errorMessage: .Chart.Name-.Chart.Version alfa-1.0-test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 ist zu lang (max. 63 Zeichen) - - it: should not fail on .Chart.Name-.Chart.Version length less than 63 characters - asserts: - - notFailedTemplate: {} diff --git a/src/test/helm/deployment_upload_env_test.yaml b/src/test/helm/deployment_upload_env_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b0791698b17b5ca94efebbcb2b831d2fe163626a --- /dev/null +++ b/src/test/helm/deployment_upload_env_test.yaml @@ -0,0 +1,72 @@ +# +# Copyright (C) 2025 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: deployment upload env +release: + name: alfa + namespace: sh-helm-test +templates: + - templates/deployment.yaml +set: + baseUrl: test.company.local + ozgcloud: + environment: test + bundesland: sh + bezeichner: helm + barrierefreiheitUrl: http://barrierefreiheit.test.url + sso: + serverUrl: https://sso.company.local + imagePullSecret: image-pull-secret +tests: + - it: should set upload values + set: + ozgcloud: + upload: + maxFileSize: + postfachNachrichtAttachment: "50MB" + contentTypes: + postfachNachrichtAttachment: "text/plain,application/pdf" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_upload_maxFileSize_postfachNachrichtAttachment + value: "50MB" + - contains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_upload_contentTypes_postfachNachrichtAttachment + value: "text/plain,application/pdf" + - it: should not set upload values when missing + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_upload_maxFileSize_postfachNachrichtAttachment + any: true + - notContains: + path: spec.template.spec.containers[0].env + content: + name: ozgcloud_upload_contentTypes_postfachNachrichtAttachment + any: true \ No newline at end of file