added azure related code 28/1328/1 azure
authorRohan Patel <rp5811@att.com>
Fri, 1 Nov 2019 20:05:47 +0000 (16:05 -0400)
committerRohan Patel <rp5811@att.com>
Fri, 1 Nov 2019 20:13:24 +0000 (20:13 +0000)
Change-Id: Iec028f76f0260fa50a3c0eaa14536ea7dfcf5d72
Signed-off-by: Rohan Patel <rp5811@att.com>
74 files changed:
otf-camunda/docker/Dockerfile
otf-camunda/pom.xml
otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/CallTestHeadDelegate.java
otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/LogTestResultDelegate.java
otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/PostResultsToDMaaPDelegate.java
otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/AsynchronousTestInstanceCallable.java
otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/SynchronousTestInstanceCallable.java
otf-camunda/src/main/java/org/oran/otf/camunda/delegate/otf/common/runnable/TestHeadCallable.java
otf-camunda/src/main/java/org/oran/otf/camunda/listener/StartEventListener.java
otf-camunda/src/main/java/org/oran/otf/camunda/workflow/WorkflowProcessor.java
otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/ExternalTaskIncidentHandler.java
otf-camunda/src/main/java/org/oran/otf/camunda/workflow/handler/FailedJobIncidentHandler.java
otf-camunda/src/main/java/org/oran/otf/common/model/TestHead.java
otf-camunda/src/main/java/org/oran/otf/common/model/TestInstance.java
otf-camunda/src/main/java/org/oran/otf/common/utility/permissions/PermissionUtil.java
otf-camunda/src/main/java/org/oran/otf/spring/configuration/OTFMongoConfiguration.java
otf-camunda/src/main/resources/application.yaml
otf-frontend/Dockerfile
otf-frontend/client/config/karma.conf.js
otf-frontend/client/config/protractor.conf.js
otf-frontend/client/src/app/layout/modeler/modeler.component.ts
otf-frontend/client/src/app/shared/services/group.service.ts
otf-frontend/package.json
otf-frontend/server/config/custom-environment-variables.json
otf-frontend/server/config/default.json
otf-frontend/server/src/agenda/agenda.js
otf-frontend/server/src/feathers/app.hooks.js
otf-frontend/server/src/feathers/hooks/delete-definition.js
otf-frontend/server/src/feathers/hooks/delete-version.js
otf-frontend/server/src/feathers/hooks/filters.js
otf-frontend/server/src/feathers/hooks/insertShardKey.js [new file with mode: 0644]
otf-frontend/server/src/feathers/hooks/permissions/permissions.js
otf-frontend/server/src/feathers/index.js
otf-frontend/server/src/feathers/models/file.model.js
otf-frontend/server/src/feathers/models/groups.model.js
otf-frontend/server/src/feathers/models/jobs.model.js
otf-frontend/server/src/feathers/models/test-definitions.model.js
otf-frontend/server/src/feathers/models/test-executions.model.js
otf-frontend/server/src/feathers/models/test-heads.model.js
otf-frontend/server/src/feathers/models/test-instances.model.js
otf-frontend/server/src/feathers/models/users.model.js
otf-frontend/server/src/feathers/services/bpmn-upload/bpmn-upload.class.js
otf-frontend/server/src/feathers/services/bpmn-validate/bpmn-validate.class.js
otf-frontend/server/src/feathers/services/execute/execute.hooks.js
otf-frontend/server/src/feathers/services/file-transfer/file-transfer.class.js
otf-frontend/server/src/feathers/services/jobs/jobs.hooks.js
otf-frontend/server/src/feathers/services/users/users.service.js
otf-frontend/server/src/lib/azure-storage.js [new file with mode: 0644]
otf-frontend/server/src/lib/mongoose.js
otf-frontend/server/test/app.test.js
otf-frontend/server/test/hooks/group-filter.test.js
otf-frontend/server/test/services/bpmn-upload.test.js
otf-frontend/server/test/services/bpmn-validate.test.js
otf-frontend/server/test/services/groups-m.test.js
otf-frontend/server/test/services/groups.test.js
otf-frontend/server/test/services/health.test.js
otf-frontend/server/test/services/strategy-upload.test.js
otf-frontend/server/test/services/test-definition.test.js
otf-frontend/server/test/services/test-heads.test.js
otf-frontend/server/test/services/test-instances.test.js
otf-frontend/server/test/services/test-requests.test.js
otf-frontend/server/test/services/test-strategies.test.js
otf-frontend/server/test/services/tests.test.js
otf-frontend/server/test/services/users.test.js
otf-service-api/pom.xml
otf-service-api/src/main/java/org/oran/otf/api/config/DataConfig.java
otf-service-api/src/main/java/org/oran/otf/api/service/impl/TestInstanceServiceImpl.java
otf-service-api/src/main/java/org/oran/otf/api/service/impl/TestStrategyServiceImpl.java
otf-service-api/src/main/java/org/oran/otf/api/service/impl/VirtualTestHeadServiceImpl.java
otf-service-api/src/main/java/org/oran/otf/common/model/TestHead.java
otf-service-api/src/main/java/org/oran/otf/common/utility/database/TestExecutionUtility.java
otf-service-api/src/main/java/org/oran/otf/common/utility/permissions/PermissionUtil.java
otf-service-api/src/main/resources/application.properties
otf-service-api/src/test/java/org/oran/otf/api/tests/shared/MemoryDatabase.java

index d63564e..38a3ad0 100644 (file)
@@ -9,8 +9,8 @@ ENV OTF_MONGO_PASSWORD=password
 ENV OTF_MONGO_HOSTS=localhost:27017\r
 ENV OTF_MONGO_REPLICASET=rs0\r
 ENV OTF_MONGO_DATABASE=otf\r
-ENV OTF_CAMUNDA_DB_URL=localhost:3306/camunda\r
-ENV OTF_CAMUNDA_DB_USERNAME=root\r
+ENV OTF_CAMUNDA_DB_URL=localhost:3306/otf-camunda\r
+ENV OTF_CAMUNDA_DB_USERNAME=username\r
 ENV OTF_CAMUNDA_DB_PASSWORD=password\r
 ENV AAF_PERM_TYPE=type\r
 ENV CADI_HOSTNAME=localhost\r
index ad4deb3..4fa0994 100644 (file)
@@ -74,7 +74,7 @@
     </dependency>\r
     <dependency>\r
       <groupId>org.camunda.bpm.springboot</groupId>\r
-      <artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>\r
+      <artifactId>camunda-bpm-spring-boot-starter-webapp-ee</artifactId>\r
       <version>${camunda.springboot.version}</version>\r
     </dependency>\r
     <dependency>\r
 \r
     <cadi.version>2.1.10</cadi.version>\r
     <docker.registry>registry.hub.docker.io</docker.registry>\r
-    <camunda.version>7.10.0</camunda.version>\r
+    <camunda.version>7.10.0-ee</camunda.version>\r
     <camunda.bpm.assert.version>2.0-alpha2</camunda.bpm.assert.version>\r
     <camunda.bpm.base.version>7.10.0</camunda.bpm.base.version>\r
     <camunda.bpm.mail.version>1.1.0</camunda.bpm.mail.version>\r
     <camunda.bpm.reactor.version>2.1.2</camunda.bpm.reactor.version>\r
-    <camunda.bpm.version>7.10.4</camunda.bpm.version>\r
+    <camunda.bpm.version>7.10.4-ee</camunda.bpm.version>\r
     <camunda.bpm.external-task-client.version>1.1.1</camunda.bpm.external-task-client.version>\r
     <camunda.mockito.version>3.2.1</camunda.mockito.version>\r
     <camunda.spin.version>1.6.6</camunda.spin.version>\r
index 45511b0..b47dd13 100644 (file)
@@ -224,8 +224,10 @@ public class CallTestHeadDelegate implements JavaDelegate {
 //    WorkflowTask.printWorkflowTaskResources();\r
   }\r
 \r
-  private void saveTestHeadResults(String businessKey) {\r
+  private void saveTestHeadResults(String businessKey, String groupId) {\r
     Query query = new Query();\r
+    //TODO: Update needs to be changed to work with Azure\r
+    query.addCriteria(Criteria.where("groupId").is(groupId));\r
     query.addCriteria(Criteria.where("businessKey").is(businessKey));\r
     Update update = new Update();\r
     update.set("testHeadResults", testHeadResults);\r
index 0ecb37e..8d01f8c 100644 (file)
 \r
 package org.oran.otf.camunda.delegate.otf.common;\r
 \r
+import com.mongodb.client.result.UpdateResult;\r
 import org.oran.otf.camunda.exception.TestExecutionException;\r
 import org.oran.otf.camunda.model.ExecutionConstants;\r
 import org.oran.otf.camunda.workflow.utility.WorkflowUtility;\r
 import org.oran.otf.common.model.TestExecution;\r
 import org.oran.otf.common.repository.TestExecutionRepository;\r
 import org.oran.otf.common.utility.Utility;\r
-import com.mongodb.client.result.UpdateResult;\r
 \r
 import java.util.Arrays;\r
 import java.util.Date;\r
@@ -90,6 +90,8 @@ public class LogTestResultDelegate implements JavaDelegate {
     // processBusinessKey from the delegate execution because it is saved to the database before the\r
     // user can modify the value.\r
     Query query = new Query();\r
+    //TODO: Update query needs to be changed for Azure\r
+    query.addCriteria((Criteria.where("groupId").is(testExecution.getGroupId())));\r
     query.addCriteria(Criteria.where("businessKey").is(execution.getProcessBusinessKey()));\r
     Update update = new Update();\r
     update.set("testResult", testExecution.getTestResult());\r
index 41b9d8a..c3395be 100644 (file)
@@ -44,6 +44,7 @@ import org.springframework.context.annotation.Conditional;
 import org.springframework.stereotype.Component;\r
 \r
 @Component\r
+@Conditional(value= FilterCondition.class)\r
 public class PostResultsToDMaaPDelegate implements JavaDelegate {\r
 \r
   private static Logger logger = LoggerFactory.getLogger(PostResultsToDMaaPDelegate.class);\r
index 680688c..67e8bd1 100644 (file)
@@ -146,6 +146,8 @@ public class AsynchronousTestInstanceCallable extends ProcessEngineAwareService
       // Add the testExecution to the parentTestExecution\r
       parentTestExecution.getTestInstanceResults().add(testExecution);\r
       Query query = new Query();\r
+      //TODO: Update for Azure\r
+      query.addCriteria((Criteria.where("groupId").is(parentTestExecution.getGroupId())));\r
       query.addCriteria(Criteria.where("_id").is(parentTestExecution.get_id()));\r
       // Also add businessKey as a criteria because the object won't be found if the business key\r
       // was somehow modified in the workflow.\r
index cffdc1e..87559e9 100644 (file)
@@ -164,6 +164,8 @@ public class SynchronousTestInstanceCallable extends ProcessEngineAwareService
       // Add the testExecution to the parentTestExecution\r
       parentTestExecution.getTestInstanceResults().add(testExecution);\r
       Query query = new Query();\r
+      //TODO: Update for Azure\r
+      query.addCriteria((Criteria.where("groupId").is(parentTestExecution.getGroupId())));\r
       query.addCriteria(Criteria.where("_id").is(parentTestExecution.get_id()));\r
       // Also add businessKey as a criteria because the object won't be found if the business key\r
       // was somehow modified in the workflow.\r
index d0ee267..1121b8a 100644 (file)
@@ -209,6 +209,8 @@ public class TestHeadCallable implements Callable<TestHeadResult> {
 \r
   private void saveResult(TestExecution testExecution) {\r
     Query query = new Query();\r
+    //TODO: Update for Azure\r
+    query.addCriteria((Criteria.where("groupId").is(testExecution.getGroupId())));\r
     query.addCriteria(Criteria.where("_id").is(testExecution.get_id()));\r
     // Also add businessKey as a criteria because the object won't be found if the business key\r
     // was somehow modified in the workflow.\r
index 9fa6d14..b8a7424 100644 (file)
@@ -20,6 +20,7 @@ import org.oran.otf.camunda.exception.TestExecutionException;
 import org.oran.otf.camunda.model.ExecutionConstants;\r
 import org.oran.otf.camunda.workflow.utility.WorkflowUtility;\r
 import org.oran.otf.common.model.TestExecution;\r
+import org.oran.otf.common.repository.TestExecutionRepository;\r
 import org.oran.otf.common.utility.Utility;\r
 import com.google.gson.JsonObject;\r
 import com.mongodb.client.result.UpdateResult;\r
@@ -83,8 +84,9 @@ public class StartEventListener extends ReactorExecutionListener {
     testExecution.setTestResult(result);\r
     testExecution.setProcessInstanceId(execution.getProcessInstanceId());\r
 \r
-\r
     Query query = new Query();\r
+    //TODO: Update needs new query for Azure\r
+    query.addCriteria((Criteria.where("groupId").is(testExecution.getGroupId())));\r
     query.addCriteria(Criteria.where("businessKey").is(execution.getProcessBusinessKey()));\r
     Update update = new Update();\r
     update.set("testResult", testExecution.getTestResult());\r
index 10a1dfd..3230fb7 100644 (file)
@@ -345,6 +345,8 @@ public class WorkflowProcessor extends ProcessEngineAwareService {
             // available.\r
             testExecution.setProcessInstanceId(processInstance.getProcessInstanceId());\r
             Query query = new Query();\r
+            //TODO: Update for Azure\r
+            query.addCriteria((Criteria.where("groupId").is(testExecution.getGroupId())));\r
             query.addCriteria(Criteria.where("_id").is(testExecution.get_id()));\r
             // Also add businessKey as a criteria because the object won't be found if the business key\r
             // was somehow modified in the workflow.\r
@@ -407,6 +409,8 @@ public class WorkflowProcessor extends ProcessEngineAwareService {
             // available.\r
             testExecution.setProcessInstanceId(processInstance.getProcessInstanceId());\r
             Query query = new Query();\r
+            //TODO: Update for Azure\r
+            query.addCriteria((Criteria.where("groupId").is(testExecution.getGroupId())));\r
             query.addCriteria(Criteria.where("_id").is(testExecution.get_id()));\r
             // Also add businessKey as a criteria because the object won't be found if the business key\r
             // was somehow modified in the workflow.\r
index 0e7d2ca..0cd4397 100644 (file)
@@ -107,6 +107,7 @@ public class ExternalTaskIncidentHandler implements IncidentHandler {
     testExecution.setTestResult(testResult);\r
     testExecution.setTestResultMessage(testResultMessage);\r
     Query query = new Query();\r
+    query.addCriteria(Criteria.where("groupId").is(testExecution.getGroupId()));\r
     query.addCriteria(Criteria.where("_id").is(testExecution.get_id()));\r
     // Also add businessKey as a criteria because the object won't be found if the business key\r
     // was somehow modified in the workflow.\r
index f01d550..c4cdf0e 100644 (file)
@@ -111,6 +111,7 @@ public class FailedJobIncidentHandler implements IncidentHandler {
     testExecution.setTestResult(testResult);\r
     testExecution.setTestResultMessage(testResultMessage);\r
     Query query = new Query();\r
+    query.addCriteria(Criteria.where("groupId").is(testExecution.getGroupId()));\r
     query.addCriteria(Criteria.where("_id").is(testExecution.get_id()));\r
     // Also add businessKey as a criteria because the object won't be found if the business key\r
     // was somehow modified in the workflow.\r
index 7f4bcbc..35bbc95 100644 (file)
@@ -16,6 +16,7 @@
 \r
 package org.oran.otf.common.model;\r
 \r
+import javax.validation.constraints.NotNull;\r
 import org.oran.otf.common.utility.gson.Convert;\r
 import java.io.Serializable;\r
 import java.util.Date;\r
@@ -23,6 +24,7 @@ import java.util.Map;
 \r
 import org.bson.types.ObjectId;\r
 import org.springframework.data.annotation.Id;\r
+import org.springframework.data.mongodb.core.index.CompoundIndex;\r
 import org.springframework.data.mongodb.core.index.Indexed;\r
 import org.springframework.data.mongodb.core.mapping.Document;\r
 \r
@@ -34,7 +36,8 @@ public class TestHead implements Serializable {
   @Id\r
   private ObjectId _id;\r
 \r
-  @Indexed(unique = true)\r
+  //@Indexed(unique = true)\r
+  @NotNull\r
   private String testHeadName;\r
 \r
   private String testHeadDescription;\r
index 96fcfa9..39ea953 100644 (file)
@@ -16,6 +16,7 @@
 \r
 package org.oran.otf.common.model;\r
 \r
+import javax.ws.rs.PATCH;\r
 import org.oran.otf.common.model.local.ParallelFlowInput;\r
 import org.oran.otf.common.utility.gson.Convert;\r
 import java.io.Serializable;\r
index 2a180bc..d36d3e1 100644 (file)
@@ -147,7 +147,7 @@ public class PermissionUtil {
 \r
         for(Group group : groupsToCheck)\r
         {\r
-            if(group.getParentGroupId() != null) // if there is a parent\r
+            if(group != null && group.getParentGroupId() != null) // if there is a parent\r
             {\r
                 String parentId = group.getParentGroupId().toString();\r
                 Group parentGroup = groupMap.get(parentId);\r
index 665823f..5e034cf 100644 (file)
@@ -57,7 +57,8 @@ public class OTFMongoConfiguration extends AbstractMongoConfiguration {
         MongoCredential.createScramSha1Credential(username, database, password.toCharArray());\r
 \r
     MongoClientOptions options =\r
-        MongoClientOptions.builder().sslEnabled(false).requiredReplicaSetName(replicaSet).build();\r
+       // MongoClientOptions.builder().sslEnabled(false).requiredReplicaSetName(replicaSet).build();\r
+    MongoClientOptions.builder().sslEnabled(true).build();\r
 \r
     String[] hostArray = hosts.split(",");\r
     ArrayList<ServerAddress> hosts = new ArrayList<>();\r
index bf92302..2147bb1 100644 (file)
@@ -25,7 +25,7 @@ otf:
       username: ${OTF_CAMUNDA_DB_USERNAME}\r
       password: ${OTF_CAMUNDA_DB_PASSWORD}\r
   cadi:\r
-    enabled: true\r
+    enabled: false\r
     aaf-mech-id: ${AAF_ID}\r
     aaf-mech-password: ${AAF_MECH_PASSWORD}\r
     aaf-perm-type: ${AAF_PERM_TYPE}\r
@@ -64,11 +64,11 @@ server:
   port.http: 8000\r
   tomcat.max-threads: 800\r
 #  ssl:\r
-    key-store-type: 'PKCS12'\r
-    key-store: ${OTF_CERT_PATH}\r
-    key-store-password: ${OTF_CERT_PASS}\r
+    #key-store-type: 'PKCS12'\r
+    #key-store: ${OTF_CERT_PATH}\r
+    #key-store-password: ${OTF_CERT_PASS}\r
 security:\r
-  https-only: true\r
+  https-only: false\r
   require-ssl: false\r
   server.port: 8443\r
   server.port.http: 8080\r
index 6caf80d..35b68c7 100644 (file)
@@ -14,6 +14,10 @@ ENV SERVICEAPI_AAFPASSWORD=password
 ENV CAMUNDAAPI_URL=https://localhost:31313/\r
 ENV CAMUNDAAPI_AAFID=username\r
 ENV CAMUNDAAPI_AAFPASSWORD=password\r
+ENV AZURE_STORAGE_ACCOUNT=otffiles\r
+ENV AZURE_STORAGE_CONTAINER=files\r
+ENV AZURE_STORAGE_KEY=key123\r
+ENV MONGO_CONNECTION_STRING=connection_string\r
 ENV MONGO_BASEURL=localhost:27017/\r
 ENV MONGO_DBOTF=otf\r
 ENV MONGO_REPLICASET=rs0\r
index 3be39c4..74664d0 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 // Karma configuration file, see link for more information\r
 // https://karma-runner.github.io/1.0/config/configuration-file.html\r
 \r
index b1a56c1..148a41f 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 // Protractor configuration file, see link for more information\r
 // https://github.com/angular/protractor/blob/master/lib/config.ts\r
 \r
index c090769..613dd22 100644 (file)
@@ -705,16 +705,17 @@ export class ModelerComponent implements OnInit {
   //Get the xml of the default bpmn file\r
   async getDefaultFlow() {\r
     return new Promise((resolve, reject) => {\r
-      this._fileTransfer.get('5d0a5357e6624a3ef0d16164').subscribe(\r
-        data => {\r
-          let bpmn = new Buffer(data as Buffer);\r
-          resolve(bpmn.toString());\r
-        },\r
-        err => {\r
-          this.errorPopup(err.toString());\r
-          reject(err);\r
-        }\r
-      );\r
+      resolve("<?xml version=\"1.0\" encoding=\"UTF-8\"?\>\<bpmn:definitions targetNamespace=\"http:\/\/bpmn.io\/schema\/bpmn\" \>\<bpmn:process id=\"\" isExecutable=\"true\"\>\<bpmn:startEvent id=\"StartEvent_1\" /\>\</bpmn:process\>\<bpmndi:BPMNDiagram id=\"BPMNDiagram_1\"\>\<bpmndi:BPMNPlane id=\"BPMNPlane_1\" bpmnElement=\"Process_1ai7kus\"\>\<bpmndi:BPMNShape id=\"_BPMNShape_StartEvent_2\" bpmnElement=\"StartEvent_1\"\>\<dc:Bounds x=\"179\" y=\"159\" width=\"36\" height=\"36\" /\>\</bpmndi:BPMNShape\>\</bpmndi:BPMNPlane\>\</bpmndi:BPMNDiagram\>\</bpmn:definitions\>")\r
+      // this._fileTransfer.get('5d0a5357e6624a3ef0d16164').subscribe(\r
+      //   data => {\r
+      //     let bpmn = new Buffer(data as Buffer);\r
+      //     resolve(bpmn.toString());\r
+      //   },\r
+      //   err => {\r
+      //     this.errorPopup(err.toString());\r
+      //     reject(err);\r
+      //   }\r
+      // );\r
     });\r
   }\r
 \r
@@ -730,6 +731,7 @@ export class ModelerComponent implements OnInit {
       this._fileTransfer.get(this.ptd.currentInstance.bpmnFileId).subscribe(\r
         result => {\r
           let bpmn = new Buffer(result as Buffer);\r
+          console.log(bpmn.toString())\r
           resolve(bpmn.toString());\r
         },\r
         err => {\r
index 477ae92..1d41e1e 100644 (file)
@@ -129,7 +129,7 @@ export class GroupService extends ModelService {
       if (mappedArr.hasOwnProperty(_id)) {\r
         mappedElem = mappedArr[_id];\r
         // If the element is not at the root level, add it to its parent array of children.\r
-        if (mappedElem.parentGroupId) {\r
+        if (mappedElem.parentGroupId && mappedArr[mappedElem['parentGroupId']]) {\r
           mappedArr[mappedElem['parentGroupId']]['children'].push(mappedElem);\r
         }\r
         // If the element is at the root level, add it to first level elements array.\r
index 2971bcb..7a107ae 100644 (file)
@@ -44,6 +44,7 @@
     "@angular/platform-browser": "^7.0.2",\r
     "@angular/platform-browser-dynamic": "^7.0.2",\r
     "@angular/router": "^6.1.7",\r
+    "@azure/storage-blob": "^10.5.0",\r
     "@casl/ability": "^3.1.2",\r
     "@casl/angular": "^2.1.0",\r
     "@casl/mongoose": "^2.3.1",\r
@@ -86,7 +87,7 @@
     "express-rate-limit": "^3.3.2",\r
     "feathers-authentication-management": "^2.0.1",\r
     "feathers-hooks-common": "^4.17.14",\r
-    "feathers-mongoose": "^6.2.0",\r
+    "feathers-mongoose": "^8.1.0",\r
     "feathers-permissions": "^0.2.1",\r
     "file-saver": "^2.0.1",\r
     "font-awesome": "^4.7.0",\r
     "mat-progress-buttons": "^7.0.10",\r
     "material-design-icons": "^3.0.1",\r
     "moment": "^2.22.2",\r
-    "mongoose": "^5.6.4",\r
-    "mongoose-gridfs": "^0.5.0",\r
+    "mongoose": "^5.7.1",\r
+    "mongoose-gridfs": "^1.2.10",\r
     "multer": "^1.4.1",\r
     "ng-cli-pug-loader": "^0.1.7",\r
     "ng2-codemirror": "^1.1.3",\r
index a261f9a..af499d3 100644 (file)
         "aafId": "CAMUNDAAPI_AAFID",\r
         "aafPassword": "CAMUNDAAPI_AAFPASSWORD"\r
     },\r
+    "azure": {\r
+        "storage": {\r
+            "account": "AZURE_STORAGE_ACCOUNT",\r
+            "key": "AZURE_STORAGE_KEY",\r
+            "container": "AZURE_STORAGE_CONTAINER"\r
+        }\r
+    },\r
     "mongo": {\r
         "baseUrl": "MONGO_BASEURL",\r
         "dbOtf": "MONGO_DBOTF",\r
         "replicaSet": "MONGO_REPLICASET",\r
         "username": "MONGO_USERNAME",\r
-        "password": "MONGO_PASSWORD"\r
+        "password": "MONGO_PASSWORD",\r
+        "connectionString": "MONGO_CONNECTION_STRING"\r
     },\r
     "otf": {\r
       "url" : "OTF_URL",\r
index dee3f8b..8e6a8b0 100644 (file)
@@ -2,7 +2,7 @@
   "host": "0.0.0.0",\r
   "path": "otf/api/",\r
   "base-path": "otf/api/v1/",\r
-  "port": 80,\r
+  "port": 8080,\r
   "ssl": false,\r
   "public": "../../../client/dist/",\r
   "paginate": {\r
index 5094b6b..9bcb532 100644 (file)
@@ -20,8 +20,11 @@ const mongoData = require('config').mongo;
 const jobTypes = ['test-execution-job'];\r
 const agenda = new Agenda({\r
        db: {\r
-               address: 'mongodb://' + mongoData.username + ':' + mongoData.password + '@' + mongoData.baseUrl + mongoData.dbOtf + '?replicaSet=' + mongoData.replicaSet,\r
+               address: mongoData.connectionString,\r
                collection: 'agenda'\r
+       },\r
+       sort: {\r
+               nextRunAt: 1\r
        }\r
 });\r
 \r
index 4cd08ac..159ff94 100644 (file)
@@ -21,10 +21,11 @@ const createdBy = require('./hooks/createdBy');
 const updatedBy = require('./hooks/updatedBy');\r
 const {iff, disallow, isProvider, skipRemainingHooks} = require('feathers-hooks-common');\r
 const { ObjectID } = require('mongodb');\r
+const shardKey = require('./hooks/insertShardKey.js');\r
 \r
 module.exports = {\r
        before: {\r
-               all: [paginateOption(), skipRemainingHooks(context => !context.params.provider)],\r
+               all: [shardKey(), paginateOption(), skipRemainingHooks(context => !context.params.provider)],\r
                find: [\r
                        function(context){\r
                                const {query} = context.params;\r
index 718abb5..10e799f 100644 (file)
@@ -16,6 +16,7 @@
 \r
 const util = require('../../lib/otf-util');\r
 const request = require('request');\r
+const errors = require('@feathersjs/errors');\r
 module.exports = function (options = {}) { // eslint-disable-line no-unused-vars\r
     return async context => {\r
         let options = {\r
@@ -40,7 +41,7 @@ module.exports = function (options = {}) { // eslint-disable-line no-unused-vars
         }).then(result => {\r
             \r
         }).catch(err => {\r
-            console.log(err);\r
+            throw new errors.GeneralError(err.body.message);\r
         });\r
     };\r
 };\r
index d3c3ab4..50eddef 100644 (file)
@@ -61,7 +61,7 @@ module.exports = function (options = {}) { // eslint-disable-line no-unused-vars
                             return Promise.reject(context.error);\r
                         }\r
                     }).catch(err => {\r
-                        \r
+                        throw new errors.GeneralError(err.body.message);\r
                     });\r
                 }\r
             });\r
index d81cd3f..815633a 100644 (file)
@@ -24,6 +24,9 @@ const { ObjectID } = require('mongodb');
 module.exports.groupFilter = function (options = null) {\r
        return async context => {\r
 \r
+               if (!context.params.provider) {\r
+                       return Promise.resolve(context);\r
+               }\r
                \r
                switch(context.method){\r
                        case 'get':\r
@@ -56,17 +59,13 @@ module.exports.groupFilter = function (options = null) {
                                                context.app.services[context.app.get('base-path') + 'groups'].Model.aggregate([\r
                                                        {\r
                                                                $match: context.params.query\r
-                                                       },\r
-                                                       {\r
-                                                               $graphLookup: {\r
-                                                                       from: "groups",\r
-                                                                       startWith: "$parentGroupId",\r
-                                                                       connectFromField: "parentGroupId",\r
-                                                                       connectToField: "_id",\r
-                                                                       as: "parentGroups"\r
+                                                       }\r
+                                               ]).then(async res => {\r
+                                                       if(res.length){\r
+                                                               for(let i = 0; i < res.length; i++){\r
+                                                                       res[i]['parentGroups'] = await getParentGroups(context.app.services[context.app.get('base-path') + 'groups'].Model, res[i]);\r
                                                                }\r
                                                        }\r
-                                               ]).then(res => {\r
                                                        resolve(res);\r
                                                }).catch(err => {\r
                                                        throw new errors.GeneralError(err);\r
@@ -127,6 +126,35 @@ module.exports.groupFilter = function (options = null) {
        };\r
 };\r
 \r
+getParentGroups = async function(model, group){\r
+       return new Promise(async (resolve, reject) => {\r
+               let parentGroups = [];\r
+               if(group.parentGroupId){\r
+                       model.aggregate([\r
+                               {\r
+                                       $match: {\r
+                                               '_id': group.parentGroupId\r
+                                       }\r
+                               }\r
+                       ]).then(async res => {\r
+                               if(res[0] && res[0].parentGroupId){\r
+                                       parentGroups.unshift(res[0]);\r
+                                       let parents = await getParentGroups(model, res[0]);\r
+                                       parents.forEach(e => {\r
+                                               parentGroups.unshift(e);\r
+                                       });\r
+                               }\r
+                               resolve(parentGroups);\r
+                       }).catch(err => {\r
+                               reject(err);\r
+                       })\r
+               }else{\r
+                       resolve();\r
+               }\r
+       });\r
+       \r
+}\r
+\r
 getChildGroups = async function(model, group){\r
        return new Promise(async (resolve, reject) => {\r
                let childGroups = [];\r
diff --git a/otf-frontend/server/src/feathers/hooks/insertShardKey.js b/otf-frontend/server/src/feathers/hooks/insertShardKey.js
new file mode 100644 (file)
index 0000000..6a6831c
--- /dev/null
@@ -0,0 +1,57 @@
+/*  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
+module.exports = function (service) { \r
+    return async context => {\r
+        // If the method is find, get, or create, return\r
+        if(context.method == 'find' || context.method == 'get' || context.method == 'create'){\r
+            return context;\r
+        }\r
+\r
+        // If the id or service does not exist, return\r
+        if(!context.id || !context.service){\r
+            return context;\r
+        }\r
+\r
+        let serviceString;\r
+        if(service){\r
+            serviceString = context.app.get('base-path') + service;\r
+        }else{\r
+            serviceString = context.path;\r
+        }\r
+\r
+        if(!context.app.services[serviceString].Model){\r
+            return context;\r
+        }\r
+\r
+        // If the entity data hasnt been set, get and set it\r
+        if(!context.params.entityData){\r
+            context.params.entityData = await context.app.services[serviceString].get(context.id, { provider: undefined});\r
+        }\r
+\r
+        // Find the shard key from the model\r
+        let shardKeys = {};\r
+        Object.keys(context.app.services[serviceString].Model.schema.options.shardKey).forEach(key => {\r
+            shardKeys[key] = context.params.entityData[key];\r
+        })\r
+\r
+        // Add the shard keys to the query\r
+        Object.assign(context.params.query, shardKeys);\r
+\r
+        return context;\r
+\r
+    }\r
+}
\ No newline at end of file
index 3659bde..14e764e 100644 (file)
@@ -140,22 +140,25 @@ permissions = function (name = null) {
                        return context;\r
                }\r
 \r
-               const params = Object.assign({}, context.params, { provider: null });\r
+               //see if the entity has already been pulled and stored, else get it\r
+               if(!context.params.entityData){\r
+                       const params = Object.assign({}, context.params, { provider: null });\r
+                       context.params.entityData = await service.get(context.id, params);\r
+               }\r
 \r
-               const result = await service.get(context.id, params);\r
-               throwUnlessCan(action, result);\r
+               throwUnlessCan(action, context.params.entityData);\r
 \r
                if (action === 'get') {\r
-                       context.result = pick(result, allowedFields);\r
+                       context.result = pick(context.params.entityData, allowedFields);\r
                }else{\r
                        if(context.data){\r
                                Object.keys(context.data).forEach(key => {\r
                                        if(key == "$push"){\r
                                                Object.keys(context.data['$push']).forEach(k => {\r
-                                                       throwUnlessCan(action, result, k);\r
+                                                       throwUnlessCan(action, context.params.entityData, k);\r
                                                });\r
                                        }else{\r
-                                               throwUnlessCan(action, result, key);\r
+                                               throwUnlessCan(action, context.params.entityData, key);\r
                                        }\r
                                })\r
                        }\r
index ad37c1b..dc4805e 100644 (file)
@@ -39,6 +39,9 @@ const appHooks = require('./app.hooks');
 const channels = require('./channels');\r
 const authentication = require('./authentication');\r
 \r
+// Azure Storage\r
+const azureStorage = require('../lib/azure-storage');\r
+\r
 // Mongoose\r
 const mongoose = require('../lib/mongoose');\r
 const _mongoose = require('mongoose');\r
@@ -104,9 +107,11 @@ app.configure(socketio(function (io) {
 //     });\r
 // });\r
 \r
+// Configure Azure storage\r
+app.configure(azureStorage);\r
+\r
 // Configure Mongoose driver before setting up services that use Mongoose\r
 app.configure(mongoose);\r
-\r
 // Set up database dependent components once the connection is ready to prevent unexpected results\r
 _mongoose.connection.on('open', (ref) => {\r
        app.configure(authentication);\r
index a41d24c..f33e17b 100644 (file)
 ##############################################################################*/\r
 \r
 \r
-const mongooseGridFS = require('mongoose-gridfs');\r
-\r
 module.exports = function (app) {\r
-       const mongoose = app.get('mongooseClient');\r
-\r
-       const gridfs = mongooseGridFS({\r
-               collection: 'fs',\r
-               model: 'File',\r
-               mongooseConnection: mongoose.connection\r
-       });\r
+       const mongooseClient = app.get('mongooseClient');\r
+       const { Schema } = mongooseClient;\r
+       const files = new Schema({//Esquema base de los usuarios.\r
+        length: {\r
+            type: Number\r
+        },\r
+        chunkSize: {\r
+            type: Number\r
+        },\r
+        uploadDate: {\r
+            type: Date\r
+        },\r
+        md5: {\r
+            type: String\r
+        },\r
+        filename: {\r
+            type: String\r
+        },\r
+        contentType: {\r
+            type: String\r
+        },\r
+        metadata: {\r
+            type: Object\r
+        },\r
+        path:{\r
+            type:String,\r
+            readonly:true\r
+        }\r
+    },{collection:`fs.files`, shardKey: { filename: 1 }});\r
+       \r
+       return mongooseClient.model('files', files);\r
 \r
-       return gridfs.model;\r
 };\r
index d15894e..55b6469 100644 (file)
@@ -32,6 +32,7 @@ module.exports = function (app) {
                ownerId: { type: Schema.Types.ObjectId, ref: 'users', required: true },\r
                mechanizedIds: [String]\r
        }, {\r
+               shardKey: { parentGroupId: 1},\r
                timestamps: true\r
        });\r
 \r
index 35ad8b3..fe29ee0 100644 (file)
@@ -38,6 +38,7 @@ module.exports = function (app) {
                lockedAt: { type: String },\r
                lastRunAt: { type: String }\r
        }, {\r
+               shardKey: { 'data.testSchedule._testInstanceId': 1 },\r
                timestamps: true\r
        });\r
 \r
index 9e71a0f..dfa365a 100644 (file)
@@ -48,8 +48,9 @@ module.exports = function (app) {
                updatedBy: { type: Schema.Types.ObjectId, ref: 'users'},\r
                createdBy: { type: Schema.Types.ObjectId, ref: 'users'}\r
        }, {\r
-       timestamps: true,\r
-       minimize: false\r
+               shardKey: { groupId: 1 },\r
+               timestamps: true,\r
+               minimize: false\r
        });\r
 \r
        \r
index 2f152ac..2e289aa 100644 (file)
@@ -44,6 +44,7 @@ module.exports = function (app) {
                historicTestDefinition: { type: Object }\r
 \r
        }, {\r
+                       shardKey: { groupId: 1 },\r
                        timestamps: false\r
                });\r
        \r
index b1bb52d..b8b76e3 100644 (file)
@@ -35,6 +35,7 @@ module.exports = function (app) {
                authorizationEnabled: { type: Boolean, default: false },\r
                isPublic: { type: Boolean }\r
        }, {\r
+               shardKey: { groupId: 1 },\r
                timestamps: true\r
        });\r
 \r
index 1cb5f0e..3e3f4a7 100644 (file)
@@ -49,6 +49,7 @@ module.exports = function (app) {
                updatedBy: { type: Schema.Types.ObjectId, ref: 'users' },\r
                createdBy: { type: Schema.Types.ObjectId, ref: 'users' }\r
        }, {\r
+                       shardKey: { groupId: 1 },\r
                        timestamps: true,\r
                        minimize: false\r
                });\r
index aba50c1..3790b9e 100644 (file)
@@ -38,6 +38,7 @@ module.exports = function (app) {
                        testDefinitions: [{type: Schema.Types.ObjectId, ref: 'testDefinitions'}]\r
                }, { _id: false})\r
        }, {\r
+               shardKey: { email: 1 },\r
                timestamps: true\r
        });\r
 \r
index fcc11e8..be683d4 100644 (file)
@@ -149,7 +149,7 @@ class Service {
                //         console.log(err);\r
                //     }\r
                // Set as deployed\r
-               delete params.query;\r
+               params.query = {};\r
 \r
                //check to see if the process definition Key was set\r
                // if (!data.testDefinition.processDefinitionKey) {\r
index d855145..eae2f7f 100644 (file)
@@ -249,7 +249,7 @@ class Service {
                        }\r
                };\r
                let options = {\r
-                       url: this.options.app.get('otf').url + this.options.app.get('base-path') + 'file-transfer',\r
+                       uri: this.options.app.get('otf').url + this.options.app.get('base-path') + 'file-transfer',\r
                        headers: {\r
                                'Authorization': params.headers.Authorization,\r
                                'Content-Type': "multipart/form-data"\r
index f64d812..9132e57 100644 (file)
@@ -58,7 +58,7 @@ module.exports = {
        before: {\r
                all: [authenticate('jwt'), permissions('execute')],\r
                find: [ throwError(new errors.MethodNotAllowed()) ],\r
-               get: [ throwError(new errors.MethodNotAllowed())],\r
+               get: [ ],\r
                create: [\r
                        (context) => {\r
                                context.data.executorId = context.params.user._id;\r
index 0ac6670..9638922 100644 (file)
 \r
 const Response = require('http-response-object');\r
 const Readable = require('stream').Readable;\r
-const mongooseGridFS = require('mongoose-gridfs');\r
+const { createModel } = require('mongoose-gridfs');\r
 const AdmZip = require('adm-zip');\r
 const errors = require('@feathersjs/errors');\r
+const mongoose = require('mongoose');\r
+const ObjectID = require('mongodb').ObjectID;\r
+const {\r
+       Aborter,\r
+       BlockBlobURL,\r
+       BlobURL,\r
+       downloadBlobToBuffer,\r
+       uploadStreamToBlockBlob\r
+  } = require("@azure/storage-blob");\r
+\r
 \r
 class Service {\r
        constructor (options) {\r
                this.options = options || {};\r
-               this.mongoose = this.options.app.get('mongooseClient');\r
-               this.gridfs = mongooseGridFS({\r
-                       collection: 'fs',\r
-                       model: 'File',\r
-                       mongooseConnection: this.mongoose.connection\r
-               });\r
-               this.FileModel = this.gridfs.model;\r
+               // this.File = createModel({\r
+               //      collection: 'fs',\r
+               //      model: 'File',\r
+               //      mongooseConnection: mongoose.connection\r
+               // });\r
        }\r
 \r
        async find (params) {\r
@@ -37,14 +45,30 @@ class Service {
        }\r
 \r
        async get (id, params) {\r
-               let content = await this.callReadFile(id).then(res => {\r
-                       return res;\r
-               });\r
-\r
-               if(params.query && params.query.robot){\r
-                       content = await this.createRobotResponse(content);\r
+               if(!id){\r
+                       throw new errors.BadRequest("File id is required");\r
                }\r
-               return content;\r
+\r
+               // Get Blob url\r
+               const blob = BlobURL.fromContainerURL(this.options.app.get('azureStorageContainerUrl'), id);\r
+               const stats = await blob.getProperties().catch(err => {\r
+                       throw new errors.NotFound();\r
+               });\r
+               // const content = await blob.download(Aborter.none, 0);\r
+               const buffer = Buffer.alloc(stats.contentLength);\r
+               await downloadBlobToBuffer(\r
+                       Aborter.timeout(30 * 60 * 1000),\r
+                       buffer,\r
+                       blob,\r
+                       0,\r
+                       undefined,\r
+                       {\r
+                         blockSize: 4 * 1024 * 1024, // 4MB block size\r
+                         parallelism: 20, // 20 concurrency\r
+                       }\r
+                 );\r
+\r
+               return buffer;\r
        }\r
 \r
        async create (data, params) {\r
@@ -54,31 +78,37 @@ class Service {
             throw new BadRequest("No files found to upload")\r
         }\r
 \r
-        let promises = [];\r
-\r
+               let promises = [];\r
+               \r
         files.forEach(file => {\r
-            let promise = new Promise( (resolve, reject) => {\r
-\r
-                let stream = new Readable();\r
-                stream.push(file.buffer);\r
-                stream.push(null);\r
-\r
-               this.FileModel.write(\r
-                       {\r
-                               filename: file.originalname,\r
-                               contentType: file.mimeType\r
-                       },\r
-                       stream,\r
-                       function (error, savedAttachment) {\r
-                               if (error) {\r
-                                       logger.error(error);\r
-                                       reject(error);\r
-                               } else {\r
-                            stream.destroy();\r
-                            resolve(savedAttachment);\r
-                               }\r
-                    }\r
-                );\r
+            let promise = new Promise(async (resolve, reject) => {\r
+\r
+                               let exists, filename, blob, blockBlob;\r
+                               // Creates the file id and checks that there isn't already a file with that name\r
+                               do {\r
+\r
+                                       filename = ObjectID().toString();\r
+                                       \r
+                                       blob = BlobURL.fromContainerURL(this.options.app.get('azureStorageContainerUrl'), filename);\r
+                                       blockBlob = BlockBlobURL.fromBlobURL(blob);\r
+                                       exists = await blockBlob.getProperties().catch(err => {\r
+                                               if(err.statusCode == 404){\r
+                                                       exists = false;\r
+                                               }\r
+                                       });\r
+\r
+                               } while (exists);\r
+       \r
+                               blockBlob.upload(Aborter.none, file.buffer.toString(), file.size).then(\r
+                                       result => {\r
+                                               result._id = filename;\r
+                                               resolve(result);\r
+                                       }\r
+                               ).catch(\r
+                                       error => {\r
+                                               reject(error);\r
+                                       }\r
+                               );\r
 \r
             })\r
 \r
@@ -90,6 +120,8 @@ class Service {
         return result;\r
        }\r
 \r
+       \r
+\r
        async update (id, data, params) {\r
                return new Response(200, {});\r
        }\r
@@ -99,13 +131,13 @@ class Service {
        }\r
 \r
        async remove (id, params) {\r
-               let err = await this.callUnlinkFile(id).then(err => {\r
-            return err;\r
-        });\r
+               // let err = await this.callUnlinkFile(id).then(err => {\r
+        //     return err;\r
+        // });\r
 \r
-        if(err){\r
-            throw errors.GeneralError(err);\r
-        }        \r
+        // if(err){\r
+        //     throw errors.GeneralError(err);\r
+        // }        \r
 \r
         return new Response(200, {});\r
        }\r
index eec6d19..0844bd5 100644 (file)
@@ -119,7 +119,7 @@ module.exports = {
                        (context) => { console.log("AFTER PERMISSIONS")},\r
                        canExecute(), \r
                        async (context) => {\r
-                               const fullUrl = this.options.app.get('otf').url + context.app.get('base-path') + 'schedule-test';\r
+                               const fullUrl = context.app.get('otf').url + context.app.get('base-path') + 'schedule-test';\r
 \r
                                context.data.executorId = context.params.user._id;\r
 \r
@@ -155,7 +155,7 @@ module.exports = {
                        permissions('jobs'),\r
                        canExecute(),\r
                        async function (context) {\r
-                       const fullUrl = this.options.app.get('otf').url + context.app.get('base-path') + 'cancel-test';\r
+                       const fullUrl = context.app.get('otf').url + context.app.get('base-path') + 'cancel-test';\r
 \r
                        if (context.id == null || context.params.user._id == null ||\r
                                utils.isValidObjectId(context.id) || utils.isValidObjectId(context.params.user._id)) {\r
index b4350bb..981f114 100644 (file)
@@ -31,29 +31,9 @@ module.exports = function (app) {
                paginate\r
        };\r
 \r
-       const mongoConfig = app.get('mongo');\r
-       const rateLimitConfig = app.get('rate-limit');\r
-\r
-       const createUserLimiter = new RateLimit({\r
-               store: new MongoStore({\r
-                       uri: 'mongodb://' + mongoConfig.username + ':' + mongoConfig.password + '@' + mongoConfig.baseUrl +\r
-                               mongoConfig.dbOtf + '?replicaSet=' + mongoConfig.replicaSet,\r
-                       collectionName: rateLimitConfig.mongoStore.collection\r
-               }),\r
-               max: app.get('rate-limit').services.users.max,\r
-               windowsMs: app.get('rate-limit').services.users.windowMs,\r
-               message: app.get('rate-limit').services.users.message\r
-       });\r
-\r
        // Initialize our service with any options it requires,\r
        // and limit any POST methods.\r
-       app.use(app.get('base-path') + 'users', (req, res, next) => {\r
-               if (req.method === 'POST') {\r
-                       createUserLimiter(req, res, next);\r
-               } else {\r
-                       next();\r
-               }\r
-       }, createService(options));\r
+       app.use(app.get('base-path') + 'users', createService(options));\r
 \r
        // Get our initialized service so that we can register hooks\r
        const service = app.service(app.get('base-path') + 'users');\r
diff --git a/otf-frontend/server/src/lib/azure-storage.js b/otf-frontend/server/src/lib/azure-storage.js
new file mode 100644 (file)
index 0000000..29102b6
--- /dev/null
@@ -0,0 +1,51 @@
+/*  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
+const {\r
+    ServiceURL,\r
+    StorageURL,\r
+    SharedKeyCredential,\r
+    TokenCredential,\r
+    ContainerURL\r
+  } = require("@azure/storage-blob");\r
+\r
+module.exports = function(app) {\r
+    // Enter your storage account name and shared key\r
+    const account = app.get('azure').storage.account;\r
+    const accountKey = app.get('azure').storage.key;\r
+    const container = app.get('azure').storage.container;\r
+  \r
+    // Use SharedKeyCredential with storage account and account key\r
+    const sharedKeyCredential = new SharedKeyCredential(account, accountKey);\r
+  \r
+    // Use TokenCredential with OAuth token\r
+    const tokenCredential = new TokenCredential("token");\r
+    tokenCredential.token = "renewedToken"; // Renew the token by updating token field of token credential\r
+  \r
+    // Use sharedKeyCredential, tokenCredential or anonymousCredential to create a pipeline\r
+    const pipeline = StorageURL.newPipeline(sharedKeyCredential);\r
+  \r
+    // List containers\r
+    const serviceURL = new ServiceURL(\r
+      // When using AnonymousCredential, following url should include a valid SAS or support public access\r
+      `https://${account}.blob.core.windows.net`,\r
+      pipeline\r
+    );\r
+\r
+    const containerURL = ContainerURL.fromServiceURL(serviceURL, container);\r
+\r
+    app.set('azureStorageContainerUrl', containerURL);\r
+}
\ No newline at end of file
index a8d5b9d..e3bd0d1 100644 (file)
@@ -18,9 +18,8 @@ const mongoose = require('mongoose');
 \r
 module.exports = function (app) {\r
        const mongoData = app.get('mongo');\r
-       const connectionString = 'mongodb://' + mongoData.username + ':' + mongoData.password + '@' + mongoData.baseUrl + mongoData.dbOtf + '?replicaSet=' + mongoData.replicaSet;\r
 \r
-       mongoose.connect(connectionString, { useNewUrlParser: true }).then(null, error => {\r
+       mongoose.connect(mongoData.connectionString, { useNewUrlParser: true, useFindAndModify: false, useUnifiedTopology: true, useCreateIndex: true }).then(null, error => {\r
                console.log('caught', error.message);\r
        });\r
        mongoose.Promise = global.Promise;\r
index 67338c3..378377a 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const rp = require('request-promise');\r
 const url = require('url');\r
index 71d02c6..d6e352f 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const feathers = require('@feathersjs/feathers');\r
 const groupFilter = require('../../src/hooks/group-filter');\r
index 23d1ff0..7ade3b5 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index fb00767..bebe886 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 6e46510..4a1af5a 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index c66c9c7..59d13ad 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 212f034..5c6963b 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 034e933..8fa04e1 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 556d710..9b004b3 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 44fa679..f3b845a 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 2db66b9..e59da74 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 51304e5..8b96702 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 35bf0d5..7917e28 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 0d03d13..8594bdd 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index bed24e0..aec91c4 100644 (file)
@@ -1,3 +1,19 @@
+/*  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
 const assert = require('assert');\r
 const app = require('../../src/app');\r
 \r
index 46b4b21..fda9ed3 100644 (file)
     <dependency>\r
       <artifactId>httpmime</artifactId>\r
       <groupId>org.apache.httpcomponents</groupId>\r
-      <version>4.5.7</version>\r
+      <version>4.5.7-SNAPSHOT</version>\r
     </dependency>\r
 \r
     <dependency>\r
index 0546a7d..31d4e9e 100644 (file)
@@ -62,7 +62,7 @@ public class DataConfig extends AbstractMongoConfiguration {
         MongoCredential.createScramSha1Credential(username, database, password.toCharArray());\r
 \r
     MongoClientOptions options =\r
-        MongoClientOptions.builder().sslEnabled(false).requiredReplicaSetName(replicaSet).build();\r
+        MongoClientOptions.builder().sslEnabled(true).build();\r
 \r
     String[] hostArray = hosts.split(",");\r
     ArrayList<ServerAddress> hosts = new ArrayList<>();\r
index d171206..bdc2607 100644 (file)
@@ -748,11 +748,7 @@ public class TestInstanceServiceImpl implements TestInstanceService {
     }\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
+        return email.equalsIgnoreCase(System.getenv("AAF_ID"));\r
     }\r
 \r
     private BpmnInstance findBpmnInstance(TestDefinition testDefinition, int version, boolean latest)\r
index 13d125a..afc0f24 100644 (file)
@@ -108,7 +108,7 @@ public class TestStrategyServiceImpl implements TestStrategyService {
     //                 logger.error(Utilities.getStackTrace(e));\r
     //         }\r
 \r
-    // If a test definition id is supplied, the request intends to update an existing test\r
+    // If a test definition id is supplied, the request intends to  updatean existing test\r
     // definition.\r
     if (request.getTestDefinitionId() != null) {\r
       // Check if the test definition exists in the database.\r
@@ -212,8 +212,7 @@ public class TestStrategyServiceImpl implements TestStrategyService {
 \r
   private boolean isAuthorized(String authorization) {\r
     User user = Utilities.findUserByAuthHeader(authorization, userRepository);\r
-    return (user.getEmail().equalsIgnoreCase("email@localhost")\r
-        || user.getEmail().equalsIgnoreCase("email@localhost"));\r
+    return (user.getEmail().equalsIgnoreCase(System.getenv("AAF_ID")));\r
   }\r
 \r
   private DeployTestStrategyRequest mapToDeployTestStrategyRequest(String body) {\r
index d2a662b..8bf53ff 100644 (file)
@@ -100,7 +100,7 @@ public class VirtualTestHeadServiceImpl implements VirtualTestHeadService {
     }\r
 \r
     private Response updateTestHeadFields(TestHead testHead, TestHead newTestHead, User user) {\r
-        Query select = Query.query(Criteria.where("_id").is(testHead.get_id()));\r
+        Query select = Query.query(Criteria.where("_id").is(testHead.get_id())).addCriteria(Criteria.where("groupId").is(testHead.getGroupId()));\r
         Update update = new Update();\r
 \r
         if (newTestHead.getTestHeadName() != null) {\r
index 7f4bcbc..780ec36 100644 (file)
@@ -34,7 +34,7 @@ public class TestHead implements Serializable {
   @Id\r
   private ObjectId _id;\r
 \r
-  @Indexed(unique = true)\r
+  //@Indexed(unique = true)\r
   private String testHeadName;\r
 \r
   private String testHeadDescription;\r
index c54359f..db242bb 100644 (file)
@@ -28,6 +28,7 @@ public class TestExecutionUtility {
   public static void saveTestResult(\r
       MongoTemplate mongoOperation, TestExecution execution, String testResult) {\r
     Query query = new Query();\r
+    query.addCriteria(Criteria.where("groupId").is(execution.getGroupId()));\r
     query.addCriteria(Criteria.where("businessKey").is(execution.getBusinessKey()));\r
     Update update = new Update();\r
     update.set("testResult", testResult);\r
index e8cdfea..2c3dac1 100644 (file)
@@ -146,7 +146,7 @@ public class PermissionUtil {
 \r
         for(Group group : groupsToCheck)\r
         {\r
-            if(group.getParentGroupId() != null) // if there is a parent\r
+            if(group != null && group.getParentGroupId() != null) // if there is a parent\r
             {\r
                 String parentId = group.getParentGroupId().toString();\r
                 Group parentGroup = groupMap.get(parentId);\r
index 0a68a60..1cce69d 100644 (file)
@@ -3,9 +3,9 @@ server.port=8443
 server.port.http=8080\r
 security.require-ssl=false\r
 \r
-server.ssl.key-store-type=PKCS12\r
-server.ssl.key-store=${OTF_CERT_PATH}\r
-server.ssl.key-store-password=${OTF_CERT_PASS}\r
+#server.ssl.key-store-type=PKCS12\r
+#server.ssl.key-store=${OTF_CERT_PATH}\r
+#server.ssl.key-store-password=${OTF_CERT_PASS}\r
 #server.servlet.context-path=/otf/api\r
 #spring.jersey.application-path=/otf\r
 #springfox.documentation.swagger.v2.path=/otf/api/swagger.json\r
@@ -29,12 +29,12 @@ logging.path=otf/logs
 \r
 spring.resources.add-mappings=true\r
 \r
-ssl.flag =${https-only.flag:true}\r
+ssl.flag =false\r
 #springfox.documentation.auto-startup=false\r
 #springfox.documentation.swagger.v2.path=/otf/swagger.json\r
 \r
 #config\r
-aaf.enabled=true\r
+aaf.enabled=false\r
 aaf.call-timeout=10000\r
 aaf.conn-timeout=6000\r
 aaf.default-realm=localhost\r
index 2c17abb..7b2a262 100644 (file)
@@ -129,7 +129,7 @@ public abstract class MemoryDatabase {
       user = new User();\r
       user.setFirstName("Mech");\r
       user.setLastName("Id");\r
-      user.setEmail("email@localhost");\r
+      user.setEmail(System.getenv("AAF_ID"));\r
       mongoTemplate.save(user, "users");\r
       user = mongoTemplate.findOne(userQuery, User.class);\r
     }\r