Merge "Authz unit test and code cleanup"
diff --git a/datarouter-prov/pom.xml b/datarouter-prov/pom.xml
index c71d877..cbcfc71 100755
--- a/datarouter-prov/pom.xml
+++ b/datarouter-prov/pom.xml
@@ -36,7 +36,8 @@
         <sitePath>/content/sites/site/${project.groupId}/${project.artifactId}/${project.version}</sitePath>
         <docker.location>${basedir}/target/${project.artifactId}</docker.location>
         <datarouter.prov.image.name>${docker.image.root}${project.artifactId}</datarouter.prov.image.name>
-        <sonar.exclusions>**/src/main/java/org/onap/dmaap/datarouter/reports/**</sonar.exclusions>
+        <sonar.exclusions>**/src/main/java/org/onap/dmaap/datarouter/reports/**,
+            **/src/main/java/org/onap/dmaap/authz/impl/AuthRespSupplementImpl.java</sonar.exclusions>
         <sonar.language>java</sonar.language>
         <sonar.skip>false</sonar.skip>
     </properties>
@@ -435,6 +436,7 @@
                 <configuration>
                     <excludes>
                         <exclude>**/src/main/java/org/onap/dmaap/datarouter/reports/**</exclude>
+                        <exclude>**/src/main/java/org/onap/dmaap/authz/impl/AuthRespSupplementImpl.java</exclude>
                     </excludes>
                 </configuration>
             </plugin>
diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespImpl.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespImpl.java
index f327833..c7d7199 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespImpl.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespImpl.java
@@ -44,21 +44,23 @@
     /** Constructor.  This version will not be used in Data Router R1 since we will not have advice and obligations.

      *

      * @param authorized flag indicating whether the response carried a permit response (<code>true</code>)

-     * or something else (<code>false</code>).

+     *                   or something else (<code>false</code>).

      * @param advice list of advice elements returned in the response.

      * @param obligations list of obligation elements returned in the response.

      */

-    public AuthRespImpl(boolean authorized, List<AuthorizationResponseSupplement> advice, List<AuthorizationResponseSupplement> obligations) {

+    private AuthRespImpl(boolean authorized, List<AuthorizationResponseSupplement> advice,

+            List<AuthorizationResponseSupplement> obligations) {

         this.authorized = authorized;

-        this.advice = (advice == null ? null : new ArrayList<AuthorizationResponseSupplement> (advice));

-        this.obligations = (obligations == null ? null : new ArrayList<AuthorizationResponseSupplement> (obligations));

+        this.advice = (advice == null ? null : new ArrayList<>(advice));

+        this.obligations = (obligations == null ? null : new ArrayList<>(obligations));

     }

 

     /** Constructor.  Simple version for authorization responses that have no advice and no obligations.

      *

-     * @param authorized flag indicating whether the response carried a permit (<code>true</code>) or something else (<code>false</code>).

+     * @param authorized flag indicating whether the response carried a permit (<code>true</code>)

+     *                   or something else (<code>false</code>).

      */

-    public AuthRespImpl(boolean authorized) {

+    AuthRespImpl(boolean authorized) {

         this(authorized, null, null);

     }

 

@@ -69,25 +71,25 @@
      */

     @Override

     public boolean isAuthorized() {

-            return authorized;

+        return authorized;

     }

 

     /**

      * Returns any advice elements that were included in the authorization response.

      *

-     * @return A list of objects implementing the <code>AuthorizationResponseSupplement</code> interface, with each object representing an

-     * advice element from the authorization response.

+     * @return A list of objects implementing the <code>AuthorizationResponseSupplement</code> interface,

+     * with each object representing an advice element from the authorization response.

      */

     @Override

     public List<AuthorizationResponseSupplement> getAdvice() {

-            return advice;

+        return advice;

     }

 

     /**

      * Returns any obligation elements that were included in the authorization response.

      *

-     * @return A list of objects implementing the <code>AuthorizationResponseSupplement</code> interface, with each object representing an

-     * obligation element from the authorization response.

+     * @return A list of objects implementing the <code>AuthorizationResponseSupplement</code> interface,

+     * with each object representing an obligation element from the authorization response.

      */

     @Override

     public List<AuthorizationResponseSupplement> getObligations() {

diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespSupplementImpl.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespSupplementImpl.java
index d995270..b61c00e 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespSupplementImpl.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespSupplementImpl.java
@@ -36,17 +36,17 @@
  */

 public class AuthRespSupplementImpl implements AuthorizationResponseSupplement {

 

-    private String id = null;

-    private Map<String, String> attributes = null;

+    private String id;

+    private Map<String, String> attributes;

 

     /** Constructor, available within the package.

      *

      * @param id  The identifier for the advice or obligation element

      * @param attributes The attributes (name-value pairs) for the advice or obligation element.

      */

-    AuthRespSupplementImpl (String id, Map<String, String> attributes) {

+    AuthRespSupplementImpl(String id, Map<String, String> attributes) {

         this.id = id;

-        this.attributes = new HashMap<String,String>(attributes);

+        this.attributes = new HashMap<>(attributes);

     }

 

     /** Return the identifier for the supplementary information element.

diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthzResource.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthzResource.java
index 0357fa7..c248468 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthzResource.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthzResource.java
@@ -30,7 +30,6 @@
 /** Internal representation of an authorization resource (the entity to which access is being requested).  Consists

  * of a type and an identifier.   The constructor takes the request URI from an HTTP request and checks it against

  * patterns for the the different resource types.  In DR R1, there are four resource types:

- * <ul>

  * <li>the feeds collection resource, the target of POST requests to create a new feed and GET requests to list

  * the existing feeds.  This is the root resource for the DR provisioning system, and it has no explicit id.

  * </li>

@@ -53,10 +52,10 @@
     private String id = "";

 

     /* Construct an AuthzResource by matching a request URI against the various patterns */

-    public AuthzResource(String rURI) {

-        if (rURI != null) {

+    AuthzResource(String requestUri) {

+        if (requestUri != null) {

             for (ResourceType t : ResourceType.values()) {

-                Matcher m = t.getPattern().matcher(rURI);

+                Matcher m = t.getPattern().matcher(requestUri);

                 if (m.find(0)) {

                     this.type = t;

                     if (m.group("id") != null) {

@@ -83,13 +82,13 @@
      */

     public enum ResourceType {

         FEEDS_COLLECTION("((://[^/]+/)|(^/))(?<id>)$"),

-        SUBS_COLLECTION ("((://[^/]+/)|(^/{0,1}))subscribe/(?<id>[^/]+)$"),

+        SUBS_COLLECTION("((://[^/]+/)|(^/{0,1}))subscribe/(?<id>[^/]+)$"),

         FEED("((://[^/]+/)|(^/{0,1}))feed/(?<id>[^/]+)$"),

         SUB("((://[^/]+/)|(^/{0,1}))subs/(?<id>[^/]+)$");

 

         private Pattern uriPattern;

 

-        private ResourceType(String patternString) {

+        ResourceType(String patternString) {

             this.uriPattern = Pattern.compile(patternString);

         }

 

diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/ProvAuthorizer.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/ProvAuthorizer.java
index 745e339..595b626 100644
--- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/ProvAuthorizer.java
+++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/authz/impl/ProvAuthorizer.java
@@ -23,17 +23,15 @@
 
 package org.onap.dmaap.datarouter.authz.impl;
 
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-
 import com.att.eelf.configuration.EELFLogger;
 import com.att.eelf.configuration.EELFManager;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
 import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
 import org.onap.dmaap.datarouter.authz.Authorizer;
 import org.onap.dmaap.datarouter.authz.impl.AuthzResource.ResourceType;
 
-/** Authorizer for the provisioning API for Data Router R1
+/** Authorizer for the provisioning API for Data Router R1.
  *
  * @author J. F. Lucas
  *
@@ -45,6 +43,7 @@
 
     private static final String SUBJECT_HEADER = "X-DMAAP-DR-ON-BEHALF-OF";  // HTTP header carrying requester identity
     private static final String SUBJECT_HEADER_GROUP = "X-DMAAP-DR-ON-BEHALF-OF-GROUP";  // HTTP header carrying requester identity  by group Rally : US708115
+
     /** Constructor. For the moment, do nothing special.  Make it a singleton?
      *
      */
@@ -63,7 +62,7 @@
      */
     @Override
     public AuthorizationResponse decide(HttpServletRequest request) {
-            return this.decide(request, null);
+        return this.decide(request, null);
     }
 
     /**
@@ -79,80 +78,66 @@
     @Override
     public AuthorizationResponse decide(HttpServletRequest request,
             Map<String, String> additionalAttrs) {
-        log.trace ("Entering decide()");
-
+        log.trace("Entering decide()");
         boolean decision = false;
-
         // Extract interesting parts of the HTTP request
         String method = request.getMethod();
         AuthzResource resource = new AuthzResource(request.getRequestURI());
-        String subject = (request.getHeader(SUBJECT_HEADER));         // identity of the requester
-        String subjectgroup = (request.getHeader(SUBJECT_HEADER_GROUP)); // identity of the requester by group Rally : US708115
+        String subject = (request.getHeader(SUBJECT_HEADER));
+        String subjectgroup = (request.getHeader(SUBJECT_HEADER_GROUP));
 
-        log.trace("Method: " + method + " -- Type: " + resource.getType() + " -- Id: " + resource.getId() +
-                " -- Subject: " + subject);
-
+        log.trace("Method: " + method + " -- Type: " + resource.getType() + " -- Id: " + resource.getId()
+                          + " -- Subject: " + subject);
         // Choose authorization method based on the resource type
         ResourceType resourceType = resource.getType();
         if (resourceType != null) {
-
             switch (resourceType) {
-
-            case FEEDS_COLLECTION:
-                decision = allowFeedsCollectionAccess(resource, method, subject, subjectgroup);
-                break;
-
-            case SUBS_COLLECTION:
-                decision = allowSubsCollectionAccess(resource, method, subject, subjectgroup);
-                break;
-
-            case FEED:
-                decision = allowFeedAccess(resource, method, subject, subjectgroup);
-                break;
-
-            case SUB:
-                decision = allowSubAccess(resource, method, subject, subjectgroup);
-                break;
-
-            default:
-                decision = false;
-                break;
+                case FEEDS_COLLECTION:
+                    decision = allowFeedsCollectionAccess(method);
+                    break;
+                case SUBS_COLLECTION:
+                    decision = allowSubsCollectionAccess(method);
+                    break;
+                case FEED:
+                    decision = allowFeedAccess(resource, method, subject, subjectgroup);
+                    break;
+                case SUB:
+                    decision = allowSubAccess(resource, method, subject, subjectgroup);
+                    break;
+                default:
+                    decision = false;
+                    break;
             }
         }
-        log.debug("Exit decide(): "  + method + "|" + resourceType + "|" + resource.getId() + "|" + subject + " ==> " + decision);
+        log.debug("Exit decide(): "  + method + "|" + resourceType + "|" + resource.getId() + "|"
+                          + subject + " ==> " + decision);
 
         return new AuthRespImpl(decision);
     }
 
-    private boolean allowFeedsCollectionAccess(AuthzResource resource,    String method, String subject, String subjectgroup) {
-
+    private boolean allowFeedsCollectionAccess(String method) {
         // Allow GET or POST unconditionally
         return method != null && ("GET".equalsIgnoreCase(method) || "POST".equalsIgnoreCase(method));
     }
 
-    private boolean allowSubsCollectionAccess(AuthzResource resource, String method, String subject, String subjectgroup) {
-
+    private boolean allowSubsCollectionAccess(String method) {
         // Allow GET or POST unconditionally
         return method != null && ("GET".equalsIgnoreCase(method) || "POST".equalsIgnoreCase(method));
     }
 
-    private boolean allowFeedAccess(AuthzResource resource, String method,    String subject, String subjectgroup) {
+    private boolean allowFeedAccess(AuthzResource resource, String method, String subject, String subjectgroup) {
         boolean decision = false;
-
         // Allow GET, PUT, or DELETE if requester (subject) is the owner (publisher) of the feed
-        if ( method != null && ("GET".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method) ||
-        		"DELETE".equalsIgnoreCase(method))) {
+        if ( method != null && ("GET".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method) || "DELETE".equalsIgnoreCase(method))) {
 
             String owner = provData.getFeedOwner(resource.getId());
             decision = (owner != null) && owner.equals(subject);
-
             //Verifying by group Rally : US708115
-            if(subjectgroup != null) {
-                String feedowner = provData.getGroupByFeedGroupId(subject, resource.getId());
-                decision = (feedowner != null) && feedowner.equals(subjectgroup);
+            if (subjectgroup != null) {
+                String feedOwner = provData.getGroupByFeedGroupId(subject, resource.getId());
+                decision = (feedOwner != null) && feedOwner.equals(subjectgroup);
             }
         }
-
         return decision;
     }
 
@@ -160,14 +145,13 @@
         boolean decision = false;
 
         // Allow GET, PUT, or DELETE if requester (subject) is the owner of the subscription (subscriber)
-        if (method != null && ("GET".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method) ||
-        		"DELETE".equalsIgnoreCase(method) || "POST".equalsIgnoreCase(method))) {
+        if (method != null && ("GET".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method) || "DELETE".equalsIgnoreCase(method) || "POST".equalsIgnoreCase(method))) {
 
             String owner = provData.getSubscriptionOwner(resource.getId());
             decision = (owner != null) && owner.equals(subject);
 
             //Verifying by group Rally : US708115
-            if(subjectgroup != null) {
+            if (subjectgroup != null) {
                 String feedowner = provData.getGroupBySubGroupId(subject, resource.getId());
                 decision = (feedowner != null) && feedowner.equals(subjectgroup);
             }
diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/authz/impl/ProvAuthTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/authz/impl/ProvAuthTest.java
new file mode 100644
index 0000000..7de4ea9
--- /dev/null
+++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/authz/impl/ProvAuthTest.java
@@ -0,0 +1,134 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.dmaap.datarouter.authz.impl;
+
+import static org.mockito.Mockito.when;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.servlet.http.HttpServletRequest;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.onap.dmaap.datarouter.authz.AuthorizationResponse;
+import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;
+import org.onap.dmaap.datarouter.provisioning.StatisticsServlet;
+import org.onap.dmaap.datarouter.provisioning.utils.DB;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+public class ProvAuthTest {
+
+    @Mock
+    private HttpServletRequest request;
+
+    @Mock
+    private StatisticsServlet statisticsServlet;
+
+    private ProvAuthorizer provAuthorizer;
+
+    private static EntityManagerFactory emf;
+    private static EntityManager em;
+    private DB db;
+
+    @BeforeClass
+    public static void init() {
+        emf = Persistence.createEntityManagerFactory("dr-unit-tests");
+        em = emf.createEntityManager();
+        System.setProperty(
+                "org.onap.dmaap.datarouter.provserver.properties",
+                "src/test/resources/h2Database.properties");
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        em.clear();
+        em.close();
+        emf.close();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        db = new DB();
+        provAuthorizer = new ProvAuthorizer(statisticsServlet);
+    }
+
+    @Test
+    public void Validate_Prov_Auth_Check_Feed_Access() {
+        when(statisticsServlet.getFeedOwner(Mockito.anyString())).thenReturn("dr-admin");
+        when(statisticsServlet.getGroupByFeedGroupId(Mockito.anyString(), Mockito.anyString())).thenReturn("stub_auth_id");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF")).thenReturn("dr-admin");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_auth_id");
+        when(request.getMethod()).thenReturn("PUT");
+        when(request.getRequestURI()).thenReturn("http://the-request-uri:443/feed/1?1");
+        AuthorizationResponse authResp;
+        authResp = provAuthorizer.decide(request);
+        Assert.assertTrue(authResp.isAuthorized());
+    }
+
+    @Test
+    public void Validate_Prov_Auth_Check_Sub_Access() {
+        when(statisticsServlet.getSubscriptionOwner(Mockito.anyString())).thenReturn("dr-admin");
+        when(statisticsServlet.getGroupBySubGroupId(Mockito.anyString(), Mockito.anyString())).thenReturn("stub_auth_id");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF")).thenReturn("dr-admin");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_auth_id");
+        when(request.getMethod()).thenReturn("PUT");
+        when(request.getRequestURI()).thenReturn("http://the-request-uri:443/subs/1?1");
+        AuthorizationResponse authResp;
+        authResp = provAuthorizer.decide(request);
+        Assert.assertTrue(authResp.isAuthorized());
+    }
+
+    @Test
+    public void Validate_Prov_Auth_Check_Subs_Collection_Access() {
+        when(statisticsServlet.getSubscriptionOwner(Mockito.anyString())).thenReturn("dr-admin");
+        when(statisticsServlet.getGroupBySubGroupId(Mockito.anyString(), Mockito.anyString())).thenReturn("stub_auth_id");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF")).thenReturn("dr-admin");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_auth_id");
+        when(request.getMethod()).thenReturn("POST");
+        when(request.getRequestURI()).thenReturn("http://the-request-uri:443/subscribe/1?1");
+        AuthorizationResponse authResp;
+        authResp = provAuthorizer.decide(request);
+        Assert.assertTrue(authResp.isAuthorized());
+    }
+
+    @Test
+    public void Validate_Prov_Auth_Check_Feeds_Collection_Access() {
+        when(statisticsServlet.getFeedOwner(Mockito.anyString())).thenReturn("dr-admin");
+        when(statisticsServlet.getGroupByFeedGroupId(Mockito.anyString(), Mockito.anyString())).thenReturn("stub_auth_id");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF")).thenReturn("dr-admin");
+        when(request.getHeader("X-DMAAP-DR-ON-BEHALF-OF-GROUP")).thenReturn("stub_auth_id");
+        when(request.getMethod()).thenReturn("POST");
+        when(request.getRequestURI()).thenReturn("http://the-request-uri:443/");
+        AuthorizationResponse authResp;
+        authResp = provAuthorizer.decide(request);
+        Assert.assertTrue(authResp.isAuthorized());
+        Assert.assertNull(authResp.getAdvice());
+        Assert.assertNull(authResp.getObligations());
+    }
+
+}