From 50e6d139fba6456b2fd2c2aac04ef83e4fe72c59 Mon Sep 17 00:00:00 2001 From: Gaurav Mishra Date: Mon, 2 Dec 2024 16:48:50 +0530 Subject: [PATCH] test(config): add test docs for /config actuator Signed-off-by: Gaurav Mishra --- .../src/docs/asciidoc/config.adoc | 32 ++++++++++ .../resourceserver/Sw360ResourceServer.java | 18 ++++++ .../security/ResourceServerConfiguration.java | 3 +- .../src/main/resources/application.yml | 3 +- .../actuator/SW360ConfigActuatorTest.java | 64 +++++++++++++++++++ ...Sw360AuthorizationServerConfiguration.java | 1 + .../restdocs/ConfigSpecTest.java | 58 +++++++++++++++++ .../src/test/resources/application.yml | 3 +- 8 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 rest/resource-server/src/docs/asciidoc/config.adoc create mode 100644 rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/actuator/SW360ConfigActuatorTest.java create mode 100644 rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ConfigSpecTest.java diff --git a/rest/resource-server/src/docs/asciidoc/config.adoc b/rest/resource-server/src/docs/asciidoc/config.adoc new file mode 100644 index 0000000000..ba872a8198 --- /dev/null +++ b/rest/resource-server/src/docs/asciidoc/config.adoc @@ -0,0 +1,32 @@ +// +// Copyright Siemens AG, 2024. Part of the SW360 Portal Project. +// +// This program and the accompanying materials are made +// available under the terms of the Eclipse Public License 2.0 +// which is available at https://www.eclipse.org/legal/epl-2.0/ +// +// SPDX-License-Identifier: EPL-2.0 +// +[[resources-config]] +=== Config + +The config resource is used to give information from the `sw360.properties` file. +The configurations exposed are useful for the frontend UI. The backend only configs are not exposed. + +[[resources-config-get]] +==== Getting config + +A `GET` request will get the service's configurations. + +===== Example request +include::{snippets}/should_document_get_config/curl-request.adoc[] + +The response structure is the config object of the config actuator. + +===== Response structure +include::{snippets}/should_document_get_config/response-fields.adoc[] + +===== Example response +include::{snippets}/should_document_get_config/http-response.adoc[] + +The response structure is not complete as it will grow overtime. But it is a key-value pair of strings. diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/Sw360ResourceServer.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/Sw360ResourceServer.java index 715e72aacf..21f67bd863 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/Sw360ResourceServer.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/Sw360ResourceServer.java @@ -174,6 +174,24 @@ public OpenAPI customOpenAPI() { .schema(new Schema()) )) )) + )) + .path("/config", new PathItem().get( + new Operation().tags(Collections.singletonList("Health")) + .summary("Configuration properties").operationId("config") + .responses(new ApiResponses().addApiResponse("200", + new ApiResponse().description("OK") + .content(new Content() + .addMediaType("application/json", new MediaType() + .example(""" + { + "property.1": "value1", + "property.2": "false", + "property.3": "value3,value4" + } + """) + .schema(new Schema>()) + )) + )) )); } } diff --git a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/security/ResourceServerConfiguration.java b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/security/ResourceServerConfiguration.java index b9ac930ad0..7b7433cf20 100644 --- a/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/security/ResourceServerConfiguration.java +++ b/rest/resource-server/src/main/java/org/eclipse/sw360/rest/resourceserver/security/ResourceServerConfiguration.java @@ -62,7 +62,7 @@ public class ResourceServerConfiguration { public WebSecurityCustomizer webSecurityCustomizer() { return (web) -> web.ignoring().requestMatchers("/", "/*/*.html", "/*/*.css", "/*/*.js", "/*.js", "/*.json", "/*/*.json", "/*/*.png", "/*/*.gif", "/*/*.ico", "/*/*.woff/*", "/*/*.ttf", "/*/*.html", "/*/*/*.html", - "/*/*.yaml", "/v3/api-docs/**", "/api/health", "/api/info"); + "/*/*.yaml", "/v3/api-docs/**", "/api/health", "/api/info", "/api/config"); } @Bean @@ -84,6 +84,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti return http.addFilterBefore(filter, BasicAuthenticationFilter.class).authorizeHttpRequests(auth -> { auth.requestMatchers(HttpMethod.GET, "/api/health").permitAll(); auth.requestMatchers(HttpMethod.GET, "/api/info").hasAuthority("WRITE"); + auth.requestMatchers(HttpMethod.GET, "/api/config").permitAll(); auth.requestMatchers(HttpMethod.GET, "/api").permitAll(); auth.requestMatchers(HttpMethod.GET, "/api/reports/download").permitAll(); auth.requestMatchers(HttpMethod.GET, "/api/**").hasAuthority("READ"); diff --git a/rest/resource-server/src/main/resources/application.yml b/rest/resource-server/src/main/resources/application.yml index 02d3c90f62..8ebfb080db 100644 --- a/rest/resource-server/src/main/resources/application.yml +++ b/rest/resource-server/src/main/resources/application.yml @@ -19,10 +19,11 @@ management: web: base-path: / exposure: - include: health,info + include: health,info,config path-mapping: health: /api/health info: /api/info + config: /api/config endpoint: health: show-details: always diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/actuator/SW360ConfigActuatorTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/actuator/SW360ConfigActuatorTest.java new file mode 100644 index 0000000000..1fbb952b52 --- /dev/null +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/actuator/SW360ConfigActuatorTest.java @@ -0,0 +1,64 @@ +/* + * Copyright Siemens AG, 2024. Part of the SW360 Portal Project. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.rest.resourceserver.actuator; + +import org.eclipse.sw360.rest.resourceserver.Sw360ResourceServer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Map; + +import static org.assertj.core.api.BDDAssertions.then; + +/* @DirtiesContext is necessary because the context needs to be reloaded inbetween the tests + otherwise the responses of previous tests are taken. NoOpCacheManager through @AutoConfigureCache + was not enough to avoid this bug. + */ +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +@RunWith(SpringRunner.class) +@SpringBootTest(classes = Sw360ResourceServer.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class SW360ConfigActuatorTest { + + @LocalServerPort + private int port; + + @SpyBean + private SW360ConfigActuator restConfigActuatorMock; + + @Autowired + private TestRestTemplate testRestTemplate; + + /** + * Makes a request to localhost with the default server port and returns + * the response as a response entity with type Map + * @param endpoint endpoint that will be called + * @return response of request + */ + private ResponseEntity getMapResponseEntityForHealthEndpointRequest(String endpoint) { + return this.testRestTemplate.getForEntity( + "http://localhost:" + this.port + Sw360ResourceServer.REST_BASE_PATH + endpoint, Map.class); + } + + @Test + public void config_should_return_200() { + ResponseEntity entity = getMapResponseEntityForHealthEndpointRequest("/config"); + + then(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + } +} diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/configuration/security/Sw360AuthorizationServerConfiguration.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/configuration/security/Sw360AuthorizationServerConfiguration.java index 21b51000f7..3dd3d7d355 100644 --- a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/configuration/security/Sw360AuthorizationServerConfiguration.java +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/configuration/security/Sw360AuthorizationServerConfiguration.java @@ -42,6 +42,7 @@ public SecurityFilterChain appSecurtiy(HttpSecurity httpSecurity) throws Excepti authz -> authz .requestMatchers(HttpMethod.GET, "/api/health").permitAll() .requestMatchers(HttpMethod.GET, "/api/info").permitAll() + .requestMatchers(HttpMethod.GET, "/api/config").permitAll() .anyRequest().authenticated() ).httpBasic(Customizer.withDefaults()).formLogin(Customizer.withDefaults()) .exceptionHandling(x -> x.authenticationEntryPoint(saep)); diff --git a/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ConfigSpecTest.java b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ConfigSpecTest.java new file mode 100644 index 0000000000..d59f814e2c --- /dev/null +++ b/rest/resource-server/src/test/java/org/eclipse/sw360/rest/resourceserver/restdocs/ConfigSpecTest.java @@ -0,0 +1,58 @@ +/* + * Copyright Siemens AG, 2024. Part of the SW360 Portal Project. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.eclipse.sw360.rest.resourceserver.restdocs; + +import org.eclipse.sw360.rest.resourceserver.actuator.SW360ConfigActuator; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@RunWith(SpringJUnit4ClassRunner.class) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +public class ConfigSpecTest extends TestRestDocsSpecBase{ + + @MockBean + private SW360ConfigActuator restConfigActuatorMock; + + @Test + public void should_document_get_config() throws Exception { + Map properties = new ConcurrentHashMap<>(); + properties.put("admin.private.project.access.enabled", "true"); + properties.put("clearing.teams", "org1,org2,org3"); + properties.put("rest.apitoken.read.validity.days", "90"); + properties.put("rest.write.access.usergroup", "ADMIN"); + + given(this.restConfigActuatorMock.config()).willReturn(properties); + + mockMvc.perform(get("/api/config") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andDo(this.documentationHandler.document( + responseFields( + fieldWithPath("admin.private.project.access.enabled").description("Sample boolean property."), + fieldWithPath("clearing.teams").description("Sample set property (separated by comma)."), + fieldWithPath("rest.apitoken.read.validity.days").description("Sample integer property."), + fieldWithPath("rest.write.access.usergroup").description("Sample string property.") + ) + )); + } +} diff --git a/rest/resource-server/src/test/resources/application.yml b/rest/resource-server/src/test/resources/application.yml index 3db9ecabe9..4dd86e03c4 100644 --- a/rest/resource-server/src/test/resources/application.yml +++ b/rest/resource-server/src/test/resources/application.yml @@ -10,10 +10,11 @@ management: web: base-path: / exposure: - include: health,info + include: health,info,config path-mapping: health: /api/health info: /api/info + config: /api/config endpoint: health: show-details: always