From 329b53efb578dd41a6de31eafd5f228f3f10987c Mon Sep 17 00:00:00 2001 From: "Lott, Christopher (cl778h)" Date: Tue, 19 May 2020 17:27:57 -0400 Subject: [PATCH] Validate request bodies in controller methods Add @Validated annotation to force validation of request bodies sent via POST and PUT to controller methods. Revise tests to use JUnit construct that asserts an exception is thrown instead of a try-catch-assert(false) construct. Bump version to 2.0.3. Change-Id: Ifc1316e6f6cb0d1299e41252aa813aa04aa08d5b Signed-off-by: Lott, Christopher (cl778h) --- dashboard/app-mgr-client/pom.xml | 2 +- dashboard/e2-mgr-client/pom.xml | 2 +- dashboard/pom.xml | 2 +- dashboard/webapp-backend/pom.xml | 2 +- .../dashboard/controller/AdminController.java | 5 +-- .../dashboard/controller/AppManagerController.java | 15 +++++---- .../controller/CaasIngressController.java | 11 +++--- .../CustomResponseEntityExceptionHandler.java | 30 +++++++++++++---- .../dashboard/controller/E2ManagerController.java | 13 +++++--- .../exception/InvalidArgumentException.java | 33 ++++++++++++++++++ .../ric/portal/dashboard/AppStatsManagerTest.java | 39 ++++++++-------------- .../portal/dashboard/DashboardUserManagerTest.java | 14 +++----- .../config/AppManagerMockConfiguration.java | 4 +++ .../config/WebSecurityMockConfiguration.java | 3 +- .../dashboard/controller/AdminControllerTest.java | 7 ++-- .../controller/AppManagerControllerTest.java | 9 ++++- .../controller/E2ManagerControllerTest.java | 3 +- .../portal/dashboard/k8sapi/CaasIngressTest.java | 16 ++------- .../k8sapi/SimpleKubernetesClientTest.java | 16 +++------ .../ric/portal/dashboard/model/ModelTest.java | 11 +++--- .../dashboard/portalapi/PortalAuthManagerTest.java | 17 ++++------ dashboard/webapp-frontend/pom.xml | 2 +- docs/release-notes.rst | 6 +++- 23 files changed, 144 insertions(+), 118 deletions(-) create mode 100644 dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/exception/InvalidArgumentException.java diff --git a/dashboard/app-mgr-client/pom.xml b/dashboard/app-mgr-client/pom.xml index 90b1109d..80ce2a8e 100644 --- a/dashboard/app-mgr-client/pom.xml +++ b/dashboard/app-mgr-client/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.o-ran-sc.portal.ric-dashboard ric-dash-parent - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT org.o-ran-sc.ric-plt.appmgr.client diff --git a/dashboard/e2-mgr-client/pom.xml b/dashboard/e2-mgr-client/pom.xml index eeac2ef3..bcde4756 100644 --- a/dashboard/e2-mgr-client/pom.xml +++ b/dashboard/e2-mgr-client/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.o-ran-sc.portal.ric-dashboard ric-dash-parent - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT org.o-ran-sc.ric-plt.e2mgr.client diff --git a/dashboard/pom.xml b/dashboard/pom.xml index 0a67d4d3..c8d33d18 100644 --- a/dashboard/pom.xml +++ b/dashboard/pom.xml @@ -32,7 +32,7 @@ limitations under the License. ric-dash-parent RIC Dashboard Project pom - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT 11 diff --git a/dashboard/webapp-backend/pom.xml b/dashboard/webapp-backend/pom.xml index 96c58172..9c4a3172 100644 --- a/dashboard/webapp-backend/pom.xml +++ b/dashboard/webapp-backend/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.o-ran-sc.portal.ric-dashboard ric-dash-parent - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT ric-dash-be diff --git a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AdminController.java b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AdminController.java index 3369f156..9e492267 100644 --- a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AdminController.java +++ b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AdminController.java @@ -42,6 +42,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -139,7 +140,7 @@ public class AdminController { + STATAPPMETRIC_METHOD) @Secured({ DashboardConstants.ROLE_ADMIN }) public IDashboardResponse createStats(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, - @RequestBody StatsDetailsTransport statsSetupRequest) throws StatsManagerException, IOException { + @Validated @RequestBody StatsDetailsTransport statsSetupRequest) throws StatsManagerException, IOException { logger.debug("createStats with instance {} request {}", instanceKey, statsSetupRequest); return appStatsManager.createStats(instanceKey, statsSetupRequest); } @@ -149,7 +150,7 @@ public class AdminController { + STATAPPMETRIC_METHOD) @Secured({ DashboardConstants.ROLE_ADMIN }) public void updateStats(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, - @RequestBody StatsDetailsTransport statsSetupRequest) throws StatsManagerException, IOException { + @Validated @RequestBody StatsDetailsTransport statsSetupRequest) throws StatsManagerException, IOException { logger.debug("updateStats for instance {} request {}", instanceKey, statsSetupRequest); appStatsManager.updateStats(instanceKey, statsSetupRequest); } diff --git a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java index cd3d8a91..47e68686 100644 --- a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java +++ b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java @@ -44,6 +44,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.util.Assert; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -58,10 +59,9 @@ import io.swagger.annotations.ApiOperation; /** * Proxies calls from the front end to the App Manager API. * - * If a method throws RestClientResponseException, it is handled by - * {@link CustomResponseEntityExceptionHandler#handleProxyMethodException(Exception, org.springframework.web.context.request.WebRequest)} - * which returns status 502. All other exceptions are handled by Spring which - * returns status 500. + * If a method throws RestClientResponseException, it is handled by a method in + * {@link CustomResponseEntityExceptionHandler} which returns status 502. All + * other exceptions are handled by Spring which returns status 500. */ @Configuration @RestController @@ -138,7 +138,8 @@ public class AppManagerController { @PutMapping(CONFIG_METHOD_PATH) @Secured({ DashboardConstants.ROLE_ADMIN }) public ConfigValidationErrors modifyXappConfig( - @PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, @RequestBody XAppConfig xAppConfig) { + @PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, // + @Validated @RequestBody XAppConfig xAppConfig) { logger.debug("modifyXappConfig instance {} config {}", instanceKey, xAppConfig); return appManagerApiBuilder.getXappApi(instanceKey).modifyXappConfig(xAppConfig); } @@ -180,8 +181,8 @@ public class AppManagerController { @ApiOperation(value = "Deploy a xapp.", response = Xapp.class) @PostMapping(XAPPS_METHOD_PATH) @Secured({ DashboardConstants.ROLE_ADMIN }) - public Xapp deployXapp(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, - @RequestBody XappDescriptor appDescriptor) { + public Xapp deployXapp(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, // + @Validated @RequestBody XappDescriptor appDescriptor) { logger.debug("deployXapp instance {} descriptor {}", instanceKey, appDescriptor); return appManagerApiBuilder.getXappApi(instanceKey).deployXapp(appDescriptor); } diff --git a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CaasIngressController.java b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CaasIngressController.java index 455e1793..35ba2121 100644 --- a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CaasIngressController.java +++ b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CaasIngressController.java @@ -40,13 +40,12 @@ import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.ApiOperation; /** - * Proxies calls from the front end to a CAAS-Ingress API, which is a proxy for - * a Kubernetes API. + * Proxies calls from the front end to a CAAS-Ingress API, which in turn is a + * proxy for a Kubernetes API. * - * If a method throws RestClientResponseException, it is handled by - * {@link CustomResponseEntityExceptionHandler#handleProxyMethodException(Exception, org.springframework.web.context.request.WebRequest)} - * which returns status 502. All other exceptions are handled by Spring which - * returns status 500. + * If a method throws RestClientResponseException, it is handled by a method in + * {@link CustomResponseEntityExceptionHandler} which returns status 502. All + * other exceptions are handled by Spring which returns status 500. */ @Configuration @RestController diff --git a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CustomResponseEntityExceptionHandler.java b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CustomResponseEntityExceptionHandler.java index a328e477..f4a873d8 100644 --- a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CustomResponseEntityExceptionHandler.java +++ b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CustomResponseEntityExceptionHandler.java @@ -21,6 +21,7 @@ package org.oransc.ric.portal.dashboard.controller; import java.lang.invoke.MethodHandles; +import org.oransc.ric.portal.dashboard.exception.InvalidArgumentException; import org.oransc.ric.portal.dashboard.exception.StatsManagerException; import org.oransc.ric.portal.dashboard.exception.UnknownInstanceException; import org.slf4j.Logger; @@ -81,10 +82,10 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio * @return A response entity with status code 502 and an unstructured message. */ @ExceptionHandler({ RestClientResponseException.class }) - public final ResponseEntity handleProxyMethodException(Exception ex, WebRequest request) { + public final ResponseEntity handleRestClientResponse(Exception ex, WebRequest request) { // Capture the full stack trace in the log. if (log.isErrorEnabled()) - log.error("handleProxyMethodException: request " + request.getDescription(false), ex); + log.error("handleRestClientResponse: request " + request.getDescription(false), ex); if (ex instanceof HttpStatusCodeException) { HttpStatusCodeException hsce = (HttpStatusCodeException) ex; return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body(hsce.getResponseBodyAsString()); @@ -104,9 +105,24 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio * @return A response entity with status code 400 and an unstructured message. */ @ExceptionHandler({ UnknownInstanceException.class }) - public final ResponseEntity handleUnknownInstanceException(Exception ex, WebRequest request) { - log.warn("handleUnknownInstanceException: request {}, exception {}", request.getDescription(false), - ex.toString()); + public final ResponseEntity handleUnknownInstance(Exception ex, WebRequest request) { + log.warn("handleUnknownInstance: request {}, exception {}", request.getDescription(false), ex.toString()); + return ResponseEntity.badRequest().body(getShortExceptionMessage(ex)); + } + + /** + * Logs the error and generates a response when a REST controller method takes + * an InvalidArgumentException, an invalid JSON was sent. + * + * @param ex + * The exception + * @param request + * The original request + * @return A response entity with status code 400 and an unstructured message. + */ + @ExceptionHandler({ InvalidArgumentException.class }) + public final ResponseEntity handleInvalidArgument(Exception ex, WebRequest request) { + log.warn("handleInvalidArgument: request {}, exception {}", request.getDescription(false), ex.toString()); return ResponseEntity.badRequest().body(getShortExceptionMessage(ex)); } @@ -121,8 +137,8 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio * @return A response entity with status code 400 and an unstructured message. */ @ExceptionHandler({ StatsManagerException.class }) - public final ResponseEntity handleStatsManagerException(Exception ex, WebRequest request) { - log.warn("handleStatsManagerException: request {}, exception {}", request.getDescription(false), ex.toString()); + public final ResponseEntity handleStatsManager(Exception ex, WebRequest request) { + log.warn("handleStatsManager: request {}, exception {}", request.getDescription(false), ex.toString()); return ResponseEntity.badRequest().body(getShortExceptionMessage(ex)); } diff --git a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/E2ManagerController.java b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/E2ManagerController.java index dabb6b47..06cbc6b7 100644 --- a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/E2ManagerController.java +++ b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/E2ManagerController.java @@ -23,6 +23,8 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; +import javax.validation.Valid; + import org.oransc.ric.portal.dashboard.DashboardApplication; import org.oransc.ric.portal.dashboard.DashboardConstants; import org.oransc.ric.portal.dashboard.config.E2ManagerApiBuilder; @@ -41,6 +43,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; import org.springframework.util.Assert; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PutMapping; @@ -54,10 +57,9 @@ import io.swagger.annotations.ApiOperation; /** * Proxies calls from the front end to the E2 Manager API. * - * If a method throws RestClientResponseException, it is handled by - * {@link CustomResponseEntityExceptionHandler#handleProxyMethodException(Exception, org.springframework.web.context.request.WebRequest)} - * which returns status 502. All other exceptions are handled by Spring which - * returns status 500. + * If a method throws RestClientResponseException, it is handled by a method in + * {@link CustomResponseEntityExceptionHandler} which returns status 502. All + * other exceptions are handled by Spring which returns status 500. */ @Configuration @RestController @@ -168,7 +170,8 @@ public class E2ManagerController { + "/{" + PP_RANNAME + "}") @Secured({ DashboardConstants.ROLE_ADMIN }) public ResponseEntity updateGnb(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey, - @PathVariable(PP_RANNAME) String ranName, @RequestBody UpdateGnbRequest updateGnbRequest) { + @PathVariable(PP_RANNAME) String ranName, // + @Valid @Validated @RequestBody UpdateGnbRequest updateGnbRequest) { logger.debug("updateGnb instance {} ran {}", instanceKey, ranName); NodebApi api = e2ManagerApiBuilder.getNodebApi(instanceKey); api.updateGnb(updateGnbRequest, ranName); diff --git a/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/exception/InvalidArgumentException.java b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/exception/InvalidArgumentException.java new file mode 100644 index 00000000..7f1f4800 --- /dev/null +++ b/dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/exception/InvalidArgumentException.java @@ -0,0 +1,33 @@ +/*- + * ========================LICENSE_START================================= + * O-RAN-SC + * %% + * Copyright (C) 2019 AT&T Intellectual Property + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================LICENSE_END=================================== + */ +package org.oransc.ric.portal.dashboard.exception; + +public class InvalidArgumentException extends IllegalArgumentException { + + private static final long serialVersionUID = 6897065423512216018L; + + public InvalidArgumentException() { + super(); + } + + public InvalidArgumentException(String s) { + super(s); + } +} diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/AppStatsManagerTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/AppStatsManagerTest.java index 5aaace21..67a82c0a 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/AppStatsManagerTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/AppStatsManagerTest.java @@ -23,6 +23,7 @@ import java.lang.invoke.MethodHandles; import java.util.List; import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.oransc.ric.portal.dashboard.config.RICInstanceMockConfiguration; import org.oransc.ric.portal.dashboard.exception.StatsManagerException; @@ -40,12 +41,9 @@ public class AppStatsManagerTest { @Test public void testStatsMgr() throws Exception { new AppStatsManager("file.json"); - try { + Assertions.assertThrows(IllegalArgumentException.class, () -> { new AppStatsManager(null); - throw new Exception("Unexpected success"); - } catch (IllegalArgumentException ex) { - logger.info("caught expected exception: {}", ex.toString()); - } + }); AppStatsManager mgr = new AppStatsManager(true); AppStats as1 = mgr.createStats(RICInstanceMockConfiguration.INSTANCE_KEY_1, new StatsDetailsTransport(-1, "app1 name", "http://app1")); @@ -57,16 +55,13 @@ public class AppStatsManagerTest { Assert.assertFalse(all.isEmpty()); List byInstance = mgr.getStatsByInstance(RICInstanceMockConfiguration.INSTANCE_KEY_1); Assert.assertFalse(byInstance.isEmpty()); - mgr = new AppStatsManager(false); - AppStats as3 = mgr.createStats(RICInstanceMockConfiguration.INSTANCE_KEY_1, + final AppStatsManager mgr2 = new AppStatsManager(false); + AppStats as3 = mgr2.createStats(RICInstanceMockConfiguration.INSTANCE_KEY_1, new StatsDetailsTransport(-1, "app3 name", "http://app3")); Assert.assertNotEquals(as2.getStatsDetails().getAppId(), as3.getStatsDetails().getAppId()); - try { - mgr.createStats(as3.getInstanceKey(), as3.getStatsDetails()); - throw new Exception("Unexpected success"); - } catch (StatsManagerException ex) { - logger.info("caught expected exception: {}", ex.toString()); - } + Assertions.assertThrows(StatsManagerException.class, () -> { + mgr2.createStats(as3.getInstanceKey(), as3.getStatsDetails()); + }); AppStats as = mgr.getStatsById(as1.getInstanceKey(), as1.getStatsDetails().getAppId()); Assert.assertEquals(as1, as); AppStats notFound = mgr.getStatsById("bogus", 12345); @@ -74,18 +69,12 @@ public class AppStatsManagerTest { as1.getStatsDetails().setMetricUrl("http://other"); mgr.updateStats(as1.getInstanceKey(), as1.getStatsDetails()); mgr.deleteStats(as1.getInstanceKey(), as1.getStatsDetails().getAppId()); - try { - mgr.updateStats("bogus", as1.getStatsDetails()); - throw new Exception("Unexpected success"); - } catch (StatsManagerException ex) { - logger.info("caught expected exception: {}", ex.toString()); - } - try { - mgr.deleteStats("bogus", 999); - throw new Exception("Unexpected success"); - } catch (StatsManagerException ex) { - logger.info("caught expected exception: {}", ex.toString()); - } + Assertions.assertThrows(StatsManagerException.class, () -> { + mgr2.updateStats("bogus", as1.getStatsDetails()); + }); + Assertions.assertThrows(StatsManagerException.class, () -> { + mgr2.deleteStats("bogus", 999); + }); } } diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/DashboardUserManagerTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/DashboardUserManagerTest.java index a1811599..68887740 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/DashboardUserManagerTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/DashboardUserManagerTest.java @@ -24,6 +24,7 @@ import java.util.HashSet; import java.util.Set; import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.onap.portalsdk.core.onboarding.exception.PortalAPIException; import org.onap.portalsdk.core.restful.domain.EcompRole; @@ -59,12 +60,9 @@ public class DashboardUserManagerTest { EcompUser user = createEcompUser(loginId); dum.createUser(user); logger.info("Created user {}", user); - try { + Assertions.assertThrows(PortalAPIException.class, () -> { dum.createUser(user); - throw new Exception("Unexpected success"); - } catch (PortalAPIException ex) { - logger.info("caught expected exception: {}", ex.toString()); - } + }); Assert.assertFalse(dum.getUsers().isEmpty()); EcompUser fetched = dum.getUser(loginId); Assert.assertEquals(fetched, user); @@ -73,11 +71,9 @@ public class DashboardUserManagerTest { EcompUser missing = dum.getUser("foo"); Assert.assertNull(missing); EcompUser unk = createEcompUser("unknown"); - try { + Assertions.assertThrows(PortalAPIException.class, () -> { dum.updateUser("unk", unk); - } catch (PortalAPIException ex) { - logger.info("caught expected exception: {}", ex.toString()); - } + }); } } diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java index 27e59ad6..65f1850d 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.when; import java.lang.invoke.MethodHandles; +import org.oransc.ric.portal.dashboard.exception.InvalidArgumentException; import org.oransc.ric.portal.dashboard.model.RicRegionList; import org.oransc.ricplt.appmgr.client.api.HealthApi; import org.oransc.ricplt.appmgr.client.api.XappApi; @@ -144,6 +145,9 @@ public class AppManagerMockConfiguration { logger.debug("deployXapp of {} sleeping {}", inv.getArgument(0), delayMs); Thread.sleep(delayMs); } + XappDescriptor descr = inv.getArgument(0); + if (descr == null || descr.getXappName() == null) + throw new InvalidArgumentException("Name is required"); return deployedXapps.get(0); }).when(mockApi).deployXapp(any(XappDescriptor.class)); doAnswer(inv -> { diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/WebSecurityMockConfiguration.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/WebSecurityMockConfiguration.java index c90c3d61..afa97117 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/WebSecurityMockConfiguration.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/WebSecurityMockConfiguration.java @@ -98,8 +98,7 @@ public class WebSecurityMockConfiguration extends WebSecurityConfigurerAdapter { @Bean public PortalAuthManager portalAuthManagerBean() throws Exception { logger.debug("portalAuthManagerBean: app {}", appName); - return new PortalAuthManager(appName, portalApiUsername, portalApiPassword, - decryptor, userCookie); + return new PortalAuthManager(appName, portalApiUsername, portalApiPassword, decryptor, userCookie); } } diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AdminControllerTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AdminControllerTest.java index 37ab4849..f3f9fad3 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AdminControllerTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AdminControllerTest.java @@ -138,12 +138,9 @@ public class AdminControllerTest extends AbstractControllerTest { statsDetails.setMetricUrl("https://www.example2-next.com"); AppStats stNext = testRestTemplateAdminRole().postForObject(uri, statsDetails, AppStats.class); Assertions.assertTrue(st.getStatsDetails().getAppId() < stNext.getStatsDetails().getAppId()); - try { + Assertions.assertThrows(RestClientException.class, () -> { testRestTemplateAdminRole().postForObject(uri, statsDetails, AppStats.class); - Assert.assertTrue(false); - } catch (RestClientException ex) { - logger.info("Caught exception on create as expected: {}", ex.toString()); - } + }); } @Order(3) diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AppManagerControllerTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AppManagerControllerTest.java index 779feaf5..0132c197 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AppManagerControllerTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AppManagerControllerTest.java @@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestClientException; public class AppManagerControllerTest extends AbstractControllerTest { @@ -102,9 +103,15 @@ public class AppManagerControllerTest extends AbstractControllerTest { URI uri = buildUri(null, AppManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY, RICInstanceMockConfiguration.INSTANCE_KEY_1, AppManagerController.XAPPS_METHOD); logger.info("Invoking {}", uri); - XappDescriptor descr = new XappDescriptor(); + XappDescriptor descr = new XappDescriptor().xappName("app"); Xapp app = testRestTemplateAdminRole().postForObject(uri, descr, Xapp.class); + Assertions.assertNotNull(app); Assertions.assertFalse(app.getName().isEmpty()); + + // An invalid request must be rejected + Assertions.assertThrows(RestClientException.class, () -> { + testRestTemplateAdminRole().postForObject(uri, new XappDescriptor(), Xapp.class); + }); } @Test diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/E2ManagerControllerTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/E2ManagerControllerTest.java index 64dc4a7b..328a5ad5 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/E2ManagerControllerTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/E2ManagerControllerTest.java @@ -55,7 +55,8 @@ public class E2ManagerControllerTest extends AbstractControllerTest { logger.info("Invoking {}", uri); UpdateGnbRequest update = new UpdateGnbRequest(); HttpEntity entity = new HttpEntity<>(update); - ResponseEntity voidResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, entity, Void.class); + ResponseEntity voidResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, entity, + Void.class); Assertions.assertTrue(voidResponse.getStatusCode().is2xxSuccessful()); } diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/CaasIngressTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/CaasIngressTest.java index f28494d2..cc1a7e86 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/CaasIngressTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/CaasIngressTest.java @@ -19,32 +19,22 @@ */ package org.oransc.ric.portal.dashboard.k8sapi; -import java.lang.invoke.MethodHandles; - -import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.oransc.ric.portal.dashboard.util.HttpsURLConnectionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.client.RestTemplate; public class CaasIngressTest { - private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - @Test public void coverHttpsUtils() throws Exception { HttpsURLConnectionUtils.turnOffSslChecking(); // Get IP address from REC deployment team for testing final String podsUrl = "https://localhost:16443/api/v1/namespaces/ricaux/pods"; RestTemplate rt = new RestTemplate(); - try { + Assertions.assertThrows(Exception.class, () -> { rt.getForEntity(podsUrl, String.class); - Assert.assertTrue(false); - } catch (Exception ex) { - Assert.assertNotNull(ex); - logger.warn("Failed as expected"); - } + }); HttpsURLConnectionUtils.turnOnSslChecking(); } diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/SimpleKubernetesClientTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/SimpleKubernetesClientTest.java index dadd1b26..37f2148b 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/SimpleKubernetesClientTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/SimpleKubernetesClientTest.java @@ -19,25 +19,17 @@ */ package org.oransc.ric.portal.dashboard.k8sapi; -import java.lang.invoke.MethodHandles; - -import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class SimpleKubernetesClientTest { - private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @Test public void simpleK8sClientTest() { SimpleKubernetesClient client = new SimpleKubernetesClient("http://foo.bar"); - try { - String json = client.listPods("namespace"); - Assert.assertNotNull(json); - } catch (RuntimeException ex) { - logger.warn("Failed as expected"); - } + Assertions.assertThrows(RuntimeException.class, () -> { + client.listPods("namespace"); + }); } } diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/model/ModelTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/model/ModelTest.java index 78458d01..067bdcb7 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/model/ModelTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/model/ModelTest.java @@ -24,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.onap.portalsdk.core.restful.domain.EcompUser; import org.oransc.ric.portal.dashboard.DashboardUserManagerTest; @@ -192,16 +193,14 @@ public class ModelTest extends AbstractModelTest { @Test public void testRicRegionList() { - RicRegionList m = new RicRegionList(); + new RicRegionList(); List list = new ArrayList<>(); - m = new RicRegionList(list); + final RicRegionList m = new RicRegionList(list); Assert.assertEquals(list, m.getRegions()); Assert.assertNotNull(m.getSimpleInstances()); - try { + Assertions.assertThrows(UnknownInstanceException.class, () -> { m.getInstance(s1); - } catch (UnknownInstanceException ex) { - logger.info("failed as expected: {}", ex.toString()); - } + }); logger.info(m.toString()); } diff --git a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthManagerTest.java b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthManagerTest.java index a2747e87..028921b4 100644 --- a/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthManagerTest.java +++ b/dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthManagerTest.java @@ -27,6 +27,7 @@ import javax.servlet.ServletException; import javax.servlet.http.Cookie; import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.onap.portalsdk.core.onboarding.util.PortalApiConstants; @@ -71,22 +72,16 @@ public class PortalAuthManagerTest { Assert.assertNull(s); DashboardUserManager dum = new DashboardUserManager(true); - PortalAuthenticationFilter filter = new PortalAuthenticationFilter(false, m, dum); + final PortalAuthenticationFilter filter = new PortalAuthenticationFilter(false, m, dum); filter.init(null); filter.destroy(); MockHttpServletResponse response = new MockHttpServletResponse(); - try { + Assertions.assertThrows(NullPointerException.class, () -> { filter.doFilter(request, response, null); - } catch (NullPointerException ex) { - logger.debug("chain is null"); - } + }); - filter = new PortalAuthenticationFilter(true, m, dum); - try { - filter.doFilter(request, response, null); - } catch (NullPointerException ex) { - logger.debug("chain is null"); - } + PortalAuthenticationFilter filter2 = new PortalAuthenticationFilter(true, m, dum); + filter2.doFilter(request, response, null); } } \ No newline at end of file diff --git a/dashboard/webapp-frontend/pom.xml b/dashboard/webapp-frontend/pom.xml index 2ba2a1c4..3721c2eb 100644 --- a/dashboard/webapp-frontend/pom.xml +++ b/dashboard/webapp-frontend/pom.xml @@ -25,7 +25,7 @@ limitations under the License. org.o-ran-sc.portal.ric-dashboard ric-dash-parent - 2.0.2-SNAPSHOT + 2.0.3-SNAPSHOT ric-dash-fe diff --git a/docs/release-notes.rst b/docs/release-notes.rst index 147795a3..16ffa1fd 100644 --- a/docs/release-notes.rst +++ b/docs/release-notes.rst @@ -5,9 +5,13 @@ RIC Dashboard Release Notes =========================== +Version 2.0.3, 19 May 2020 +-------------------------- +* Validate request bodies in backend REST controller methods + Version 2.0.2, 18 May 2020 -------------------------- -* Repair App Manager data models in webapp frontend +* Repair App Manager data models in webapp frontend (`OAM-103 `_) Version 2.0.1, 30 Apr 2020 -------------------------- -- 2.16.6