diff --git a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java index 92939794743402ec18276e3101f3c6392375123b..ea8d68914c6127281a5c660eee66014eacb906b5 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/RootController.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/RootController.java @@ -28,9 +28,7 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; import java.time.Instant; import java.util.Optional; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.info.BuildProperties; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; @@ -41,16 +39,19 @@ import org.springframework.web.bind.annotation.RestController; import de.itvsh.goofy.common.ModelBuilder; import de.itvsh.goofy.common.downloadtoken.DownloadTokenController; import de.itvsh.goofy.common.user.CurrentUserService; -import de.itvsh.goofy.common.user.UserRemoteService; import de.itvsh.goofy.common.user.UserId; +import de.itvsh.goofy.common.user.UserManagerUrlProvider; +import de.itvsh.goofy.common.user.UserRemoteService; import de.itvsh.goofy.common.user.UserRole; import de.itvsh.goofy.system.SystemStatusService; import de.itvsh.goofy.vorgang.VorgangController; @RestController -@RequestMapping("/api") +@RequestMapping(RootController.PATH) public class RootController { + static final String PATH = "/api"; // NOSONAR + static final String REL_VORGAENGE = "vorgaenge"; static final String REL_SEARCH = "search"; static final String REL_SEARCH_USER = "search-user-profiles"; @@ -68,26 +69,20 @@ public class RootController { @Autowired private UserRemoteService internalUserIdService; - @Value("${kop.user-manager.url:}") - private String userManagerUrl; - - @Value("${kop.user-manager.profile-template:}") - private String userProfileTemplate; - - @Value("${kop.user-manager.search-template:}") - private String userSearchTemplate; + @Autowired + private UserManagerUrlProvider userManagerUrlProvider; @GetMapping public EntityModel<RootResource> getRootResource() { - var userManagerSearchUrl = userManagerUrl + userSearchTemplate; var internalUserId = internalUserIdService.getUserId(currentUserService.getUserId()); var modelBuilder = ModelBuilder.fromEntity(new RootResource()) .ifMatch(this::hasRole).addLinks( linkTo(RootController.class).withSelfRel(), linkTo(VorgangController.class).withRel(REL_VORGAENGE), - Link.of(userManagerSearchUrl, REL_SEARCH_USER), linkTo(DownloadTokenController.class).withRel(REL_DOWNLOAD_TOKEN)) + .ifMatch(this::hasRoleAndUserManagerIsConfigured) + .addLink(() -> Link.of(userManagerUrlProvider.getUserProfileSearchTemplate(), REL_SEARCH_USER)) .ifMatch(this::hasRoleAndSearchServerAvailable).addLinks( buildVorgangListByPageLink(REL_SEARCH, Optional.empty())); @@ -98,12 +93,17 @@ public class RootController { buildVorgangListByPageLink(REL_SEARCH_MY_VORGAENGE, Optional.of(userId)))); var model = modelBuilder.buildModel(); + getUserProfilesUrl() .ifPresent(urlTemplate -> model.add(Link.of(String.format(urlTemplate, currentUserService.getUserId()), REL_CURRENT_USER))); return model; } + private boolean hasRoleAndUserManagerIsConfigured() { + return hasRole() && userManagerUrlProvider.isConfiguredForSearchUserProfile(); + } + private boolean hasRoleAndSearchServerAvailable() { return hasRole() && systemStatusService.isSearchServerAvailable(); } @@ -121,18 +121,18 @@ public class RootController { || currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE); } + private Link buildVorgangListByPageLink(String linkRel, Optional<UserId> assignedTo) { + return linkTo(methodOn(VorgangController.class).getVorgangListByPage(0, null, null, assignedTo)).withRel(linkRel); + } + Optional<String> getUserProfilesUrl() { - if (StringUtils.isNotEmpty(userManagerUrl) && StringUtils.isNotEmpty(userProfileTemplate)) { - return Optional.of(userManagerUrl + userProfileTemplate); + if (userManagerUrlProvider.isConfiguredForUserProfile()) { + return Optional.of(userManagerUrlProvider.getUserProfileTemplate()); } return Optional.empty(); } - private Link buildVorgangListByPageLink(String linkRel, Optional<UserId> assignedTo) { - return linkTo(methodOn(VorgangController.class).getVorgangListByPage(0, null, null, assignedTo)).withRel(linkRel); - } - class RootResource { public String getVersion() { diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/LinkedUserProfileResourceSerializer.java b/goofy-server/src/main/java/de/itvsh/goofy/common/LinkedUserProfileResourceSerializer.java index f92b97950efbe55618ec73116a4029c0e946f641..df1eea531784bf4be748500077486b6de0984d56 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/LinkedUserProfileResourceSerializer.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/LinkedUserProfileResourceSerializer.java @@ -23,20 +23,24 @@ */ package de.itvsh.goofy.common; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.Collection; import org.apache.commons.lang3.reflect.ConstructorUtils; import org.springframework.hateoas.Link; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; import de.itvsh.kop.common.errorhandling.TechnicalException; import lombok.NoArgsConstructor; @NoArgsConstructor -public class LinkedUserProfileResourceSerializer extends AbstractLinkedResourceSerializer { +public class LinkedUserProfileResourceSerializer extends JsonSerializer<Object> implements ContextualSerializer { private LinkedUserProfileResource annotation; @@ -49,12 +53,14 @@ public class LinkedUserProfileResourceSerializer extends AbstractLinkedResourceS return new LinkedUserProfileResourceSerializer(property.getAnnotation(LinkedUserProfileResource.class)); } - @Override String buildLink(Object id) { - return Link.of(UserProfileUrlProvider.getUrl(getExtractor().extractId(id))).getHref(); + if (UserProfileUrlProvider.isConfigured()) { + return Link.of(UserProfileUrlProvider.getUrl(getExtractor().extractId(id))).getHref(); + } else { + return id.toString(); + } } - @Override IdExtractor<Object> getExtractor() { try { return ConstructorUtils.invokeConstructor(annotation.extractor()); @@ -63,4 +69,22 @@ public class LinkedUserProfileResourceSerializer extends AbstractLinkedResourceS } } -} + @Override + public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + if (value instanceof Collection) { + gen.writeStartArray(); + ((Collection<?>) value).forEach(val -> writeObject(gen, buildLink(val))); + gen.writeEndArray(); + } else { + writeObject(gen, buildLink(value)); + } + } + + void writeObject(JsonGenerator gen, Object value) { + try { + gen.writeObject(value); + } catch (IOException e) { + throw new TechnicalException("Error writing String to json", e); + } + } +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java b/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java index 4ba954e31ac56a14e804ef86dee5912b30182bb8..b484c19bdbdda160d7e2ab085678b792580688bd 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/ModelBuilder.java @@ -149,7 +149,11 @@ public class ModelBuilder<T> { } private void handleLinkedUserProfileResourceField(EntityModel<T> resource, Field field) { - getEntityFieldValue(field).ifPresent(val -> resource.add(Link.of(UserProfileUrlProvider.getUrl(val)).withRel(sanitizeName(field.getName())))); + getEntityFieldValue(field).ifPresent(val -> { + if (UserProfileUrlProvider.isConfigured()) { + resource.add(Link.of(UserProfileUrlProvider.getUrl(val)).withRel(sanitizeName(field.getName()))); + } + }); } private boolean shouldAddLink(EntityModel<T> resource, Field field) { diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java b/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java index c084a7c6cf3cffd11a19677e169888b675dc4c07..97aacab5e2086ac32bb9de4c491fb105acedd1fb 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/UserProfileUrlProvider.java @@ -23,6 +23,8 @@ */ package de.itvsh.goofy.common; +import java.util.Objects; + import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; @@ -49,6 +51,11 @@ public class UserProfileUrlProvider implements ApplicationContextAware { applicationContext = context; } + public static boolean isConfigured() { + return Objects.nonNull(applicationContext.getEnvironment().getProperty(URL_ROOT_KEY)) + && Objects.nonNull(applicationContext.getEnvironment().getProperty(USER_PROFILES_TEMPLATE_KEY)); + } + public static String getUrl(Object val) { // TODO Abhängingkeit zu com.google.common ausbauen Preconditions.checkNotNull(applicationContext, "ApplicationContext not initialized"); diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserManagerProperties.java b/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserManagerProperties.java index 9f337df92fadbbc877489ed9f06084417cf939d3..2a576cecb614191b8c84456482e26a701f182950 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserManagerProperties.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserManagerProperties.java @@ -29,6 +29,7 @@ import org.springframework.context.annotation.Configuration; import lombok.Getter; import lombok.Setter; +@Getter @Setter @Configuration @ConfigurationProperties(UserManagerProperties.PREFIX) @@ -40,7 +41,6 @@ public class UserManagerProperties { private String url; private String profileTemplate; - @Getter private String searchTempalte; private String internalurl; diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserManagerUrlProvider.java b/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserManagerUrlProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..0e6ff45623d4ac87162b1309b7d001fc693bde8f --- /dev/null +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserManagerUrlProvider.java @@ -0,0 +1,40 @@ +package de.itvsh.goofy.common.user; + +import java.util.Objects; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class UserManagerUrlProvider { + + @Autowired + private UserManagerProperties userManagerProperties; + + public String getUserProfileTemplate() { + return userManagerProperties.getUrl() + userManagerProperties.getProfileTemplate(); + } + + public String getUserProfileSearchTemplate() { + return userManagerProperties.getUrl() + userManagerProperties.getSearchTempalte(); + } + + public String getInternalUserIdTemplate() { + return userManagerProperties.getInternalUrlTemplate(); + } + + public boolean isConfiguredForUserProfile() { + return Objects.nonNull(StringUtils.trimToNull(userManagerProperties.getUrl())) + && Objects.nonNull(StringUtils.trimToNull(userManagerProperties.getProfileTemplate())); + } + + public boolean isConfiguredForSearchUserProfile() { + return Objects.nonNull(StringUtils.trimToNull(userManagerProperties.getUrl())) + && Objects.nonNull(StringUtils.trimToNull(userManagerProperties.getSearchTempalte())); + } + + public boolean isConfiguredForInternalUserId() { + return Objects.nonNull(StringUtils.trimToNull(userManagerProperties.getInternalurl())); + } +} diff --git a/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserRemoteService.java b/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserRemoteService.java index 86581748b1db00446918a5015718a486a2192ac9..ddcd94f911108718d4a31d1a0670653d79702833 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserRemoteService.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/common/user/UserRemoteService.java @@ -55,13 +55,19 @@ public class UserRemoteService { @Autowired private UserManagerProperties userManagerProperties; + @Autowired + private UserManagerUrlProvider userManagerUrlProvider; private RestTemplate restTemplate = new RestTemplate(); public Optional<UserId> getUserId(UserId externalUserId) { try { - var internalId = restTemplate.getForObject(userManagerProperties.getInternalUrlTemplate(), String.class, externalUserId.toString()); - return StringUtils.isNotEmpty(internalId) ? Optional.of(UserId.from(internalId)) : Optional.empty(); + if (userManagerUrlProvider.isConfiguredForInternalUserId()) { + var internalId = restTemplate.getForObject(userManagerProperties.getInternalUrlTemplate(), String.class, externalUserId.toString()); + return StringUtils.isNotEmpty(internalId) ? Optional.of(UserId.from(internalId)) : Optional.empty(); + } else { + return Optional.empty(); + } } catch (RestClientException e) { LOG.warn("Error loading internal Userid.", e); return Optional.empty(); diff --git a/goofy-server/src/main/java/de/itvsh/goofy/historie/HistorieModelAssembler.java b/goofy-server/src/main/java/de/itvsh/goofy/historie/HistorieModelAssembler.java index 63c6f46586c10dc5d4435b6203220f66ea9c6b7f..c224c02c4c5f2cf8303cf3ba8d8ae2c91651d9d3 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/historie/HistorieModelAssembler.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/historie/HistorieModelAssembler.java @@ -29,7 +29,7 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; @@ -38,6 +38,7 @@ import org.springframework.stereotype.Component; import de.itvsh.goofy.common.ModelBuilder; import de.itvsh.goofy.common.command.Command; +import de.itvsh.goofy.common.user.UserManagerUrlProvider; @Component class HistorieModelAssembler implements RepresentationModelAssembler<Command, EntityModel<Command>> { @@ -47,11 +48,8 @@ class HistorieModelAssembler implements RepresentationModelAssembler<Command, En static final String ASSIGNED_TO_BODY_FIELD = "assignedTo"; - @Value("${kop.user-manager.url}") - private String rootUrl; - - @Value("${kop.user-manager.profile-template}") - private String profileTemplate; + @Autowired + private UserManagerUrlProvider userManagerUrlProvider; @Override public EntityModel<Command> toModel(Command entity) { @@ -76,10 +74,12 @@ class HistorieModelAssembler implements RepresentationModelAssembler<Command, En } private void addAssignedTo(Command entity, ModelBuilder<Command> modelBuilder) { - var url = rootUrl + profileTemplate; Optional.ofNullable(entity.getBody()).map(body -> body.get(ASSIGNED_TO_BODY_FIELD)) - .ifPresent(assignedTo -> modelBuilder - .addLink(Link.of(String.format(url, assignedTo), REL_ASSIGNED_TO))); + .ifPresent(assignedTo -> { + if (userManagerUrlProvider.isConfiguredForUserProfile()) { + modelBuilder.addLink(Link.of(String.format(userManagerUrlProvider.getUserProfileTemplate(), assignedTo), REL_ASSIGNED_TO)); + } + }); } public CollectionModel<EntityModel<Command>> toCollectionModel(Stream<Command> entities) { diff --git a/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailModelAssembler.java b/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailModelAssembler.java index 0b2068c4b6e4c92310caba1bbd904fb8704ff316..6914d78d08db17897bea3bdb3b92ae7567718d42 100644 --- a/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailModelAssembler.java +++ b/goofy-server/src/main/java/de/itvsh/goofy/postfach/PostfachMailModelAssembler.java @@ -31,7 +31,7 @@ import java.util.stream.Stream; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; @@ -41,6 +41,7 @@ import org.springframework.stereotype.Component; import de.itvsh.goofy.common.ModelBuilder; import de.itvsh.goofy.common.binaryfile.BinaryFileController; import de.itvsh.goofy.common.command.CommandController.CommandByRelationController; +import de.itvsh.goofy.common.user.UserManagerUrlProvider; import de.itvsh.goofy.postfach.PostfachMailController.PostfachMailCommandController; import de.itvsh.goofy.vorgang.VorgangController; import de.itvsh.goofy.vorgang.VorgangWithEingang; @@ -62,11 +63,8 @@ class PostfachMailModelAssembler implements RepresentationModelAssembler<Postfac private static final Predicate<PostfachMail> SENT_BY_CLIENT_USER = postfachNachricht -> Optional.ofNullable(postfachNachricht.getCreatedBy()) .map(createdBy -> !createdBy.toString().startsWith(SYSTEM_USER_IDENTIFIER)).orElse(false); - @Value("${kop.user-manager.url}") - private String rootUrl; - - @Value("${kop.user-manager.profile-template}") - private String profileTemplate; + @Autowired + private UserManagerUrlProvider userManagerUrlProvider; public CollectionModel<EntityModel<PostfachMail>> toCollectionModel(Stream<PostfachMail> entities, VorgangWithEingang vorgang, Optional<String> postfachId) { @@ -81,7 +79,6 @@ class PostfachMailModelAssembler implements RepresentationModelAssembler<Postfac @Override public EntityModel<PostfachMail> toModel(PostfachMail postfachMail) { var selfLink = linkTo(PostfachMailController.class).slash(postfachMail.getId()); - var url = rootUrl + profileTemplate; return ModelBuilder.fromEntity(postfachMail).addLink(selfLink.withSelfRel()) .ifMatch(SENT_FAILED) @@ -90,8 +87,8 @@ class PostfachMailModelAssembler implements RepresentationModelAssembler<Postfac .ifMatch(HAS_ATTACHMENTS) .addLink(linkTo(methodOn(PostfachMailController.class).findAttachments(PostfachNachrichtId.from(postfachMail.getId()))) .withRel(REL_ATTACHMENTS)) - .ifMatch(SENT_BY_CLIENT_USER) - .addLink(Link.of(String.format(url, postfachMail.getCreatedBy()), REL_CREATED_BY)) + .ifMatch(() -> userManagerUrlProvider.isConfiguredForUserProfile() && SENT_BY_CLIENT_USER.test(postfachMail)) + .addLink(() -> Link.of(String.format(userManagerUrlProvider.getUserProfileTemplate(), postfachMail.getCreatedBy()), REL_CREATED_BY)) .buildModel(); } @@ -106,4 +103,5 @@ class PostfachMailModelAssembler implements RepresentationModelAssembler<Postfac model.add(linkTo(VorgangController.class).slash(vorgangId).slash("hasNewPostfachNachricht").withRel(REL_RESET_NEW_POSTFACH_MAIL)); } } + } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java index 91ce9c7abe759ba19ba850e2394196a9047184f1..1d5f14146949381a80e253b6ee0b8bfa911b882f 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/RootControllerTest.java @@ -43,12 +43,12 @@ import org.mockito.Spy; import org.springframework.boot.info.BuildProperties; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; -import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import de.itvsh.goofy.common.user.CurrentUserService; +import de.itvsh.goofy.common.user.UserManagerUrlProvider; import de.itvsh.goofy.common.user.UserProfileTestFactory; import de.itvsh.goofy.common.user.UserRemoteService; import de.itvsh.goofy.common.user.UserRole; @@ -56,13 +56,6 @@ import de.itvsh.goofy.system.SystemStatusService; class RootControllerTest { - private static final String SEARCH_BY = "/test?searchBy={searchBy}"; - private static final String API_USER_PROFILES_TEMLPATE = "/api/userProfiles/%s"; - private static final String API_USER_PROFILES = "/api/userProfiles/"; - private static final String USERMANAGER_URL = "http://localhost:8080"; - - private final String PATH = "/api"; - @Spy @InjectMocks // NOSONAR private RootController controller; @@ -74,6 +67,8 @@ class RootControllerTest { private SystemStatusService systemStatusService; @Mock private UserRemoteService internalUserIdService; + @Mock + private UserManagerUrlProvider userManagerUrlProvider; private MockMvc mockMvc; @@ -83,9 +78,6 @@ class RootControllerTest { when(currentUserService.getUserId()).thenReturn(UserProfileTestFactory.ID); when(internalUserIdService.getUserId(any())).thenReturn(Optional.of(UserProfileTestFactory.ID)); - - ReflectionTestUtils.setField(controller, "userSearchTemplate", SEARCH_BY); - ReflectionTestUtils.setField(controller, "userManagerUrl", USERMANAGER_URL); } @DisplayName("Links for user") @@ -100,6 +92,7 @@ class RootControllerTest { void mockCurrentUserService() { doReturn(true).when(controller).hasVerwaltungRole(); when(systemStatusService.isSearchServerAvailable()).thenReturn(true); + when(userManagerUrlProvider.isConfiguredForSearchUserProfile()).thenReturn(false); } @Test @@ -126,11 +119,10 @@ class RootControllerTest { } @Test - void shouldHaveSearchUserLink() { + void shouldNotHaveSearchUserLinkIfNotConfigured() { var model = controller.getRootResource(); - assertThat(model.getLink(RootController.REL_SEARCH_USER)).isPresent().get().extracting(Link::getHref) - .isEqualTo(USERMANAGER_URL + SEARCH_BY); + assertThat(model.getLink(RootController.REL_SEARCH_USER)).isNotPresent(); } @Test @@ -157,6 +149,29 @@ class RootControllerTest { .isEqualTo("/api/downloadtoken"); } + @DisplayName("and userManager is configured") + @Nested + class TestAndUserManagerIsConfigured { + + private String userProfileSearchTemplate = "UserProfileSearchTemplate"; + + @BeforeEach + void mockCurrentUserService() { + when(userManagerUrlProvider.getUserProfileSearchTemplate()).thenReturn(userProfileSearchTemplate); + } + + @Test + void shouldHaveSearchUserLink() { + when(userManagerUrlProvider.isConfiguredForSearchUserProfile()).thenReturn(true); + + var model = controller.getRootResource(); + + assertThat(model.getLink(RootController.REL_SEARCH_USER)).isPresent().get().extracting(Link::getHref) + .isEqualTo(userProfileSearchTemplate); + + } + } + @DisplayName("search service not available") @Nested class TestWithoutSearchService { @@ -250,19 +265,27 @@ class RootControllerTest { @DisplayName("current user") @Nested class CurrentUser { + @DisplayName("when usermanager url is configured") @Nested class UsermanagerUrlConfigured { - @Test - void shouldHaveCurrentUserLink() { - when(controller.getUserProfilesUrl()).thenReturn(Optional.of(USERMANAGER_URL + API_USER_PROFILES_TEMLPATE)); + + private String userProfileTemplate = "UserProfileTemplate/%s"; + + @BeforeEach + void mock() { when(currentUserService.getUserId()).thenReturn(UserProfileTestFactory.ID); + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(true); + when(userManagerUrlProvider.getUserProfileTemplate()).thenReturn(userProfileTemplate); + } + + @Test + void shouldHaveCurrentUserLink() { var model = controller.getRootResource(); assertThat(model.getLink(RootController.REL_CURRENT_USER)).isPresent().get().extracting(Link::getHref) - .isEqualTo(Link.of(USERMANAGER_URL + API_USER_PROFILES + UserProfileTestFactory.ID, RootController.REL_CURRENT_USER) - .getHref()); + .isEqualTo("UserProfileTemplate/" + UserProfileTestFactory.ID.toString()); } } @@ -270,6 +293,11 @@ class RootControllerTest { @Nested class UsermanagerUrlNotConfigured { + @BeforeEach + void mock() { + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(false); + } + @Test void shouldNotHaveCurrentUserLink() { var model = controller.getRootResource(); @@ -285,13 +313,13 @@ class RootControllerTest { @BeforeEach void init() { doReturn(true).when(controller).hasVerwaltungRole(); - when(controller.getUserProfilesUrl()).thenReturn(Optional.of(USERMANAGER_URL + API_USER_PROFILES)); + when(internalUserIdService.getUserId(any())).thenReturn(Optional.empty()); + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(false); } @Test void shouldNotHaveMyVorgaengeLink() { - var model = controller.getRootResource(); assertThat(model.getLink(RootController.REL_MY_VORGAENGE)).isNotPresent(); @@ -327,6 +355,6 @@ class RootControllerTest { } private ResultActions callEndpoint() throws Exception { - return mockMvc.perform(get(PATH)).andExpect(status().isOk()); + return mockMvc.perform(get(RootController.PATH)).andExpect(status().isOk()); } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/ModelBuilderTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/ModelBuilderTest.java index 0ee19d5ac41b6d71db7092f5e7794de8ed367d20..97a15a5e6898d2c1d2358a058db56aadfc0f8392 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/ModelBuilderTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/ModelBuilderTest.java @@ -70,7 +70,7 @@ class ModelBuilderTest { void shouldHaveAddLinkByLinkedResource() { var model = ModelBuilder.fromEntity(entity).buildModel(); - assertThat(model.getLink(TestController.FILE_REL).get().getHref()).isEqualTo("/api/test/" + TestEntityTestFactory.FILE); + assertThat(model.getLink(TestController.FILE_REL).get().getHref()).isEqualTo(TestController.PATH + "/" + TestEntityTestFactory.FILE); } @Test @@ -81,6 +81,42 @@ class ModelBuilderTest { .isEqualTo(String.format(USER_MANAGER_URL + USER_MANAGER_PROFILE_TEMPLATE, TestEntityTestFactory.USER)); } } + + @DisplayName("if usermanager is not configured") + @Nested + class TestNotAddLinkByAnnotationIfNotConfigured { + + private UserProfileUrlProvider provider = new UserProfileUrlProvider(); + + @Mock + private ApplicationContext context; + @Mock + private Environment env; + + private TestEntity entity = TestEntityTestFactory.create(); + + @BeforeEach + void mockEnvironment() { + when(env.getProperty(UserProfileUrlProvider.URL_ROOT_KEY)).thenReturn(null); + when(context.getEnvironment()).thenReturn(env); + + provider.setApplicationContext(context); + } + + @Test + void shouldHaveAddLinkByLinkedResource() { + var model = ModelBuilder.fromEntity(entity).buildModel(); + + assertThat(model.getLink(TestController.FILE_REL).get().getHref()).isEqualTo(TestController.PATH + "/" + TestEntityTestFactory.FILE); + } + + @Test + void shouldNotHaveLinkAddByLinkedUserProfileAnnotation() { + var model = ModelBuilder.fromEntity(entity).buildModel(); + + assertThat(model.getLink(TestController.USER_REL)).isNotPresent(); + } + } } @Builder @@ -93,9 +129,11 @@ class TestEntity { private String user; } -@RequestMapping("/api/test") +@RequestMapping(TestController.PATH) class TestController { + static final String PATH = "/api/test"; + static final String USER_REL = "user"; static final String FILE_REL = "file"; diff --git a/goofy-server/src/test/java/de/itvsh/goofy/common/user/UserRemoteServiceTest.java b/goofy-server/src/test/java/de/itvsh/goofy/common/user/UserRemoteServiceTest.java index 11858b85105343747ee306bf2d2c1ecaf9afc15b..772b65b2351ab457ad77f86cd1a407ee39c3767a 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/common/user/UserRemoteServiceTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/common/user/UserRemoteServiceTest.java @@ -55,6 +55,8 @@ class UserRemoteServiceTest { private UserRemoteService service; @Mock private UserManagerProperties userManagerProperties; + @Mock + private UserManagerUrlProvider userManagerUrlProvider; @Mock private RestTemplate restTemplate; @@ -65,48 +67,78 @@ class UserRemoteServiceTest { private final String internalUrlTemplate = "DummyInternalUrlTemplate"; - @BeforeEach - void mock() { - when(userManagerProperties.getInternalUrlTemplate()).thenReturn(internalUrlTemplate); - } - - @DisplayName("on valid response") + @DisplayName("with configured usermanager") @Nested - class TestSuccess { + class TestWithConfiguredUserManager { @BeforeEach void mock() { - when(restTemplate.getForObject(anyString(), eq(String.class), anyString())).thenReturn(UserProfileTestFactory.ID.toString()); + when(userManagerProperties.getInternalUrlTemplate()).thenReturn(internalUrlTemplate); + when(userManagerUrlProvider.isConfiguredForInternalUserId()).thenReturn(true); } - @Test - void shouldReturnResponseAsUserId() { - var userId = service.getUserId(UserProfileTestFactory.ID); + @DisplayName("on valid response") + @Nested + class TestSuccess { + + @BeforeEach + void mock() { + when(restTemplate.getForObject(anyString(), eq(String.class), anyString())).thenReturn(UserProfileTestFactory.ID.toString()); + } + + @Test + void shouldReturnResponseAsUserId() { + var userId = service.getUserId(UserProfileTestFactory.ID); + + assertThat(userId).hasValue(UserProfileTestFactory.ID); + } + } + + @DisplayName("on error response") + @Nested + class TestErrorCases { - assertThat(userId).hasValue(UserProfileTestFactory.ID); + @Test + void shouldHandleEmptyValue() { + when(restTemplate.getForObject(anyString(), eq(String.class), anyString())).thenReturn(""); + + var res = service.getUserId(UserProfileTestFactory.ID); + + assertThat(res).isNotPresent(); + } + + @Test + void shouldHandleError() { + when(restTemplate.getForObject(anyString(), eq(String.class), anyString())).thenThrow(new RestClientException("Test error")); + + var res = service.getUserId(UserProfileTestFactory.ID); + + assertThat(res).isNotPresent(); + } } } - @DisplayName("on error response") + @DisplayName("with not configured usermanager") @Nested - class TestErrorCases { + class TestOnNotConfiguredUserManager { - @Test - void shouldHandleEmptyValue() { - when(restTemplate.getForObject(anyString(), eq(String.class), anyString())).thenReturn(""); + @BeforeEach + void mock() { + when(userManagerUrlProvider.isConfiguredForInternalUserId()).thenReturn(false); + } - var res = service.getUserId(UserProfileTestFactory.ID); + @Test + void shouldNotCallUserManagerProperties() { + service.getUserId(UserProfileTestFactory.ID); - assertThat(res).isNotPresent(); + verify(userManagerProperties, never()).getInternalUrlTemplate(); } @Test - void shouldHandleError() { - when(restTemplate.getForObject(anyString(), eq(String.class), anyString())).thenThrow(new RestClientException("Test error")); - - var res = service.getUserId(UserProfileTestFactory.ID); + void shouldReturnEmptyOptional() { + var user = service.getUserId(UserProfileTestFactory.ID); - assertThat(res).isNotPresent(); + assertThat(user).isNotPresent(); } } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/historie/HistorieModelAssemblerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/historie/HistorieModelAssemblerTest.java index 1523f4350bf6a955a7dba3c3877a994836135920..7f4c9f11f337d6a62c4edd1c2b24bb29f4128754 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/historie/HistorieModelAssemblerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/historie/HistorieModelAssemblerTest.java @@ -25,39 +25,37 @@ package de.itvsh.goofy.historie; import static de.itvsh.goofy.common.UserProfileUrlProviderTestFactory.*; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; import java.util.Map; -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.InjectMocks; +import org.mockito.Mock; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; -import org.springframework.test.util.ReflectionTestUtils; import de.itvsh.goofy.common.UserProfileUrlProvider; import de.itvsh.goofy.common.command.CommandTestFactory; import de.itvsh.goofy.common.user.UserId; +import de.itvsh.goofy.common.user.UserManagerUrlProvider; import de.itvsh.goofy.common.user.UserProfileTestFactory; class HistorieModelAssemblerTest { + private static final String CREATED_BY = "createdBy"; @InjectMocks private HistorieModelAssembler modelAssembler; + @Mock + private UserManagerUrlProvider userManagerUrlProvider; private final String COMMAND_SINGLE_PATH = "/api/histories/" + CommandTestFactory.ID; private UserProfileUrlProvider urlProvider = new UserProfileUrlProvider(); - @BeforeEach - void init() { - ReflectionTestUtils.setField(modelAssembler, "rootUrl", ROOT_URL); - ReflectionTestUtils.setField(modelAssembler, "profileTemplate", USER_PROFILES_API_PATH + "%s"); - } - @Test void shouldHaveSelfLink() { initUserProfileUrlProvider(urlProvider); @@ -70,26 +68,59 @@ class HistorieModelAssemblerTest { @DisplayName("AssignedTo Link") @Nested class TestAssignedToLink { - @Test - void shouldBePresentOnExistingValue() { - var model = modelAssembler.toModel(CommandTestFactory.createBuilder() - .body(Map.of(HistorieModelAssembler.ASSIGNED_TO_BODY_FIELD, UserProfileTestFactory.ID)).build()); + private final String userProfileTemplateDummy = "UserProfileTemplateDummy/%s"; - assertThat(model.getLink(HistorieModelAssembler.REL_ASSIGNED_TO)).isPresent().get().extracting(Link::getHref) - .isEqualTo(ROOT_URL + USER_PROFILES_API_PATH + UserProfileTestFactory.ID); + @Nested + class TesOnConfiguredUserManager { + + @Test + void shouldBePresentOnExistingValue() { + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(true); + when(userManagerUrlProvider.getUserProfileTemplate()).thenReturn(userProfileTemplateDummy); + + var model = modelAssembler.toModel(CommandTestFactory.createBuilder() + .body(Map.of(HistorieModelAssembler.ASSIGNED_TO_BODY_FIELD, UserProfileTestFactory.ID)).build()); + + assertThat(model.getLink(HistorieModelAssembler.REL_ASSIGNED_TO)).isPresent().get().extracting(Link::getHref) + .isEqualTo("UserProfileTemplateDummy/" + UserProfileTestFactory.ID); + } + + @Test + void shouldNotBePresentOnMissingValue() { + var model = modelAssembler.toModel(CommandTestFactory.create()); + + assertThat(model.getLink(HistorieModelAssembler.REL_ASSIGNED_TO)).isNotPresent(); + } } - @Test - void shouldNotBePresentOnMissingValue() { + @Nested + class TestOnNotConfiguredUserManager { - var model = modelAssembler.toModel(CommandTestFactory.create()); + @Test + void shouldBePresentOnExistingValue() { + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(false); + + var model = modelAssembler.toModel(CommandTestFactory.createBuilder() + .body(Map.of(HistorieModelAssembler.ASSIGNED_TO_BODY_FIELD, UserProfileTestFactory.ID)).build()); - assertThat(model.getLink(HistorieModelAssembler.REL_ASSIGNED_TO)).isNotPresent(); + assertThat(model.getLink(HistorieModelAssembler.REL_ASSIGNED_TO)).isNotPresent(); + } + + @Test + void shouldNotGetTemplateFromUserManagerUrlProvider() { + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(false); + + modelAssembler.toModel(CommandTestFactory.createBuilder() + .body(Map.of(HistorieModelAssembler.ASSIGNED_TO_BODY_FIELD, UserProfileTestFactory.ID)).build()); + + verify(userManagerUrlProvider, never()).getUserProfileTemplate(); + } } } @DisplayName("createdBy Link") + @Nested class TestCreatedByLink { @Test diff --git a/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailModelAssemblerTest.java b/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailModelAssemblerTest.java index c385612b9eff4ca1af497f96e77e43c75332ae25..1214f6a74d39fb64a904f51852fd8f9f3cd27951 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailModelAssemblerTest.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/postfach/PostfachMailModelAssemblerTest.java @@ -24,6 +24,7 @@ package de.itvsh.goofy.postfach; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; import java.util.List; import java.util.Optional; @@ -35,13 +36,14 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; +import org.mockito.Mock; import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; -import org.springframework.test.util.ReflectionTestUtils; import de.itvsh.goofy.common.user.UserId; +import de.itvsh.goofy.common.user.UserManagerUrlProvider; import de.itvsh.goofy.vorgang.VorgangHeaderTestFactory; import de.itvsh.goofy.vorgang.VorgangWithEingangTestFactory; @@ -52,11 +54,12 @@ class PostfachMailModelAssemblerTest { @InjectMocks private PostfachMailModelAssembler modelAssembler; + @Mock + private UserManagerUrlProvider userManagerUrlProvider; @BeforeEach - void init() { - ReflectionTestUtils.setField(modelAssembler, "rootUrl", ROOT_URL); - ReflectionTestUtils.setField(modelAssembler, "profileTemplate", USER_PROFILES_API_PATH + "%s"); + void mock() { + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(false); } @Nested @@ -142,31 +145,82 @@ class PostfachMailModelAssemblerTest { @DisplayName("created by link") @Nested class CreatedByLink { - @Test - void shouldBePresent() { - var link = modelAssembler.toModel(PostfachMailTestFactory.create()).getLink(PostfachMailModelAssembler.REL_CREATED_BY); - assertThat(link).isPresent().get().extracting(Link::getHref) - .isEqualTo(ROOT_URL + USER_PROFILES_API_PATH + PostfachMailTestFactory.CREATED_BY); - } + @Nested + class TestOnConfiguredUserManager { - @DisplayName("should not be present if the value of createdBy starts with 'system'") - @Test - void shouldNOTBePresentOnSystemUser() { - var link = modelAssembler - .toModel(PostfachMailTestFactory.createBuilder() - .createdBy(UserId.from(PostfachMailModelAssembler.SYSTEM_USER_IDENTIFIER + UUID.randomUUID().toString())).build()) - .getLink(PostfachMailModelAssembler.REL_CREATED_BY); + private final String userProfileTemplate = "UserProfileTemplateDummy/%s"; - assertThat(link).isNotPresent(); - } + @BeforeEach + void mock() { + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(true); + } - @Test - void shouldNotBePresentOnNull() { - var link = modelAssembler.toModel(PostfachMailTestFactory.createBuilder().createdBy(null).build()) - .getLink(PostfachMailModelAssembler.REL_CREATED_BY); + @Test + void shouldBePresent() { + when(userManagerUrlProvider.getUserProfileTemplate()).thenReturn(userProfileTemplate); - assertThat(link).isNotPresent(); + var link = modelAssembler.toModel(PostfachMailTestFactory.create()).getLink(PostfachMailModelAssembler.REL_CREATED_BY); + + assertThat(link).isPresent().get().extracting(Link::getHref) + .isEqualTo("UserProfileTemplateDummy/" + PostfachMailTestFactory.CREATED_BY); + } + + @DisplayName("should not be present if the value of createdBy starts with 'system'") + @Test + void shouldNOTBePresentOnSystemUser() { + var link = modelAssembler + .toModel(PostfachMailTestFactory.createBuilder() + .createdBy(UserId.from(PostfachMailModelAssembler.SYSTEM_USER_IDENTIFIER + UUID.randomUUID().toString())).build()) + .getLink(PostfachMailModelAssembler.REL_CREATED_BY); + + assertThat(link).isNotPresent(); + } + + @Test + void shouldNotBePresentOnNull() { + var link = modelAssembler.toModel(PostfachMailTestFactory.createBuilder().createdBy(null).build()) + .getLink(PostfachMailModelAssembler.REL_CREATED_BY); + + assertThat(link).isNotPresent(); + } + } + + @Nested + class TestOnNonConfiguredUserManager { + + @BeforeEach + void mock() { + when(userManagerUrlProvider.isConfiguredForUserProfile()).thenReturn(false); + } + + @Test + void shouldNOTBePresentOnNotConfiguredUserManager() { + var link = modelAssembler + .toModel(PostfachMailTestFactory.createBuilder() + .createdBy(UserId.from(PostfachMailModelAssembler.SYSTEM_USER_IDENTIFIER + UUID.randomUUID().toString())).build()) + .getLink(PostfachMailModelAssembler.REL_CREATED_BY); + + assertThat(link).isNotPresent(); + } + + @Test + void shouldNotCallUserManagerUrlProvider() { + modelAssembler + .toModel(PostfachMailTestFactory.createBuilder() + .createdBy(UserId.from(PostfachMailModelAssembler.SYSTEM_USER_IDENTIFIER + UUID.randomUUID().toString())).build()) + .getLink(PostfachMailModelAssembler.REL_CREATED_BY); + + verify(userManagerUrlProvider, never()).getUserProfileTemplate(); + } + + @Test + void shouldNotBePresentOnNull() { + var link = modelAssembler.toModel(PostfachMailTestFactory.createBuilder().createdBy(null).build()) + .getLink(PostfachMailModelAssembler.REL_CREATED_BY); + + assertThat(link).isNotPresent(); + } } } } diff --git a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/VorgangControllerITCase.java b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/VorgangControllerITCase.java index 6926d66e66a6704f1bff3b0b52877221c28d46bd..431053d8afa5f56322e4060c34ff1a798c47f527 100644 --- a/goofy-server/src/test/java/de/itvsh/goofy/vorgang/VorgangControllerITCase.java +++ b/goofy-server/src/test/java/de/itvsh/goofy/vorgang/VorgangControllerITCase.java @@ -143,7 +143,7 @@ class VorgangControllerITCase { void shouldBePresentIfAssigned() throws Exception { when(remoteService.findVorgangWithEingang(anyString())).thenReturn(VorgangWithEingangTestFactory.create()); - doRequest().andExpect(jsonPath("$._links.assignedTo.href").value("http://localhost:9092/api/userProfiles/" + UserProfileTestFactory.ID)); + doRequest().andExpect(jsonPath("$._links.assignedTo.href").value("https://localhost/api/userProfiles/" + UserProfileTestFactory.ID)); } @Test