--- /dev/null
+/* 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.camunda.workflow.utility;\r
+\r
+import static org.camunda.spin.Spin.JSON;\r
+\r
+import org.oran.otf.camunda.exception.TestExecutionException;\r
+import org.oran.otf.camunda.model.ExecutionConstants;\r
+import org.oran.otf.camunda.model.ExecutionConstants.ExecutionVariable;\r
+import org.oran.otf.common.model.TestExecution;\r
+import org.oran.otf.common.model.local.ParallelFlowInput;\r
+import org.oran.otf.common.utility.Utility;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import org.bson.types.ObjectId;\r
+import org.camunda.bpm.engine.delegate.DelegateExecution;\r
+import org.camunda.spin.json.SpinJsonNode;\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
+@Service\r
+public class WorkflowUtility {\r
+\r
+ private static Logger logger = LoggerFactory.getLogger(WorkflowUtility.class);\r
+ @Autowired\r
+ private RsaEncryptDecrypt rsaUtility;\r
+\r
+ public boolean verifyTestExecutionChecksum(\r
+ DelegateExecution execution, TestExecution testExecution) {\r
+ try {\r
+ byte[] enc = (byte[]) execution.getVariable(ExecutionVariable.TEST_EXECUTION);\r
+\r
+ String test = ""; // testExecution.createTestDescription();\r
+ String dec = new String(rsaUtility.decrypt(enc));\r
+ if (!dec.equals(test)) {\r
+ return false;\r
+ // throw new TestExecutionException("Modification Error: User modified platform data");\r
+ }\r
+ } catch (Exception e) {\r
+ logger.error(\r
+ execution.getCurrentActivityId()\r
+ + ": Failed to decrypt test execution. May have been tampered with.\n"\r
+ + e.getMessage());\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ public <T> T getExecutionVariable(Map<String, Object> variables, String key, Class<T> type) {\r
+ Object obj = variables.get(key);\r
+ if (obj == null) {\r
+ logger.error(String.format("Failed to get variable because the key %s does not exist.", key));\r
+ }\r
+ // return spin json nodes as maps\r
+ if (obj instanceof SpinJsonNode) {\r
+ SpinJsonNode node = (SpinJsonNode) obj;\r
+ if (!node.isObject()) {\r
+ throw new TestExecutionException(\r
+ "Unable to retrieve variable as type Map from the execution. Variable was set to SpinJsonNode");\r
+ }\r
+ Map<String, Object> map = (Map<String, Object>) node.mapTo(HashMap.class);\r
+ }\r
+\r
+ return type.isInstance(obj) ? type.cast(obj) : null;\r
+ }\r
+\r
+// public boolean hasPermission(User user, TestInstance testInstance) {\r
+// // Groups that the user holds a membership in.\r
+// List<UserGroup> userGroups = user.getGroups();\r
+// // The groupId associated with the test instance.\r
+// ObjectId targetGroupId = testInstance.getGroupId();\r
+// // Check if any of the groups has access to the test instance.\r
+// UserGroup targetGroup =\r
+// userGroups.stream()\r
+// .filter(userGroup -> userGroup.getGroupId().equals(targetGroupId))\r
+// .findAny()\r
+// .orElse(null);\r
+//\r
+// return targetGroup != null;\r
+// }\r
+\r
+ public TestExecution getTestExecution(Map<String, Object> variables, String logPrefix)\r
+ throws TestExecutionException {\r
+ // Get the current test execution object.\r
+ TestExecution testExecution =\r
+ this.getExecutionVariable(variables, ExecutionVariable.TEST_EXECUTION, TestExecution.class);\r
+ // Perform a null-check to ensure it is available. It's critical to throw an exception if it\r
+ // is not available since the object is essential for results.\r
+ if (testExecution == null) {\r
+ logger.error(logPrefix + " Test execution is null.");\r
+ throw new TestExecutionException("The test execution was not found.");\r
+ }\r
+ return testExecution;\r
+ }\r
+\r
+ public Map<String, Object> getTestData(Map<String, Object> variables, String logPrefix)\r
+ throws TestExecutionException {\r
+ // Get vthInput from the Camunda execution variable map.\r
+ @SuppressWarnings({"unchecked"})\r
+ Map<String, Object> testData =\r
+ (Map<String, Object>)\r
+ this.getExecutionVariable(variables, ExecutionVariable.TEST_DATA, Map.class);\r
+\r
+ if (testData == null) {\r
+ throw new TestExecutionException(\r
+ "Unable to retrieve testData as type Map from the execution.");\r
+ }\r
+ return testData;\r
+ }\r
+\r
+ public Object getTestDataByActivity(\r
+ Map<String, Object> variables, String currentActivityId, String logPrefix)\r
+ throws TestExecutionException, NullPointerException {\r
+ // Get vthInput from the Camunda execution variable map.\r
+ @SuppressWarnings({"unchecked"})\r
+ Map<String, Object> testData =\r
+ (Map<String, Object>)\r
+ this.getExecutionVariable(variables, ExecutionVariable.TEST_DATA, Map.class);\r
+\r
+ if (testData == null) {\r
+ throw new TestExecutionException(\r
+ "Unable to retrieve testData as type Map from the execution.");\r
+ }\r
+ Object activityParameters = testData.get(currentActivityId);\r
+ if (activityParameters == null) {\r
+ throw new NullPointerException(\r
+ logPrefix\r
+ + String.format(\r
+ "A testData parameter was not found for the activityId, %s.", currentActivityId));\r
+ }\r
+ return activityParameters;\r
+ }\r
+\r
+\r
+ public Map<String, ParallelFlowInput> getPfloInputByActivity(\r
+ Map<String, Object> variables, String currentActivityId, String logPrefix)\r
+ throws TestExecutionException, NullPointerException {\r
+ // Get vthInput from the Camunda execution variable map.\r
+ @SuppressWarnings({"unchecked"})\r
+ Map<String, Object> pfloInput =\r
+ (Map<String, Object>)\r
+ this.getExecutionVariable(variables, ExecutionVariable.PFLO_INPUT, Map.class);\r
+\r
+ if (pfloInput == null) {\r
+ throw new TestExecutionException(\r
+ "Unable to retrieve testData as type Map from the execution.");\r
+ }\r
+ Map<String, ParallelFlowInput> activityParameters =\r
+ (Map<String, ParallelFlowInput>) pfloInput.get(currentActivityId);\r
+ if (activityParameters == null) {\r
+ throw new NullPointerException(\r
+ logPrefix\r
+ + String.format(\r
+ "A plfoInput parameter was not found for the activityId, %s.",\r
+ currentActivityId));\r
+ }\r
+ return activityParameters;\r
+ }\r
+\r
+ public List<Map<String, Object>> getVthInput(\r
+ Map<String, Object> variables, String currentActivityId, String logPrefix)\r
+ throws TestExecutionException, NullPointerException, IllegalArgumentException {\r
+ // Get vthInput from the Camunda execution variable map.\r
+ @SuppressWarnings({"unchecked"})\r
+ Map<String, Object> vthInput =\r
+ (Map<String, Object>)\r
+ this.getExecutionVariable(variables, ExecutionVariable.VTH_INPUT, Map.class);\r
+\r
+ if (vthInput == null) {\r
+ throw new TestExecutionException(\r
+ "Unable to retrieve vthInput as type Map from the execution.");\r
+ }\r
+\r
+ // Get the current activityId to use as a key to retrieve the vthInput for this task.\r
+ // vthInput is expected to be a JSON array of size [1, inf)\r
+ Object oActivityParameters = vthInput.get(currentActivityId);\r
+ // Throw an exception if no parameters were found for this activity.\r
+ if (oActivityParameters == null) {\r
+ throw new NullPointerException(\r
+ logPrefix\r
+ + String.format(\r
+ "A vthInput parameter was not found for the activityId, %s.", currentActivityId));\r
+ }\r
+\r
+ List<Map<String, Object>> lActivityParameters;\r
+ // Legacy hack\r
+ try {\r
+ @SuppressWarnings("unchecked")\r
+ Map<String, Object> mActivityParameters = new HashMap<>();\r
+ mActivityParameters.put("method", "post");\r
+ mActivityParameters.put("payload", Utility.toMap(oActivityParameters));\r
+ Map<String, Object> headers = new HashMap<>();\r
+ headers.put("Content-Type", "application/json");\r
+ mActivityParameters.put("headers", headers);\r
+ lActivityParameters = new ArrayList();\r
+ lActivityParameters.add(mActivityParameters);\r
+ } catch (Exception e) {\r
+ try {\r
+ // Try to convert the parameters to an array of "vthInput(s)"\r
+ lActivityParameters = (List<Map<String, Object>>) Utility.toList(oActivityParameters);\r
+ } catch (Exception ee) {\r
+ throw new IllegalArgumentException(\r
+ String.format("Unable to parse the value for vthInput[%s].", currentActivityId));\r
+ }\r
+ }\r
+ return lActivityParameters;\r
+ }\r
+\r
+ public String getTestResult(Map<String, Object> variables, String logPrefix) {\r
+ String testResult =\r
+ this.getExecutionVariable(variables, ExecutionVariable.TEST_RESULT, String.class);\r
+ // Set the test result to UNKNOWN\r
+ if (testResult == null) {\r
+ logger.debug(\r
+ logPrefix\r
+ + "Unable to retrieve test result as primitive type String. Setting result to unknown.");\r
+ testResult = ExecutionConstants.TestResult.UNKNOWN;\r
+ }\r
+ return testResult;\r
+ }\r
+\r
+ public String getTestResultMessage(Map<String, Object> variables, String logPrefix) {\r
+ String testResultMessage =\r
+ this.getExecutionVariable(variables, ExecutionVariable.TEST_RESULT_MESSAGE, String.class);\r
+ // Set the test result to UNKNOWN\r
+ if (testResultMessage == null) {\r
+ testResultMessage = "";\r
+// logger.debug(\r
+// logPrefix\r
+// + "Unable to retrieve test result message as primitive type String. Setting message to empty string.");\r
+// testResultMessage = "";\r
+ }\r
+ return testResultMessage;\r
+ }\r
+\r
+ public Map<String, Object> getTestDetails(Map<String, Object> variables, String logPrefix)\r
+ throws TestExecutionException {\r
+ // Get test details as a String because it can be saved as one of many "JSON" types. Then try\r
+ // to convert it to a generic map.\r
+ String testDetailsString =\r
+ this.getExecutionVariable(variables, ExecutionVariable.TEST_DETAILS, String.class);\r
+ if (testDetailsString != null) {\r
+ // Use Spin to map the string to a Map.\r
+ @SuppressWarnings({"unchecked"})\r
+ Map<String, Object> mTestDetails;\r
+ try {\r
+ mTestDetails = JSON(testDetailsString).mapTo(HashMap.class);\r
+ } catch (Exception e) {\r
+ logger.error(\r
+ "Unable to convert testDetails to a map.\nError: "\r
+ + e.getMessage()\r
+ + "\ntestDetails: "\r
+ + testDetailsString);\r
+ mTestDetails = new HashMap<>();\r
+ }\r
+ return mTestDetails;\r
+ }\r
+\r
+ // get testDetails as a map.\r
+ @SuppressWarnings({"unchecked"})\r
+ Map<String, Object> testDetails =\r
+ (Map<String, Object>)\r
+ this.getExecutionVariable(variables, ExecutionVariable.TEST_DETAILS, Map.class);\r
+\r
+ if (testDetails == null) {\r
+ logger.debug(\r
+ logPrefix\r
+ + "Unable to retrieve test details as primitive type String. Setting to an empty JSON.");\r
+ testDetails = new HashMap<>();\r
+ }\r
+ return testDetails;\r
+ }\r
+}\r