+/* Copyright (c) 2019 AT&T Intellectual Property. #\r
+# #\r
+# Licensed under the Apache License, Version 2.0 (the "License"); #\r
+# you may not use this file except in compliance with the License. #\r
+# You may obtain a copy of the License at #\r
+# #\r
+# http://www.apache.org/licenses/LICENSE-2.0 #\r
+# #\r
+# Unless required by applicable law or agreed to in writing, software #\r
+# distributed under the License is distributed on an "AS IS" BASIS, #\r
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #\r
+# See the License for the specific language governing permissions and #\r
+# limitations under the License. #\r
+##############################################################################*/\r
+\r
+\r
+package org.oran.otf.api.service.impl;\r
+\r
+import org.oran.otf.api.Utilities;\r
+import org.oran.otf.api.Utilities.LogLevel;\r
+import org.oran.otf.api.handler.CamundaProcessExecutionHandler;\r
+import org.oran.otf.api.service.TestInstanceService;\r
+import org.oran.otf.common.model.Group;\r
+import org.oran.otf.common.model.TestDefinition;\r
+import org.oran.otf.common.model.TestInstance;\r
+import org.oran.otf.common.model.User;\r
+import org.oran.otf.common.model.local.BpmnInstance;\r
+import org.oran.otf.common.model.local.TestInstanceCreateRequest;\r
+import org.oran.otf.common.model.local.WorkflowRequest;\r
+import org.oran.otf.common.repository.GroupRepository;\r
+import org.oran.otf.common.repository.TestDefinitionRepository;\r
+import org.oran.otf.common.repository.TestInstanceRepository;\r
+import org.oran.otf.common.repository.UserRepository;\r
+import org.oran.otf.common.utility.Utility;\r
+import org.oran.otf.common.utility.database.Generic;\r
+import org.oran.otf.common.utility.http.ResponseUtility;\r
+import org.oran.otf.common.utility.permissions.PermissionChecker;\r
+import org.oran.otf.common.utility.permissions.UserPermission;\r
+import com.google.common.base.Strings;\r
+import org.bson.types.ObjectId;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.stereotype.Service;\r
+\r
+import javax.ws.rs.core.MediaType;\r
+import javax.ws.rs.core.Response;\r
+import java.util.*;\r
+\r
+@Service\r
+public class TestInstanceServiceImpl implements TestInstanceService {\r
+ @Autowired\r
+ CamundaProcessExecutionHandler camundaProcessExecutionHandler;\r
+ @Autowired\r
+ UserRepository userRepository;\r
+ @Autowired\r
+ TestInstanceRepository testInstanceRepository;\r
+ @Autowired\r
+ TestDefinitionRepository testDefinitionRepository;\r
+ @Autowired\r
+ GroupRepository groupRepository;\r
+\r
+ private static final Logger logger = LoggerFactory.getLogger(TestInstanceServiceImpl.class);\r
+ private static final String logPrefix = Utility.getLoggerPrefix();\r
+\r
+ @Override\r
+ public Response execute(String testInstanceId, String authorization, WorkflowRequest request) {\r
+ try {\r
+ if (request == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage("Request body is null.");\r
+ }\r
+\r
+ // Check if the testInstanceId is a valid BSON ObjectI, otherwise return a bad request\r
+ // response.\r
+ if (!Utilities.isObjectIdValid(testInstanceId)) {\r
+ String error =\r
+ String.format(\r
+ "%sThe testInstanceId, %s, is not a valid ObjectId (BSON).",\r
+ logPrefix, testInstanceId);\r
+ return ResponseUtility.Build.badRequestWithMessage(error);\r
+ }\r
+\r
+ // Create an ObjectId now that we know the provided String was valid.\r
+ ObjectId oiTestInstanceId = new ObjectId(testInstanceId);\r
+ // Check if the testInstance exists, otherwise return a not found response.\r
+ TestInstance testInstance = Generic.findByIdGeneric(testInstanceRepository, oiTestInstanceId);\r
+ if (testInstance == null) {\r
+ String error =\r
+ String.format(\r
+ "%sThe testInstance with _id, %s, was not found.", logPrefix, testInstanceId);\r
+ return ResponseUtility.Build.notFoundWithMessage(error);\r
+ }\r
+ // Check if the testDefinition exists.\r
+ TestDefinition testDefinition =\r
+ Generic.findByIdGeneric(testDefinitionRepository, testInstance.getTestDefinitionId());\r
+ if (testDefinition == null) {\r
+ String error =\r
+ String.format(\r
+ "%sThe testDefinition with _id, %s, was not found.",\r
+ logPrefix, testInstance.getTestDefinitionId().toString());\r
+ return ResponseUtility.Build.notFoundWithMessage(error);\r
+ }\r
+\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format(\r
+ "%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ // If the mechanizedId is not an OTF mechanizedId, check if the user is authorized to\r
+ // execute\r
+ // the test instance. This is required because the executorId only needs to be read from the\r
+ // otf-frontend component. The user/group system is not fully integrated with AAF, so this\r
+ // is\r
+ // required. A better way might be to use certificates to check identities.\r
+ Group testInstanceGroup = Utilities.resolveOptional(groupRepository.findById(testInstance.getGroupId().toString()));\r
+ // if we cant find the test instance group then we cant check the permission\r
+ if (testInstanceGroup == null) {\r
+ return ResponseUtility.Build.\r
+ badRequestWithMessage(\r
+ String.format("Can not find test instance group, id:%s", testInstance.getGroupId().toString()));\r
+ }\r
+ // If the mechanizedId is authorized, set the executorId in the WorkflowRequest to the\r
+ // mechanizedId's ObjectId to make sure that the executorId isn't spoofed. Only use the\r
+ // executorId sent with the request if it uses the OTF mechanizedId because we "trust" it.\r
+ if (isOtfMechanizedIdentifier(mechanizedIdUser.getEmail()) && request.getExecutorId() != null) {\r
+ mechanizedIdUser = Utilities.resolveOptional(userRepository.findById(request.getExecutorId().toString()));\r
+ } else {\r
+ request.setExecutorId(mechanizedIdUser.get_id());\r
+ }\r
+ if (!PermissionChecker.hasPermissionTo(mechanizedIdUser,testInstanceGroup, UserPermission.Permission.EXECUTE,groupRepository)) {\r
+ String error =\r
+ String.format(\r
+ "%sUnauthorized the execute test instance with _id, %s.",\r
+ logPrefix, testInstanceId);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ // Set the test instance _id after authorization.\r
+ request.setTestInstanceId(testInstance.get_id());\r
+\r
+ // Check if the test instance is disabled.\r
+ if (testInstance.isDisabled()) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("The test instance with identifier %s is disabled.", testInstanceId));\r
+ }\r
+ // Check if the test definition is disabled.\r
+ if (testDefinition.isDisabled()) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format(\r
+ "The test definition with identifier %s is disabled.",\r
+ testInstance.getTestDefinitionId().toString()));\r
+ }\r
+\r
+ // Send the request to Camunda.\r
+ return camundaProcessExecutionHandler.startProcessInstance(request);\r
+ } catch (Exception e) {\r
+ Utilities.printStackTrace(e, LogLevel.ERROR);\r
+ return ResponseUtility.Build.internalServerError();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Response createByTestDefinitionId(\r
+ String testDefinitionId, String authorization, TestInstanceCreateRequest request) {\r
+ try {\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format(\r
+ "%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ // Check if the String correctly parses as an ObjectId.\r
+ if (!Utilities.isObjectIdValid(testDefinitionId)) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format(\r
+ "The testDefinitionId %s is not a valid BSON ObjectId.", testDefinitionId));\r
+ }\r
+ ObjectId oiTestDefintionId = new ObjectId(testDefinitionId);\r
+\r
+ // Find the testDefinition\r
+ TestDefinition testDefinition =\r
+ Generic.findByIdGeneric(testDefinitionRepository, oiTestDefintionId);\r
+ if (testDefinition == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format("Test definition with id, %s, was not found.", testDefinitionId));\r
+ }\r
+ // Check if the mechanizedId has access to the test definition.\r
+ Group testDefGroup = Utilities.resolveOptional(groupRepository.findById(testDefinition.getGroupId().toString()));\r
+ if (testDefGroup == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Can not find test definition's group, id: %s", testDefinition.getGroupId().toString()));\r
+ }\r
+// if (PermissionChecker.hasReadPermission(mechanizedIdUser, testDefGroup, groupRepository)) {\r
+// return ResponseUtility.Build.unauthorizedWithMessage(\r
+// String.format(\r
+// "MechanizedId, %s, does not have read access to test definition in group with name, %s",\r
+// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+// }\r
+// if (PermissionChecker.hasWritePermission(mechanizedIdUser, testDefGroup)) {\r
+// return ResponseUtility.Build.unauthorizedWithMessage(\r
+// String.format(\r
+// "MechanizedId, %s, does not have write access to the group with name, %s",\r
+// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+// }\r
+ if (PermissionChecker.hasPermissionTo(mechanizedIdUser, testDefGroup,\r
+ Arrays.asList(UserPermission.Permission.READ,UserPermission.Permission.WRITE),groupRepository))\r
+ {\r
+ return ResponseUtility.Build.unauthorizedWithMessage(\r
+ String.format(\r
+ "MechanizedId, %s, does not have access (read/write) to the group with name, %s",\r
+ mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+ }\r
+ // Get the latest version of the test definition to link it with the test instance\r
+ BpmnInstance bpmnInstance = findBpmnInstance(testDefinition, Integer.MIN_VALUE, true);\r
+ if (bpmnInstance == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format(\r
+ "Test definition with id, %s, does not have any versions associated with it.",\r
+ testDefinitionId));\r
+ }\r
+\r
+ TestInstance testInstance =\r
+ new TestInstance(\r
+ new ObjectId(),\r
+ request.getTestInstanceName(),\r
+ request.getTestInstanceDescription(),\r
+ testDefinition.getGroupId(),\r
+ testDefinition.get_id(),\r
+ bpmnInstance.getProcessDefinitionId(),\r
+ request.isUseLatestTestDefinition(),\r
+ false,\r
+ request.isSimulationMode(),\r
+ request.getMaxExecutionTimeInMillis(),\r
+ request.getPfloInput(),\r
+ new HashMap<>(),\r
+ request.getSimulationVthInput(),\r
+ request.getTestData(),\r
+ request.getVthInput(),\r
+ new Date(System.currentTimeMillis()),\r
+ new Date(System.currentTimeMillis()),\r
+ mechanizedIdUser.get_id(),\r
+ mechanizedIdUser.get_id());\r
+\r
+ return Response.ok()\r
+ .type(MediaType.APPLICATION_JSON_TYPE)\r
+ .entity(testInstance.toString())\r
+ .build();\r
+ } catch (Exception e) {\r
+ Utilities.printStackTrace(e, LogLevel.ERROR);\r
+ return ResponseUtility.Build.internalServerError();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Response createByTestDefinitionId(\r
+ String testDefinitionId,\r
+ int version,\r
+ String authorization,\r
+ TestInstanceCreateRequest request) {\r
+ try {\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format(\r
+ "%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ // Check if the String correctly parses as an ObjectId.\r
+ if (!Utilities.isObjectIdValid(testDefinitionId)) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format(\r
+ "The testDefinitionId %s is not a valid BSON ObjectId.", testDefinitionId));\r
+ }\r
+ ObjectId oiTestDefintionId = new ObjectId(testDefinitionId);\r
+\r
+ // Find the testDefinition\r
+ TestDefinition testDefinition =\r
+ Generic.findByIdGeneric(testDefinitionRepository, oiTestDefintionId);\r
+ if (testDefinition == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format("Test definition with id, %s, was not found.", testDefinitionId));\r
+ }\r
+ // permission checking\r
+ Group testDefGroup = Utilities.resolveOptional(groupRepository.findById(testDefinition.getGroupId().toString()));\r
+ if (testDefGroup == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Can not find test definition's group, id: %s", testDefinition.getGroupId().toString()));\r
+ }\r
+ // if not otf email and is not authorized\r
+// if (PermissionChecker.hasReadPermission(mechanizedIdUser, testDefGroup, groupRepository)) {\r
+//// return ResponseUtility.Build.unauthorizedWithMessage(\r
+//// String.format(\r
+//// "MechanizedId, %s, does not have read access to test definition in group with name, %s",\r
+//// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+//// }\r
+//// if (PermissionChecker.hasWritePermission(mechanizedIdUser, testDefGroup)) {\r
+//// return ResponseUtility.Build.unauthorizedWithMessage(\r
+//// String.format(\r
+//// "MechanizedId, %s, does not have write access to the group with name, %s",\r
+//// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+//// }\r
+ if (PermissionChecker.hasPermissionTo(mechanizedIdUser, testDefGroup,\r
+ Arrays.asList(UserPermission.Permission.READ,UserPermission.Permission.WRITE),groupRepository))\r
+ {\r
+ return ResponseUtility.Build.unauthorizedWithMessage(\r
+ String.format(\r
+ "MechanizedId, %s, does not have access (read/write) to the group with name, %s",\r
+ mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+ }\r
+ // Get the latest version of the test definition to link it with the test instance\r
+ BpmnInstance bpmnInstance = findBpmnInstance(testDefinition, version, false);\r
+ if (bpmnInstance == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format(\r
+ "Test definition with id, %s, does not have any versions associated with it.",\r
+ testDefinitionId));\r
+ }\r
+\r
+ TestInstance testInstance =\r
+ new TestInstance(\r
+ new ObjectId(),\r
+ request.getTestInstanceName(),\r
+ request.getTestInstanceDescription(),\r
+ testDefinition.getGroupId(),\r
+ testDefinition.get_id(),\r
+ bpmnInstance.getProcessDefinitionId(),\r
+ request.isUseLatestTestDefinition(),\r
+ false,\r
+ request.isSimulationMode(),\r
+ request.getMaxExecutionTimeInMillis(),\r
+ request.getPfloInput(),\r
+ new HashMap<>(),\r
+ request.getSimulationVthInput(),\r
+ request.getTestData(),\r
+ request.getVthInput(),\r
+ new Date(System.currentTimeMillis()),\r
+ new Date(System.currentTimeMillis()),\r
+ mechanizedIdUser.get_id(),\r
+ mechanizedIdUser.get_id());\r
+\r
+ return Response.ok()\r
+ .type(MediaType.APPLICATION_JSON_TYPE)\r
+ .entity(testInstance.toString())\r
+ .build();\r
+ } catch (Exception e) {\r
+ Utilities.printStackTrace(e, LogLevel.ERROR);\r
+ return ResponseUtility.Build.internalServerError();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Response createByProcessDefinitionKey(\r
+ String processDefinitionKey, String authorization, TestInstanceCreateRequest request) {\r
+ try {\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format(\r
+ "%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ // Check if the String correctly parses as an ObjectId.\r
+ if (Strings.isNullOrEmpty(processDefinitionKey)) {\r
+ return ResponseUtility.Build.badRequestWithMessage("The processDefinitionKey is required.");\r
+ }\r
+\r
+ // Find the testDefinition\r
+ TestDefinition testDefinition =\r
+ testDefinitionRepository.findByProcessDefinitionKey(processDefinitionKey).orElse(null);\r
+ if (testDefinition == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format(\r
+ "Test definition with processDefinitionKey, %s, was not found.",\r
+ processDefinitionKey));\r
+ }\r
+\r
+ Group testDefGroup = Utilities.resolveOptional(groupRepository.findById(testDefinition.getGroupId().toString()));\r
+ if (testDefGroup == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Can not find test definition's group, id: %s", testDefinition.getGroupId().toString()));\r
+ }\r
+ // if not otf email and is not authorized\r
+// if (PermissionChecker.hasReadPermission(mechanizedIdUser, testDefGroup, groupRepository)) {\r
+// return ResponseUtility.Build.unauthorizedWithMessage(\r
+// String.format(\r
+// "MechanizedId, %s, does not have read access to test definition in group with name, %s",\r
+// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+// }\r
+// if (PermissionChecker.hasWritePermission(mechanizedIdUser, testDefGroup)) {\r
+// return ResponseUtility.Build.unauthorizedWithMessage(\r
+// String.format(\r
+// "MechanizedId, %s, does not have write access to the group with name, %s",\r
+// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+// }\r
+ if (PermissionChecker.hasPermissionTo(mechanizedIdUser, testDefGroup,\r
+ Arrays.asList(UserPermission.Permission.READ,UserPermission.Permission.WRITE),groupRepository))\r
+ {\r
+ return ResponseUtility.Build.unauthorizedWithMessage(\r
+ String.format(\r
+ "MechanizedId, %s, does not have access (read/write) to the group with name, %s",\r
+ mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+ }\r
+ // Get the latest version of the test definition to link it with the test instance\r
+ BpmnInstance bpmnInstance = findBpmnInstance(testDefinition, Integer.MIN_VALUE, false);\r
+ if (bpmnInstance == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format(\r
+ "Test definition with id, %s, does not have any versions associated with it.",\r
+ testDefinition.get_id().toString()));\r
+ }\r
+\r
+ TestInstance testInstance =\r
+ new TestInstance(\r
+ new ObjectId(),\r
+ request.getTestInstanceName(),\r
+ request.getTestInstanceDescription(),\r
+ testDefinition.getGroupId(),\r
+ testDefinition.get_id(),\r
+ bpmnInstance.getProcessDefinitionId(),\r
+ request.isUseLatestTestDefinition(),\r
+ false,\r
+ request.isSimulationMode(),\r
+ request.getMaxExecutionTimeInMillis(),\r
+ request.getPfloInput(),\r
+ new HashMap<>(),\r
+ request.getSimulationVthInput(),\r
+ request.getTestData(),\r
+ request.getVthInput(),\r
+ new Date(System.currentTimeMillis()),\r
+ new Date(System.currentTimeMillis()),\r
+ mechanizedIdUser.get_id(),\r
+ mechanizedIdUser.get_id());\r
+\r
+ return Response.ok()\r
+ .type(MediaType.APPLICATION_JSON_TYPE)\r
+ .entity(testInstance.toString())\r
+ .build();\r
+ } catch (Exception e) {\r
+ Utilities.printStackTrace(e, LogLevel.ERROR);\r
+ return ResponseUtility.Build.internalServerError();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Response createByProcessDefinitionKey(\r
+ String processDefinitionKey,\r
+ int version,\r
+ String authorization,\r
+ TestInstanceCreateRequest request) {\r
+ try {\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format(\r
+ "%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ // Check if the String correctly parses as an ObjectId.\r
+ if (Strings.isNullOrEmpty(processDefinitionKey)) {\r
+ return ResponseUtility.Build.badRequestWithMessage("The processDefinitionKey is required.");\r
+ }\r
+\r
+ // Find the testDefinition\r
+ TestDefinition testDefinition =\r
+ testDefinitionRepository.findByProcessDefinitionKey(processDefinitionKey).orElse(null);\r
+ if (testDefinition == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format(\r
+ "Test definition with processDefinitionKey, %s, was not found.",\r
+ processDefinitionKey));\r
+ }\r
+\r
+ Group testDefGroup = Utilities.resolveOptional(groupRepository.findById(testDefinition.getGroupId().toString()));\r
+ if (testDefGroup == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Can not find test definition's group, id: %s", testDefinition.getGroupId().toString()));\r
+ }\r
+ // if not otf email and is not authorized\r
+// if (PermissionChecker.hasReadPermission(mechanizedIdUser, testDefGroup, groupRepository)) {\r
+// return ResponseUtility.Build.unauthorizedWithMessage(\r
+// String.format(\r
+// "MechanizedId, %s, does not have read access to test definition in group with name, %s",\r
+// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+// }\r
+// if (PermissionChecker.hasWritePermission(mechanizedIdUser, testDefGroup)) {\r
+// return ResponseUtility.Build.unauthorizedWithMessage(\r
+// String.format(\r
+// "MechanizedId, %s, does not have write access to the group with name, %s",\r
+// mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+// }\r
+ if (PermissionChecker.hasPermissionTo(mechanizedIdUser, testDefGroup,\r
+ Arrays.asList(UserPermission.Permission.READ,UserPermission.Permission.WRITE),groupRepository))\r
+ {\r
+ return ResponseUtility.Build.unauthorizedWithMessage(\r
+ String.format(\r
+ "MechanizedId, %s, does not have access (read/write) to the group with name, %s",\r
+ mechanizedIdUser.getEmail(), testDefGroup.getGroupName()));\r
+ }\r
+ // Get the latest version of the test definition to link it with the test instance\r
+ BpmnInstance bpmnInstance = findBpmnInstance(testDefinition, version, false);\r
+ if (bpmnInstance == null) {\r
+ return ResponseUtility.Build.notFoundWithMessage(\r
+ String.format(\r
+ "Test definition with id, %s, does not have any versions associated with it.",\r
+ testDefinition.get_id().toString()));\r
+ }\r
+\r
+ TestInstance testInstance =\r
+ new TestInstance(\r
+ new ObjectId(),\r
+ request.getTestInstanceName(),\r
+ request.getTestInstanceDescription(),\r
+ testDefinition.getGroupId(),\r
+ testDefinition.get_id(),\r
+ bpmnInstance.getProcessDefinitionId(),\r
+ request.isUseLatestTestDefinition(),\r
+ false,\r
+ request.isSimulationMode(),\r
+ request.getMaxExecutionTimeInMillis(),\r
+ request.getPfloInput(),\r
+ new HashMap<>(),\r
+ request.getSimulationVthInput(),\r
+ request.getTestData(),\r
+ request.getVthInput(),\r
+ new Date(System.currentTimeMillis()),\r
+ new Date(System.currentTimeMillis()),\r
+ mechanizedIdUser.get_id(),\r
+ mechanizedIdUser.get_id());\r
+\r
+ return Response.ok()\r
+ .type(MediaType.APPLICATION_JSON_TYPE)\r
+ .entity(testInstance.toString())\r
+ .build();\r
+ } catch (Exception e) {\r
+ Utilities.printStackTrace(e, LogLevel.ERROR);\r
+ return ResponseUtility.Build.internalServerError();\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Response findById(String testInstanceId, String authorization) {\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format("%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ // Check if the testInstanceId is a valid BSON ObjectI, otherwise return a bad request\r
+ // response.\r
+ if (!Utilities.isObjectIdValid(testInstanceId)) {\r
+ String error =\r
+ String.format(\r
+ "%sThe testInstanceId, %s, is not a valid ObjectId (BSON).",\r
+ logPrefix, testInstanceId);\r
+ return ResponseUtility.Build.badRequestWithMessage(error);\r
+ }\r
+\r
+ // Create an ObjectId now that we know the provided String was valid.\r
+ ObjectId oiTestInstanceId = new ObjectId(testInstanceId);\r
+ // Check if the testInstance exists, otherwise return a not found response.\r
+ TestInstance testInstance = Generic.findByIdGeneric(testInstanceRepository, oiTestInstanceId);\r
+ if (testInstance == null) {\r
+ String error =\r
+ String.format(\r
+ "%sThe testInstance with _id, %s, was not found.", logPrefix, testInstanceId);\r
+ return ResponseUtility.Build.notFoundWithMessage(error);\r
+ }\r
+\r
+ Group testInstanceGroup = Utilities.resolveOptional(groupRepository.findById(testInstance.getGroupId().toString()));\r
+ if (testInstanceGroup == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Can not find test instance's group, group name :%s", testInstance.get_id().toString()));\r
+ }\r
+ if (!PermissionChecker.hasPermissionTo(mechanizedIdUser,testInstanceGroup,UserPermission.Permission.READ,groupRepository)) {\r
+ return ResponseUtility.Build.unauthorizedWithMessage(\r
+ String.format(\r
+ "User %s does not have read access to test instance group, group name: %s.",\r
+ mechanizedIdUser.getEmail(), testInstanceGroup.getGroupName()));\r
+ }\r
+ return Response.ok(testInstance.toString(), MediaType.APPLICATION_JSON_TYPE).build();\r
+ }\r
+\r
+ @Override\r
+ public Response findByProcessDefinitionKey(String processDefinitionKey, String authorization) {\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format("%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ Optional<TestDefinition> optionalTestDefinition =\r
+ testDefinitionRepository.findByProcessDefinitionKey(processDefinitionKey);\r
+ TestDefinition testDefinition = optionalTestDefinition.orElse(null);\r
+ if (testDefinition == null) {\r
+ return Utilities.Http.BuildResponse.badRequestWithMessage(\r
+ String.format(\r
+ "Cannot find test instance because a test"\r
+ + " definition with the process definition key (%s) does not exist.",\r
+ processDefinitionKey));\r
+ }\r
+\r
+ List<TestInstance> testInstances =\r
+ testInstanceRepository.findAllByTestDefinitionId(testDefinition.get_id());\r
+ if (testInstances.isEmpty()) {\r
+ return Utilities.Http.BuildResponse.badRequestWithMessage(\r
+ String.format(\r
+ "No test instances found with process " + "definition key (%s).",\r
+ processDefinitionKey));\r
+ }\r
+\r
+ List<TestInstance> result = new ArrayList<>();\r
+ for (TestInstance testInstance : testInstances) {\r
+ Group testInstanceGroup = Utilities.resolveOptional(groupRepository.findById(testInstance.getGroupId().toString()));\r
+ if (testInstanceGroup != null && PermissionChecker.hasPermissionTo(mechanizedIdUser,testInstanceGroup,UserPermission.Permission.READ,groupRepository)) {\r
+ result.add(testInstance);\r
+ }\r
+ }\r
+\r
+ return Response.ok(result.toString()).build();\r
+ }\r
+\r
+ @Override\r
+ public Response findByProcessDefinitionKeyAndVersion(\r
+ String processDefinitionKey, String version, String authorization) {\r
+ // Check if a user associated with the mechanizedId used in the authorization header exists in\r
+ // the database.\r
+ User mechanizedIdUser = Utilities.findUserByAuthHeader(authorization, userRepository);\r
+ if (mechanizedIdUser == null) {\r
+ String[] decodedAuth = Utilities.decodeBase64AuthorizationHeader(authorization);\r
+ if (decodedAuth == null) {\r
+ return ResponseUtility.Build.badRequestWithMessage(\r
+ String.format("Unable to decode authorization header: %s", authorization));\r
+ }\r
+ String error =\r
+ String.format("%sMechanizedId is not onboarded with OTF. %s.", logPrefix, decodedAuth[0]);\r
+ return ResponseUtility.Build.unauthorizedWithMessage(error);\r
+ }\r
+\r
+ Optional<TestDefinition> optionalTestDefinition =\r
+ testDefinitionRepository.findByProcessDefinitionKey(processDefinitionKey);\r
+ TestDefinition testDefinition = optionalTestDefinition.orElse(null);\r
+\r
+ if (testDefinition == null) {\r
+ return Utilities.Http.BuildResponse.badRequestWithMessage(\r
+ String.format(\r
+ "Cannot find test instance because a test"\r
+ + " definition with the process definition key (%s) does not exist.",\r
+ processDefinitionKey));\r
+ }\r
+\r
+ int iVersion;\r
+ try {\r
+ iVersion = Integer.parseInt(version);\r
+ } catch (NumberFormatException nfe) {\r
+ return Utilities.Http.BuildResponse.badRequestWithMessage("Version must be a valid integer.");\r
+ }\r
+\r
+ BpmnInstance bpmnInstance =\r
+ testDefinition.getBpmnInstances().stream()\r
+ .filter(_bpmnInstance -> _bpmnInstance.getVersion() == iVersion)\r
+ .findAny()\r
+ .orElse(null);\r
+\r
+ if (bpmnInstance == null) {\r
+ return Utilities.Http.BuildResponse.badRequestWithMessage(\r
+ String.format("Cannot find any test instances using " + "version %s.", version));\r
+ }\r
+\r
+ List<TestInstance> testInstances =\r
+ testInstanceRepository.findAllByTestDefinitionIdAndPDId(\r
+ testDefinition.get_id(), bpmnInstance.getProcessDefinitionId());\r
+\r
+ if (testInstances.isEmpty()) {\r
+ return Utilities.Http.BuildResponse.badRequestWithMessage(\r
+ String.format(\r
+ "No test instances found with process " + "definition key (%s).",\r
+ processDefinitionKey));\r
+ }\r
+\r
+ List<TestInstance> result = new ArrayList<>();\r
+ for (TestInstance testInstance : testInstances) {\r
+ Group testInstanceGroup = Utilities.resolveOptional(groupRepository.findById(testInstance.getGroupId().toString()));\r
+ if (testInstanceGroup != null && PermissionChecker.hasPermissionTo(mechanizedIdUser,testInstanceGroup,UserPermission.Permission.READ,groupRepository)) {\r
+ result.add(testInstance);\r
+ }\r
+ }\r
+\r
+ return Response.ok(result.toString()).build();\r
+ }\r
+\r
+ private boolean isOtfMechanizedIdentifier(String email) {\r
+ return email.equalsIgnoreCase("email@localhost")\r
+ || email.equalsIgnoreCase("email@localhost")\r
+ || email.equalsIgnoreCase("email@localhost")\r
+ || email.equalsIgnoreCase("email@localhost")\r
+ || email.equalsIgnoreCase("email@localhost");\r
+ }\r
+\r
+ private BpmnInstance findBpmnInstance(TestDefinition testDefinition, int version, boolean latest)\r
+ throws Exception {\r
+ BpmnInstance bpmnInstance = null;\r
+ int maxVersion = Integer.MIN_VALUE;\r
+ // Check if the version exists\r
+ for (BpmnInstance bi : testDefinition.getBpmnInstances()) {\r
+ // If this field is null or empty, it means the bpmn hasn't been deployed, or there was a\r
+ // creation error on the Test Definition page (UI). Skip the field so the user isn't allowed\r
+ // to create a test instance based off this bpmn instance.\r
+ if (Strings.isNullOrEmpty(bi.getProcessDefinitionId())) {\r
+ continue;\r
+ }\r
+\r
+ // Split the processDefinitionId based on it's format:\r
+ // {processDefinitionKey}:{version}:{processDefinitionId}.\r
+ String processDefinitionId = bi.getProcessDefinitionId();\r
+ String[] processDefinitionIdSplit = processDefinitionId.split(":");\r
+ if (processDefinitionIdSplit.length != 3) {\r
+ throw new Exception(\r
+ String.format(\r
+ "testDefinition[%s].bpmnInstances.processDefinitionId[%s] is invalid.",\r
+ testDefinition.get_id().toString(), bi.getProcessDefinitionId()));\r
+ }\r
+\r
+ String sVersion = processDefinitionIdSplit[1];\r
+ int currentVersion = Integer.parseInt(sVersion);\r
+ if (latest && currentVersion > maxVersion) {\r
+ bpmnInstance = bi;\r
+ } else if (currentVersion == version) {\r
+ bpmnInstance = bi;\r
+ break;\r
+ }\r
+ }\r
+\r
+ return bpmnInstance;\r
+ }\r
+\r
+// private boolean isAuthorized(User user, Group group, String permission, GroupRepository groupRepository) {\r
+// if (isOtfMechanizedIdentifier(user.getEmail())) {\r
+// return true;\r
+// }\r
+// return PermissionChecker.isAuthorized(user, group, permission.toUpperCase(), groupRepository);\r
+// }\r
+}\r
+/*\r
+ PermissionChecker.hasReadPermission(mechanizedIdUser,testInstanceGroup,groupRepository)\r
+\r
+ PermissionChecker.hasPermission(mechanizedIdUser,testInstanceGroup,groupRepository, [READ, WRITE])\r
+ PermissionsMAp = PermissionChecker.Build.hasRead\r
+ */
\ No newline at end of file