Respect permissions by owning-entity-id when searching instances by owning entity
[vid.git] / vid-app-common / src / main / java / org / onap / vid / services / AaiServiceImpl.java
index 9848121..1e79ab4 100644 (file)
@@ -21,6 +21,8 @@
 
 package org.onap.vid.services;
 
+import static java.util.Collections.emptyList;
+import static org.apache.commons.collections4.ListUtils.emptyIfNull;
 import static org.onap.vid.aai.AaiClient.QUERY_FORMAT_RESOURCE;
 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
 
@@ -33,8 +35,10 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.StringUtils;
@@ -75,7 +79,6 @@ import org.onap.vid.aai.model.RelationshipData;
 import org.onap.vid.aai.model.RelationshipList;
 import org.onap.vid.aai.model.Result;
 import org.onap.vid.aai.model.ServiceRelationships;
-import org.onap.vid.aai.model.VnfResult;
 import org.onap.vid.asdc.beans.Service;
 import org.onap.vid.exceptions.GenericUncheckedException;
 import org.onap.vid.model.ServiceInstanceSearchResult;
@@ -86,9 +89,12 @@ import org.onap.vid.model.aaiTree.NodeType;
 import org.onap.vid.model.aaiTree.RelatedVnf;
 import org.onap.vid.model.aaiTree.VpnBinding;
 import org.onap.vid.model.aaiTree.VpnBindingKt;
+import org.onap.vid.roles.PermissionPropertiesSubscriberAndServiceType;
 import org.onap.vid.roles.RoleValidator;
 import org.onap.vid.utils.Intersection;
+import org.onap.vid.utils.Logging;
 import org.onap.vid.utils.Tree;
+import org.slf4j.MDC;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpMethod;
 
@@ -96,6 +102,7 @@ public class AaiServiceImpl implements AaiService {
     private static final String SERVICE_INSTANCE_ID = "service-instance.service-instance-id";
     private static final String SERVICE_TYPE = "service-subscription.service-type";
     private static final String CUSTOMER_ID = "customer.global-customer-id";
+    private static final String OWNING_ENTITY_ID = "owning-entity.owning-entity-id";
     private static final String SERVICE_INSTANCE_NAME = "service-instance.service-instance-name";
     private static final String TENANT_NODE_TYPE = "tenant";
     private static final String CLOUD_REGION_NODE_TYPE = "cloud-region";
@@ -105,6 +112,7 @@ public class AaiServiceImpl implements AaiService {
     private AaiResponseTranslator aaiResponseTranslator;
     private AAIServiceTree aaiServiceTree;
     private ExecutorService executorService;
+    private final Logging logging;
 
 
     private static final EELFLoggerDelegate LOGGER = EELFLoggerDelegate.getLogger(AaiServiceImpl.class);
@@ -114,12 +122,13 @@ public class AaiServiceImpl implements AaiService {
         AaiClientInterface aaiClient,
         AaiResponseTranslator aaiResponseTranslator,
         AAIServiceTree aaiServiceTree,
-        ExecutorService executorService)
+        ExecutorService executorService, Logging logging)
     {
         this.aaiClient = aaiClient;
         this.aaiResponseTranslator = aaiResponseTranslator;
         this.aaiServiceTree = aaiServiceTree;
         this.executorService = executorService;
+        this.logging = logging;
     }
 
     private List<Service> convertModelToService(Model model) {
@@ -152,6 +161,10 @@ public class AaiServiceImpl implements AaiService {
         return services;
     }
 
+    private boolean hasData(AaiResponse<?> aaiResponse) {
+        return aaiResponse != null && aaiResponse.getT() != null;
+    }
+
     private boolean validateModel(Model model){
         if (model == null) {
             return false;
@@ -160,39 +173,42 @@ public class AaiServiceImpl implements AaiService {
         }
     }
 
-    private List<ServiceInstanceSearchResult> getServicesByOwningEntityId(List<String> owningEntities, RoleValidator roleValidator) {
+    List<ServiceInstanceSearchResult> getServicesByOwningEntityId(List<String> owningEntities, RoleValidator roleValidator) {
         AaiResponse<OwningEntityResponse> owningEntityResponse = aaiClient.getServicesByOwningEntityId(owningEntities);
         List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
         if (owningEntityResponse.getT() != null) {
             for (OwningEntity owningEntity : owningEntityResponse.getT().getOwningEntity()) {
                 if (owningEntity.getRelationshipList() != null) {
-                    serviceInstanceSearchResultList = convertRelationshipToSearchResult(owningEntity, serviceInstanceSearchResultList, roleValidator);
+                    serviceInstanceSearchResultList.addAll(convertRelationshipToSearchResult(owningEntity, roleValidator, owningEntity.getOwningEntityId()));
                 }
             }
         }
         return serviceInstanceSearchResultList;
     }
 
-    private List<ServiceInstanceSearchResult> getServicesByProjectNames(List<String> projectNames, RoleValidator roleValidator) {
+    List<ServiceInstanceSearchResult> getServicesByProjectNames(List<String> projectNames, RoleValidator roleValidator) {
         AaiResponse<ProjectResponse> projectByIdResponse = aaiClient.getServicesByProjectNames(projectNames);
         List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
         if (projectByIdResponse.getT() != null) {
             for (Project project : projectByIdResponse.getT().getProject()) {
                 if (project.getRelationshipList() != null) {
-                    serviceInstanceSearchResultList = convertRelationshipToSearchResult(project, serviceInstanceSearchResultList, roleValidator);
+                    serviceInstanceSearchResultList.addAll(convertRelationshipToSearchResult(project, roleValidator, null));
                 }
             }
         }
         return serviceInstanceSearchResultList;
     }
 
-    private List<ServiceInstanceSearchResult> convertRelationshipToSearchResult(AaiRelationResponse owningEntityResponse, List<ServiceInstanceSearchResult> serviceInstanceSearchResultList, RoleValidator roleValidator) {
-        if (owningEntityResponse.getRelationshipList().getRelationship() != null) {
-            List<Relationship> relationshipList = owningEntityResponse.getRelationshipList().getRelationship();
+    private List<ServiceInstanceSearchResult> convertRelationshipToSearchResult(AaiRelationResponse aaiRelationResponse, RoleValidator roleValidator, String owningEntityId) {
+        List<ServiceInstanceSearchResult> serviceInstanceSearchResultList = new ArrayList<>();
+        if (aaiRelationResponse.getRelationshipList().getRelationship() != null) {
+            List<Relationship> relationshipList = aaiRelationResponse.getRelationshipList().getRelationship();
             for (Relationship relationship : relationshipList) {
                 ServiceInstanceSearchResult serviceInstanceSearchResult = new ServiceInstanceSearchResult();
                 extractRelationshipData(relationship, serviceInstanceSearchResult, roleValidator);
                 extractRelatedToProperty(relationship, serviceInstanceSearchResult);
+                serviceInstanceSearchResult.setOwningEntityId(owningEntityId);
+                serviceInstanceSearchResult.setIsPermitted(roleValidator.isServicePermitted(serviceInstanceSearchResult));
                 serviceInstanceSearchResultList.add(serviceInstanceSearchResult);
             }
         }
@@ -210,12 +226,9 @@ public class AaiServiceImpl implements AaiService {
                 } else if (key.equals(SERVICE_TYPE)) {
                     serviceInstanceSearchResult.setServiceType(relationshipData.getRelationshipValue());
                 } else if (key.equals(CUSTOMER_ID)) {
-                    serviceInstanceSearchResult.setGlobalCustomerId(relationshipData.getRelationshipValue());
+                    serviceInstanceSearchResult.setSubscriberId(relationshipData.getRelationshipValue());
                 }
             }
-
-            boolean isPermitted = roleValidator.isServicePermitted(serviceInstanceSearchResult.getSubscriberName(), serviceInstanceSearchResult.getServiceType());
-            serviceInstanceSearchResult.setIsPermitted(isPermitted);
         }
     }
 
@@ -258,10 +271,9 @@ public class AaiServiceImpl implements AaiService {
     @Override
     public AaiResponse getSubscriberData(String subscriberId, RoleValidator roleValidator, boolean omitServiceInstances) {
         AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId, omitServiceInstances);
-        String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
         for (ServiceSubscription serviceSubscription : subscriberResponse.getT().serviceSubscriptions.serviceSubscription) {
-            String serviceType = serviceSubscription.serviceType;
-            serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
+            serviceSubscription.isPermitted = roleValidator.isServicePermitted(
+                new PermissionPropertiesSubscriberAndServiceType(serviceSubscription, subscriberResponse.getT().globalCustomerId));
         }
         return subscriberResponse;
 
@@ -291,38 +303,45 @@ public class AaiServiceImpl implements AaiService {
 
     private List<ServiceInstanceSearchResult> getServicesBySubscriber(String subscriberId, String instanceIdentifier, RoleValidator roleValidator) {
         AaiResponse<Services> subscriberResponse = aaiClient.getSubscriberData(subscriberId, false);
-        String subscriberGlobalId = subscriberResponse.getT().globalCustomerId;
         String subscriberName = subscriberResponse.getT().subscriberName;
         ServiceSubscriptions serviceSubscriptions = subscriberResponse.getT().serviceSubscriptions;
 
-        return getSearchResultsForSubscriptions(serviceSubscriptions, subscriberId, instanceIdentifier, roleValidator, subscriberGlobalId, subscriberName);
-
+        return getSearchResultsForSubscriptions(serviceSubscriptions, subscriberId, instanceIdentifier, roleValidator, subscriberName);
     }
 
 
-    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSubscriptions(ServiceSubscriptions serviceSubscriptions, String subscriberId, String instanceIdentifier, RoleValidator roleValidator, String subscriberGlobalId, String subscriberName) {
+    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSubscriptions(
+        ServiceSubscriptions serviceSubscriptions, String subscriberId, String instanceIdentifier,
+        RoleValidator roleValidator, String subscriberName) {
         ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();
 
         if (serviceSubscriptions != null) {
             for (ServiceSubscription serviceSubscription : serviceSubscriptions.serviceSubscription) {
-                String serviceType = serviceSubscription.serviceType;
-                serviceSubscription.isPermitted = roleValidator.isServicePermitted(subscriberGlobalId, serviceType);
-                ArrayList<ServiceInstanceSearchResult> resultsForSubscription = getSearchResultsForSingleSubscription(serviceSubscription, subscriberId, instanceIdentifier, subscriberName, serviceType);
-                results.addAll(resultsForSubscription);
+                serviceSubscription.isPermitted = roleValidator.isServicePermitted(new PermissionPropertiesSubscriberAndServiceType(serviceSubscription, subscriberId));
+                results.addAll(getSearchResultsForSingleSubscription(
+                    serviceSubscription, subscriberId, instanceIdentifier, subscriberName,
+                    serviceSubscription.serviceType, roleValidator)
+                );
             }
         }
 
         return results;
     }
 
-    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSingleSubscription(ServiceSubscription serviceSubscription, String subscriberId, String instanceIdentifier, String subscriberName, String serviceType) {
+    private ArrayList<ServiceInstanceSearchResult> getSearchResultsForSingleSubscription(
+        ServiceSubscription serviceSubscription, String subscriberId, String instanceIdentifier, String subscriberName,
+        String serviceType, RoleValidator roleValidator) {
         ArrayList<ServiceInstanceSearchResult> results = new ArrayList<>();
 
         if (serviceSubscription.serviceInstances != null) {
             for (ServiceInstance serviceInstance : serviceSubscription.serviceInstances.serviceInstance) {
+
                 ServiceInstanceSearchResult serviceInstanceSearchResult =
-                        new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType, serviceInstance.serviceInstanceName,
-                                subscriberName, serviceInstance.modelInvariantId, serviceInstance.modelVersionId, serviceSubscription.isPermitted);
+                        new ServiceInstanceSearchResult(serviceInstance.serviceInstanceId, subscriberId, serviceType,
+                            serviceInstance.serviceInstanceName, subscriberName, serviceInstance.modelInvariantId,
+                            serviceInstance.modelVersionId, relatedOwningEntityId(serviceInstance), false);
+
+                serviceInstanceSearchResult.setIsPermitted(roleValidator.isServicePermitted(serviceInstanceSearchResult));
 
                 if ((instanceIdentifier == null) || (serviceInstanceMatchesIdentifier(instanceIdentifier, serviceInstance))){
                     results.add(serviceInstanceSearchResult);
@@ -333,6 +352,43 @@ public class AaiServiceImpl implements AaiService {
         return results;
     }
 
+    protected String relatedOwningEntityId(ServiceInstance serviceInstance) {
+        /*
+        For reference, consider the service-instance structure below. Method will null-safely extract the
+        `relationship-value` where `relationship-key` == `owning-entity.owning-entity-id`.
+
+        {
+          "service-instance-id": "5d521981-33be-4bb5-bb20-5616a9c52a5a",
+          ...
+          "relationship-list": {
+            "relationship": [
+              {
+                "related-to": "owning-entity",
+                "related-link": "/aai/v11/business/owning-entities/owning-entity/4d4ecf59-41f1-40d4-818d-885234680a42",
+                "relationship-data": [
+                  {
+                    "relationship-key": "owning-entity.owning-entity-id",
+                    "relationship-value": "4d4ecf59-41f1-40d4-818d-885234680a42"
+                  }
+                ]
+              }
+            ]
+          }
+        }
+        */
+
+        Stream<RelationshipData> allRelationships =
+            Optional.ofNullable(serviceInstance.relationshipList)
+                .map(it -> it.getRelationship())
+                .map(it -> it.stream().flatMap(r -> emptyIfNull(r.getRelationDataList()).stream()))
+                .orElse(Stream.empty());
+
+        return allRelationships
+            .filter(r -> StringUtils.equals(r.getRelationshipKey(), OWNING_ENTITY_ID))
+            .map(it -> it.getRelationshipValue())
+            .findAny().orElse(null);
+    }
+
     private boolean serviceInstanceMatchesIdentifier(String instanceIdentifier, ServiceInstance serviceInstance) {
         return instanceIdentifier.equals(serviceInstance.serviceInstanceId) || instanceIdentifier.equals(serviceInstance.serviceInstanceName);
     }
@@ -390,24 +446,7 @@ public class AaiServiceImpl implements AaiService {
     @Override
     public AaiResponse<AaiGetVnfResponse> getVNFData(String globalSubscriberId, String serviceType) {
         AaiResponse<AaiGetVnfResponse> response = aaiClient.getVNFData(globalSubscriberId, serviceType);
-        return filterChangeManagementVNFCandidatesResponse(response);
-    }
-
-    protected AaiResponse<AaiGetVnfResponse> filterChangeManagementVNFCandidatesResponse(AaiResponse<AaiGetVnfResponse> response) {
-
-        if (response != null && response.getT() != null) {
-            List<VnfResult> filteredVnfs = response.getT().results.stream()
-                    .filter(result -> (
-                            result.nodeType.equalsIgnoreCase("generic-vnf") ||
-                                    result.nodeType.equalsIgnoreCase("service-instance")))
-                    .collect(Collectors.toList());
-
-            AaiGetVnfResponse aaiGetVnfResponse = new AaiGetVnfResponse();
-            aaiGetVnfResponse.results = filteredVnfs;
-            return new AaiResponse<>(aaiGetVnfResponse, response.getErrorMessage(), response.getHttpCode());
-        }
-
-        return new AaiResponse<>();
+        return hasData(response) ? response : new AaiResponse<>();
     }
 
     @Override
@@ -537,10 +576,12 @@ public class AaiServiceImpl implements AaiService {
                 .map(RelatedVnf::from)
                 .collect(Collectors.toList());
 
+        final Map<String, String> copyOfParentMDC = MDC.getCopyOfContextMap();
+
         try {
             return executorService.submit(() ->
                     convertedVnfs.parallelStream()
-                            .map(this::enrichRelatedVnfWithCloudRegionAndTenant)
+                            .map(logging.withMDC(copyOfParentMDC, this::enrichRelatedVnfWithCloudRegionAndTenant))
                             .collect(Collectors.toList())
             ).get();
         } catch (Exception e) {
@@ -675,7 +716,7 @@ public class AaiServiceImpl implements AaiService {
             return aaiTree.stream().map(VpnBindingKt::from).collect(Collectors.toList());
         } catch (ExceptionWithRequestInfo exception) {
             if (Objects.equals(404, exception.getHttpCode())) {
-                return Collections.emptyList();
+                return emptyList();
             }
             throw exception;
         }
@@ -691,7 +732,7 @@ public class AaiServiceImpl implements AaiService {
             return aaiTree.stream().map(Network::from).collect(Collectors.toList());
         } catch (ExceptionWithRequestInfo exception) {
             if (Objects.equals(404, exception.getHttpCode())) {
-                return Collections.emptyList();
+                return emptyList();
             }
             throw exception;
         }