diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6e56c8d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +.DS_Store/* +test/node_modules/* diff --git a/caMicroscope.yml b/caMicroscope.yml index 1ac326e..6cb5b1d 100644 --- a/caMicroscope.yml +++ b/caMicroscope.yml @@ -40,7 +40,7 @@ services: volumes: - ./images/:/images/ viewer: - build: "https://github.com/camicroscope/caMicroscope.git#v3.4.0" + build: "https://github.com/camicroscope/caMicroscope.git#v3.4.1" container_name: ca-front restart: unless-stopped volumes: diff --git a/config/bindaas_projects/caMicroscope.project b/config/bindaas_projects/caMicroscope.project index ce3afd5..e7ef4d9 100644 --- a/config/bindaas_projects/caMicroscope.project +++ b/config/bindaas_projects/caMicroscope.project @@ -14,275 +14,275 @@ "metaData": {}, "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "get", "timeCreated": "Wed Aug 29 18:40:50 UTC 2018", "createdBy": "admin", "description": " " }, - "findBound": { - "queryTemplate": "{ \"_operation\" : \"find\" , \"_operation_args\" : { \"query\" : {\"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"provenance.analysis.source\" : {$regex: \"$key$\", $options: \"i\"}, \"geometries.features.bound\": { $geoIntersects: { $geometry: { \"type\": \"Polygon\", \"coordinates\": [[[ $x0$, $y0$ ],[ $x0$, $y1$ ],[ $x1$, $y1$ ],[ $x1$, $y0$ ],[ $x0$, $y0$ ]]] } } } }, \"limit\" : 1000} } ", + "findTypesExec": { + "queryTemplate": "{ \"_operation\" : \"distinct\" , \"_operation_args\" : { \"field\" : \"provenance.analysis\", \"query\" : {\u0027provenance.image.slide\u0027: \"$slide$\",\u0027provenance.analysis.execution_id\u0027: $name$ } } } ", "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": false, - "defaultValue": "", - "description": "" - }, - "key": { - "name": "key", - "required": false, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - }, - "x0": { - "name": "x0", - "required": true, - "defaultValue": "", - "description": "" - }, - "y0": { - "name": "y0", - "required": true, - "defaultValue": "", - "description": "" - }, - "x1": { - "name": "x1", - "required": true, - "defaultValue": "", - "description": "" - }, - "y1": { - "name": "y1", - "required": true, - "defaultValue": "", - "description": "" - } +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +}, +"name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, - "name": "findBound", - "timeCreated": "Thur Nov 1 18:12:11 UTC 2018", + "name": "findTypesExec", + "timeCreated": "Thu May 09 15:09:53 GMT 2019", "createdBy": "admin", - "description": "find where bound intersects given rect" + "description": " " }, - "findTypes": { - "queryTemplate": "{ \"_operation\" : \"distinct\" , \"_operation_args\" : { \"field\" : \"provenance.analysis\", \"query\" : {\u0027provenance.image.slide\u0027: $slide$ } } } ", + "multiFind": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" :{$and: [\n{\"provenance.analysis.execution_id\": {$in: $name$},\n \"provenance.image.slide\" : \"$slide$\",\n \"footprint\": { $not: {$lt: $footprint$}},\n \"provenance.analysis.source\" : {$regex: \"$source$\", $options: \"i\"}},\n{\"x\": { $not: {$lt: $x0$}}},\n{\"x\": { $not: {$gt: $x1$}}},\n{\"y\": { $not: {$lt: $y0$}}},\n{\"y\": { $not: {$gt: $y1$}}}\n ]}\n}\n}\n ", "metaData": {}, "tags": [], "bindVariables": { - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +}, +"footprint": { + "name": "footprint", + "required": false, + "defaultValue": "0", + "description": "" +}, +"source": { + "name": "source", + "required": false, + "defaultValue": "", + "description": "" +}, +"x0": { + "name": "x0", + "required": false, + "defaultValue": "0", + "description": "" +}, +"x1": { + "name": "x1", + "required": false, + "defaultValue": "9", + "description": "" +}, +"y0": { + "name": "y0", + "required": false, + "defaultValue": "0", + "description": "" +}, +"y1": { + "name": "y1", + "required": false, + "defaultValue": "9", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, - "name": "findTypes", - "timeCreated": "Thu May 09 14:52:28 GMT 2019", + "name": "multiFind", + "timeCreated": "Tue Jul 02 17:47:09 GMT 2019", "createdBy": "admin", "description": " " }, - "findTypesExec": { - "queryTemplate": "{ \"_operation\" : \"distinct\" , \"_operation_args\" : { \"field\" : \"provenance.analysis\", \"query\" : {\u0027provenance.image.slide\u0027: $slide$,\u0027provenance.analysis.execution_id\u0027: $name$ } } } ", + "find": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" :{$and: [\n{\"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : \"$slide$\",\n \"footprint\": { $not: {$lt: $footprint$}},\n \"provenance.analysis.source\" : {$regex: \"$source$\", $options: \"i\"}},\n{\"x\": { $not: {$lt: $x0$}}},\n{\"x\": { $not: {$gt: $x1$}}},\n{\"y\": { $not: {$lt: $y0$}}},\n{\"y\": { $not: {$gt: $y1$}}}\n ]}\n}\n}\n ", "metaData": {}, "tags": [], "bindVariables": { - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - }, - "name": { - "name": "name", - "required": true, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +}, +"source": { + "name": "source", + "required": false, + "defaultValue": "", + "description": "" +}, +"footprint": { + "name": "footprint", + "required": false, + "defaultValue": "0", + "description": "" +}, +"x0": { + "name": "x0", + "required": false, + "defaultValue": "0", + "description": "" +}, +"x1": { + "name": "x1", + "required": false, + "defaultValue": "9", + "description": "" +}, +"y0": { + "name": "y0", + "required": false, + "defaultValue": "0", + "description": "" +}, +"y1": { + "name": "y1", + "required": false, + "defaultValue": "9", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, - "name": "findTypesExec", - "timeCreated": "Thu May 09 15:09:53 GMT 2019", + "name": "find", + "timeCreated": "Tue Jul 02 17:48:26 GMT 2019", "createdBy": "admin", - "description": " " + "description": " " }, - "find": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" :{$and: [\n {\"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"footprint\": { $not: {$lt: $footprint$}},\n \"provenance.analysis.source\" : {$regex: \"$source$\", $options: \"i\"}},\n {\"x\": { $not: {$lt: $x0$}}},\n {\"x\": { $not: {$gt: $x1$}}},\n {\"y\": { $not: {$lt: $y0$}}},\n {\"y\": { $not: {$gt: $y1$}}}\n ]}\n }\n}\n ", + "findBound": { + "queryTemplate": "{ \"_operation\" : \"find\" , \"_operation_args\" : { \"query\" : {\"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : \"$slide$\",\n \"provenance.analysis.source\" : {$regex: \"$key$\", $options: \"i\"}, \"geometries.features.bound\": { $geoIntersects: { $geometry: { \"type\": \"Polygon\", \"coordinates\": [[[ $x0$, $y0$ ],[ $x0$, $y1$ ],[ $x1$, $y1$ ],[ $x1$, $y0$ ],[ $x0$, $y0$ ]]] } } } }, \"limit\" : 1000} } ", "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": false, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - }, - "source": { - "name": "source", - "required": false, - "defaultValue": "", - "description": "" - }, - "footprint": { - "name": "footprint", - "required": false, - "defaultValue": "0", - "description": "" - }, - "x0": { - "name": "x0", - "required": false, - "defaultValue": "0", - "description": "" - }, - "x1": { - "name": "x1", - "required": false, - "defaultValue": "9", - "description": "" - }, - "y0": { - "name": "y0", - "required": false, - "defaultValue": "0", - "description": "" - }, - "y1": { - "name": "y1", - "required": false, - "defaultValue": "9", - "description": "" - } +"name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" +}, +"key": { + "name": "key", + "required": false, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +}, +"x0": { + "name": "x0", + "required": true, + "defaultValue": "", + "description": "" +}, +"y0": { + "name": "y0", + "required": true, + "defaultValue": "", + "description": "" +}, +"x1": { + "name": "x1", + "required": true, + "defaultValue": "", + "description": "" +}, +"y1": { + "name": "y1", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, - "name": "find", - "timeCreated": "Fri Jun 14 16:26:22 GMT 2019", + "name": "findBound", + "timeCreated": "Tue Jul 02 17:49:32 GMT 2019", "createdBy": "admin", - "description": " " + "description": "find where bound intersects given rect " }, - "multiFind": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" :{$and: [\n {\"provenance.analysis.execution_id\": {$in: $name$},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"footprint\": { $not: {$lt: $footprint$}},\n \"provenance.analysis.source\" : {$regex: \"$source$\", $options: \"i\"}},\n {\"x\": { $not: {$lt: $x0$}}},\n {\"x\": { $not: {$gt: $x1$}}},\n {\"y\": { $not: {$lt: $y0$}}},\n {\"y\": { $not: {$gt: $y1$}}}\n ]}\n }\n}\n ", + "findTypes": { + "queryTemplate": "{ \"_operation\" : \"distinct\" , \"_operation_args\" : { \"field\" : \"provenance.analysis\", \"query\" : {\u0027provenance.image.slide\u0027: \"$slide$\" } } } ", "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": true, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - }, - "footprint": { - "name": "footprint", - "required": false, - "defaultValue": "0", - "description": "" - }, - "source": { - "name": "source", - "required": false, - "defaultValue": "", - "description": "" - }, - "x0": { - "name": "x0", - "required": false, - "defaultValue": "0", - "description": "" - }, - "x1": { - "name": "x1", - "required": false, - "defaultValue": "9", - "description": "" - }, - "y0": { - "name": "y0", - "required": false, - "defaultValue": "0", - "description": "" - }, - "y1": { - "name": "y1", - "required": false, - "defaultValue": "9", - "description": "" - } +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, - "name": "multiFind", - "timeCreated": "Fri Jun 14 16:27:26 GMT 2019", + "name": "findTypes", + "timeCreated": "Tue Jul 02 18:37:03 GMT 2019", "createdBy": "admin", - "description": " " + "description": " " } }, "deleteEndpoints": { "deleteMark": { - "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027provenance.image.slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027provenance.image.slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "name": "deleteMark", - "timeCreated": "Wed Aug 29 18:43:50 UTC 2018", + "timeCreated": "Tue Jul 02 18:20:50 GMT 2019", "createdBy": "admin", "description": "" } @@ -291,7 +291,7 @@ "csvFile": { "type": "MULTIPART", "properties": { - "inputType": "CSV_FILE" +"inputType": "CSV_FILE" }, "name": "csvFile", "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", @@ -301,7 +301,7 @@ "jsonFile": { "type": "MULTIPART", "properties": { - "inputType": "JSON_FILE" +"inputType": "JSON_FILE" }, "name": "jsonFile", "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", @@ -311,7 +311,7 @@ "csv": { "type": "FORM_DATA", "properties": { - "inputType": "CSV" +"inputType": "CSV" }, "name": "csv", "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", @@ -321,7 +321,7 @@ "json": { "type": "FORM_DATA", "properties": { - "inputType": "JSON" +"inputType": "JSON" }, "name": "json", "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", @@ -350,16 +350,16 @@ "metaData": {}, "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "get", "timeCreated": "Wed Aug 29 18:41:00 UTC 2018", @@ -367,32 +367,32 @@ "description": " " }, "find": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : { \"name\" : {$regex: \"$name$\", $options: \"i\"},\n \"slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"location\" : {$regex: \"$location$\", $options: \"i\"}}\n }\n} ", + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" : { \"name\" : {$regex: \"$name$\", $options: \"i\"},\n\"slide\" : {$regex: \"$slide$\", $options: \"i\"},\n\"location\" : {$regex: \"$location$\", $options: \"i\"}}\n}\n} ", "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": false, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - }, - "location": { - "name": "location", - "required": false, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +}, +"location": { + "name": "location", + "required": false, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "find", "timeCreated": "Mon Sep 24 18:13:58 UTC 2018", @@ -401,61 +401,61 @@ } }, "deleteEndpoints": { - "deleteOverlay": { - "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", + "updateOverlay": { + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027slide\u0027 : \"$slide$\", \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027$field$\u0027 : \u0027$value$\u0027 }},\n\t\t\t\t\t\t\t\"upsert\": \u0027true\u0027,\n\t\t\t\t\t\t\t\"multi\" : \u0027false\u0027\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - } +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +}, +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +}, +"field": { + "name": "field", + "required": true, + "defaultValue": "", + "description": "" +}, +"value": { + "name": "value", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", - "name": "deleteOverlay", - "timeCreated": "Wed Aug 29 18:44:12 UTC 2018", + "name": "updateOverlay", + "timeCreated": "Tue Jul 02 18:21:53 GMT 2019", "createdBy": "admin", "description": "" }, - "updateOverlay": { - "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027slide\u0027 : \u0027$slide$\u0027, \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027$field$\u0027 : \u0027$value$\u0027 }},\n\t\t\t\t\t\t\t\"upsert\": \u0027true\u0027,\n\t\t\t\t\t\t\t\"multi\" : \u0027false\u0027\n\t\t\t\t\t\t}\n}\n ", + "deleteOverlay": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - }, - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - }, - "field": { - "name": "field", - "required": true, - "defaultValue": "", - "description": "" - }, - "value": { - "name": "value", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", - "name": "updateOverlay", - "timeCreated": "Wed Aug 29 20:04:49 UTC 2018", + "name": "deleteOverlay", + "timeCreated": "Tue Jul 02 18:22:07 GMT 2019", "createdBy": "admin", "description": "" } @@ -464,7 +464,7 @@ "csvFile": { "type": "MULTIPART", "properties": { - "inputType": "CSV_FILE" +"inputType": "CSV_FILE" }, "name": "csvFile", "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", @@ -474,7 +474,7 @@ "jsonFile": { "type": "MULTIPART", "properties": { - "inputType": "JSON_FILE" +"inputType": "JSON_FILE" }, "name": "jsonFile", "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", @@ -484,7 +484,7 @@ "csv": { "type": "FORM_DATA", "properties": { - "inputType": "CSV" +"inputType": "CSV" }, "name": "csv", "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", @@ -494,7 +494,7 @@ "json": { "type": "FORM_DATA", "properties": { - "inputType": "JSON" +"inputType": "JSON" }, "name": "json", "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", @@ -523,16 +523,16 @@ "metaData": {}, "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "get", "timeCreated": "Wed Aug 29 18:41:29 UTC 2018", @@ -540,89 +540,89 @@ "description": " " }, "find": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : {\u0027name\u0027: {$regex: \"$slide$\", $options: \"i\"},\n \u0027specimen\u0027: {$regex: \"$specimen$\", $options: \"i\"},\n \u0027study\u0027: {$regex: \"$study$\", $options: \"i\"},\n \u0027location\u0027: {$regex: \"$location$\", $options: \"i\"}}\n }\n} ", + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" : {\u0027name\u0027: {$regex: \"$slide$\", $options: \"i\"},\n \u0027specimen\u0027: {$regex: \"$specimen$\", $options: \"i\"},\n \u0027study\u0027: {$regex: \"$study$\", $options: \"i\"},\n \u0027location\u0027: {$regex: \"$location$\", $options: \"i\"}}\n}\n} ", "metaData": {}, "tags": [], "bindVariables": { - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - }, - "location": { - "name": "location", - "required": false, - "defaultValue": "", - "description": "" - }, - "specimen": { - "name": "specimen", - "required": false, - "defaultValue": "", - "description": "" - }, - "study": { - "name": "study", - "required": false, - "defaultValue": "", - "description": "" - } +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +}, +"location": { + "name": "location", + "required": false, + "defaultValue": "", + "description": "" +}, +"specimen": { + "name": "specimen", + "required": false, + "defaultValue": "", + "description": "" +}, +"study": { + "name": "study", + "required": false, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "find", "timeCreated": "Wed Nov 28 20:40:33 UTC 2018", "createdBy": "admin", - "description": " " + "description": " " } }, "deleteEndpoints": { - "deleteSlide": { - "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027slide.name\u0027 : \u0027$slide$\u0027 }\n\t\t\t\t\t\t}\n}\n", + "updateSlide": { + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027name\u0027 : $slide$} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027$field$\u0027 : \u0027$value$\u0027 }},\n\t\t\t\t\t\t\t\"upsert\": \u0027true\u0027,\n\t\t\t\t\t\t\t\"multi\" : \u0027false\u0027\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - } +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +}, +"field": { + "name": "field", + "required": true, + "defaultValue": "", + "description": "" +}, +"value": { + "name": "value", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", - "name": "deleteSlide", - "timeCreated": "Wed Aug 29 17:45:23 UTC 2018", + "name": "updateSlide", + "timeCreated": "Tue Jul 02 18:21:13 GMT 2019", "createdBy": "admin", "description": "" }, - "updateSlide": { - "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027name\u0027 : \u0027$slide$\u0027} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027$field$\u0027 : \u0027$value$\u0027 }},\n\t\t\t\t\t\t\t\"upsert\": \u0027true\u0027,\n\t\t\t\t\t\t\t\"multi\" : \u0027false\u0027\n\t\t\t\t\t\t}\n}\n ", + "deleteSlide": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027slide.name\u0027 : \"\"$slide$\"\" }\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - }, - "field": { - "name": "field", - "required": true, - "defaultValue": "", - "description": "" - }, - "value": { - "name": "value", - "required": true, - "defaultValue": "", - "description": "" - } +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", - "name": "updateSlide", - "timeCreated": "Wed Aug 29 17:52:22 UTC 2018", + "name": "deleteSlide", + "timeCreated": "Tue Jul 02 18:21:26 GMT 2019", "createdBy": "admin", "description": "" } @@ -631,7 +631,7 @@ "csvFile": { "type": "MULTIPART", "properties": { - "inputType": "CSV_FILE" +"inputType": "CSV_FILE" }, "name": "csvFile", "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", @@ -641,7 +641,7 @@ "jsonFile": { "type": "MULTIPART", "properties": { - "inputType": "JSON_FILE" +"inputType": "JSON_FILE" }, "name": "jsonFile", "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", @@ -651,7 +651,7 @@ "csv": { "type": "FORM_DATA", "properties": { - "inputType": "CSV" +"inputType": "CSV" }, "name": "csv", "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", @@ -661,7 +661,7 @@ "json": { "type": "FORM_DATA", "properties": { - "inputType": "JSON" +"inputType": "JSON" }, "name": "json", "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", @@ -686,26 +686,26 @@ }, "queryEndpoints": { "find": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : {\"name\": {$regex: \"$name$\", $options: \"i\"},\n \"type\": {$regex: \"$type$\", $options: \"i\"}}\n }\n} ", + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" : {\"name\": {$regex: \"$name$\", $options: \"i\"},\n \"type\": {$regex: \"$type$\", $options: \"i\"}}\n}\n} ", "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": false, - "defaultValue": "", - "description": "" - }, - "type": { - "name": "type", - "required": false, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" +}, +"type": { + "name": "type", + "required": false, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "find", "timeCreated": "Mon Aug 27 15:46:51 UTC 2018", @@ -717,16 +717,16 @@ "metaData": {}, "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "get", "timeCreated": "Wed Aug 29 18:41:36 UTC 2018", @@ -739,12 +739,12 @@ "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}}\n\t\t\t\t\t\t}\n} ", "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "name": "deleteTemplate", @@ -757,7 +757,7 @@ "csvFile": { "type": "MULTIPART", "properties": { - "inputType": "CSV_FILE" +"inputType": "CSV_FILE" }, "name": "csvFile", "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", @@ -767,7 +767,7 @@ "jsonFile": { "type": "MULTIPART", "properties": { - "inputType": "JSON_FILE" +"inputType": "JSON_FILE" }, "name": "jsonFile", "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", @@ -777,7 +777,7 @@ "csv": { "type": "FORM_DATA", "properties": { - "inputType": "CSV" +"inputType": "CSV" }, "name": "csv", "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", @@ -787,7 +787,7 @@ "json": { "type": "FORM_DATA", "properties": { - "inputType": "JSON" +"inputType": "JSON" }, "name": "json", "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", @@ -816,16 +816,16 @@ "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": true, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "getAuth", "timeCreated": "Fri Aug 10 19:27:36 UTC 2018", @@ -838,7 +838,7 @@ "csvFile": { "type": "MULTIPART", "properties": { - "inputType": "CSV_FILE" +"inputType": "CSV_FILE" }, "name": "csvFile", "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", @@ -848,7 +848,7 @@ "jsonFile": { "type": "MULTIPART", "properties": { - "inputType": "JSON_FILE" +"inputType": "JSON_FILE" }, "name": "jsonFile", "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", @@ -858,7 +858,7 @@ "csv": { "type": "FORM_DATA", "properties": { - "inputType": "CSV" +"inputType": "CSV" }, "name": "csv", "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", @@ -868,7 +868,7 @@ "json": { "type": "FORM_DATA", "properties": { - "inputType": "JSON" +"inputType": "JSON" }, "name": "json", "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", @@ -892,86 +892,86 @@ "initialize": true }, "queryEndpoints": { - "get": { - "queryTemplate": "{\n\t\u0027_operation\u0027: \u0027find\u0027,\n\t\u0027_operation_args\u0027: \n\t{\n\t\u0027query\u0027: {\n\t\t\"provenance.image.slide\": \"$slide$\",\n\t\t\"provenance.analysis.execution_id\":\"$name$\"\n\t},\n\t\t\u0027fields\u0027: {\n\t\t\t\u0027provenance\u0027:1,\n \u0027data\u0027:1,\n\t\t\t\u0027_id\u0027: 1\n\t\t}\n\t}\n} ", + "findTypes": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" : { \"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n\"provenance.image.slide\" : \"$slide$\"},\n\"fields\" :{ \u0027data\u0027 : 0 }\n}\n\n} ", "metaData": {}, "tags": [], "bindVariables": { - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - }, - "name": { - "name": "name", - "required": true, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, - "name": "get", - "timeCreated": "Fri Jun 14 16:29:22 GMT 2019", + "name": "findTypes", + "timeCreated": "Thu Jun 27 19:39:21 GMT 2019", "createdBy": "admin", - "description": " " + "description": " " }, "find": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : { \"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.specimen\" : {$regex: \"$specimen$\", $options: \"i\"}\n }\n} ", + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" : { \"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n\"provenance.image.slide\" : \"$slide$\"\n}\n} ", "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": false, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "find", - "timeCreated": "Fri Jun 14 16:29:58 GMT 2019", + "timeCreated": "Thu Jun 27 19:40:22 GMT 2019", "createdBy": "admin", - "description": " " + "description": " " }, - "findTypes": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : { \"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"}},\n \"fields\" :{ \u0027data\u0027 : 0 } \n}\n\n} ", + "get": { + "queryTemplate": "{\n\t\u0027_operation\u0027: \u0027find\u0027,\n\t\u0027_operation_args\u0027: \n\t{\n\t\u0027query\u0027: {\n\t\t\"provenance.image.slide\": \"$slide$\",\n\t\t\"provenance.analysis.execution_id\":\"$name$\"\n\t},\n\t\t\u0027fields\u0027: {\n\t\t\t\u0027provenance\u0027:1,\n\u0027data\u0027:1,\n\t\t\t\u0027_id\u0027: 1\n\t\t}\n\t}\n} ", "metaData": {}, "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": false, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - } +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +}, +"name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, - "name": "findTypes", - "timeCreated": "Fri Jun 14 16:30:43 GMT 2019", + "name": "get", + "timeCreated": "Mon Jul 01 20:07:42 GMT 2019", "createdBy": "admin", - "description": " " + "description": " " } }, "deleteEndpoints": { @@ -979,18 +979,18 @@ "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027provenance.image.slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "name": "deleteHeatmap", @@ -999,37 +999,37 @@ "description": "" }, "updateThreshold": { - "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : {\u0027provenance.analysis.execution_id\u0027 : \u0027$name$\u0027,\u0027provenance.image.slide\u0027 : \u0027$slide$\u0027} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027provenance.analysis.fields\u0027 : $fields$,\u0027provenance.analysis.setting\u0027 : $setting$ }},\n\t\t\t\t\t\t\t\"upsert\": true,\n\t\t\t\t\t\t\t\"multi\" : true\n\t\t\t\t\t\t}\n}\n ", + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : {\u0027provenance.analysis.execution_id\u0027 : \u0027$name$\u0027,\u0027provenance.image.slide\u0027 : \"$slide$\"} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027provenance.analysis.fields\u0027 : $fields$,\u0027provenance.analysis.setting\u0027 : $setting$ }},\n\t\t\t\t\t\t\t\"upsert\": true,\n\t\t\t\t\t\t\t\"multi\" : true\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "name": { - "name": "name", - "required": true, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - }, - "fields": { - "name": "fields", - "required": true, - "defaultValue": "", - "description": "" - }, - "setting": { - "name": "setting", - "required": true, - "defaultValue": "", - "description": "" - } +"name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +}, +"fields": { + "name": "fields", + "required": true, + "defaultValue": "", + "description": "" +}, +"setting": { + "name": "setting", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "name": "updateThreshold", - "timeCreated": "Fri Jun 14 16:31:37 GMT 2019", + "timeCreated": "Tue Jul 02 17:06:06 GMT 2019", "createdBy": "admin", "description": "" } @@ -1038,7 +1038,7 @@ "csvFile": { "type": "MULTIPART", "properties": { - "inputType": "CSV_FILE" +"inputType": "CSV_FILE" }, "name": "csvFile", "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", @@ -1048,7 +1048,7 @@ "jsonFile": { "type": "MULTIPART", "properties": { - "inputType": "JSON_FILE" +"inputType": "JSON_FILE" }, "name": "jsonFile", "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", @@ -1058,7 +1058,7 @@ "csv": { "type": "FORM_DATA", "properties": { - "inputType": "CSV" +"inputType": "CSV" }, "name": "csv", "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", @@ -1068,7 +1068,7 @@ "json": { "type": "FORM_DATA", "properties": { - "inputType": "JSON" +"inputType": "JSON" }, "name": "json", "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", @@ -1097,16 +1097,16 @@ "metaData": {}, "tags": [], "bindVariables": { - "id": { - "name": "id", - "required": true, - "defaultValue": "", - "description": "" - } +"id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "get", "timeCreated": "Wed Apr 24 18:10:50 GMT 2019", @@ -1114,107 +1114,107 @@ "description": "" }, "find": { - "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : {\u0027user_id\u0027: {$regex: \"$user$\", $options: \"i\"},\n \u0027provenance.image.slide\u0027: {$regex: \"$slide$\", $options: \"i\"},\n \u0027provenance.analysis.execution_id\u0027: {$regex: \"$name$\", $options: \"i\"}}\n }\n} ", + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n\"query\" : {\u0027user_id\u0027: {$regex: \"$user$\", $options: \"i\"},\n \u0027provenance.image.slide\u0027: \"$slide$\",\n \u0027provenance.analysis.execution_id\u0027: {$regex: \"$name$\", $options: \"i\"}}\n}\n}", "metaData": {}, "tags": [], "bindVariables": { - "user": { - "name": "user", - "required": false, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": false, - "defaultValue": "", - "description": "" - }, - "name": { - "name": "name", - "required": false, - "defaultValue": "", - "description": "" - } +"user": { + "name": "user", + "required": false, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" +}, +"name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "outputFormat": { - "outputFormat": "JSON" +"outputFormat": "JSON" }, "name": "find", - "timeCreated": "Fri Jun 14 16:32:57 GMT 2019", + "timeCreated": "Thu Jun 27 19:40:01 GMT 2019", "createdBy": "admin", - "description": " " + "description": " " } }, "deleteEndpoints": { "update": { - "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027user_id\u0027 : \u0027$user$\u0027, \u0027provenance.image.specimen\u0027:\u0027$specimen$\u0027, \n\u0027provenance.image.slide\u0027:\u0027$slide$\u0027,\u0027provenance.analysis.execution_id\u0027:\u0027$name$\u0027 } ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027data\u0027 : $data$}},\n\t\t\t\t\t\t\t\"upsert\": true,\n\t\t\t\t\t\t\t\"multi\" : true\n\t\t\t\t\t\t}\n}\n ", + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027user_id\u0027 : \u0027$user$\u0027, \u0027provenance.image.specimen\u0027:\u0027$specimen$\u0027, \n\u0027provenance.image.slide\u0027:\"$slide$\",\u0027provenance.analysis.execution_id\u0027:\u0027$name$\u0027 } ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027data\u0027 : $data$}},\n\t\t\t\t\t\t\t\"upsert\": true,\n\t\t\t\t\t\t\t\"multi\" : true\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "user": { - "name": "user", - "required": true, - "defaultValue": "", - "description": "" - }, - "specimen": { - "name": "specimen", - "required": true, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - }, - "name": { - "name": "name", - "required": true, - "defaultValue": "", - "description": "" - }, - "data": { - "name": "data", - "required": true, - "defaultValue": "", - "description": "" - } +"user": { + "name": "user", + "required": true, + "defaultValue": "", + "description": "" +}, +"specimen": { + "name": "specimen", + "required": true, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +}, +"name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" +}, +"data": { + "name": "data", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "name": "update", - "timeCreated": "Mon Jun 10 17:58:52 GMT 2019", + "timeCreated": "Tue Jul 02 17:50:23 GMT 2019", "createdBy": "admin", "description": "" }, "delete": { - "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027user_id\u0027 : \u0027$user$\u0027,\u0027provenance.image.slide\u0027: \"$slide$\", \u0027provenance.analysis.execution_id\u0027: \"$name$\" }\n\t\t\t\t\t\t}\n}\n ", + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027user_id\u0027 : \u0027$user$\u0027,\u0027provenance.image.slide\u0027: \"$slide$\", \u0027provenance.analysis.execution_id\u0027: \"$name$\" }\n\t\t\t\t\t\t}\n}\n ", "tags": [], "bindVariables": { - "user": { - "name": "user", - "required": true, - "defaultValue": "", - "description": "" - }, - "slide": { - "name": "slide", - "required": true, - "defaultValue": "", - "description": "" - }, - "name": { - "name": "name", - "required": true, - "defaultValue": "", - "description": "" - } +"user": { + "name": "user", + "required": true, + "defaultValue": "", + "description": "" +}, +"slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" +}, +"name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" +} }, "stage": "UNVERIFIED", "name": "delete", - "timeCreated": "Fri Jun 14 18:09:59 GMT 2019", + "timeCreated": "Tue Jul 02 18:24:29 GMT 2019", "createdBy": "admin", "description": "" } @@ -1223,7 +1223,7 @@ "csvFile": { "type": "MULTIPART", "properties": { - "inputType": "CSV_FILE" +"inputType": "CSV_FILE" }, "name": "csvFile", "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", @@ -1233,7 +1233,7 @@ "jsonFile": { "type": "MULTIPART", "properties": { - "inputType": "JSON_FILE" +"inputType": "JSON_FILE" }, "name": "jsonFile", "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", @@ -1243,7 +1243,7 @@ "csv": { "type": "FORM_DATA", "properties": { - "inputType": "CSV" +"inputType": "CSV" }, "name": "csv", "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", @@ -1253,7 +1253,7 @@ "json": { "type": "FORM_DATA", "properties": { - "inputType": "JSON" +"inputType": "JSON" }, "name": "json", "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", @@ -1274,4 +1274,4 @@ "timeCreated": "Wed Aug 01 17:17:55 UTC 2018", "createdBy": "admin", "description": "caMicroscope Data model" -} \ No newline at end of file +} diff --git a/config/httpd.conf.template b/config/httpd.conf.template index 3f3debd..3b4871a 100644 --- a/config/httpd.conf.template +++ b/config/httpd.conf.template @@ -137,8 +137,11 @@ DocumentRoot "/data/pathdb/quip/web" RewriteEngine On DirectoryIndex index.php index.htm index.html RewriteEngine on - RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) - RewriteRule .* - [F] + RewriteBase / + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} !=/favicon.ico + RewriteRule ^ index.php [L] # @@ -341,12 +344,8 @@ IncludeOptional conf.d/*.conf # SSLCertificateKeyFile /config/quip.bmi.stonybrook.edu.key # SSLCertificateChainFile /config/inter.cer Options Indexes FollowSymLinks IncludesNOEXEC - RewriteEngine On KeepAlive On DirectoryIndex index.php index.htm index.html - RewriteEngine on - RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) - RewriteRule .* - [F] ProxyPass /caMicroscope/img/ http://ca-security:4010/img/ ProxyPassReverse /caMicroscope/img/ http://ca-security:4010/img/ ProxyPass /caMicroscope/data/ http://ca-security:4010/data/ @@ -363,9 +362,6 @@ IncludeOptional conf.d/*.conf RewriteEngine On KeepAlive On DirectoryIndex index.php index.htm index.html - RewriteEngine on - RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) - RewriteRule .* - [F] ProxyPass /caMicroscope/img/ http://ca-security:4010/img/ ProxyPassReverse /caMicroscope/img/ http://ca-security:4010/img/ ProxyPass /caMicroscope/data/ http://ca-security:4010/data/ diff --git a/quip-pathdb.yml b/quip-pathdb.yml index 21e6dce..f035164 100644 --- a/quip-pathdb.yml +++ b/quip-pathdb.yml @@ -53,7 +53,7 @@ services: logging: driver: none pathdb: - build: "https://github.com/SBU-BMI/PathDB.git#1.0.5" + build: "https://github.com/SBU-BMI/PathDB.git#1.0.6" container_name: quip-pathdb restart: unless-stopped ports: ["443:443","80:80"] diff --git a/test/Deps/Bindaas/Dockerfile b/test/Deps/Bindaas/Dockerfile new file mode 100644 index 0000000..f8b9391 --- /dev/null +++ b/test/Deps/Bindaas/Dockerfile @@ -0,0 +1,34 @@ +FROM alpine:3.9 +LABEL maintainer="ashish@dbmi.emory.edu" + +### update and include Shadow to manage users and groups +RUN apk update +RUN apk --no-cache add wget +RUN apk --no-cache add shadow + +# Add group Bindaas and user Bindaas +RUN groupadd -g 9999 bindaas && \ + useradd -r -u 9999 -g bindaas bindaas + +WORKDIR /root/src + +RUN apk --no-cache add openjdk8-jre +WORKDIR /root/bindaas/ +RUN wget https://github.com/sharmalab/bindaas/releases/download/v3.3.8/bindaas-dist-3.3.8.tar.gz +RUN tar -xvf bindaas-dist-3.3.8.tar.gz && rm bindaas-dist-3.3.8.tar.gz +COPY bindaas.config.json /root/bindaas/bin/ +COPY run.sh /root/bindaas/bin/ + +# Add java to path +ENV PATH /root/src/jre1.8.0_171/bin:$PATH + +RUN chown -R bindaas:bindaas /root/ + +WORKDIR /root/bindaas/bin + +USER bindaas + +EXPOSE 9099 +EXPOSE 8080 + +CMD ["sh", "run.sh"] diff --git a/test/Deps/Bindaas/bindaas.config.json b/test/Deps/Bindaas/bindaas.config.json new file mode 100644 index 0000000..665dc08 --- /dev/null +++ b/test/Deps/Bindaas/bindaas.config.json @@ -0,0 +1,13 @@ +{ + "host": "0.0.0.0", + "port": 9099, + "protocol": "http", + "enableAuthentication": false, + "enableAuthorization": false, + "enableAudit": true, + "authenticationProviderClass": "edu.emory.cci.bindaas.security.impl.DBAuthenticationProvider", + "authorizationProviderClass": "edu.emory.cci.bindaas.security_dashboard.service.AuthorizationProviderImpl", + "auditProviderClass": "edu.emory.cci.bindaas.security.impl.DBAuditProvider", + "proxyUrl": "http://localhost:9099", + "instanceName": "bindaas" +} diff --git a/test/Deps/Bindaas/run.sh b/test/Deps/Bindaas/run.sh new file mode 100644 index 0000000..ed8ba61 --- /dev/null +++ b/test/Deps/Bindaas/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +java -jar -Dpid=BINDAAS_INSTANCE org.eclipse.osgi_3.10.100.v20150529-1857.jar + +while true; do sleep 1000; done diff --git a/test/Deps/auth_service/Dockerfile b/test/Deps/auth_service/Dockerfile new file mode 100644 index 0000000..bc86932 --- /dev/null +++ b/test/Deps/auth_service/Dockerfile @@ -0,0 +1,9 @@ +FROM node:8-alpine +RUN mkdir /root/src +COPY . /root/src +WORKDIR /root/src + +RUN npm install +RUN npm install -g forever +EXPOSE 8010 +CMD forever app.js diff --git a/test/Deps/auth_service/about.md b/test/Deps/auth_service/about.md new file mode 100644 index 0000000..a0048a0 --- /dev/null +++ b/test/Deps/auth_service/about.md @@ -0,0 +1 @@ +This is a pre-pathdb service to answer auth questions. diff --git a/test/Deps/auth_service/app.js b/test/Deps/auth_service/app.js new file mode 100644 index 0000000..6c9ff05 --- /dev/null +++ b/test/Deps/auth_service/app.js @@ -0,0 +1,111 @@ +const express = require('express') +const rp = require('request-promise'); +const app = express(); +const fs = require("fs"); +var jwt = require('jsonwebtoken'); +var jwkToPem = require('jwk-to-pem'); +var cookieParser = require('cookie-parser'); +var PORT = process.env.PORT || 8010 +var BASE_USER_URL = "http://ca-data:9099/services/caMicroscope/Authorization/query/getAuth?name=" +var SECRET = process.env.SECRET +var EXPIRY = process.env.EXPIRY || "1d" + +// get cookies +app.use(cookieParser()) + +try { + let prikey_path = "/keys/key" + if(fs.existsSync(prikey_path)){ + var PRIKEY = fs.readFileSync(prikey_path, 'utf8') + } +} catch (err){ + console.error(err) +} + +try { + let pubkey_path = "/keys/key.pub" + if(fs.existsSync(pubkey_path)){ + var PUBKEY = fs.readFileSync(pubkey_path, 'utf8') + } +} catch (err){ + console.error(err) +} + +try { + let cert_path = "/keys/certificate" + if(fs.existsSync(cert_path)){ + var SECRET = fs.readFileSync(cert_path, 'utf8') + } +} catch (err){ + console.error(err) +} +// jwks +try { + let jwk_path = "/keys/jwk.json" + if(fs.existsSync(jwk_path)){ + var SECRET = jwkToPem(JSON.parse(fs.readFileSync(jwk_path, 'utf8'))) + } +} catch (err){ + console.error(err) +} + +const getToken = function(req) { + if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') { // Authorization: Bearer g1jipjgi1ifjioj + // Handle token presented as a Bearer token in the Authorization header + return req.headers.authorization.split(' ')[1]; + } else if (req.query && req.query.token) { + // Handle token presented as URI param + return req.query.token; + } else if (req.cookies && req.cookies.token) { + // Handle token presented as a cookie parameter + return req.cookies.token; + } +} +// curry these calls +function token_trade(check_key, sign_key){ + return function(req,res){ + jwt.verify(getToken(req), check_key, function(err, token){ + if (err){ + res.status(401).send(err) + } else { + if (!(token && (token.email || token.sub))){ + // jwt doesn't say who you are, so bye + res.send(401).send({err:"email and sub are unset from source token"}) + } else { + var name = token.email || token.sub + user_detail = rp({ + uri: BASE_USER_URL + name, + json: true + }) + user_detail.then(x=>{ + console.log(x) + if (x.length >= 1 && x[0].hasOwnProperty('name')){ + let attrs = x[0].attrs || [] + data = { + 'sub':name, + 'name':x[0].name, + 'attrs':attrs + } + // sign using the mounted key + var token = jwt.sign(data, sign_key, {algorithm:"RS256", expiresIn: EXPIRY}) + res.send({'token':token}) + } else { + res.status(401).send({"err":"User Unauthorized"}) + } + }) + user_detail.catch(e=>{ + console.log(e) + res.status(401).send(e) + }) + } + } + }) + } +} + +// convert or "check" a token +app.get("/check", token_trade(SECRET, PRIKEY)) +// renew a token +app.get("/renew", token_trade(PUBKEY, PRIKEY)) + +app.listen(PORT, () => console.log('listening on ' + PORT)) diff --git a/test/Deps/auth_service/package-lock.json b/test/Deps/auth_service/package-lock.json new file mode 100644 index 0000000..09b4082 --- /dev/null +++ b/test/Deps/auth_service/package-lock.json @@ -0,0 +1,879 @@ +{ + "name": "auth_service", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "ajv": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz", + "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "express-promise": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/express-promise/-/express-promise-0.4.0.tgz", + "integrity": "sha1-BDw8t3iND/KZsGUG30RXIv360eQ=" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonwebtoken": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz", + "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==", + "requires": { + "jws": "^3.1.5", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jwa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.2.0.tgz", + "integrity": "sha512-Grku9ZST5NNQ3hqNUodSkDfEBqAmGA1R8yiyPHOnLzEKI0GaCQC/XhFmsheXYuXzFQJdILbh+lYBiliqG5R/Vg==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.10", + "safe-buffer": "^5.0.1" + } + }, + "jwk-to-pem": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwk-to-pem/-/jwk-to-pem-2.0.1.tgz", + "integrity": "sha512-KKu0WuDDjqw2FlRFp9/vk9TMO/KvgpZVKzdhhYcNyy5OwE8dw9lOK5OQTQHIJ7m+HioI/4P44sAtVuDrQ8KQfw==", + "requires": { + "asn1.js": "^4.5.2", + "elliptic": "^6.2.3", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz", + "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==", + "requires": { + "jwa": "^1.2.0", + "safe-buffer": "^5.0.1" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.38.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", + "integrity": "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + }, + "mime-types": { + "version": "2.1.22", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz", + "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", + "requires": { + "mime-db": "~1.38.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + } + } + }, + "request-promise": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz", + "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==", + "requires": { + "bluebird": "^3.5.0", + "request-promise-core": "1.1.2", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "request-promise-core": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz", + "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", + "requires": { + "lodash": "^4.17.11" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + } + } +} diff --git a/test/Deps/auth_service/package.json b/test/Deps/auth_service/package.json new file mode 100644 index 0000000..681788a --- /dev/null +++ b/test/Deps/auth_service/package.json @@ -0,0 +1,20 @@ +{ + "name": "auth_service", + "version": "1.0.0", + "description": "", + "main": "app.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "birm", + "license": "UNLICENSED", + "dependencies": { + "cookie-parser": "^1.4.4", + "express": "^4.16.4", + "express-promise": "^0.4.0", + "jsonwebtoken": "^8.4.0", + "jwk-to-pem": "^2.0.1", + "request": "^2.88.0", + "request-promise": "^4.2.4" + } +} diff --git a/test/Deps/auth_service/readme.md b/test/Deps/auth_service/readme.md new file mode 100644 index 0000000..111be3a --- /dev/null +++ b/test/Deps/auth_service/readme.md @@ -0,0 +1,10 @@ +# Auth Service for Elevate + + +Uses bindaas endpoint to determine users and their permissions. + +Set SECRET to the jwt secret, or use /keys/certificate with a certificate, or /keys/jwk.json with a jwk. + +Use EXPIRY to set a token expiration other than the default one hour. + +This tool needs key and key.pub mounted to /keys to sign JWTs to elevate. In this distribution, run jwt_keys/make_keys.sh to do so. diff --git a/test/LICENSE b/test/LICENSE new file mode 100644 index 0000000..4213d86 --- /dev/null +++ b/test/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, caMicroscope +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..82c9718 --- /dev/null +++ b/test/README.md @@ -0,0 +1,56 @@ +# caMicroscope Distribution + +[![Build Status](https://travis-ci.org/camicroscope/Distro.svg?branch=master)](https://travis-ci.org/camicroscope/Distro) + +caMicroscope 3.X distribution + + +run with `docker-compose -f caMicroscope.yml up` + +this will build all services and run in the foreground. +Use `docker-compose -f caMicroscope.yml build` to rebuild the services. + +Once everything is up, go to :4010/ to see the landing page. + +## SSL +To enable ssl, mount the private key and certificate files to the security service in /root/src/ssl/privatekey.pem and /root/src/ssl/certificate.pem respectively. HTTPS mode will only be enabled if both of these files are present. + +## Component Services +mongo - vanilla mongo container + +idxMongo - ephemeral container to index mongo (that is, this container is *expected* to exit once it's done its job) + +bindaas - api service for mongo (see https://github.com/sharmalab/bindaas) + +iip - slide tile server (see https://github.com/camicroscope/iipImage) + +viewer - hosts the viewer files and builds packages ( see https://github.com/camicroscope/caMicroscope) + +loader - extracts metadata needed for image loading (see https://github.com/camicroscope/SlideLoader) + +security - security proxy (see https://github.com/camicroscope/Security) + +## Configuration +Logging - Container Logging is, for HIPAA reasons, disabled. Feel free to use a different logging engine if desired, especially for development. + +Security and Routes - This is handled by the security container. By default routes go the viewer, unless a specific pattern in routes.json is matched. If security is enabled, supply the SECRET (pub key or secret of JWT) for verification, otherwise set DISABLE_SEC to true. + +Image Volume - This is, by default, the images directory in this directory. If this is changed, please make the same change across all impacted services. + +Packages - Packages are built in the viewer service using parcel, mount a different directory with packages.js to the package directory to overwrite or add functionality. + +## PathDB + +To use PathDB, use quip-pathdb.yml instead of caMicroscope.yml. This deployment does not include the auth and loader as separate services, as this PathDB provides that functionality. + +Running QuIP with PathDB: + +0) place yourself in quip\_distro folder.
+1) copy config/httpd.conf.template to config/httpd.conf
+2) copy config/pathdb\_routes.json to config/routes.json (this will overwrite an existing routes.json file)
+3) configure httpd.conf with your certificates to enable https.
+4) build with, "docker-compose -f quip-pathdb.yml build"
+5) run with, "docker-compose -f quip-pathdb.yml up -d" + +## Support +Feel free to add any support inquiry as a github issue to this repository. Other feedback can be given via [this form](https://docs.google.com/forms/d/e/1FAIpQLScL91LxrpAZjU88GBZP9gmcdgdf8__uNUwhws2lzU6Lr4qNwA/viewform). diff --git a/test/auth_without_pathdb.md b/test/auth_without_pathdb.md new file mode 100644 index 0000000..403da2e --- /dev/null +++ b/test/auth_without_pathdb.md @@ -0,0 +1,33 @@ +# QUIP Auth Without PathDB + +## About this Method and Guide + +PathDB is used as both authentication and authorization. In instances where PathDB is not desired, we use a combination of an external identity provider and an internal authorization service. The authorization service consumes Json Web Tokens (JWTs) from the identity provider, and then will issue JWTs which convey both authentication and authorization, which are consumed by the application. + +This guide aims to explain how to make a deployment use this method. + +## Getting an Identity Provider and Setting up Login + +There are many identity providers, but for testing and examples, we have been using auth0. + +When selecting, an identity provider, note that we expect it to provide a JWT, and to have a certificate/public key/secret which can be used to verify such JWTs. + +The example given in the Distro within config/login.html is set up for auth0; simply change the corresponding variables for your auth0 application if auth0 is used. If using another identity provider, then login.html, or equivalent, needs to, at least, set the JWT to a cookie called "token", and call the auth service's 'check' route, and save a successful result as the token. Follow the guide which your identity provider uses for further guidance. + +## Keys/Certificates + +Add the following files; by default, they are mounted: + +- --./jwt\_keys/certificate or ./jwt\_keys/jwk.json is the certificate/public key/secret or jwk (respectively) from the **identity provider**. (If both are included, the jwk takes precedence). +- --./jwt\_keys/key and ./jwt\_keys/key.pub are used as the signing and check keys for the **auth service** + - --These can (and should) be generated with ./kwt\_keys/make\_keys.sh + +## Deployment Configuration + +Turn off disable security under the elevate service to block routes. + +## Adding Users to Database + +Add users as in ./config/add\_mongo\_users.js. Attributes can be added to deny access to routes (e.g. allow only some users to post and delete) + +The name field is the email field (or failing that, sub field) in that priority from the identity provider. diff --git a/test/caMicroscope.yml b/test/caMicroscope.yml new file mode 100644 index 0000000..1ac326e --- /dev/null +++ b/test/caMicroscope.yml @@ -0,0 +1,76 @@ +version: '3' + +services: + mongo: + image: mongo:3.4.19-jessie + container_name: ca-mongo + restart: unless-stopped + volumes: + - ./db:/data/db + logging: + driver: none + idxMongo: + image: mongo:3.4.19-jessie + container_name: ca-idx + logging: + driver: none + links: + - mongo + volumes: + - ./config:/config + command: + - /config/run_idx.sh + depends_on: + - mongo + bindaas: + build: "./Deps/Bindaas/" + depends_on: + - "mongo" + container_name: ca-data + restart: unless-stopped + logging: + driver: none + volumes: + - ./config/bindaas_projects/:/root/bindaas/bin/projects/ + - ./config/bindaas.config.json:/root/bindaas/bin/bindaas.config.json + iip: + build: "https://github.com/camicroscope/iipImage.git#v3.2.0" + container_name: ca-iip + restart: unless-stopped + volumes: + - ./images/:/images/ + viewer: + build: "https://github.com/camicroscope/caMicroscope.git#v3.4.0" + container_name: ca-front + restart: unless-stopped + volumes: + - ./config/login.html:/var/www/html/login.html + logging: + driver: none + loader: + build: "https://github.com/camicroscope/SlideLoader.git#v3.2.0" + container_name: ca-load + restart: unless-stopped + logging: + driver: none + volumes: + - ./images/:/images/ + security: + build: "https://github.com/camicroscope/Security.git#v3.2.2" + container_name: ca-security + restart: unless-stopped + ports: + - "4010:4010" + volumes: + - ./config/routes.json:/root/src/routes.json + - ./jwt_keys/:/keys/ + environment: + - DISABLE_SEC=true + auth: + build: "./Deps/auth_service/" + volumes: + - ./jwt_keys/:/keys/ + container_name: ca-auth + restart: unless-stopped + logging: + driver: none diff --git a/test/config/add_mongo_users.js b/test/config/add_mongo_users.js new file mode 100644 index 0000000..f0cfbfa --- /dev/null +++ b/test/config/add_mongo_users.js @@ -0,0 +1,28 @@ +// these roles are customizable, and should match the routes.json attrs + +// lists +let admin_list = ["admin@camicroscope.org"]; +let editor_list = ["editor@camicroscope.org"]; +let viewer_list = ["viewer@camicroscope.org"]; +// admin users +let admin_attrs = ['admin', 'write'] +// edit users +let editor_attrs = ['write'] +// normal users +let viewer_attrs = [] +// prep for mongo +var users = [] + +admin_list.forEach(x=>{ + users.push({name:x, attrs: admin_attrs}) +}) + +editor_list.forEach(x=>{ + users.push({name:x, attrs: editor_attrs}) +}) + +viewer_list.forEach(x=>{ + users.push({name:x, attrs: viewer_attrs}) +}) + +db.authorization.insertMany(users) diff --git a/test/config/bindaas.config.json b/test/config/bindaas.config.json new file mode 100644 index 0000000..665dc08 --- /dev/null +++ b/test/config/bindaas.config.json @@ -0,0 +1,13 @@ +{ + "host": "0.0.0.0", + "port": 9099, + "protocol": "http", + "enableAuthentication": false, + "enableAuthorization": false, + "enableAudit": true, + "authenticationProviderClass": "edu.emory.cci.bindaas.security.impl.DBAuthenticationProvider", + "authorizationProviderClass": "edu.emory.cci.bindaas.security_dashboard.service.AuthorizationProviderImpl", + "auditProviderClass": "edu.emory.cci.bindaas.security.impl.DBAuditProvider", + "proxyUrl": "http://localhost:9099", + "instanceName": "bindaas" +} diff --git a/test/config/bindaas_projects/caMicroscope.project b/test/config/bindaas_projects/caMicroscope.project new file mode 100644 index 0000000..ce3afd5 --- /dev/null +++ b/test/config/bindaas_projects/caMicroscope.project @@ -0,0 +1,1277 @@ +{ + "profiles": { + "Mark": { + "dataSource": { + "host": "ca-mongo", + "port": "27017", + "db": "camic", + "collection": "mark", + "initialize": true + }, + "queryEndpoints": { + "get": { + "queryTemplate": "{\n\t\"_operation\" : \"find\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"limit\" : 1\n\t\t\t\t\t\t}\n}\n ", + "metaData": {}, + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "get", + "timeCreated": "Wed Aug 29 18:40:50 UTC 2018", + "createdBy": "admin", + "description": " " + }, + "findBound": { + "queryTemplate": "{ \"_operation\" : \"find\" , \"_operation_args\" : { \"query\" : {\"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"provenance.analysis.source\" : {$regex: \"$key$\", $options: \"i\"}, \"geometries.features.bound\": { $geoIntersects: { $geometry: { \"type\": \"Polygon\", \"coordinates\": [[[ $x0$, $y0$ ],[ $x0$, $y1$ ],[ $x1$, $y1$ ],[ $x1$, $y0$ ],[ $x0$, $y0$ ]]] } } } }, \"limit\" : 1000} } ", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" + }, + "key": { + "name": "key", + "required": false, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + }, + "x0": { + "name": "x0", + "required": true, + "defaultValue": "", + "description": "" + }, + "y0": { + "name": "y0", + "required": true, + "defaultValue": "", + "description": "" + }, + "x1": { + "name": "x1", + "required": true, + "defaultValue": "", + "description": "" + }, + "y1": { + "name": "y1", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "findBound", + "timeCreated": "Thur Nov 1 18:12:11 UTC 2018", + "createdBy": "admin", + "description": "find where bound intersects given rect" + }, + "findTypes": { + "queryTemplate": "{ \"_operation\" : \"distinct\" , \"_operation_args\" : { \"field\" : \"provenance.analysis\", \"query\" : {\u0027provenance.image.slide\u0027: $slide$ } } } ", + "metaData": {}, + "tags": [], + "bindVariables": { + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "findTypes", + "timeCreated": "Thu May 09 14:52:28 GMT 2019", + "createdBy": "admin", + "description": " " + }, + "findTypesExec": { + "queryTemplate": "{ \"_operation\" : \"distinct\" , \"_operation_args\" : { \"field\" : \"provenance.analysis\", \"query\" : {\u0027provenance.image.slide\u0027: $slide$,\u0027provenance.analysis.execution_id\u0027: $name$ } } } ", + "metaData": {}, + "tags": [], + "bindVariables": { + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + }, + "name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "findTypesExec", + "timeCreated": "Thu May 09 15:09:53 GMT 2019", + "createdBy": "admin", + "description": " " + }, + "find": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" :{$and: [\n {\"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"footprint\": { $not: {$lt: $footprint$}},\n \"provenance.analysis.source\" : {$regex: \"$source$\", $options: \"i\"}},\n {\"x\": { $not: {$lt: $x0$}}},\n {\"x\": { $not: {$gt: $x1$}}},\n {\"y\": { $not: {$lt: $y0$}}},\n {\"y\": { $not: {$gt: $y1$}}}\n ]}\n }\n}\n ", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + }, + "source": { + "name": "source", + "required": false, + "defaultValue": "", + "description": "" + }, + "footprint": { + "name": "footprint", + "required": false, + "defaultValue": "0", + "description": "" + }, + "x0": { + "name": "x0", + "required": false, + "defaultValue": "0", + "description": "" + }, + "x1": { + "name": "x1", + "required": false, + "defaultValue": "9", + "description": "" + }, + "y0": { + "name": "y0", + "required": false, + "defaultValue": "0", + "description": "" + }, + "y1": { + "name": "y1", + "required": false, + "defaultValue": "9", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "find", + "timeCreated": "Fri Jun 14 16:26:22 GMT 2019", + "createdBy": "admin", + "description": " " + }, + "multiFind": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" :{$and: [\n {\"provenance.analysis.execution_id\": {$in: $name$},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"footprint\": { $not: {$lt: $footprint$}},\n \"provenance.analysis.source\" : {$regex: \"$source$\", $options: \"i\"}},\n {\"x\": { $not: {$lt: $x0$}}},\n {\"x\": { $not: {$gt: $x1$}}},\n {\"y\": { $not: {$lt: $y0$}}},\n {\"y\": { $not: {$gt: $y1$}}}\n ]}\n }\n}\n ", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + }, + "footprint": { + "name": "footprint", + "required": false, + "defaultValue": "0", + "description": "" + }, + "source": { + "name": "source", + "required": false, + "defaultValue": "", + "description": "" + }, + "x0": { + "name": "x0", + "required": false, + "defaultValue": "0", + "description": "" + }, + "x1": { + "name": "x1", + "required": false, + "defaultValue": "9", + "description": "" + }, + "y0": { + "name": "y0", + "required": false, + "defaultValue": "0", + "description": "" + }, + "y1": { + "name": "y1", + "required": false, + "defaultValue": "9", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "multiFind", + "timeCreated": "Fri Jun 14 16:27:26 GMT 2019", + "createdBy": "admin", + "description": " " + } + }, + "deleteEndpoints": { + "deleteMark": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027provenance.image.slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "deleteMark", + "timeCreated": "Wed Aug 29 18:43:50 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "submitEndpoints": { + "csvFile": { + "type": "MULTIPART", + "properties": { + "inputType": "CSV_FILE" + }, + "name": "csvFile", + "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "jsonFile": { + "type": "MULTIPART", + "properties": { + "inputType": "JSON_FILE" + }, + "name": "jsonFile", + "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "csv": { + "type": "FORM_DATA", + "properties": { + "inputType": "CSV" + }, + "name": "csv", + "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "json": { + "type": "FORM_DATA", + "properties": { + "inputType": "JSON" + }, + "name": "json", + "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "providerId": "edu.emory.cci.bindaas.datasource.provider.mongodb.MongoDBProvider", + "providerVersion": 1, + "name": "Mark", + "timeCreated": "Wed Aug 01 17:23:41 UTC 2018", + "createdBy": "admin", + "description": "Geospatial Marking Objects" + }, + "Overlay": { + "dataSource": { + "host": "ca-mongo", + "port": "27017", + "db": "camic", + "collection": "overlay", + "initialize": true + }, + "queryEndpoints": { + "get": { + "queryTemplate": "{\n\t\"_operation\" : \"find\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"limit\" : 1\n\t\t\t\t\t\t}\n}\n ", + "metaData": {}, + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "get", + "timeCreated": "Wed Aug 29 18:41:00 UTC 2018", + "createdBy": "admin", + "description": " " + }, + "find": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : { \"name\" : {$regex: \"$name$\", $options: \"i\"},\n \"slide\" : {$regex: \"$slide$\", $options: \"i\"},\n \"location\" : {$regex: \"$location$\", $options: \"i\"}}\n }\n} ", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + }, + "location": { + "name": "location", + "required": false, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "find", + "timeCreated": "Mon Sep 24 18:13:58 UTC 2018", + "createdBy": "admin", + "description": " " + } + }, + "deleteEndpoints": { + "deleteOverlay": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "deleteOverlay", + "timeCreated": "Wed Aug 29 18:44:12 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "updateOverlay": { + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027slide\u0027 : \u0027$slide$\u0027, \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027$field$\u0027 : \u0027$value$\u0027 }},\n\t\t\t\t\t\t\t\"upsert\": \u0027true\u0027,\n\t\t\t\t\t\t\t\"multi\" : \u0027false\u0027\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + }, + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + }, + "field": { + "name": "field", + "required": true, + "defaultValue": "", + "description": "" + }, + "value": { + "name": "value", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "updateOverlay", + "timeCreated": "Wed Aug 29 20:04:49 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "submitEndpoints": { + "csvFile": { + "type": "MULTIPART", + "properties": { + "inputType": "CSV_FILE" + }, + "name": "csvFile", + "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "jsonFile": { + "type": "MULTIPART", + "properties": { + "inputType": "JSON_FILE" + }, + "name": "jsonFile", + "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "csv": { + "type": "FORM_DATA", + "properties": { + "inputType": "CSV" + }, + "name": "csv", + "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "json": { + "type": "FORM_DATA", + "properties": { + "inputType": "JSON" + }, + "name": "json", + "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "providerId": "edu.emory.cci.bindaas.datasource.provider.mongodb.MongoDBProvider", + "providerVersion": 1, + "name": "Overlay", + "timeCreated": "Wed Aug 01 17:24:16 UTC 2018", + "createdBy": "admin", + "description": "Overlay Representation" + }, + "Slide": { + "dataSource": { + "host": "ca-mongo", + "port": "27017", + "db": "camic", + "collection": "slide", + "initialize": true + }, + "queryEndpoints": { + "get": { + "queryTemplate": "{\n\t\"_operation\" : \"find\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"limit\" : 1\n\t\t\t\t\t\t}\n}\n ", + "metaData": {}, + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "get", + "timeCreated": "Wed Aug 29 18:41:29 UTC 2018", + "createdBy": "admin", + "description": " " + }, + "find": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : {\u0027name\u0027: {$regex: \"$slide$\", $options: \"i\"},\n \u0027specimen\u0027: {$regex: \"$specimen$\", $options: \"i\"},\n \u0027study\u0027: {$regex: \"$study$\", $options: \"i\"},\n \u0027location\u0027: {$regex: \"$location$\", $options: \"i\"}}\n }\n} ", + "metaData": {}, + "tags": [], + "bindVariables": { + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + }, + "location": { + "name": "location", + "required": false, + "defaultValue": "", + "description": "" + }, + "specimen": { + "name": "specimen", + "required": false, + "defaultValue": "", + "description": "" + }, + "study": { + "name": "study", + "required": false, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "find", + "timeCreated": "Wed Nov 28 20:40:33 UTC 2018", + "createdBy": "admin", + "description": " " + } + }, + "deleteEndpoints": { + "deleteSlide": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027slide.name\u0027 : \u0027$slide$\u0027 }\n\t\t\t\t\t\t}\n}\n", + "tags": [], + "bindVariables": { + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "deleteSlide", + "timeCreated": "Wed Aug 29 17:45:23 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "updateSlide": { + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027name\u0027 : \u0027$slide$\u0027} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027$field$\u0027 : \u0027$value$\u0027 }},\n\t\t\t\t\t\t\t\"upsert\": \u0027true\u0027,\n\t\t\t\t\t\t\t\"multi\" : \u0027false\u0027\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + }, + "field": { + "name": "field", + "required": true, + "defaultValue": "", + "description": "" + }, + "value": { + "name": "value", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "updateSlide", + "timeCreated": "Wed Aug 29 17:52:22 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "submitEndpoints": { + "csvFile": { + "type": "MULTIPART", + "properties": { + "inputType": "CSV_FILE" + }, + "name": "csvFile", + "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "jsonFile": { + "type": "MULTIPART", + "properties": { + "inputType": "JSON_FILE" + }, + "name": "jsonFile", + "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "csv": { + "type": "FORM_DATA", + "properties": { + "inputType": "CSV" + }, + "name": "csv", + "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "json": { + "type": "FORM_DATA", + "properties": { + "inputType": "JSON" + }, + "name": "json", + "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "providerId": "edu.emory.cci.bindaas.datasource.provider.mongodb.MongoDBProvider", + "providerVersion": 1, + "name": "Slide", + "timeCreated": "Wed Aug 01 17:24:37 UTC 2018", + "createdBy": "admin", + "description": "Represents Slide Objects" + }, + "Template": { + "dataSource": { + "host": "ca-mongo", + "port": "27017", + "db": "camic", + "collection": "template", + "initialize": true + }, + "queryEndpoints": { + "find": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : {\"name\": {$regex: \"$name$\", $options: \"i\"},\n \"type\": {$regex: \"$type$\", $options: \"i\"}}\n }\n} ", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" + }, + "type": { + "name": "type", + "required": false, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "find", + "timeCreated": "Mon Aug 27 15:46:51 UTC 2018", + "createdBy": "admin", + "description": " " + }, + "get": { + "queryTemplate": "{\n\t\"_operation\" : \"find\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"limit\" : 1\n\t\t\t\t\t\t}\n}\n ", + "metaData": {}, + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "get", + "timeCreated": "Wed Aug 29 18:41:36 UTC 2018", + "createdBy": "admin", + "description": " " + } + }, + "deleteEndpoints": { + "deleteTemplate": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}}\n\t\t\t\t\t\t}\n} ", + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "deleteTemplate", + "timeCreated": "Wed Aug 29 18:44:30 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "submitEndpoints": { + "csvFile": { + "type": "MULTIPART", + "properties": { + "inputType": "CSV_FILE" + }, + "name": "csvFile", + "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "jsonFile": { + "type": "MULTIPART", + "properties": { + "inputType": "JSON_FILE" + }, + "name": "jsonFile", + "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "csv": { + "type": "FORM_DATA", + "properties": { + "inputType": "CSV" + }, + "name": "csv", + "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "json": { + "type": "FORM_DATA", + "properties": { + "inputType": "JSON" + }, + "name": "json", + "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "providerId": "edu.emory.cci.bindaas.datasource.provider.mongodb.MongoDBProvider", + "providerVersion": 1, + "name": "Template", + "timeCreated": "Wed Aug 01 17:25:14 UTC 2018", + "createdBy": "admin", + "description": "Templates for Forms, JSONFORM type" + }, + "Authorization": { + "dataSource": { + "host": "ca-mongo", + "port": "27017", + "db": "camic", + "collection": "authorization", + "initialize": true + }, + "queryEndpoints": { + "getAuth": { + "queryTemplate": "{\n\t\"_operation\" : \"find\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027name\u0027 : \u0027$name$\u0027 }\n\t\t\t\t\t\t}\n}\n", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "getAuth", + "timeCreated": "Fri Aug 10 19:27:36 UTC 2018", + "createdBy": "admin", + "description": "get auth for user" + } + }, + "deleteEndpoints": {}, + "submitEndpoints": { + "csvFile": { + "type": "MULTIPART", + "properties": { + "inputType": "CSV_FILE" + }, + "name": "csvFile", + "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "jsonFile": { + "type": "MULTIPART", + "properties": { + "inputType": "JSON_FILE" + }, + "name": "jsonFile", + "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "csv": { + "type": "FORM_DATA", + "properties": { + "inputType": "CSV" + }, + "name": "csv", + "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "json": { + "type": "FORM_DATA", + "properties": { + "inputType": "JSON" + }, + "name": "json", + "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "providerId": "edu.emory.cci.bindaas.datasource.provider.mongodb.MongoDBProvider", + "providerVersion": 1, + "name": "Authorization", + "timeCreated": "Fri Aug 10 19:26:51 UTC 2018", + "createdBy": "admin", + "description": "authorization for slides and collections" + }, + "Heatmap": { + "dataSource": { + "host": "ca-mongo", + "port": "27017", + "db": "camic", + "collection": "heatmap", + "initialize": true + }, + "queryEndpoints": { + "get": { + "queryTemplate": "{\n\t\u0027_operation\u0027: \u0027find\u0027,\n\t\u0027_operation_args\u0027: \n\t{\n\t\u0027query\u0027: {\n\t\t\"provenance.image.slide\": \"$slide$\",\n\t\t\"provenance.analysis.execution_id\":\"$name$\"\n\t},\n\t\t\u0027fields\u0027: {\n\t\t\t\u0027provenance\u0027:1,\n \u0027data\u0027:1,\n\t\t\t\u0027_id\u0027: 1\n\t\t}\n\t}\n} ", + "metaData": {}, + "tags": [], + "bindVariables": { + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + }, + "name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "get", + "timeCreated": "Fri Jun 14 16:29:22 GMT 2019", + "createdBy": "admin", + "description": " " + }, + "find": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : { \"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.specimen\" : {$regex: \"$specimen$\", $options: \"i\"}\n }\n} ", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "find", + "timeCreated": "Fri Jun 14 16:29:58 GMT 2019", + "createdBy": "admin", + "description": " " + }, + "findTypes": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : { \"provenance.analysis.execution_id\" : {$regex: \"$name$\", $options: \"i\"},\n \"provenance.image.slide\" : {$regex: \"$slide$\", $options: \"i\"}},\n \"fields\" :{ \u0027data\u0027 : 0 } \n}\n\n} ", + "metaData": {}, + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "findTypes", + "timeCreated": "Fri Jun 14 16:30:43 GMT 2019", + "createdBy": "admin", + "description": " " + } + }, + "deleteEndpoints": { + "deleteHeatmap": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}, \u0027provenance.image.slide\u0027: \"$slide$\" }\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "deleteHeatmap", + "timeCreated": "Wed Nov 14 16:24:04 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "updateThreshold": { + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : {\u0027provenance.analysis.execution_id\u0027 : \u0027$name$\u0027,\u0027provenance.image.slide\u0027 : \u0027$slide$\u0027} ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027provenance.analysis.fields\u0027 : $fields$,\u0027provenance.analysis.setting\u0027 : $setting$ }},\n\t\t\t\t\t\t\t\"upsert\": true,\n\t\t\t\t\t\t\t\"multi\" : true\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + }, + "fields": { + "name": "fields", + "required": true, + "defaultValue": "", + "description": "" + }, + "setting": { + "name": "setting", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "updateThreshold", + "timeCreated": "Fri Jun 14 16:31:37 GMT 2019", + "createdBy": "admin", + "description": "" + } + }, + "submitEndpoints": { + "csvFile": { + "type": "MULTIPART", + "properties": { + "inputType": "CSV_FILE" + }, + "name": "csvFile", + "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "jsonFile": { + "type": "MULTIPART", + "properties": { + "inputType": "JSON_FILE" + }, + "name": "jsonFile", + "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "csv": { + "type": "FORM_DATA", + "properties": { + "inputType": "CSV" + }, + "name": "csv", + "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", + "createdBy": "admin", + "description": "" + }, + "json": { + "type": "FORM_DATA", + "properties": { + "inputType": "JSON" + }, + "name": "json", + "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", + "createdBy": "admin", + "description": "" + } + }, + "providerId": "edu.emory.cci.bindaas.datasource.provider.mongodb.MongoDBProvider", + "providerVersion": 1, + "name": "Heatmap", + "timeCreated": "Wed Nov 14 15:49:26 UTC 2018", + "createdBy": "admin", + "description": "Point Marking Objects" + }, + "HeatmapEdit": { + "dataSource": { + "host": "ca-mongo", + "port": "27017", + "db": "camic", + "collection": "heatmapEdit", + "initialize": true + }, + "queryEndpoints": { + "get": { + "queryTemplate": "{\n\t\"_operation\" : \"find\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027_id\u0027 : {\"$oid\":\"$id$\"}} ,\n\t\t\t\t\t\t\t\"limit\" : 1\n\t\t\t\t\t\t}\n}", + "metaData": {}, + "tags": [], + "bindVariables": { + "id": { + "name": "id", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "get", + "timeCreated": "Wed Apr 24 18:10:50 GMT 2019", + "createdBy": "admin", + "description": "" + }, + "find": { + "queryTemplate": "{\n \"_operation\" : \"find\" ,\n \"_operation_args\" : {\n \"query\" : {\u0027user_id\u0027: {$regex: \"$user$\", $options: \"i\"},\n \u0027provenance.image.slide\u0027: {$regex: \"$slide$\", $options: \"i\"},\n \u0027provenance.analysis.execution_id\u0027: {$regex: \"$name$\", $options: \"i\"}}\n }\n} ", + "metaData": {}, + "tags": [], + "bindVariables": { + "user": { + "name": "user", + "required": false, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": false, + "defaultValue": "", + "description": "" + }, + "name": { + "name": "name", + "required": false, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "outputFormat": { + "outputFormat": "JSON" + }, + "name": "find", + "timeCreated": "Fri Jun 14 16:32:57 GMT 2019", + "createdBy": "admin", + "description": " " + } + }, + "deleteEndpoints": { + "update": { + "queryTemplate": "{\n\t\"_operation\" : \"update\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027user_id\u0027 : \u0027$user$\u0027, \u0027provenance.image.specimen\u0027:\u0027$specimen$\u0027, \n\u0027provenance.image.slide\u0027:\u0027$slide$\u0027,\u0027provenance.analysis.execution_id\u0027:\u0027$name$\u0027 } ,\n\t\t\t\t\t\t\t\"update\": {$set: { \u0027data\u0027 : $data$}},\n\t\t\t\t\t\t\t\"upsert\": true,\n\t\t\t\t\t\t\t\"multi\" : true\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "user": { + "name": "user", + "required": true, + "defaultValue": "", + "description": "" + }, + "specimen": { + "name": "specimen", + "required": true, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + }, + "name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" + }, + "data": { + "name": "data", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "update", + "timeCreated": "Mon Jun 10 17:58:52 GMT 2019", + "createdBy": "admin", + "description": "" + }, + "delete": { + "queryTemplate": "{\n\t\"_operation\" : \"delete\" ,\n\t\"_operation_args\" : {\n\t\t\t\t\t\t\t\"query\" : { \u0027user_id\u0027 : \u0027$user$\u0027,\u0027provenance.image.slide\u0027: \"$slide$\", \u0027provenance.analysis.execution_id\u0027: \"$name$\" }\n\t\t\t\t\t\t}\n}\n ", + "tags": [], + "bindVariables": { + "user": { + "name": "user", + "required": true, + "defaultValue": "", + "description": "" + }, + "slide": { + "name": "slide", + "required": true, + "defaultValue": "", + "description": "" + }, + "name": { + "name": "name", + "required": true, + "defaultValue": "", + "description": "" + } + }, + "stage": "UNVERIFIED", + "name": "delete", + "timeCreated": "Fri Jun 14 18:09:59 GMT 2019", + "createdBy": "admin", + "description": "" + } + }, + "submitEndpoints": { + "csvFile": { + "type": "MULTIPART", + "properties": { + "inputType": "CSV_FILE" + }, + "name": "csvFile", + "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", + "createdBy": "admin", + "description": "" + }, + "jsonFile": { + "type": "MULTIPART", + "properties": { + "inputType": "JSON_FILE" + }, + "name": "jsonFile", + "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", + "createdBy": "admin", + "description": "" + }, + "csv": { + "type": "FORM_DATA", + "properties": { + "inputType": "CSV" + }, + "name": "csv", + "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", + "createdBy": "admin", + "description": "" + }, + "json": { + "type": "FORM_DATA", + "properties": { + "inputType": "JSON" + }, + "name": "json", + "timeCreated": "Wed Apr 24 18:02:23 GMT 2019", + "createdBy": "admin", + "description": "" + } + }, + "providerId": "edu.emory.cci.bindaas.datasource.provider.mongodb.MongoDBProvider", + "providerVersion": 1, + "name": "HeatmapEdit", + "timeCreated": "Wed Apr 24 18:02:21 GMT 2019", + "createdBy": "admin", + "description": "Edit Data for Heatmaps" + } + }, + "params": {}, + "name": "caMicroscope", + "timeCreated": "Wed Aug 01 17:17:55 UTC 2018", + "createdBy": "admin", + "description": "caMicroscope Data model" +} \ No newline at end of file diff --git a/test/config/default_data.js b/test/config/default_data.js new file mode 100644 index 0000000..abc320f --- /dev/null +++ b/test/config/default_data.js @@ -0,0 +1,26 @@ +let defaultTemplate = { + "_id": "0", + "type": "object", + "id": "annotation-form", + "name": "AnnotSchema", + "description": "", + "links": [], + "additionalProperties": false, + "properties": { + "name": { + "id": "a0", + "title": "Identity Name", + "type": "string", + "required": true, + "description": "note name" + },"notes": { + "id": "a1", + "title": "Notes: ", + "type": "string", + "format":"textarea", + "maxLength": 128 + } + } +} + +db.template.insert(defaultTemplate) diff --git a/test/config/httpd.conf b/test/config/httpd.conf new file mode 100755 index 0000000..8204fad --- /dev/null +++ b/test/config/httpd.conf @@ -0,0 +1,331 @@ +# +# This is the main Apache HTTP server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information. +# In particular, see +# +# for a discussion of each configuration directive. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so 'log/access_log' +# with ServerRoot set to '/www' will be interpreted by the +# server as '/www/log/access_log', where as '/log/access_log' will be +# interpreted as '/log/access_log'. + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# Do not add a slash at the end of the directory path. If you point +# ServerRoot at a non-local disk, be sure to specify a local disk on the +# Mutex directive, if file-based mutexes are used. If you wish to share the +# same ServerRoot for multiple httpd daemons, you will need to change at +# least PidFile. +# +ServerRoot "/etc/httpd" + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, instead of the default. See also the +# directive. +# +# Change this to Listen on specific IP addresses as shown below to +# prevent Apache from glomming onto all bound IP addresses. +# +#Listen 12.34.56.78:80 +Listen 80 + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Statically compiled modules (those listed by `httpd -l') do not need +# to be loaded here. +# +# Example: +# LoadModule foo_module modules/mod_foo.so +# +Include conf.modules.d/*.conf + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. +# +# +# User/Group: The name (or #number) of the user/group to run httpd as. +# It is usually good practice to create a dedicated user and group for +# running httpd, as with most system services. +# +User apache +Group apache + +# 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. e.g. admin@your-domain.com +# +ServerAdmin root@localhost + +# +# ServerName gives the name and port that the server uses to identify itself. +# This can often be determined automatically, but we recommend you specify +# it explicitly to prevent problems during startup. +# +# If your host doesn't have a registered DNS name, enter its IP address here. +# +#ServerName www.example.com:80 + ProxyPass /caMicroscope/img/ http://ca-security:4010/img/ + ProxyPassReverse /caMicroscope/img/ http://ca-security:4010/img/ + ProxyPass /caMicroscope/data/ http://ca-security:4010/data/ + ProxyPassReverse /caMicroscope/data/ http://ca-security:4010/data/ + +# +# Deny access to the entirety of your server's filesystem. You must +# explicitly permit access to web content directories in other +# blocks below. +# + + AllowOverride none + Require all denied + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "/data/pathdb/quip/web" +# + + AllowOverride all + Require all granted + Options Indexes FollowSymLinks IncludesNOEXEC + RewriteEngine On + DirectoryIndex index.php index.htm index.html + RewriteEngine on + RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) + RewriteRule .* - [F] + + +# +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# + + DirectoryIndex index.html + + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog "logs/error_log" + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + + # + # The following directives define some format nicknames for use with + # a CustomLog directive (see below). + # + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + # You need to enable mod_logio.c to use %I and %O + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + # + # The location and format of the access logfile (Common Logfile Format). + # If you do not define any access logfiles within a + # container, they will be logged here. Contrariwise, if you *do* + # define per- access logfiles, transactions will be + # logged therein and *not* in this file. + # + #CustomLog "logs/access_log" common + + # + # If you prefer a logfile with access, agent, and referer information + # (Combined Logfile Format) you can use the following directive. + # + CustomLog "logs/access_log" combined + + + + # + # Redirect: Allows you to tell clients about documents that used to + # exist in your server's namespace, but do not anymore. The client + # will make a new request for the document at its new location. + # Example: + # Redirect permanent /foo http://www.example.com/bar + + # + # Alias: Maps web paths into filesystem paths and is used to + # access content that does not live under the DocumentRoot. + # Example: + # Alias /webpath /full/filesystem/path + # + # If you include a trailing / on /webpath then the server will + # require it to be present in the URL. You will also likely + # need to provide a section to allow access to + # the filesystem path. + + # + # ScriptAlias: This controls which directories contain server scripts. + # ScriptAliases are essentially the same as Aliases, except that + # documents in the target directory are treated as applications and + # run by the server when requested rather than as documents sent to the + # client. The same rules about trailing "/" apply to ScriptAlias + # directives as to Alias. + # + ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" + + +# +# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# + + AllowOverride None + Options None + Require all granted + + + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + TypesConfig /etc/mime.types + + # + # AddType allows you to add to or override the MIME configuration + # file specified in TypesConfig for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # For type maps (negotiated resources): + #AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + AddType text/html .shtml + AddOutputFilter INCLUDES .shtml + + +# +# Specify a default charset for all content served; this enables +# interpretation of all content as UTF-8 by default. To use the +# default browser choice (ISO-8859-1), or to allow the META tags +# in HTML content to override this choice, comment out this +# directive: +# +AddDefaultCharset UTF-8 + + + # + # The mod_mime_magic module allows the server to use various hints from the + # contents of the file itself to determine its type. The MIMEMagicFile + # directive tells the module where the hint definitions are located. + # + MIMEMagicFile conf/magic + + +# +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html +# + +# +# EnableMMAP and EnableSendfile: On systems that support it, +# memory-mapping or the sendfile syscall may be used to deliver +# files. This usually improves server performance, but must +# be turned off when serving from networked-mounted +# filesystems or if support for these functions is otherwise +# broken on your system. +# Defaults if commented: EnableMMAP On, EnableSendfile Off +# +#EnableMMAP off +EnableSendfile on + +# Supplemental configuration +# +# Load config files in the "/etc/httpd/conf.d" directory, if any. +IncludeOptional conf.d/*.conf + + diff --git a/test/config/httpd.conf.template b/test/config/httpd.conf.template new file mode 100644 index 0000000..3f3debd --- /dev/null +++ b/test/config/httpd.conf.template @@ -0,0 +1,376 @@ +# +# This is the main Apache HTTP server configuration file. It contains the +# configuration directives that give the server its instructions. +# See for detailed information. +# In particular, see +# +# for a discussion of each configuration directive. +# +# Do NOT simply read the instructions in here without understanding +# what they do. They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path. If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so 'log/access_log' +# with ServerRoot set to '/www' will be interpreted by the +# server as '/www/log/access_log', where as '/log/access_log' will be +# interpreted as '/log/access_log'. + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# Do not add a slash at the end of the directory path. If you point +# ServerRoot at a non-local disk, be sure to specify a local disk on the +# Mutex directive, if file-based mutexes are used. If you wish to share the +# same ServerRoot for multiple httpd daemons, you will need to change at +# least PidFile. +# +ServerRoot "/etc/httpd" + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, instead of the default. See also the +# directive. +# +# Change this to Listen on specific IP addresses as shown below to +# prevent Apache from glomming onto all bound IP addresses. +# +#Listen 12.34.56.78:80 +Listen 80 +Listen 443 + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Statically compiled modules (those listed by `httpd -l') do not need +# to be loaded here. +# +# Example: +# LoadModule foo_module modules/mod_foo.so +# +Include conf.modules.d/*.conf + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch. +# +# +# User/Group: The name (or #number) of the user/group to run httpd as. +# It is usually good practice to create a dedicated user and group for +# running httpd, as with most system services. +# +User apache +Group apache + +# 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# definition. These values also provide defaults for +# any containers you may define later in the file. +# +# All of these directives may appear inside containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed. This address appears on some server-generated pages, such +# as error documents. e.g. admin@your-domain.com +# +ServerAdmin root@localhost + +# +# ServerName gives the name and port that the server uses to identify itself. +# This can often be determined automatically, but we recommend you specify +# it explicitly to prevent problems during startup. +# +# If your host doesn't have a registered DNS name, enter its IP address here. +# +#ServerName quip.bmi.stonybrook.edu + +# SSLEngine on +# SSLCertificateFile /config/quip.bmi.stonybrook.edu.cer +# SSLCertificateKeyFile /config/quip.bmi.stonybrook.edu.key +# SSLCertificateChainFile /config/inter.cer + +# ProxyPass /caMicroscope/img/ http://ca-security:4010/img/ +# ProxyPassReverse /caMicroscope/img/ http://ca-security:4010/img/ +# ProxyPass /caMicroscope/data/ http://ca-security:4010/data/ +# ProxyPassReverse /caMicroscope/data/ http://ca-security:4010/data/ + +# +# Deny access to the entirety of your server's filesystem. You must +# explicitly permit access to web content directories in other +# blocks below. +# + + AllowOverride none + Require all denied + + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "/data/pathdb/quip/web" +# + + AllowOverride all + Require all granted + Options Indexes FollowSymLinks IncludesNOEXEC + RewriteEngine On + DirectoryIndex index.php index.htm index.html + RewriteEngine on + RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) + RewriteRule .* - [F] + + +# +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# + + DirectoryIndex index.html + + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog "logs/error_log" + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + + # + # The following directives define some format nicknames for use with + # a CustomLog directive (see below). + # + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + # You need to enable mod_logio.c to use %I and %O + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + # + # The location and format of the access logfile (Common Logfile Format). + # If you do not define any access logfiles within a + # container, they will be logged here. Contrariwise, if you *do* + # define per- access logfiles, transactions will be + # logged therein and *not* in this file. + # + #CustomLog "logs/access_log" common + + # + # If you prefer a logfile with access, agent, and referer information + # (Combined Logfile Format) you can use the following directive. + # + CustomLog "logs/access_log" combined + + + + # + # Redirect: Allows you to tell clients about documents that used to + # exist in your server's namespace, but do not anymore. The client + # will make a new request for the document at its new location. + # Example: + # Redirect permanent /foo http://www.example.com/bar + + # + # Alias: Maps web paths into filesystem paths and is used to + # access content that does not live under the DocumentRoot. + # Example: + # Alias /webpath /full/filesystem/path + # + # If you include a trailing / on /webpath then the server will + # require it to be present in the URL. You will also likely + # need to provide a section to allow access to + # the filesystem path. + + # + # ScriptAlias: This controls which directories contain server scripts. + # ScriptAliases are essentially the same as Aliases, except that + # documents in the target directory are treated as applications and + # run by the server when requested rather than as documents sent to the + # client. The same rules about trailing "/" apply to ScriptAlias + # directives as to Alias. + # + ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" + + +# +# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# + + AllowOverride None + Options None + Require all granted + + + + # + # TypesConfig points to the file containing the list of mappings from + # filename extension to MIME-type. + # + TypesConfig /etc/mime.types + + # + # AddType allows you to add to or override the MIME configuration + # file specified in TypesConfig for specific file types. + # + #AddType application/x-gzip .tgz + # + # AddEncoding allows you to have certain browsers uncompress + # information on the fly. Note: Not all browsers support this. + # + #AddEncoding x-compress .Z + #AddEncoding x-gzip .gz .tgz + # + # If the AddEncoding directives above are commented-out, then you + # probably should define those extensions to indicate media types: + # + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + # + # AddHandler allows you to map certain file extensions to "handlers": + # actions unrelated to filetype. These can be either built into the server + # or added with the Action directive (see below) + # + # To use CGI scripts outside of ScriptAliased directories: + # (You will also need to add "ExecCGI" to the "Options" directive.) + # + #AddHandler cgi-script .cgi + + # For type maps (negotiated resources): + #AddHandler type-map var + + # + # Filters allow you to process content before it is sent to the client. + # + # To parse .shtml files for server-side includes (SSI): + # (You will also need to add "Includes" to the "Options" directive.) + # + AddType text/html .shtml + AddOutputFilter INCLUDES .shtml + + +# +# Specify a default charset for all content served; this enables +# interpretation of all content as UTF-8 by default. To use the +# default browser choice (ISO-8859-1), or to allow the META tags +# in HTML content to override this choice, comment out this +# directive: +# +AddDefaultCharset UTF-8 + + + # + # The mod_mime_magic module allows the server to use various hints from the + # contents of the file itself to determine its type. The MIMEMagicFile + # directive tells the module where the hint definitions are located. + # + MIMEMagicFile conf/magic + + +# +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html +# + +# +# EnableMMAP and EnableSendfile: On systems that support it, +# memory-mapping or the sendfile syscall may be used to deliver +# files. This usually improves server performance, but must +# be turned off when serving from networked-mounted +# filesystems or if support for these functions is otherwise +# broken on your system. +# Defaults if commented: EnableMMAP On, EnableSendfile Off +# +#EnableMMAP off +EnableSendfile on + +# Supplemental configuration +# +# Load config files in the "/etc/httpd/conf.d" directory, if any. +IncludeOptional conf.d/*.conf + + + SSLEngine off +# SSLCertificateFile /config/quip.bmi.stonybrook.edu.cer +# SSLCertificateKeyFile /config/quip.bmi.stonybrook.edu.key +# SSLCertificateChainFile /config/inter.cer + Options Indexes FollowSymLinks IncludesNOEXEC + RewriteEngine On + KeepAlive On + DirectoryIndex index.php index.htm index.html + RewriteEngine on + RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) + RewriteRule .* - [F] + ProxyPass /caMicroscope/img/ http://ca-security:4010/img/ + ProxyPassReverse /caMicroscope/img/ http://ca-security:4010/img/ + ProxyPass /caMicroscope/data/ http://ca-security:4010/data/ + ProxyPassReverse /caMicroscope/data/ http://ca-security:4010/data/ + ProxyRequests Off + + + +# SSLEngine on +# SSLCertificateFile /config/quip.bmi.stonybrook.edu.cer +# SSLCertificateKeyFile /config/quip.bmi.stonybrook.edu.key +# SSLCertificateChainFile /config/inter.cer + Options Indexes FollowSymLinks IncludesNOEXEC + RewriteEngine On + KeepAlive On + DirectoryIndex index.php index.htm index.html + RewriteEngine on + RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) + RewriteRule .* - [F] + ProxyPass /caMicroscope/img/ http://ca-security:4010/img/ + ProxyPassReverse /caMicroscope/img/ http://ca-security:4010/img/ + ProxyPass /caMicroscope/data/ http://ca-security:4010/data/ + ProxyPassReverse /caMicroscope/data/ http://ca-security:4010/data/ + ProxyRequests Off + + + diff --git a/test/config/login.html b/test/config/login.html new file mode 100644 index 0000000..2a32682 --- /dev/null +++ b/test/config/login.html @@ -0,0 +1,75 @@ + +

Redirecting...

+ + diff --git a/test/config/mongo_idx.js b/test/config/mongo_idx.js new file mode 100644 index 0000000..5a74fe6 --- /dev/null +++ b/test/config/mongo_idx.js @@ -0,0 +1,12 @@ +db.authorization.createIndex( { "name": 1 }, { unique: true } ) +db.mark.createIndex({"provenance.image.slide": 1, "provenance.analysis.execution_id": 1, "footprint":1, "x":1, "y":1}) +db.mark.createIndex({"provenance.image.slide":1,"provenance.analysis.execution_id":1,"provenance.analysis": 1}) +db.mark.createIndex({"provenance.image.slide":1,"provenance.analysis": 1}) +db.mark.createIndex({"provenance.image.slide": 1, "provenance.analysis.execution_id": 1}) +db.mark.createIndex({"provenance.image.slide": 1}) +db.slide.createIndex({'study':1, 'specimen': 1, 'name': 1}) +db.template.createIndex({'id': 1}) +db.template.createIndex({'name': 1}) +db.heatmap.createIndex({"provenance.image.slide": 1, "provenance.analysis.execution_id": 1}) +db.heatmap.createIndex({"provenance.image.slide": 1}) +db.heatmapEdit.createIndex({"provenance.image.slide":1, "provenance.analysis.execution_id":1, "user_id":1}) diff --git a/test/config/pathdb_pre.sh b/test/config/pathdb_pre.sh new file mode 100755 index 0000000..9b8ee8f --- /dev/null +++ b/test/config/pathdb_pre.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +cp /etc/httpd/conf/quip.key /keys/key +cp /etc/httpd/conf/quip.crt /keys/key.pub +sh /root/run.sh diff --git a/test/config/pathdb_routes.json b/test/config/pathdb_routes.json new file mode 100644 index 0000000..6ca916e --- /dev/null +++ b/test/config/pathdb_routes.json @@ -0,0 +1,88 @@ +{ + "root":"http://quip-pathdb/", + "_root_public": "true", + "services":{ + "data":{ + "_base": "http://ca-data:9099/services/caMicroscope", + "Mark": { + "get":"/Mark/query/get", + "find":"/Mark/query/find", + "multi":"/Mark/query/multiFind", + "findBound":"/Mark/query/findBound", + "types":"/Mark/query/findTypes", + "typesExec":"/Mark/query/findTypesExec", + "post":{"path": "/Mark/submit/json", "attr": "write"}, + "delete":{"path": "/Mark/delete/deleteMark", "attr": "write"} + }, + "Heatmap": { + "get":"/Heatmap/query/get", + "find":"/Heatmap/query/find", + "types":"/Heatmap/query/findTypes", + "post":{"path": "/Heatmap/submit/json", "attr": "write"}, + "delete":{"path": "/Heatmap/delete/deleteHeatmap", "attr": "write"}, + "threshold":{"path": "/Heatmap/delete/updateThreshold", "attr": "write"} + }, + "Overlay": { + "get":"/Overlay/query/get", + "find":"/Overlay/query/find", + "post":{"path": "/Overlay/submit/json", "attr": "write"}, + "delete":{"path": "/Overlay/delete/deleteOverlay", "attr": "write"} + }, + "Slide": { + "get":"/Slide/query/get", + "find":"/Slide/query/find", + "post":{"path": "/Slide/submit/json", "attr": "write"}, + "delete":{"path": "/Slide/delete/deleteSlide", "attr": "write"}, + "update":{"path": "/Slide/update/updateSlide", "attr": "write"} + }, + "Template": { + "get":"/Template/query/get", + "find":"/Template/query/find", + "post":{"path": "/Template/submit/json", "attr": "write"}, + "delete":{"path": "/Template/delete/deleteTemplate", "attr": "write"} + }, + "HeatmapEdit": { + "get":"/HeatmapEdit/query/get", + "find":"/HeatmapEdit/query/find", + "post":{"path": "/HeatmapEdit/submit/json", "attr": "write"}, + "delete":{"path": "/HeatmapEdit/delete/delete", "attr": "write"}, + "update":{"path": "/HeatmapEdit/delete/update", "attr": "write"} + } + }, + "img": { + "_public": "true", + "_base":"http://ca-iip/fcgi-bin/iipsrv.fcgi", + "IIP": { + "raw":"" + }, + "Slide":{ + "_resolver":{ + "destination":"?DeepZoom={OUT}", + "url": "http://ca-pathdb/node/{IN}?_format=json", + "field":"field_iip_path[0].value", + "before":["_files", ".dzi"] + } + } + }, + "load": { + "_base": "http://ca-load:4000", + "Upload": { + "start": {"path":"/upload/start", "attr": "write"}, + "continue":"/upload/continue", + "finish":"/upload/finish" + }, + "Slide":{ + "info":"/data/one", + "thumb":"/data/thumbnail" + } + }, + "pathdb":{ + "_public": "true", + "_base": "http://quip-pathdb/", + "slide":{ + "info":"/node/", + "unmod":"" + } + } + } +} diff --git a/test/config/routes.json b/test/config/routes.json new file mode 100644 index 0000000..6426fa9 --- /dev/null +++ b/test/config/routes.json @@ -0,0 +1,89 @@ +{ + "root":"http://ca-front:80/", + "_root_public": "true", + "auth":{ + "permissions_field":"attrs" + }, + "services":{ + "data":{ + "_base": "http://ca-data:9099/services/caMicroscope", + "Mark": { + "get":"/Mark/query/get", + "find":"/Mark/query/find", + "multi":"/Mark/query/multiFind", + "findBound":"/Mark/query/findBound", + "types":"/Mark/query/findTypes", + "typesExec":"/Mark/query/findTypesExec", + "post":{"path": "/Mark/submit/json", "attr": "write"}, + "delete":{"path": "/Mark/delete/deleteMark", "attr": "write"} + }, + "Heatmap": { + "get":"/Heatmap/query/get", + "find":"/Heatmap/query/find", + "types":"/Heatmap/query/findTypes", + "post":{"path": "/Heatmap/submit/json", "attr": "write"}, + "delete":{"path": "/Heatmap/delete/deleteHeatmap", "attr": "write"}, + "threshold":{"path": "/Heatmap/delete/updateThreshold", "attr": "write"} + }, + "Overlay": { + "get":"/Overlay/query/get", + "find":"/Overlay/query/find", + "post":{"path": "/Overlay/submit/json", "attr": "write"}, + "delete":{"path": "/Overlay/delete/deleteOverlay", "attr": "write"} + }, + "Slide": { + "get":"/Slide/query/get", + "find":"/Slide/query/find", + "post":{"path": "/Slide/submit/json", "attr": "write"}, + "delete":{"path": "/Slide/delete/deleteSlide", "attr": "write"}, + "update":{"path": "/Slide/delete/updateSlide", "attr": "write"} + }, + "Template": { + "get":"/Template/query/get", + "find":"/Template/query/find", + "post":{"path": "/Template/submit/json", "attr": "write"}, + "delete":{"path": "/Template/delete/deleteTemplate", "attr": "write"} + }, + "HeatmapEdit": { + "get":"/HeatmapEdit/query/get", + "find":"/HeatmapEdit/query/find", + "post":{"path": "/HeatmapEdit/submit/json", "attr": "write"}, + "delete":{"path": "/HeatmapEdit/delete/delete", "attr": "write"}, + "update":{"path": "/HeatmapEdit/delete/update", "attr": "write"} + } + }, + "img": { + "_base":"http://ca-iip/fcgi-bin/iipsrv.fcgi", + "IIP": { + "raw":"" + }, + "Slide":{ + "_resolver":{ + "destination":"?DeepZoom={OUT}", + "url":"http://ca-data:9099/services/caMicroscope/Slide/query/get?id={IN}", + "field":"location", + "before":["_files", ".dzi"] + } + } + }, + "load": { + "_base": "http://ca-load:4000", + "Upload": { + "start": {"path":"/upload/start", "attr": "write"}, + "continue":"/upload/continue", + "finish":"/upload/finish" + }, + "Slide":{ + "info":"/data/one", + "thumb":"/data/thumbnail" + } + }, + "auth": { + "_public": "true", + "_base": "http://ca-auth:8010", + "Token":{ + "check":"/check" + } + } + } +} diff --git a/test/config/run_idx.sh b/test/config/run_idx.sh new file mode 100755 index 0000000..314f02a --- /dev/null +++ b/test/config/run_idx.sh @@ -0,0 +1,11 @@ +until mongo --host ca-mongo --eval "print(\"waited for connection\")" +do + sleep 2 +done + +mongo --host ca-mongo camic /config/mongo_idx.js +echo "indexes created" +mongo --host ca-mongo camic /config/add_mongo_users.js +echo "users created" +mongo --host ca-mongo camic /config/default_data.js +echo "defaults added" diff --git a/test/config/test_seed.js b/test/config/test_seed.js new file mode 100644 index 0000000..649ef47 --- /dev/null +++ b/test/config/test_seed.js @@ -0,0 +1,288 @@ +var slides = [{ + "_id": new ObjectId("5bec456369056d7e537c2a9b"), + name: "CMU1", + location: "/images/sample.svs", + mpp: 0.499, + study: '', + specimen: '' +}] + +var marks = [ + { + "provenance": { + "image": { + "slide": "5bec456369056d7e537c2a9b" + }, + "analysis": { + "source": "human", + "execution_id": "Gamma", + "name": "test 1" + } + }, + "properties": { + "annotations": { + "name": "test 1", + "digital_slide_quality": true, + "histology": "PDAC", + "hist_other_type": "Colloid carcinoma (mucinous noncystic carcinoma)", + "cellularity_10": "31-40%", + "tumor_cellularity": "<20%", + "tumor_necrosis": "<20%", + "adequacy": "Adequate", + "normal_tissue_type": "Duodenum", + "tumor_present": false, + "additional_notes": "test note" + } + }, + "geometries": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "style": { + "color": "#7cfc00", + "lineCap": "round", + "lineJoin": "round", + "lineWidth": 3 + } + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 0, + 1.333075238564 + ], + [ + 0.9211833251318, + 1.333075238564 + ], + [ + 0.9211833251318, + 1.4056976389659 + ], + [ + 0.84856092473, + 1.4056976389659 + ], + [ + 0, + 1.333075238564 + ] + ] + ] + }, + "bound": { + "type": "Polygon", + "coordinates": [ + [ + [ + 0.0819138121014, + 1.2558071323124 + ], + [ + 0.987611451067, + 1.2558071323124 + ], + [ + 0.987611451067, + 1.9173119035902 + ], + [ + 0.0819138121014, + 1.9173119035902 + ], + [ + 0.0819138121014, + 1.2558071323124 + ] + ] + ] + } + } + ] + } + } +]; + +heatmap_data = [] +for (var i = 0; i<1; i+=0.007243258749282846){ + for (var j = 0; j<1; j+=0.010489147367327867){ + heatmap_data.push([i,j,Math.random(),Math.floor(Math.random()*10)]) + } +} + + +var heatmaps = [{ + "provenance": { + "image": { + "slide": "5bec456369056d7e537c2a9b", + }, + "analysis": { + "study_id":"test", + "type": "heatmap", + "computation": "heatmap", + "execution_id": "heatmap_test", + "size": [0.007243258749282846,0.010489147367327867], + "fields": [{"name":"necrosis", "range":[0,1]}, {"name":"tumor", "range":[0,10]}], + "coordinateSystem": "image" + } + }, + "data": heatmap_data +}] + +const annotation_schema = { + "type": "object", + "id": "annotation-form", + "name": "AnnotSchema", + "description": "", + "links": [], + "additionalProperties": false, + "properties": { + "name": { + "id": "a0", + "title": "Identity Name", + "type": "string", + "required": true, + "description": "note name" + }, + "digital_slide_quality": { + "id": "a1", + "title": "Check if histology is able to be evaluated", + "type": "boolean" + }, + "histology": { + "id": "a2", + "title": "Histology: (For BL1 and BL2 only)", + "type": "string", + "enum": ["-", "PDAC", "PNET", "other"], + "default": "-" + }, + "hist_other_type": { + "id": "a3", + "title": "Other Histology: (For BL1 and BL2 only)", + "type": "string", + "enum": ["-", "N/A", "Colloid carcinoma (mucinous noncystic carcinoma)", "Signet-ring cell carcinoma", "Adenosquamous carcinoma", "Intraductal papillary-mucinous neoplasm with an associated invasive carcinoma", "Intraductal tubulopapillary neoplasm with an associated invasive carcinoma", "Mucinous cystic neoplasm with an associated invasive carcinoma", "Large cell neuroendocrine carcinoma", "Small cell neuroendocrine carcinoma", "Neuroendocrine carcinoma (poorly differentiated)", "Undifferentiated (anaplastic) carcinoma", "Undifferentiated carcinoma with osteoclast-like giant cells", "Acinar cell carcinoma", "Acinar cell cystadenocarcinoma", "Serous cystadenocarcinoma", "Mixed acinar-ductal carcinoma", "Mixed ductal-neuroendocrine carcinoma", "Mixed acinar-neuroendocrine carcinoma", "Mixed acinar-neuroendocrine-ductal carcinoma", "Solid-pseudopapillary neoplasm", "Hepatoid carcinoma", "Medullary carcinoma"], + "default": "-" + }, + "cellularity_10": { + "id": "a4", + "title": "Cellularity percentage", + "type": "string", + "enum": ["-", "0-10%", "11-20%", "21-30%", "31-40%", "41-50%", "51-60%", "61-70%", "71-80%", "81-90%", "91-100%"], + "default": "-" + }, + "tumor_cellularity": { + "id": "a5", + "title": "Tumor Cellularity: (For BL1 and BL2 only)", + "type": "string", + "enum": ["-", "<20% ", ">=20%"], + "default": "-" + }, + "tumor_necrosis": { + "id": "a6", + "title": "Tumor Necrosis: (For BL1 and BL2 only)", + "type": "string", + "enum": ["-", "<20% ", ">=20%"], + "default": "-" + }, + "adequacy": { + "id": "a7", + "title": "Adequacy: (For BL1 and BL2 only)", + "type": "string", + "enum": ["-", "Adequate", "Inadequate"], + "default": "-" + }, + "normal_tissue_type": { + "id": "a8", + "title": "Normal Tissue Type: (For BL3 only)", + "type": "string", + "enum": ["-", "Duodenum", "Lymph Node", "Spleen", "Other"], + "default": "-" + }, + "tumor_present": { + "id": "a9", + "title": "Check if tumor present (For BL3 only)", + "type": "boolean" + }, + "notes": { + "id": "a10", + "title": "Notes: ", + "type": "string", + "format":"textarea", + "maxLength": 128 + } + } +}; + +const algorithm_1_schema = { + "type": "object", + "id": "algorithm01", + "name": "Alg1Schema", + "description": "", + "links": [], + "additionalProperties": false, + "properties": { + "arg1": { + "id": "01", + "title": "Argument 01", + "type": "boolean" + }, + "arg2": { + "id": "02", + "title": "Argument 02", + "type": "string", + "enum": ["arg_01", "arg_02", "arg_03", "arg_04"], + "default": "-" + }, + "arg3": { + "id": "03", + "title": "Argument 03", + "type": "textarea" + } + } +}; +const algorithm_2_schema = { + "type": "object", + "id": "algorithm02", + "name": "Alg1Schema", + "description": "", + "links": [], + "additionalProperties": false, + "properties": { + "arg1": { + "id": "01", + "title": "Argument 01", + "type": "boolean" + }, + "arg2": { + "id": "02", + "title": "Argument 02", + "type": "string", + "enum": ["arg_01", "arg_02", "arg_03", "arg_04"], + "default": "-" + }, + "arg3": { + "id": "03", + "title": "Argument 03", + "type": "boolean" + }, + "arg4": { + "id": "04", + "title": "Argument 04", + "type": "range" + }, + } +}; + + + + +var templates = [algorithm_2_schema, algorithm_1_schema, annotation_schema] +db.slide.insertMany(slides) +db.mark.insertMany(marks) +db.template.insertMany(templates) +//db.authorization.insertMany(auths) +db.heatmap.insertMany(heatmaps) diff --git a/test/customization/table.html b/test/customization/table.html new file mode 100644 index 0000000..57b4060 --- /dev/null +++ b/test/customization/table.html @@ -0,0 +1,379 @@ + + + + + + + + + + + + + + + + + + + + + + CaMicroscope Data Table + + + +
+
+
+
+
+ + + diff --git a/test/customization/viewer_init.js b/test/customization/viewer_init.js new file mode 100644 index 0000000..4555179 --- /dev/null +++ b/test/customization/viewer_init.js @@ -0,0 +1,668 @@ +// CAMIC is an instance of camicroscope core +// $CAMIC in there +let $CAMIC = null; +let $minorCAMIC = {}; +// for all instances of UI components +const $UI = new Map(); + +const $D = { + pages:{ + home:'../table.html', + table:'../table.html' + }, + params:null, // parameter from url - slide Id and status in it (object). + overlayers:null, // array for each layers + templates:null // json schema for prue-form +}; + +window.addEventListener('keydown', (e) => { + if(!$CAMIC || !$CAMIC.viewer) return; + const keyCode = e.keyCode; + // escape key to close all operations + if(keyCode==27){ + magnifierOff(); + measurementOff(); + annotationOff(); + } + + // open annotation (ctrl + a) + if(e.ctrlKey && keyCode == 65 && $CAMIC.viewer.canvasDrawInstance){ + const li = $UI.toolbar.getSubTool('annotation'); + eventFire(li,'click'); + return; + } + // open magnifier (ctrl + m) + if(e.ctrlKey && keyCode == 77 && $UI.spyglass){ + const li = $UI.toolbar.getSubTool('magnifier'); + const chk = li.querySelector('input[type=checkbox]'); + chk.checked = !chk.checked; + eventFire(chk,'change'); + return; + } + // open measurement (ctrl + r) + if(e.ctrlKey && keyCode == 82 && $CAMIC.viewer.measureInstance){ + const li = $UI.toolbar.getSubTool('measurement'); + const chk = li.querySelector('input[type=checkbox]'); + chk.checked = !chk.checked; + eventFire(chk,'click'); + return; + } + // open side-by-side (ctrl + s) + if(e.ctrlKey && keyCode == 83){ + const li = $UI.toolbar.getSubTool('sbsviewer'); + const chk = li.querySelector('input[type=checkbox]'); + chk.checked = !chk.checked; + eventFire(chk,'click'); + return; + } + +}); + +// initialize viewer page +function initialize(){ + var checkPackageIsReady = setInterval(function () { + if(IsPackageLoading) { + clearInterval(checkPackageIsReady); + // create a viewer and set up + initCore(); + + // loading the form template data + FormTempaltesLoader(); + + // loading the overlayers data + OverlayersLoader(); + } + }, 100); +} + +// setting core functionalities +function initCore(){ + // start initial + + // create the message queue + // $UI.message = new MessageQueue(); + + // TODO zoom info and mmp + const opt = { + draw:{ + // extend context menu btn group + btns:[ + { // annotation + type:'btn', + title:'Annotation', + class:'material-icons', + text:'description', + callback:saveAnnotation + }, + { // analytics + type:'btn', + title:'Analytics', + class:'material-icons', + text:'settings_backup_restore', + callback:saveAnalytics + } + ] + } + } + // set states if exist + if($D.params.states){ + opt.states = $D.params.states; + } + + try{ + let slideQuery = {} + slideQuery.id = $D.params.slideId + slideQuery.name = $D.params.slide + slideQuery.location = $D.params.location + $CAMIC = new CaMic("main_viewer", slideQuery, opt); + }catch(error){ + Loading.close(); + $UI.message.addError('Core Initialization Failed'); + console.error(error); + return; + } + + $CAMIC.loadImg(function(e){ + // image loaded + if(e.hasError){ + $UI.message.addError(e.message) + // can't reach Slide and return to home page + if(e.isServiceError) redirect($D.pages.table,e.message, 0); + }else{ + $D.params.data = e; + + // popup panel + $CAMIC.viewer.addHandler('canvas-lay-click',function(e){ + if(!e.data) { + $UI.annotPopup.close(); + return; + } + // for support QUIP 2.0 + const data = Array.isArray(e.data)? e.data[e.data.selected]: e.data; + + + const type = data.provenance.analysis.source; + let body; + let attributes; + let warning = null; + switch (type) { + case "human": + let area; + let circumference; + if(data.geometries){ + if((data.selected!=null || data.selected!=undefined) && data.geometries.features[data.selected] &&data.geometries.features[data.selected].properties.area) + area = `${Math.round(data.geometries.features[data.selected].properties.area)}μm^2`; + if((data.selected!=null || data.selected!=undefined) && data.geometries.features[data.selected] &&data.geometries.features[data.selected].properties.circumference) + circumference = `${Math.round(data.geometries.features[data.selected].properties.circumference)}μm`; + } // othereise, don't try to calculate area and circumference + // human + + attributes = data.properties.annotations; + if(area) attributes.area = area; + if(circumference) attributes.circumference = circumference; + body = convertHumanAnnotationToPopupBody(attributes); + if(data.geometries && data.geometries.features[data.selected].properties.isIntersect){ + warning = `
Inaccurate Area and Circumference
`; + } + if(data.geometries && data.geometries.features[data.selected].properties.nommp){ + warning = `
This slide has no mpp
`; + } + + $UI.annotPopup.showFooter(); + break; + case "computer": + // handle data.provenance.analysis.computation = `segmentation` + attributes = data.properties.scalar_features[0].nv; + body = {type:'map',data:attributes}; + $UI.annotPopup.hideFooter(); + break; + default: + return; + // statements_def + break; + } + $UI.annotPopup.data = { + id:data.provenance.analysis.execution_id, + oid:data._id.$oid, + annotation:attributes, + selected:e.data.selected, + }; + $UI.annotPopup.setTitle(`id:${data.provenance.analysis.execution_id}`); + $UI.annotPopup.setBody(body); + if(warning)$UI.annotPopup.body.innerHTML += warning; + + $UI.annotPopup.open(e.position); + }); + + // create the message bar TODO for reading slide Info TODO + $UI.slideInfos = new CaMessage({ + /* opts that need to think of*/ + id:'cames', + defaultText:`Slide: ${$D.params.data.name}` + }); + + // spyglass + $UI.spyglass = new Spyglass({ + targetViewer:$CAMIC.viewer, + imgsrc:$D.params.data.url + }); + } + }); + + $CAMIC.viewer.addHandler('open',function(){ + $CAMIC.viewer.canvasDrawInstance.addHandler('start-drawing',startDrawing); + $CAMIC.viewer.canvasDrawInstance.addHandler('stop-drawing',stopDrawing); + // init UI -- some of them need to wait data loader to load data + // because UI components need data to initialize + initUIcomponents(); + }); +} + + +// initialize all UI components +function initUIcomponents(){ + /* create UI components */ + + $UI.modalbox = new ModalBox({ + id:'modalbox', + hasHeader:true, + headerText:'HeatMap List', + hasFooter:false + }); + + const subToolsOpt = []; + // home + if( ImgloaderMode =='iip') subToolsOpt.push({ + name:'home', + icon:'home', // material icons' name + title:'Home', + type:'btn', // btn/check/dropdown + value:'home', + callback:goHome + }); + // pen + subToolsOpt.push({ + name:'annotation', + icon:'create',// material icons' name + title:'Draw', + type:'multistates', + callback:draw + }); + // magnifier + subToolsOpt.push({ + name:'magnifier', + icon:'search', + title:'Magnifier', + type:'dropdown', + value:'magn', + dropdownList:[ + { + value:0.5, + title:'0.5', + checked:true + }, + { + value:1, + title:'1.0' + }, + { + value:2, + title:'2.0' + } + ], + callback:toggleMagnifier + }); + // measurement tool + if($CAMIC.viewer.measureInstance) subToolsOpt.push({ + name:'measurement', + icon:'space_bar', + title:'Measurement', + type:'check', + value:'measure', + callback:toggleMeasurement + }); + // share + if( ImgloaderMode =='iip') subToolsOpt.push({ + name:'share', + icon:'share', + title:'Share View', + type:'btn', + value:'share', + callback:shareURL + }); + // side-by-side + subToolsOpt.push({ + name:'sbsviewer', + icon:'view_carousel', + title:'Side By Side Viewer', + value:'dbviewers', + type:'check', + callback:toggleViewerMode + }); + // heatmap + subToolsOpt.push({ + name:'heatmap', + icon:'satellite', + title:'Heat Map', + value:'heatmap', + type:'btn', + callback:openHeatmap + }); + subToolsOpt.push({ + name:'labeling', + icon:'label', + title:'Labeling', + value:'labeling', + type:'btn', + callback:function(){ + window.location.href = `../labeling/labeling.html${window.location.search}`; + } + }); + subToolsOpt.push({ + name:'segment', + icon: 'timeline', + type: 'btn', + value: 'rect', + title: 'Segment', + callback: function () { + if(window.location.search.length > 0) { + window.location.href = '../segment/segment.html' + window.location.search; + }else{ + window.location.href = '../segment/segment.html'; + } + } + }); + + // -- For Nano borb Start -- // + if(ImgloaderMode =='imgbox'){ + // download + subToolsOpt.push({ + name:'downloadmarks', + icon:'cloud_download', + title:'Download Marks', + type:'btn', + value:'download', + callback:Store.prototype.DownloadMarksToFile + }); + subToolsOpt.push({ + name:'uploadmarks', + icon:'cloud_upload', + title:'Load Marks', + type:'btn', + value:'upload', + callback:Store.prototype.LoadMarksFromFile + }); + + } + // -- For Nano borb End -- // + + // bug report + subToolsOpt.push({ + name:'bugs', + icon: 'bug_report', + title: 'Bug Report', + value: 'bugs', + type: 'btn', + callback: ()=>{window.open('https://goo.gl/forms/mgyhx4ADH0UuEQJ53','_blank').focus()} + }); + + + // -- view btn START -- // + if(!($D.params.data.hasOwnProperty('review') && $D.params.data['review']=='true')){ + console.log('create check'); + subToolsOpt.push({ + name:'review', + icon:'playlist_add_check', + title:'has reviewed', + type:'btn', + value:'review', + callback:updateSlideView + }); + } + // -- END -- // + // create the tool bar + $UI.toolbar = new CaToolbar({ + /* opts that need to think of*/ + id:'ca_tools', + zIndex:601, + mainToolsCallback:mainMenuChange, + subTools:subToolsOpt + }); + + // create two side menus for tools + $UI.appsSideMenu = new SideMenu({ + id:'side_apps', + width: 300, + //, isOpen:true + callback:toggleSideMenu + }); + + $UI.layersSideMenu = new SideMenu({ + id:'side_layers', + width: 300, + contentPadding:5, + //, isOpen:true + callback:toggleSideMenu + }); + + /* annotation popup */ + $UI.annotPopup = new PopupPanel({ + footer:[ + // { // edit + // title:'Edit', + // class:'material-icons', + // text:'notes', + // callback:anno_edit + // }, + { // delete + title:'Delete', + class:'material-icons', + text:'delete_forever', + callback:anno_delete + } + ] + }); + + var checkOverlaysDataReady = setInterval(function () { + if($D.overlayers) { + clearInterval(checkOverlaysDataReady); + // create control + + // create main layer viewer items with states + const mainViewerData = $D.overlayers.map(d=>{ + const isShow = $D.params.states&&$D.params.states.l&&$D.params.states.l.includes(d.id)?true:false; + return {item:d,isShow:isShow} + }) + + // create monir layer viewer items + const minorViewerData = $D.overlayers.map(d=>{ + return {item:d,isShow:false} + }) + + // create UI and set data + $UI.layersViewer = createLayerViewer('overlayers', mainViewerData, callback.bind('main')); + // create UI and set data - minor + $UI.layersViewerMinor = createLayerViewer('overlayersMinor', minorViewerData, callback.bind('minor')); + + // + if($D.params.states&& $D.params.states.l){ + $D.params.states.l.forEach(id=> loadAnnotationById($CAMIC,$UI.layersViewer.getDataItemById(id),null)) + } + + $UI.layersList = new CollapsibleList({ + id:'layerslist', + list:[ + { + id:'left', + title:'Left Viewer', + // icon:'border_color', + content: "No Template Loaded" //$UI.annotOptPanel.elt + // isExpand:true + + },{ + id:'right', + // icon:'find_replace', + title:'Right Viewer', + content:"No Template Loaded" //$UI.algOptPanel.elt, + } + ], + changeCallBack:function(e){console.log(e)} + }); + // add to layers side menu + const title = document.createElement('div'); + title.classList.add('item_head'); + title.textContent = 'Layers Manager'; + $UI.layersSideMenu.addContent(title); + + $UI.layersList.clearContent('left'); + $UI.layersList.addContent('left',$UI.layersViewer.elt); + $UI.layersList.clearContent('right'); + $UI.layersList.addContent('right',$UI.layersViewerMinor.elt); + + $UI.layersList.elt.parentNode.removeChild($UI.layersList.elt); + closeMinorControlPanel(); + $UI.layersSideMenu.addContent($UI.layersList.elt); + } + }, 500); + + + + + + var checkTemplateSchemasDataReady = setInterval(function () { + if($D.templates) { + clearInterval(checkTemplateSchemasDataReady); + const annotRegex = new RegExp('annotation', 'gi'); + const annotSchemas = $D.templates.filter(item=> item.id.match(annotRegex)); + /* annotation control */ + $UI.annotOptPanel = new OperationPanel({ + //id: + //element: + formSchemas:annotSchemas, + resetCallback:reset_callback, + action:{ + title:'Save', + callback:anno_callback, + } + }); + // START QUIP550 TEMPORARILY REMOVE Algorithm Panel // + // add to layers side menu + const title = document.createElement('div'); + title.classList.add('item_head'); + title.textContent = 'Annotation'; + $UI.appsSideMenu.addContent(title); + $UI.annotOptPanel.elt.classList.add('item_body'); + $UI.appsSideMenu.addContent($UI.annotOptPanel.elt); + + //$UI.appsList.clearContent('annotation'); + //$UI.appsList.addContent('annotation',$UI.annotOptPanel.elt); + /* algorithm control */ + // const algoRegex = new RegExp('algo', 'gi'); + // const algoSchemas = $D.templates.filter(item => item.id.match(algoRegex)); + // $UI.algOptPanel = new OperationPanel({ + // //id: + // //element: + // title:'Algorithm:', + // formSchemas:algoSchemas, + // action:{ + // title:'Run', + // callback:algo_callback + // } + // }); + // $UI.appsList.clearContent('analytics'); + // $UI.appsList.addContent('analytics',$UI.algOptPanel.elt); + // $UI.appsList.addContent('analytics', AnalyticsPanelContent); + // END QUIP550 TEMPORARILY REMOVE Algorithm Panel // + + } + }, 500); + + + // START QUIP550 // + // // collapsible list + // $UI.appsList = new CollapsibleList({ + // id:'collapsiblelist', + // list:[ + // { + // id:'annotation', + // title:'Annotation', + // icon:'border_color', + // content: "No Template Loaded" //$UI.annotOptPanel.elt + // // isExpand:true + + // } + // ,{ + // id:'analytics', + // icon:'find_replace', + // title:'Analytics', + // content:"No Template Loaded" //$UI.algOptPanel.elt, + // } + // ], + // changeCallBack:getCurrentItem + // }); + + + // // detach collapsible_list + // $UI.appsList.elt.parentNode.removeChild($UI.appsList.elt); + // $UI.appsSideMenu.addContent($UI.appsList.elt); + // END QUIP550 // + // $UI.multSelector = new MultSelector({id:'mult_selector'}); + // $UI.multSelector.addHandler('cancel',multSelector_cancel); + // $UI.multSelector.addHandler('action',multSelector_action); +} +function createLayerViewer(id, viewerData, callback){ + const layersViewer = new LayersViewer({id:id, data:viewerData, callback:callback}); + layersViewer.elt.parentNode.removeChild(layersViewer.elt); + return layersViewer; +} +// create lay panel for side-by-side control +function createLayPanelControl(){ + + $UI.layCtrlbar = document.createElement('div'); + $UI.layCtrlbar.style =` + display:none; + margin: .2rem; + background-color: #365f9c; + cursor: default; + padding: .5rem; + width: 100%; + border: none; + text-align: left; + outline: none; + font-size: 1.2rem;`; + + createRadios(); + $UI.layersSideMenu.addContent($UI.layCtrlbar); + // control + const radios = $UI.layCtrlbar.querySelectorAll('input[name=ctrlPane]'); + radios.forEach(r=>{ + r.addEventListener('change', function(e){ + const val = e.target.value; + switch (val) { + case 'main': + $UI.layersViewer.elt.style.display = 'flex'; + $UI.layersViewerMinor.elt.style.display = 'none'; + break; + case 'minor': + $UI.layersViewer.elt.style.display = 'none'; + $UI.layersViewerMinor.elt.style.display = 'flex'; + break; + default: + // statements_def + break; + } + }) + }); +} + +function createRadios(){ + const temp = ` + + + + + ` + $UI.layCtrlbar.innerHTML = temp; +} + +function redirect(url ,text = '', sec = 5){ + let timer = sec; + setInterval(function(){ + if(!timer) { + window.location.href = url; + } + + if(Loading.instance&&Loading.instance.parentNode){ + Loading.text.textContent = `${text} ${timer}s.`; + }else{ + Loading.open(document.body,`${text} ${timer}s.`); + } + // Hint Message for clients that page is going to redirect to Flex table in 5s + timer--; + + }, 1000); +} + + +function updateSlideView(){ + if(!confirm(`Do you want to change this slide's reivew status?`)) return; + Loading.open(document.body, 'changing review status ...'); + var url = "../../data/Slide/update" + var query = {} + + query.slide = $D.params.data.name; + query.field = 'review' + query.value = true + + fetch(url + "?" + objToParamStr(query), { + method: "DELETE", + credentials: "include", + mode: "cors" + }).then(this.errorHandler).then(function(e){ + if(e.status==200){ + $UI.toolbar.getSubTool('review').style.display = 'none'; + } + }).finally(function(){ + Loading.close(); + }) +} diff --git a/test/db/.gitignore b/test/db/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/test/db/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/test/dev-pathdb.yml b/test/dev-pathdb.yml new file mode 100644 index 0000000..861fe72 --- /dev/null +++ b/test/dev-pathdb.yml @@ -0,0 +1,64 @@ +version: '3' + +services: + mongo: + image: mongo + container_name: ca-mongo + restart: unless-stopped + logging: + driver: none + idxMongo: + image: mongo + container_name: ca-idx + links: + - mongo + volumes: + - ./config:/config + command: + - /config/run_idx.sh + depends_on: + - mongo + bindaas: + build: "./Deps/Bindaas/" + depends_on: + - "mongo" + container_name: ca-data + restart: unless-stopped + logging: + driver: none + ports: ["8080:8080", "9099:9099"] + volumes: + - ./config/bindaas_projects/:/root/bindaas/bin/projects/ + - ./config/bindaas.config.json:/root/bindaas/bin/bindaas.config.json + iip: + build: "https://github.com/camicroscope/iipImage.git#v3.2.0" + container_name: ca-iip + restart: unless-stopped + volumes: + - ./images/:/data/images/ + security: + build: "https://github.com/camicroscope/Security.git#v3.2.1" + container_name: ca-security + restart: unless-stopped + ports: ["4010:4010"] + volumes: + - ./config/routes.json:/root/src/routes.json + environment: + - DISABLE_SEC=true + auth: + build: "./Deps/auth_service/" + container_name: ca-auth + logging: + driver: none + pathdb: + build: "https://github.com/camicroscope/PathDB.git#develop" + container_name: quip-pathdb + restart: unless-stopped + ports: ["443:443","80:80"] + volumes: + - ./data:/data/ + - ./images/:/data/pathdb/files/wsi + - ./jwt_keys/:/keys/ + - ./config:/config + command: + - /config/pathdb_pre.sh diff --git a/test/develop.yml b/test/develop.yml new file mode 100644 index 0000000..288ea09 --- /dev/null +++ b/test/develop.yml @@ -0,0 +1,60 @@ +version: '3' + +services: + mongo: + image: mongo:3.4.19-jessie + container_name: ca-mongo + volumes: + - ./db:/data/db + idxMongo: + image: mongo:3.4.19-jessie + container_name: ca-idx + links: + - mongo + volumes: + - ./config:/config + command: + - /config/run_idx.sh + depends_on: + - mongo + bindaas: + build: "./Deps/Bindaas/" + depends_on: + - "mongo" + ports: + - "8080:8080" + - "9099:9099" + container_name: ca-data + volumes: + - ./config/bindaas_projects/:/root/bindaas/bin/projects/ + - ./config/bindaas.config.json:/root/bindaas/bin/bindaas.config.json + iip: + build: "https://github.com/camicroscope/iipImage.git#v3.2.0" + container_name: ca-iip + volumes: + - ./images/:/images/ + viewer: + build: "https://github.com/camicroscope/caMicroscope.git#develop" + container_name: ca-front + volumes: + - ./config/login.html:/var/www/html/login.html + loader: + build: "https://github.com/camicroscope/SlideLoader.git#v3.2.0" + container_name: ca-load + volumes: + - ./images/:/images/ + security: + build: "https://github.com/camicroscope/Security.git#v3.2.1" + container_name: ca-security + ports: + - "4010:4010" + volumes: + - ./config/routes.json:/root/src/routes.json + - ./jwt_keys/:/keys/ + environment: + - DISABLE_SEC=true + auth: + build: "./Deps/auth_service/" + volumes: + - ./jwt_keys/:/keys/ + container_name: ca-auth diff --git a/test/images/.gitignore b/test/images/.gitignore new file mode 100644 index 0000000..340b0cf --- /dev/null +++ b/test/images/.gitignore @@ -0,0 +1,4 @@ +* +!uploading/.gitignore +!.gitignore +!sample.svs diff --git a/test/images/sample.svs b/test/images/sample.svs new file mode 100644 index 0000000..1125dcd Binary files /dev/null and b/test/images/sample.svs differ diff --git a/test/jwt_keys/.gitignore b/test/jwt_keys/.gitignore new file mode 100644 index 0000000..fb88324 --- /dev/null +++ b/test/jwt_keys/.gitignore @@ -0,0 +1,4 @@ +key +certificate +key.pub +jwk.json diff --git a/test/jwt_keys/make_keys.sh b/test/jwt_keys/make_keys.sh new file mode 100644 index 0000000..41de871 --- /dev/null +++ b/test/jwt_keys/make_keys.sh @@ -0,0 +1 @@ +openssl req -subj '/CN=www.mydom.com/O=My Company Name LTD./C=US' -x509 -nodes -newkey rsa:2048 -keyout key -out key.pub diff --git a/test/keys/.gitignore b/test/keys/.gitignore new file mode 100644 index 0000000..b8be7c2 --- /dev/null +++ b/test/keys/.gitignore @@ -0,0 +1,2 @@ +key +key.pub diff --git a/test/keys/make_keys.sh b/test/keys/make_keys.sh new file mode 100644 index 0000000..a7f85fb --- /dev/null +++ b/test/keys/make_keys.sh @@ -0,0 +1 @@ +ssh-keygen -f ./key -t ecdsa -b 521 diff --git a/test/landing.html b/test/landing.html new file mode 100644 index 0000000..18d88e6 --- /dev/null +++ b/test/landing.html @@ -0,0 +1,91 @@ + + caMicroscope + + + + + + + + +
+
+
+

caMicroscope Public

+
+ +
+

caMicroscope is a tool to view, annotate, and analyze biomedical images.

+ +
+
+
+ +
+

Breast Cancer Geonmic Pilot

+

Use camicroscope to explore and mark slides uploaded.

+ More +
+
+
+ +
+

PDAC CaMicroscope

+

Use camicroscope to explore and mark slides uploaded.

+ More +
+
+
+ +
+

VTR Pending Slides

+

Use camicroscope to explore and mark slides uploaded.

+ More +
+
+
+
+ +
+
+
+
+ U24 CA18092401A1, Tools to Analyze Morphology and Spatially Mapped Molecular Data +
+
+
+
+ + + + + + + + + + + diff --git a/test/login.html b/test/login.html new file mode 100644 index 0000000..6015938 --- /dev/null +++ b/test/login.html @@ -0,0 +1,59 @@ + +

Redirecting...

+ + diff --git a/test/migrate/README.md b/test/migrate/README.md new file mode 100644 index 0000000..f562346 --- /dev/null +++ b/test/migrate/README.md @@ -0,0 +1,23 @@ +# 2.X -> 3.X Migration + +## Summary +* The mongo database is camic instead of quip +* The heatmap format is vastly different +* Some slide fields have simpler names (e.g. study_id -> study) +* Templates use a different format entirely +* We do not have a separate collection for annotation metadata +* Authorization is handled differently + +It's highly recommended to leave the original source documents alone until you've confirmed everything looks okay. Issues with these tools or conversions should be reported as github issues on the distribution repository. + +## Templates +Since the new template method has different functionality, it's highly recommended that templates are re-made using (json-schema)[https://json-schema.org/] + +## Heatmaps +Before migration, move heatmaps to a different collection, as to not confuse the object->mark conversion. Run the script with the input and output folders as arguments in node. Then, you should be able to import these converted documents to the camic database under the heatmap collection. + +## Other Collections +The other collections use a single script which should run in mongo. This makes needed changes to the collections, and puts the results in the camic database. These utilities may behave strangely with non-standard or older form data. + +## Authorization +Authorization is handled differently in the 3.0 version. See config/add_mongo_users.js for an example. Edit that file to add your original users. Name should match the subject of the jwt. This is not needed for deployments which rely on pathdb, or use another custom authorization service. diff --git a/test/migrate/convert_heatmaps.js b/test/migrate/convert_heatmaps.js new file mode 100644 index 0000000..e0078b1 --- /dev/null +++ b/test/migrate/convert_heatmaps.js @@ -0,0 +1,87 @@ +//convert.js +// +const readline = require('readline'); +const path = require('path') +const fs = require('fs'); +const inputFolder = process.argv[2] || './input'; +const outputFolder = process.argv[3] || './output'; + +const fileTemps = {}; + +let remainder = 0; +fs.readdirSync(inputFolder).forEach(fileName => { + const ext = path.extname(`${inputFolder}/${fileName}`); + if(ext!=='.json') return; + fileTemps[fileName] = null; + convert(fileName) +}); + +function convert(filename){ + + let lineno = 0; + let data = []; + let size = {}; + + let fields = []; + let ranges = [0,1]; + // read file + const myInterface = readline.createInterface({ + input: fs.createReadStream(`${inputFolder}/${filename}`) + }); + + remainder++; + myInterface.on('line', function (line) { + const record = JSON.parse(line); + if(record.properties.metric_value == 0)return; + ++lineno; + if(lineno==1) { + fileTemps[filename] = record; + }; + + data.push([ + record.bbox[0], + record.bbox[1], + ...record.properties.multiheat_param.metric_array]); + }).on('close',()=>{ + const content = generateDoc(data,filename); + if(!fs.existsSync(outputFolder)) fs.mkdirSync(outputFolder); + fs.writeFile(`${outputFolder}/NEW_${filename}`, content, function(err) { + console.log('close'); + if (err) throw err; + remainder--; + console.log(`${filename} completed`); + if(remainder == 0) console.log('finished'); + else console.log(`${remainder} Files remaining`); + }); + }); +} + +function generateDoc(data,filename){ + const [x,y,x1,y1] = fileTemps[filename].bbox; + const width = x1 - x; + const height = y1 - y; + const fields = fileTemps[filename].properties.multiheat_param.heatname_array.map(d =>{ + return{ + name:d, + range:[0,1], + value:[0.1,1] + }}); +return `{ +"provenance":{ + "image":{ + "slide": "${fileTemps[filename].provenance.image.case_id}", + "specimen": "", + "study": "${fileTemps[filename].provenance.analysis.study_id}" + + }, + "analysis":{ + "computation":"heatmap", + "size": [${width},${height}], + "fields":${JSON.stringify(fields)}, + "execution_id":"${fileTemps[filename].provenance.analysis.execution_id}", + "source":"computer" + } +}, +"data":${JSON.stringify(data)} +}`; +} diff --git a/test/migrate/heatmap_prov_rename.js b/test/migrate/heatmap_prov_rename.js new file mode 100644 index 0000000..aa263bb --- /dev/null +++ b/test/migrate/heatmap_prov_rename.js @@ -0,0 +1,15 @@ +db.heatmap.find({"provenance.image.case_id":{ $exists: true}}).forEach(function(x){ + x.provenance.image.slide = x.provenance.image.case_id + delete x.provenance.image.case_id + x.provenance.image.study = x.provenance.image.study || "" + delete x.provenance.image.subject_id + db.heatmap.save(x) +}) + +db.heatmapEdit.find({"provenance.image.case_id":{ $exists: true}}).forEach(function(x){ + x.provenance.image.slide = x.provenance.image.case_id + delete x.provenance.image.case_id + x.provenance.image.study = x.provenance.image.study || "" + delete x.provenance.image.subject_id + db.heatmapEdit.save(x) +}) diff --git a/test/migrate/migration.js b/test/migrate/migration.js new file mode 100644 index 0000000..69c3273 --- /dev/null +++ b/test/migrate/migration.js @@ -0,0 +1,34 @@ +// run this against the quip (or otherwise source) database. +var dest_db = "camic" + +// slide update metadata structure and copy over +db.images.find().forEach(function(x){ + //MOVE case_id to name + x['name'] = x['case_id'] + delete (x['case_id']) + //COPY mpp-x and -y to _x _y + x['mpp_x'] = x['mpp-x'] + x['mpp_y'] = x['mpp-y'] + x['location'] = x['file-location'] + //MOVE study_id to study, else study as empty string + x['study'] = x['study'] || x['study_id'] || "" + delete (x['study_id']) + //move specimen_id to specimen, else specimen as empty string + x['specimen'] = x['specimen'] || x['specimen_id'] || "" + delete (x['specimen_id']) + db.getSiblingDB(dest_db)['slide'].insert(x); +}); + +// mark, update metadata structure and copy over +db.objects.find().forEach(function(x){ + // slidename and slide are old case_id + x['provenance']['image']['slide'] = x['provenance']['image']['case_id'] + x['provenance']['image']['slidename'] = x['provenance']['image']['case_id'] + delete (x['provenance']['image']['case_id']) + // specimen and study same conversion as in slide + x['provenance']['image']['study'] = x['provenance']['image']['study'] || x['provenance']['analysis']['study_id'] || "" + x['provenance']['image']['specimen'] = x['provenance']['image']['specimen'] || x['provenance']['analysis']['specimen_id'] || "" + delete (x['provenance']['analysis']['specimen_id']); + delete (x['provenance']['analysis']['study_id']); + db.getSiblingDB(dest_db)['mark'].insert(x); +}); diff --git a/test/quip-pathdb.yml b/test/quip-pathdb.yml new file mode 100644 index 0000000..21e6dce --- /dev/null +++ b/test/quip-pathdb.yml @@ -0,0 +1,66 @@ +version: '3' + +services: + mongo: + image: mongo + container_name: ca-mongo + restart: unless-stopped + volumes: + - ./db:/data/db + logging: + driver: none + idxMongo: + image: mongo + container_name: ca-idx + links: + - mongo + volumes: + - ./config:/config + command: + - /config/run_idx.sh + depends_on: + - mongo + bindaas: + build: "./Deps/Bindaas/" + depends_on: + - "mongo" + container_name: ca-data + restart: unless-stopped + logging: + driver: none + ports: ["8080:8080", "9099:9099"] + volumes: + - ./config/bindaas_projects/:/root/bindaas/bin/projects/ + - ./config/bindaas.config.json:/root/bindaas/bin/bindaas.config.json + iip: + build: "https://github.com/camicroscope/iipImage.git#v3.2.0" + container_name: ca-iip + restart: unless-stopped + volumes: + - ./images/:/data/images/ + security: + build: "https://github.com/camicroscope/Security.git#v3.2.2" + container_name: ca-security + restart: unless-stopped + ports: ["4010:4010"] + volumes: + - ./config/routes.json:/root/src/routes.json + environment: + - DISABLE_SEC=true + auth: + build: "./Deps/auth_service/" + container_name: ca-auth + logging: + driver: none + pathdb: + build: "https://github.com/SBU-BMI/PathDB.git#1.0.5" + container_name: quip-pathdb + restart: unless-stopped + ports: ["443:443","80:80"] + volumes: + - ./data:/data/ + - ./images/:/data/pathdb/files/wsi + - ./jwt_keys/:/keys/ + - ./config:/config + command: + - /config/pathdb_pre.sh diff --git a/test/test/package-lock.json b/test/test/package-lock.json new file mode 100644 index 0000000..299d6a1 --- /dev/null +++ b/test/test/package-lock.json @@ -0,0 +1,1220 @@ +{ + "name": "camic_distro", + "version": "3.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz", + "integrity": "sha512-GXmKIvbrN3TV7aVqAzVFaMW8F8wzVX7voEBRO3bDA64+EX37YSayggRJP5Xig6HYHBkWKpFg9W5gg6orklubhg==" + } + } + }, + "acorn-walk": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.0.tgz", + "integrity": "sha512-ugTb7Lq7u4GfWSqqpwE0bGyoBZNMTok/zDBXxfEG0QM50jNlGhIWjRC1pPN7bvV1anhF+bs+/gNcRw+o55Evbg==" + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==" + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cssom": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", + "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==" + }, + "cssstyle": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", + "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "requires": { + "cssom": "0.3.x" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.0.1.tgz", + "integrity": "sha512-0HdcMZzK6ubMUnsMmQmG0AcLQPvbvb47R0+7CCZQCYgcd8OUWG91CG7sM6GoXgjz+WLl4ArFzHtBMy/QqSF4eg==", + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.16.4", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", + "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.3", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.4", + "qs": "6.5.2", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.2", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "requires": { + "mime-db": "~1.37.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "node-fetch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.0.tgz", + "integrity": "sha512-OayFWziIxiHY8bCUyLX6sTpDH8Jsbp4FfYd1j1f7vZyfgkcOnAyM4oQR16f8a0s7Gl/viMGRey8eScYk4V4EZA==" + }, + "nwsapi": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", + "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==" + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "^4.13.1" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "sshpk": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "requires": { + "punycode": "^2.1.0" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", + "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==" + }, + "whatwg-mimetype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.2.0.tgz", + "integrity": "sha512-5YSO1nMd5D1hY3WzAQV3PzZL83W3YeyR1yW9PcH26Weh1t+Vzh9B6XkDh7aXm83HBZ4nSMvkjvN2H2ySWIvBgw==" + }, + "whatwg-url": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + } + } +} diff --git a/test/test/package.json b/test/test/package.json new file mode 100644 index 0000000..946f8f7 --- /dev/null +++ b/test/test/package.json @@ -0,0 +1,18 @@ +{ + "name": "camic_distro", + "version": "3.0.0", + "description": "", + "scripts": { + "test": "mocha *.js --exit" + }, + "author": "", + "license": "ISC", + "dependencies": { + "chai": "^4.1.2", + "express": "^4.16.2", + "jsdom": "^11.11.0", + "mocha": "^5.1.1", + "node-fetch": "^2.2.0", + "whatwg-fetch": "^3.0.0" + } +} diff --git a/test/test/test_add_slide.js b/test/test/test_add_slide.js new file mode 100644 index 0000000..9c31e75 --- /dev/null +++ b/test/test/test_add_slide.js @@ -0,0 +1,51 @@ +const jsdom = require('jsdom'); +const assert = require('assert'); +const { JSDOM } = jsdom; +const fetch = require("node-fetch") + +// jsdom instance +const posturl = "http://localhost:4010/data/Slide/post" +const findurl = "http://localhost:4010/data/Slide/find?slide=TEST" + + +describe('Slide Loading Step 1', function () { + + it('Posts a Slide', function (done) { + this.timeout(5000); + var slideData = {"name" : "TEST" , "specimen": '', "study": '', "location" : "/images/sample.svs" , "mpp" : 0.499}; + var postProcess = fetch(posturl, { + "method":"POST", + mode: "cors", + headers: { + "Content-Type": "application/json; charset=utf-8" + // "Content-Type": "application/x-www-form-urlencoded", + }, + body:JSON.stringify(slideData)}) + postProcess.then(x=>x.json()).then(x=>{ + console.log(x) + assert.equal(x.count,1, "Post Reported Successful") + done() + }).catch(e=>{ + console.log("err") + console.log(e) + done(e) + }) + }) +}) +describe('Slide Loading Step 2', function () { + // can we see it in find + it('Finds the added slide', function (done) { + this.timeout(5000); + let getProcess = fetch(findurl) + getProcess.then(x=>x.json()).then(x=>{ + console.log(x) + assert.equal(x.length,1, "Slide Shows up in API List") + done() + }).catch(e=>{ + console.log("err") + console.log(e) + done(e) + }) + + }); +}) diff --git a/test/test/test_loader.js b/test/test/test_loader.js new file mode 100644 index 0000000..ae50e46 --- /dev/null +++ b/test/test/test_loader.js @@ -0,0 +1,28 @@ +// test the core loader function we can here, the info get. + +// get info for the sample image, compare it to known info + +const assert = require('assert'); +const fetch = require("node-fetch") + + +const checkurl = "http://localhost:4010/load/Slide/info/sample.svs" + + +describe('Sample Slide Metadata Check', function () { + // can we see it in find + it('Gets correct metadata', function (done) { + this.timeout(10000) // there's a case for speeding up the metadata extraction... + let getProcess = fetch(checkurl) + getProcess.then(x=>x.json()).then(x=>{ + console.log(x['mpp-x']) + assert.equal(x['mpp-x'],"0.499", "Slide metadata matches known result") + done() + }).catch(e=>{ + console.log("err") + console.log(e) + done(e) + }) + + }); +}) diff --git a/test/test/test_viewer_basic.js b/test/test/test_viewer_basic.js new file mode 100644 index 0000000..a458df5 --- /dev/null +++ b/test/test/test_viewer_basic.js @@ -0,0 +1,33 @@ +const jsdom = require('jsdom'); +const assert = require('assert'); +const { JSDOM } = jsdom; + +// jsdom instance +const testurl = "http://localhost:4010/apps/viewer/viewer.html" + + +describe('Minimal Distribution Test', function () { + + // Can we see the table? + it('Routes With Correct Title', function (done) { + JSDOM.fromURL(testurl).then((dom)=>{ + let a = new Promise((resolve, reject)=>{ + setInterval(()=>{ + if (dom.window.document.body.innerHTML!==""){ + resolve() + } + }, 100) + }) + a.then(x=>{ + const title = dom.window.document.title + assert.equal(title,"caMicroscope",'Minimal Test; Title ok') + done() + }).catch(x=>{ + console.log("err") + console.log(x) + done(x) + }) + }) + + }); +}); diff --git a/test/user_docs.md b/test/user_docs.md new file mode 100644 index 0000000..940468a --- /dev/null +++ b/test/user_docs.md @@ -0,0 +1,33 @@ +# Using caMicroscope +caMicroscope is a tool to view, annotate, and analyze whole-slide, biomedical images. It manages digital pathology images, associated clinical and imaging metadata, and human/machine generated annotations and markups. + +## Selecing an Image +Depending on what is providing the image metadata, differnet login tecniques may be necessary. For public instances, no log in is necesary, and you can proceed to view slides. Use of other tools, such as annotations may or may not require login in this case. +For slim instances, login should be done through a redirect directly. For pathDB instances, login should be done on the login link on the main page. +At this point, select a collection, if applicable, and proceed to open or "view" the image of your choice. + +## Viewing an Image +Once an image is open, you can pan around the image by either clicking and dragging (when no conflicting tool, such as the pen, is open), or by moving the red bounding box in the viewport in the bottom right. +Zooming can be accomplished through the scroll wheel, pinch events on a touch screen, by using the zoom slider or its associated buttons, or by clicking on the zoom number and inputing a different number. + +## Using Tools +The toolbar is in the top-left of the main content window. Use the toolbar buttons to manipulate the slide. To close any toolbar button, click the same button again or a new button. + +| Tool | Name | Function | +| ----- |-------------| -----| +| | Annotations | Opens the Annotation panel, where you can select which annotation set to view, name that annotation set, add optional notes about the annotation set, save the annotation set, and reset the panel to its original state. | +| | Layer Manager | Opens the Layers Manager panel, where you can select which layers to view. | +| | Home | Return to the data table so that you can open another slide.| +| | Draw | Draw thin lines, thick lines, or polygons on the image. To maintain the integrity of measurements, avoid drawing shapes that overlap or intersect one another. | +| | Magnifier |The Magnifier works like a magnifying glass and allows you to see the slide at normal magnification (1.0), low magnification (0.5), or high magnification (2.0). Click a magnification level and place the bounding box on the area of the slide you want to magnify. | +| | Measurement | Drag this tool on the slide to learn the measurement in micrometers. | +| | Share View |Opens a window with a URL to the current presentation state of the slide including the magnification level, layers that are currently open, and your position on the image.| +| | Side by Side Viewer |Shows the Layer Manager panel, the left and right layers, and inset window. For the right and left layer, select which layer you want to view. | +| | Heatmap | For a slide with heatmap data, opens the choices of heatmaps available, as well as ways of displaying the heatmaps. The gradient shows all of the values on the selected spectrum for the field you selected. Contains a heatmap edit pen function.| +| | Labeling |Use this tool to draw a circle or rectangle around a tumor region, measure an area on the slide, download labels, and submit a bug report. The Labeling tool has its own toolbar with tools in the following order from left to right: return to the previous slide, place a square on the slide, place a circle on the slide, measure an area, download labels, and submit a bug report. Click the left arrow at the far right of the toolbar to hide it, then click the right arrow to show it. | +| | Segment | This tool allows you to display, count, and export nuclear segmentations on the image. Clicking this tool opens the following custom toolbar. | +| | Model | Show results from a pre-trained tensorflow compatible model on a ROI of the slide. | +| | Bug Report | Report a bug or give feedback. | + +## Credits +This guide has been adapted from the guide created for the SEER project by Carolyn Klinger. diff --git a/user_docs.md b/user_docs.md new file mode 100644 index 0000000..940468a --- /dev/null +++ b/user_docs.md @@ -0,0 +1,33 @@ +# Using caMicroscope +caMicroscope is a tool to view, annotate, and analyze whole-slide, biomedical images. It manages digital pathology images, associated clinical and imaging metadata, and human/machine generated annotations and markups. + +## Selecing an Image +Depending on what is providing the image metadata, differnet login tecniques may be necessary. For public instances, no log in is necesary, and you can proceed to view slides. Use of other tools, such as annotations may or may not require login in this case. +For slim instances, login should be done through a redirect directly. For pathDB instances, login should be done on the login link on the main page. +At this point, select a collection, if applicable, and proceed to open or "view" the image of your choice. + +## Viewing an Image +Once an image is open, you can pan around the image by either clicking and dragging (when no conflicting tool, such as the pen, is open), or by moving the red bounding box in the viewport in the bottom right. +Zooming can be accomplished through the scroll wheel, pinch events on a touch screen, by using the zoom slider or its associated buttons, or by clicking on the zoom number and inputing a different number. + +## Using Tools +The toolbar is in the top-left of the main content window. Use the toolbar buttons to manipulate the slide. To close any toolbar button, click the same button again or a new button. + +| Tool | Name | Function | +| ----- |-------------| -----| +| | Annotations | Opens the Annotation panel, where you can select which annotation set to view, name that annotation set, add optional notes about the annotation set, save the annotation set, and reset the panel to its original state. | +| | Layer Manager | Opens the Layers Manager panel, where you can select which layers to view. | +| | Home | Return to the data table so that you can open another slide.| +| | Draw | Draw thin lines, thick lines, or polygons on the image. To maintain the integrity of measurements, avoid drawing shapes that overlap or intersect one another. | +| | Magnifier |The Magnifier works like a magnifying glass and allows you to see the slide at normal magnification (1.0), low magnification (0.5), or high magnification (2.0). Click a magnification level and place the bounding box on the area of the slide you want to magnify. | +| | Measurement | Drag this tool on the slide to learn the measurement in micrometers. | +| | Share View |Opens a window with a URL to the current presentation state of the slide including the magnification level, layers that are currently open, and your position on the image.| +| | Side by Side Viewer |Shows the Layer Manager panel, the left and right layers, and inset window. For the right and left layer, select which layer you want to view. | +| | Heatmap | For a slide with heatmap data, opens the choices of heatmaps available, as well as ways of displaying the heatmaps. The gradient shows all of the values on the selected spectrum for the field you selected. Contains a heatmap edit pen function.| +| | Labeling |Use this tool to draw a circle or rectangle around a tumor region, measure an area on the slide, download labels, and submit a bug report. The Labeling tool has its own toolbar with tools in the following order from left to right: return to the previous slide, place a square on the slide, place a circle on the slide, measure an area, download labels, and submit a bug report. Click the left arrow at the far right of the toolbar to hide it, then click the right arrow to show it. | +| | Segment | This tool allows you to display, count, and export nuclear segmentations on the image. Clicking this tool opens the following custom toolbar. | +| | Model | Show results from a pre-trained tensorflow compatible model on a ROI of the slide. | +| | Bug Report | Report a bug or give feedback. | + +## Credits +This guide has been adapted from the guide created for the SEER project by Carolyn Klinger.