Validate request bodies in controller methods 61/3761/4
authorLott, Christopher (cl778h) <cl778h@att.com>
Tue, 19 May 2020 21:27:57 +0000 (17:27 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Wed, 20 May 2020 13:53:19 +0000 (09:53 -0400)
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) <cl778h@att.com>
23 files changed:
dashboard/app-mgr-client/pom.xml
dashboard/e2-mgr-client/pom.xml
dashboard/pom.xml
dashboard/webapp-backend/pom.xml
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AdminController.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AppManagerController.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CaasIngressController.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CustomResponseEntityExceptionHandler.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/E2ManagerController.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/exception/InvalidArgumentException.java [new file with mode: 0644]
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/AppStatsManagerTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/DashboardUserManagerTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/WebSecurityMockConfiguration.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AdminControllerTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/AppManagerControllerTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/controller/E2ManagerControllerTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/CaasIngressTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/k8sapi/SimpleKubernetesClientTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/model/ModelTest.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/portalapi/PortalAuthManagerTest.java
dashboard/webapp-frontend/pom.xml
docs/release-notes.rst

index 90b1109..80ce2a8 100644 (file)
@@ -25,7 +25,7 @@ limitations under the License.
        <parent>
                <groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
                <artifactId>ric-dash-parent</artifactId>
-               <version>2.0.2-SNAPSHOT</version>
+               <version>2.0.3-SNAPSHOT</version>
        </parent>
        <!-- This groupId will NOT allow deployment in LF -->
        <groupId>org.o-ran-sc.ric-plt.appmgr.client</groupId>
index eeac2ef..bcde475 100644 (file)
@@ -25,7 +25,7 @@ limitations under the License.
        <parent>
                <groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
                <artifactId>ric-dash-parent</artifactId>
-               <version>2.0.2-SNAPSHOT</version>
+               <version>2.0.3-SNAPSHOT</version>
        </parent>
        <!-- This groupId will NOT allow deployment in LF -->
        <groupId>org.o-ran-sc.ric-plt.e2mgr.client</groupId>
index 0a67d4d..c8d33d1 100644 (file)
@@ -32,7 +32,7 @@ limitations under the License.
        <artifactId>ric-dash-parent</artifactId>
        <name>RIC Dashboard Project</name>
        <packaging>pom</packaging>
-       <version>2.0.2-SNAPSHOT</version>
+       <version>2.0.3-SNAPSHOT</version>
        <properties>
                <java.version>11</java.version>
                <!-- Properties for the license-maven-plugin in child POMs -->
index 96c5817..9c4a317 100644 (file)
@@ -25,7 +25,7 @@ limitations under the License.
        <parent>
                <groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
                <artifactId>ric-dash-parent</artifactId>
-               <version>2.0.2-SNAPSHOT</version>
+               <version>2.0.3-SNAPSHOT</version>
        </parent>
        <!-- reuse parent groupId -->
        <artifactId>ric-dash-be</artifactId>
index 3369f15..9e49226 100644 (file)
@@ -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);
        }
index cd3d8a9..47e6868 100644 (file)
@@ -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);
        }
index 455e179..35ba212 100644 (file)
@@ -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
index a328e47..f4a873d 100644 (file)
@@ -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<String> handleProxyMethodException(Exception ex, WebRequest request) {
+       public final ResponseEntity<String> 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<String> handleUnknownInstanceException(Exception ex, WebRequest request) {
-               log.warn("handleUnknownInstanceException: request {}, exception {}", request.getDescription(false),
-                               ex.toString());
+       public final ResponseEntity<String> 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<String> 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<String> handleStatsManagerException(Exception ex, WebRequest request) {
-               log.warn("handleStatsManagerException: request {}, exception {}", request.getDescription(false), ex.toString());
+       public final ResponseEntity<String> handleStatsManager(Exception ex, WebRequest request) {
+               log.warn("handleStatsManager: request {}, exception {}", request.getDescription(false), ex.toString());
                return ResponseEntity.badRequest().body(getShortExceptionMessage(ex));
        }
 
index dabb6b4..06cbc6b 100644 (file)
@@ -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<String> 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 (file)
index 0000000..7f1f480
--- /dev/null
@@ -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);
+       }
+}
index 5aaace2..67a82c0 100644 (file)
@@ -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<AppStats> 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);
+               });
        }
 
 }
index a181159..6888774 100644 (file)
@@ -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());
-               }
+               });
        }
 
 }
index 27e59ad..65f1850 100644 (file)
@@ -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.<XappDescriptor>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 -> {
index c90c3d6..afa9711 100644 (file)
@@ -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);
        }
 
 }
index 37ab484..f3f9fad 100644 (file)
@@ -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)
index 779feaf..0132c19 100644 (file)
@@ -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
index 64dc4a7..328a5ad 100644 (file)
@@ -55,7 +55,8 @@ public class E2ManagerControllerTest extends AbstractControllerTest {
                logger.info("Invoking {}", uri);
                UpdateGnbRequest update = new UpdateGnbRequest();
                HttpEntity<UpdateGnbRequest> entity = new HttpEntity<>(update);
-               ResponseEntity<Void> voidResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, entity, Void.class);
+               ResponseEntity<Void> voidResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, entity,
+                               Void.class);
                Assertions.assertTrue(voidResponse.getStatusCode().is2xxSuccessful());
        }
 
index f28494d..cc1a7e8 100644 (file)
  */
 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();
        }
 
index dadd1b2..37f2148 100644 (file)
  */
 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");
+               });
        }
 
 }
index 78458d0..067bdcb 100644 (file)
@@ -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<RicRegion> 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());
        }
 
index a2747e8..028921b 100644 (file)
@@ -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
index 2ba2a1c..3721c2e 100644 (file)
@@ -25,7 +25,7 @@ limitations under the License.
        <parent>
                <groupId>org.o-ran-sc.portal.ric-dashboard</groupId>
                <artifactId>ric-dash-parent</artifactId>
-               <version>2.0.2-SNAPSHOT</version>
+               <version>2.0.3-SNAPSHOT</version>
        </parent>
        <!-- reuse parent groupId -->
        <artifactId>ric-dash-fe</artifactId>
index 147795a..16ffa1f 100644 (file)
@@ -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 <https://jira.o-ran-sc.org/browse/OAM-103>`_)
 
 Version 2.0.1, 30 Apr 2020
 --------------------------