diff --git a/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/BescheidManagerCallContextProvider.java b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/BescheidManagerCallContextProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..249a3bd2e56dd5c4da6ae1290228c97109ea7b41 --- /dev/null +++ b/bescheid-manager/src/main/java/de/ozgcloud/bescheid/common/callcontext/BescheidManagerCallContextProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2024 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. + */ +package de.ozgcloud.bescheid.common.callcontext; + +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import de.ozgcloud.apilib.common.callcontext.CallContext; +import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider; +import de.ozgcloud.apilib.user.OzgCloudUserId; +import de.ozgcloud.common.errorhandling.TechnicalException; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +@Primary +public class BescheidManagerCallContextProvider implements OzgCloudCallContextProvider { + + private final CurrentUserService currentUserService; + + @Override + public CallContext provideContext() { + return CallContext.builder() + .userId(getUserId()) + .clientName(currentUserService.getUser().getClientName()) + .build(); + } + + OzgCloudUserId getUserId() { + return currentUserService.getUser().getUserId().map(OzgCloudUserId::from) + .orElseThrow(() -> new TechnicalException("No user id found in current user profile")); + } +} diff --git a/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/callcontext/BescheidManagerCallContextProviderTest.java b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/callcontext/BescheidManagerCallContextProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cfcf4559761f622b57483a05d63f96f2a9b92cb4 --- /dev/null +++ b/bescheid-manager/src/test/java/de/ozgcloud/bescheid/common/callcontext/BescheidManagerCallContextProviderTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2024 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. + */ +package de.ozgcloud.bescheid.common.callcontext; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Optional; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.apilib.user.OzgCloudUserId; +import de.ozgcloud.common.errorhandling.TechnicalException; + +class BescheidManagerCallContextProviderTest { + + @Spy + @InjectMocks + private BescheidManagerCallContextProvider provider; + + @Mock + private CurrentUserService currentUserService; + @Mock + private CallContextUser contextUser; + @Mock + private OzgCloudUserId userId; + + @BeforeEach + void init() { + when(currentUserService.getUser()).thenReturn(contextUser); + } + + @Nested + class TestProvideContext { + + private static final String CLIENT_NAME = "clientName"; + + @BeforeEach + void init() { + doReturn(userId).when(provider).getUserId(); + when(contextUser.getClientName()).thenReturn(CLIENT_NAME); + } + + @Test + void shouldCallGetUserId() { + provider.provideContext(); + + verify(provider).getUserId(); + } + + @Test + void shouldSetUserId() { + var result = provider.provideContext(); + + assertThat(result.getUserId()).isSameAs(userId); + } + + @Test + void shouldSetClientName() { + var result = provider.provideContext(); + + assertThat(result.getClientName()).isEqualTo(CLIENT_NAME); + } + } + + @Nested + class TestGetUserId { + + private static final String USER_ID = "userId"; + + @Test + void shouldReturnUserId() { + when(contextUser.getUserId()).thenReturn(Optional.of(USER_ID)); + + var result = provider.getUserId(); + + assertThat(result).hasToString(USER_ID); + } + + @Test + void shouldThrowExceptionWhenUserIdMissing() { + Assertions.assertThrows(TechnicalException.class, provider::getUserId); + } + } +} \ No newline at end of file diff --git a/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextAuthenticationTokenTestFactory.java b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextAuthenticationTokenTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..55bc9ffb1fc75bcb130a454657d7a1c8b3c74db8 --- /dev/null +++ b/vorgang-manager-base/src/test/java/de/ozgcloud/vorgang/callcontext/CallContextAuthenticationTokenTestFactory.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 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. + */ +package de.ozgcloud.vorgang.callcontext; + +public class CallContextAuthenticationTokenTestFactory { + + public static CallContextAuthenticationToken create() { + return CallContextAuthenticationToken.authenticate(CallContextUserTestFactory.create()); + } +} diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java b/vorgang-manager-server/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java index 74eef7dbb26dfe69c8005de551357a261d07474a..e16d160e425846bb249355a1aab74450f0f1d158 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/bescheid/BescheidEventListenerITCase.java @@ -29,16 +29,14 @@ import static org.awaitility.Awaitility.*; import static org.mockito.Mockito.*; import java.util.Map; -import java.util.Optional; import java.util.concurrent.TimeUnit; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; -import org.mockito.Mock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; @@ -48,14 +46,15 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.gridfs.GridFsTemplate; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.test.annotation.DirtiesContext; import com.mongodb.client.gridfs.model.GridFSFile; +import de.ozgcloud.apilib.user.OzgCloudUserId; +import de.ozgcloud.apilib.user.OzgCloudUserProfile; +import de.ozgcloud.apilib.user.OzgCloudUserProfileService; import de.ozgcloud.bescheid.attacheditem.AttachedItemService; -import de.ozgcloud.bescheid.common.callcontext.CallContextUser; -import de.ozgcloud.bescheid.common.callcontext.CurrentUserService; -import de.ozgcloud.bescheid.common.callcontext.UserProfile; import de.ozgcloud.command.Command; import de.ozgcloud.command.CommandCreatedEvent; import de.ozgcloud.command.CommandStatus; @@ -68,6 +67,7 @@ import de.ozgcloud.nachrichten.postfach.PostfachRemoteService; import de.ozgcloud.vorgang.VorgangManagerServerApplication; import de.ozgcloud.vorgang.attached_item.VorgangAttachedItem; import de.ozgcloud.vorgang.attached_item.VorgangAttachedItemTestFactory; +import de.ozgcloud.vorgang.callcontext.CallContextAuthenticationTokenTestFactory; import de.ozgcloud.vorgang.command.CommandService; import de.ozgcloud.vorgang.command.CommandTestFactory; import de.ozgcloud.vorgang.command.CreateCommandRequest; @@ -87,7 +87,6 @@ import de.ozgcloud.vorgang.vorgang.VorgangTestFactory; }) @DataITCase @DirtiesContext -@Disabled("fix later") class BescheidEventListenerITCase { @Autowired @@ -105,11 +104,7 @@ class BescheidEventListenerITCase { @MockBean private PostfachRemoteService postfachRemoteService; @MockBean - private CurrentUserService currentUserService; - @Mock - private CallContextUser callContextUser; - @Mock - private UserProfile userProfile; + private OzgCloudUserProfileService userProfileService; @Captor private ArgumentCaptor<BescheidDocumentCreatedEvent> bescheidDocumentCreatedEventCaptor; @@ -118,9 +113,8 @@ class BescheidEventListenerITCase { void init() { mongoOperations.dropCollection(VorgangAttachedItem.COLLECTION_NAME); mongoOperations.dropCollection(Vorgang.COLLECTION_NAME); - when(currentUserService.getUser()).thenReturn(callContextUser); - when(currentUserService.getUserProfile()).thenReturn(userProfile); when(postfachRemoteService.getPostfachType()).thenReturn("dummy"); + when(userProfileService.getById(any())).thenReturn(OzgCloudUserProfile.builder().id(OzgCloudUserId.from("user-id")).build()); } @Nested @@ -270,10 +264,14 @@ class BescheidEventListenerITCase { private String vorgangId; private VorgangAttachedItem bescheidItem; + @AfterAll + static void cleanup() { + SecurityContextHolder.clearContext(); + } + @BeforeEach void init() { - when(userProfile.getId()).thenReturn(UserId.from("user-id")); - when(callContextUser.getUserId()).thenReturn(Optional.of("user-id")); + SecurityContextHolder.getContext().setAuthentication(CallContextAuthenticationTokenTestFactory.create()); vorgangId = mongoOperations.save(VorgangTestFactory.createBuilder().id(null).build()).getId(); var documentFileId = mongoOperations.save(createBescheidDocumentAttachedItem(vorgangId)).getId(); bescheidItem = mongoOperations.save(createBescheidAttachedItemWithDocument(vorgangId, documentFileId)); @@ -291,9 +289,9 @@ class BescheidEventListenerITCase { @Test void shouldSetBescheidStatusToSent() { - eventPublisher.publishEvent(buildCommandCreatedEvent(vorgangId, bescheidItem)); + commandService.createCommand(buildCreateCommandRequest(vorgangId, bescheidItem)); - await().atMost(1, TimeUnit.SECONDS).untilAsserted(() -> { + await().atMost(60, TimeUnit.SECONDS).untilAsserted(() -> { verify(bescheiTestEventListener).onBescheidSentEvent(bescheidSentEventCaptor.capture()); assertThat(loadBescheid(bescheidItem.getId()).getItem()).containsEntry(Bescheid.FIELD_STATUS, Bescheid.Status.SENT.name()); }); @@ -365,18 +363,6 @@ class BescheidEventListenerITCase { .build(); } - private CommandCreatedEvent buildCommandCreatedEvent(String vorgangId, VorgangAttachedItem bescheidItem) { - var command = CommandTestFactory.createBuilder() - .vorgangId(vorgangId) - .relationId(bescheidItem.getId()) - .relationVersion(bescheidItem.getVersion()) - .order(SEND_BESCHEID_ORDER) - .bodyObject(Map.of(BESCHEID_VOM_BODYKEY, "2024-01-01", - GENEHMIGT_BODYKEY, true)) - .build(); - return new CommandCreatedEvent(command); - } - private CreateCommandRequest buildCreateCommandRequest(String vorgangId, VorgangAttachedItem bescheidItem) { return CreateCommandRequest.builder() .vorgangId(vorgangId)