From ac5e253d02a8782b683f24b9764a8df7f6e843ed Mon Sep 17 00:00:00 2001 From: Barry Low Date: Thu, 20 Sep 2018 08:24:35 -0700 Subject: [PATCH] Basic file upload to Azure BlockBLob --- api/package-lock.json | 456 +++++++++++++++--- api/package.json | 6 +- api/src/index.js | 74 ++- api/src/schema.graphql | 1 + api/src/storage/azure.js | 133 +++++ client/package-lock.json | 171 ++++++- client/package.json | 2 + .../src/graphql/teams/GetAzureSASMutation.js | 10 + client/src/views/common/UploadImage.js | 81 +++- 9 files changed, 850 insertions(+), 84 deletions(-) create mode 100644 api/src/storage/azure.js create mode 100644 client/src/graphql/teams/GetAzureSASMutation.js diff --git a/api/package-lock.json b/api/package-lock.json index 81ed969ea..6d1c72d4f 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -3,6 +3,14 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@azure/storage-blob": { + "version": "10.0.0-preview", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-10.0.0-preview.tgz", + "integrity": "sha512-PFXKm+gipKDfg5h08hPiEr0Za4RMiFzzte+ewh4ACZeRQa0XZK55NAZxW67ZytGBd7WXdQq6pcAgo5dBnwQANQ==", + "requires": { + "ms-rest-js": "0.21.413" + } + }, "@babel/generator": { "version": "7.0.0-beta.38", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.38.tgz", @@ -213,6 +221,14 @@ "@types/express": "*" } }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "requires": { + "@types/node": "*" + } + }, "@types/graphql": { "version": "0.12.6", "resolved": "http://registry.npmjs.org/@types/graphql/-/graphql-0.12.6.tgz", @@ -247,6 +263,14 @@ "@types/mime": "*" } }, + "@types/uuid": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz", + "integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==", + "requires": { + "@types/node": "*" + } + }, "@types/zen-observable": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.5.4.tgz", @@ -808,6 +832,86 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.18.0", + "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" + } + }, + "azure-storage": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.1.tgz", + "integrity": "sha512-rnFo1uMIPtilusRCpK91tfY3P4Q7qRsDNwriXdp+OeTIGkGt0cTxL4mhqYfNPYPK+WBQmBdGWhOk+iROM05dcw==", + "requires": { + "browserify-mime": "~1.2.9", + "extend": "~1.2.1", + "json-edm-parser": "0.1.2", + "md5.js": "1.3.4", + "readable-stream": "~2.0.0", + "request": "^2.86.0", + "underscore": "~1.8.3", + "uuid": "^3.0.0", + "validator": "~9.4.1", + "xml2js": "0.2.8", + "xmlbuilder": "0.4.3" + }, + "dependencies": { + "extend": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz", + "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "sax": { + "version": "0.5.8", + "resolved": "http://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=" + }, + "validator": { + "version": "9.4.1", + "resolved": "http://registry.npmjs.org/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==" + }, + "xml2js": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz", + "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=", + "requires": { + "sax": "0.5.x" + } + }, + "xmlbuilder": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-0.4.3.tgz", + "integrity": "sha1-xGFLp04K0ZbmCcknLNnh3bKKilg=" + } + } + }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", @@ -968,6 +1072,21 @@ "qs": "6.5.2", "raw-body": "2.3.3", "type-is": "~1.6.16" + }, + "dependencies": { + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, "body-parser-graphql": { @@ -1028,6 +1147,11 @@ } } }, + "browserify-mime": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz", + "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8=" + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -1746,18 +1870,11 @@ "integrity": "sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==" }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.0.1.tgz", + "integrity": "sha512-K23FHJ/Mt404FSlp6gSZCevIbTMLX0j3fmHhUEhQ3Wq0FMODW3+cUSoLdy1Gx4polAf4t/lphhmHH35BB8cLYw==", "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "ms": "^2.1.1" } }, "decamelize": { @@ -2271,6 +2388,14 @@ "to-regex": "^3.0.1" }, "dependencies": { + "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" + } + }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -2286,6 +2411,11 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -2409,11 +2539,24 @@ "type-is": "~1.6.15" } }, + "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" + } + }, "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", @@ -2680,6 +2823,14 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "fast-xml-parser": { + "version": "3.12.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.12.5.tgz", + "integrity": "sha512-g8TSGUF1a2vdFmQ29vKcYBNnwuJQQuyr6It3cjGsiD3dkUXqVWuXZQvjEkgrrCe5K8D30X125ACyxaj7XaaH8g==", + "requires": { + "nimnjs": "^1.3.2" + } + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -2762,6 +2913,19 @@ "unpipe": "~1.0.0" }, "dependencies": { + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -2786,6 +2950,29 @@ "locate-path": "^2.0.0" } }, + "follow-redirects": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", + "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", + "requires": { + "debug": "=3.1.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=" + } + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -4225,6 +4412,15 @@ } } }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "header-case": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/header-case/-/header-case-1.0.1.tgz", @@ -4822,6 +5018,14 @@ "integrity": "sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=", "dev": true }, + "json-edm-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz", + "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=", + "requires": { + "jsonparse": "~1.2.0" + } + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -4898,6 +5102,11 @@ "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, + "jsonparse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz", + "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70=" + }, "jsonwebtoken": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz", @@ -4946,6 +5155,23 @@ "lru-memoizer": "^1.6.0", "ms": "^2.0.0", "request": "^2.73.0" + }, + "dependencies": { + "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" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + } } }, "jws": { @@ -5405,6 +5631,15 @@ "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", "dev": true }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -5419,9 +5654,9 @@ } }, "memfs": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-2.9.4.tgz", - "integrity": "sha512-wstvgqSTBGf9rQHoaRpX3wJiGzB/sj649XaO+byuHiPZQaR3Y/mOgU6n9iMFLtAHlR4BwwBWFgA4hobiU6EcCg==", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-2.10.0.tgz", + "integrity": "sha512-GuQXfXghDdDdkokv6cwaWLh8bOD9Ots4z11qUR9yKiCeO7oMPhBjFjKVc991DIHTXFbonqKYOEDAVTa4CvvkJg==", "dev": true, "requires": { "fast-extend": "0.0.2", @@ -5555,6 +5790,30 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, + "ms-rest-js": { + "version": "0.21.413", + "resolved": "https://registry.npmjs.org/ms-rest-js/-/ms-rest-js-0.21.413.tgz", + "integrity": "sha512-eX+M98Y9s+zo85Unt83TYkpuJkW4d0wuiHrpWjAxx/7YzZd3uVq8HRhJHXGDqCd22nlEvtwlchfgwILmBcWnOg==", + "requires": { + "@types/express": "^4.11.1", + "@types/form-data": "^2.2.1", + "@types/node": "^9.4.6", + "@types/uuid": "^3.4.3", + "axios": "^0.18.0", + "form-data": "^2.3.2", + "tough-cookie": "^2.4.3", + "tslib": "^1.9.2", + "uuid": "^3.2.1", + "xml2js": "^0.4.19" + }, + "dependencies": { + "@types/node": { + "version": "9.6.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.31.tgz", + "integrity": "sha512-kIVlvUBizL51ALNMPbmcZoM7quHyB7J6fLRwQe22JsMp39nrVSHdBeVVS3fnQCK1orxI3O8LScmb8cuiihkAfA==" + } + } + }, "multimatch": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", @@ -5608,6 +5867,25 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "nimn-date-parser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nimn-date-parser/-/nimn-date-parser-1.0.0.tgz", + "integrity": "sha512-1Nf+x3EeMvHUiHsVuEhiZnwA8RMeOBVTQWfB1S2n9+i6PYCofHd2HRMD+WOHIHYshy4T4Gk8wQoCol7Hq3av8Q==" + }, + "nimn_schema_builder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nimn_schema_builder/-/nimn_schema_builder-1.1.0.tgz", + "integrity": "sha512-DK5/B8CM4qwzG2URy130avcwPev4uO0ev836FbQyKo1ms6I9z/i6EJyiZ+d9xtgloxUri0W+5gfR8YbPq7SheA==" + }, + "nimnjs": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/nimnjs/-/nimnjs-1.3.2.tgz", + "integrity": "sha512-TIOtI4iqkQrUM1tiM76AtTQem0c7e56SkDZ7sj1d1MfUsqRcq2ZWQvej/O+HBTZV7u/VKnwlKTDugK/75IRPPw==", + "requires": { + "nimn-date-parser": "^1.0.0", + "nimn_schema_builder": "^1.0.0" + } + }, "no-case": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", @@ -6330,6 +6608,23 @@ "async": "^1.5.2", "debug": "^2.2.0", "mkdirp": "0.5.x" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "posix-character-classes": { @@ -6338,9 +6633,9 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postgres-array": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz", - "integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", + "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==", "dev": true }, "postgres-bytea": { @@ -6376,14 +6671,14 @@ "dev": true }, "prisma": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/prisma/-/prisma-1.16.0.tgz", - "integrity": "sha512-8jZYCrkd1xjy+JJbQi81f8PBOLe8LLWwSu0fK0cqekm3FeafBd8xk5b0RWcIsHyVd6ypKCQt3tnZEMVzmbKrdQ==", + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-1.16.4.tgz", + "integrity": "sha512-ha+SJDnJ+NVtkoP4nivcmnKV/PmkbQiXVJUPEdYfkQPpuite1kOuFp9seolE4DJFaz3m8DlF24AQf7aePf09AQ==", "dev": true, "requires": { "fs-extra": "^5.0.0", - "prisma-cli-core": "1.0.76", - "prisma-cli-engine": "1.0.79", + "prisma-cli-core": "1.0.79", + "prisma-cli-engine": "1.0.82", "semver": "^5.4.1", "source-map-support": "^0.4.18" }, @@ -6502,9 +6797,9 @@ } }, "prisma-cli-core": { - "version": "1.0.76", - "resolved": "https://registry.npmjs.org/prisma-cli-core/-/prisma-cli-core-1.0.76.tgz", - "integrity": "sha512-HtHn/RM2GlJi23KoIXHoboP97aC54SYDqr7B4uT/80JP6A6nQp5HLt4sJgNfKapaHFZVzXYM7M3LEfGq3tgQbw==", + "version": "1.0.79", + "resolved": "https://registry.npmjs.org/prisma-cli-core/-/prisma-cli-core-1.0.79.tgz", + "integrity": "sha512-3xaFE0wK48nZ8LOqx62gMoFgjIob121Uo6RHOnXNXMcCOdtGM7VfGw4o6gyDVwNDvu66fz0EVLaQGcJb5hnTpA==", "dev": true, "requires": { "adm-zip": "^0.4.7", @@ -6538,9 +6833,9 @@ "opn": "^5.1.0", "pause": "^0.1.0", "portfinder": "^1.0.13", - "prisma-db-introspection": "0.0.46", + "prisma-db-introspection": "0.0.50", "prisma-json-schema": "0.0.4", - "prisma-yml": "1.0.96", + "prisma-yml": "1.0.100", "scuid": "^1.0.2", "semver": "^5.4.1", "sillyname": "^0.1.0", @@ -6646,12 +6941,12 @@ } }, "graphql-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-2.1.0.tgz", - "integrity": "sha512-LWpkME3x+KSFMVuMpRmDHTIZLyQQsBoKtMXJrT4RgXk6y0GRf0lsJ81R3S2FmT1CKZQOJfFsOpUfPpAcfmoN/A==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-2.2.1.tgz", + "integrity": "sha512-U8+1IAhw9m6WkZRRcyj8ZarK96R6lQBQ0an4lp76Ps9FyhOXENC5YQOxOFGm5CxPrX2rD0g3Je4zG5xdNJjwzQ==", "dev": true, "requires": { - "graphql-import": "^0.4.4", + "graphql-import": "^0.7.1", "graphql-request": "^1.5.0", "js-yaml": "^3.10.0", "lodash": "^4.17.4", @@ -6697,12 +6992,13 @@ } }, "graphql-import": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/graphql-import/-/graphql-import-0.4.5.tgz", - "integrity": "sha512-G/+I08Qp6/QGTb9qapknCm3yPHV0ZL7wbaalWFpxsfR8ZhZoTBe//LsbsCKlbALQpcMegchpJhpTSKiJjhaVqQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/graphql-import/-/graphql-import-0.7.1.tgz", + "integrity": "sha512-YpwpaPjRUVlw2SN3OPljpWbVRWAhMAyfSba5U47qGMOSsPLi2gYeJtngGpymjm9nk57RFWEpjqwh4+dpYuFAPw==", "dev": true, "requires": { - "lodash": "^4.17.4" + "lodash": "^4.17.4", + "resolve-from": "^4.0.0" } }, "inquirer": { @@ -6778,9 +7074,9 @@ "dev": true }, "prisma-yml": { - "version": "1.0.96", - "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.96.tgz", - "integrity": "sha512-w3XGzJHUq5pwBoFy/amkGOcTDj4XoHh8UFUUUZcHo5fSyoF8AWeRTu1yWINaPVGxbcmpwKNetntAW4ijiq7M5g==", + "version": "1.0.100", + "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.100.tgz", + "integrity": "sha512-W2a0dpfbXyapc3WZqcvUBqtsl2r9upQRUR2p53AqQR4tQz+/6nsMcqe30vqgnOW/WmNAnknqQT3Z5P0rsq4K3Q==", "dev": true, "requires": { "ajv": "5", @@ -6803,6 +7099,12 @@ "yaml-ast-parser": "^0.0.40" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -6827,9 +7129,9 @@ } }, "prisma-cli-engine": { - "version": "1.0.79", - "resolved": "https://registry.npmjs.org/prisma-cli-engine/-/prisma-cli-engine-1.0.79.tgz", - "integrity": "sha512-CdEIJs4ld1IiQQt2CFFPmeDypN4Ct4sTgmFODVjJix790mpEtxMagzCcA+mhfnRL65P6xiHn76Gdxbz60GyYBA==", + "version": "1.0.82", + "resolved": "https://registry.npmjs.org/prisma-cli-engine/-/prisma-cli-engine-1.0.82.tgz", + "integrity": "sha512-kEqNtH0bjzVX17Vcs77UiAwk0Ei9Za03bOINcrpIjNUyI9GOOU5p+6ss8cePfK21lxvy5RSlYwthBFLkXE73Gg==", "dev": true, "requires": { "@heroku/linewrap": "^1.0.0", @@ -6872,7 +7174,7 @@ "memfs": "^2.5.3", "opn": "^5.1.0", "prisma-json-schema": "0.0.4", - "prisma-yml": "1.0.96", + "prisma-yml": "1.0.100", "raven": "2.3.0", "replaceall": "^0.1.6", "rwlockfile": "^1.4.8", @@ -6937,9 +7239,9 @@ "dev": true }, "prisma-yml": { - "version": "1.0.96", - "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.96.tgz", - "integrity": "sha512-w3XGzJHUq5pwBoFy/amkGOcTDj4XoHh8UFUUUZcHo5fSyoF8AWeRTu1yWINaPVGxbcmpwKNetntAW4ijiq7M5g==", + "version": "1.0.100", + "resolved": "https://registry.npmjs.org/prisma-yml/-/prisma-yml-1.0.100.tgz", + "integrity": "sha512-W2a0dpfbXyapc3WZqcvUBqtsl2r9upQRUR2p53AqQR4tQz+/6nsMcqe30vqgnOW/WmNAnknqQT3Z5P0rsq4K3Q==", "dev": true, "requires": { "ajv": "5", @@ -6995,9 +7297,9 @@ } }, "prisma-db-introspection": { - "version": "0.0.46", - "resolved": "https://registry.npmjs.org/prisma-db-introspection/-/prisma-db-introspection-0.0.46.tgz", - "integrity": "sha512-/b7evS9b5xKS7UrcOERkCmV+IWC6OAgFtInFsvdwn4MeLEaVbkOfzRakdOo+t2gb+N7Yy8Eey9eKYgB5jiJAbA==", + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/prisma-db-introspection/-/prisma-db-introspection-0.0.50.tgz", + "integrity": "sha512-coeJ3SRumezVnsQwc/kwNzxWFUBKHNwnD+keUJeZFFY3j7EDtRFHoL5DD7vTREvMEugoWOiovc+MYHFkDt0l+w==", "dev": true, "requires": { "ajv": "5", @@ -7637,6 +7939,14 @@ "statuses": "~1.4.0" }, "dependencies": { + "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" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -7799,6 +8109,14 @@ "use": "^3.1.0" }, "dependencies": { + "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" + } + }, "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", @@ -7815,6 +8133,11 @@ "is-extendable": "^0.1.0" } }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -8061,9 +8384,9 @@ "dev": true }, "string-similarity": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.1.tgz", - "integrity": "sha512-XqC6lRZF3UIYdxBRHjIfJwU2nYzPm+E8udKFHjIplnRQflkXP1A1Ie3HoEv04W/zY1wGnV6TQpklM2WwZO3gIA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-1.2.2.tgz", + "integrity": "sha512-IoHUjcw3Srl8nsPlW04U3qwWPk3oG2ffLM0tN853d/E/JlIvcmZmDY2Kz5HzKp4lEi2T7QD7Zuvjq/1rDw+XcQ==", "dev": true, "requires": { "lodash.every": "^4.6.0", @@ -8463,6 +8786,11 @@ "yn": "^2.0.0" } }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -8492,9 +8820,9 @@ "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, "unbzip2-stream": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz", - "integrity": "sha512-izD3jxT8xkzwtXRUZjtmRwKnZoeECrfZ8ra/ketwOcusbZEp4mjULMnJOCfTDZBgGQAAY1AJ/IgxcwkavcX9Og==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.3.0.tgz", + "integrity": "sha512-kE2WkurNnPUMcryNioS68DDbhoPB8Qxsd8btHSj+sd5Pjh2GsjmeHLzMSqV9HHziAo8FzVxVCJl9ZYhk7yY1pA==", "dev": true, "requires": { "buffer": "^3.0.1", @@ -8532,8 +8860,28 @@ "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", "requires": { "debug": "^2.2.0" + }, + "dependencies": { + "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" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } } }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", diff --git a/api/package.json b/api/package.json index 784b66264..9e5311fb1 100644 --- a/api/package.json +++ b/api/package.json @@ -7,9 +7,13 @@ "dev": "npm-run-all --parallel debug playground" }, "dependencies": { + "@azure/storage-blob": "^10.0.0-preview", + "azure-storage": "^2.10.1", "cors": "^2.8.4", + "debug": "^4.0.1", "dotenv": "^6.0.0", "express-jwt": "^5.3.1", + "fast-xml-parser": "^3.12.5", "graphql-import": "^0.6.0", "graphql-tag": "^2.9.2", "graphql-tools": "3.1.1", @@ -23,6 +27,6 @@ "devDependencies": { "graphql-cli": "^2.16.5", "npm-run-all": "4.1.3", - "prisma": "^1.16.0" + "prisma": "^1.16.4" } } diff --git a/api/src/index.js b/api/src/index.js index d640b8682..792f8505e 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -7,11 +7,32 @@ const { } = require('prisma-binding') const { makeExecutableSchema } = require('graphql-tools') const { importSchema } = require('graphql-import') +const parser = require('fast-xml-parser') const checkJwt = require('./auth/middleware/jwt') const { getMember } = require('./auth/middleware/getMember') const { validateIdToken } = require('./auth/validateIdToken') const { directiveResolvers } = require('./auth/authDirectives') +const { + createStoragePipline, + createServiceURL, + listContainers, + createContainer, + createBlob, + uploadBlob, + downloadBlob, + deleteBlob, + deleteContainer +} = require('./storage/azure') +//var azure = require('azure-storage') +const Azure = require("@azure/storage-blob") +const azureAccount = process.env.AZURE_STORAGE_ACCOUNT +const azureKey = process.env.AZURE_STORAGE_ACCESS_KEY +const azureStorageUrl = process.env.AZURE_STORAGE_URL + +var debug = require('debug')('http') + , http = require('http') + , name = 'My App'; const TEAMS_FRAGMENT = require('./graphql/TeamsFragment') const TEAMS_CONNECTIONS_FRAGMENT = require('./graphql/TeamsConnectionsFragment') @@ -115,6 +136,57 @@ const resolvers = { return error.message }) }) + }, + async getAzureSAS(parent, { teamSlug }, ctx, info) { + // Create start and expiry times + let today = new Date() + let tomorrow = new Date() + tomorrow.setDate(today.getDate() + 7) + // Create SharedKeyCredential and attach to pipline + const SKC = new Azure.SharedKeyCredential(azureAccount, azureKey) + const pipeline = Azure.StorageURL.newPipeline(SKC) + // Create container URL + const serviceURL = new Azure.ServiceURL(azureStorageUrl, pipeline) + const containerName = teamSlug + const containerURL = Azure.ContainerURL.fromServiceURL(serviceURL, containerName) + + let marker + let containerCheck = null + do { + const listContainersResponse = await serviceURL.listContainersSegment( + Azure.Aborter.None, + marker, + ) + console.log(`ContainerCheck marker: `, listContainersResponse) + marker = listContainersResponse.marker; + for (const container of listContainersResponse.containerItems) { + console.log(`ContainerCheck: ${container.name} | ${containerName} | ${marker}`) + if(container.name === containerName){ + containerCheck = container.name + } + } + } while (marker) + let newContainer + if(containerCheck === null){ + newContainer = await containerURL.create(Azure.Aborter.None, { access: 'blob' }) + } + console.log('getAzureSAS container: ', containerURL, containerCheck, newContainer) + + // Set permissions for service, resource types and containers + const SASServicePerms = Azure.AccountSASServices.parse('b') + const SASResourceTypes = Azure.AccountSASResourceTypes.parse('co') + const SASContainerPerms = Azure.ContainerSASPermissions.parse('rwl') + // Generate SAS url + const SASQueryParameters = Azure.generateAccountSASQueryParameters( + { + containerName, + permissions: SASContainerPerms, + startTime: today, + expiryTime: tomorrow, + services: SASServicePerms, + resourceTypes: SASResourceTypes + }, SKC ) + return SASQueryParameters } } } @@ -148,7 +220,7 @@ server.express.use( server.options.endpoint, checkJwt, function (err, req, res, next) { - console.log('checkJwt: ', err, req) + // console.log('checkJwt: ', err, req) if (err) { return res.status(201).send(err.message) } else { diff --git a/api/src/schema.graphql b/api/src/schema.graphql index 1450c6000..731948163 100644 --- a/api/src/schema.graphql +++ b/api/src/schema.graphql @@ -21,6 +21,7 @@ type Mutation { createTeam(name: String!, slug: String!, owner: String!): Team @isAuthenticated updateTeamProfile(slug: String!, owner: String!, description: String, motto: String, avatar: String): Team @isAuthenticated deleteTeam(slug: String!): Team @isAuthenticated @isOwner(type: "Team") + getAzureSAS(teamSlug: String!):String } input MemberProfileInput { diff --git a/api/src/storage/azure.js b/api/src/storage/azure.js new file mode 100644 index 000000000..324181b04 --- /dev/null +++ b/api/src/storage/azure.js @@ -0,0 +1,133 @@ +const Azure = require('@azure/storage-blob') + +/* Create Azure Storage pipeline +* @accountName: Azure Blob Storage account name (required) - Environment variable +* @accountKey: Azure Blob Storage storage key (required) - Environment variable +*/ +const createStoragePipline = async (accountNAme, accountKey) => { + return Azure.StorageURL.newPipeline( + new Azure.SharedKeyCredential(accountName, accountKey) + ) +} + +/* Create Azure Storage Service URL +* @storageURL: URL for Azure Storage endpoint (required) - Environment variable +* @pipeline: Azure Storage Pipline (required) - created using createStoragePipeline() +*/ +const createServiceURL = async (storageURL, pipeline) => { + return new Azure.ServiceURL( + storageURL, + pipeline + ) +} + +/* List containers +* @pipeline: Azure Storage Pipline (required) - created using createServiceURL +* @service_url: URL for Azure Storage endpoint (required) - Environment variable +*/ +const listContainers = async (serviceURL) => { + let marker; + do { + const listContainersResponse = await serviceURL.listContainersSegment( + Azure.Aborter.None, + marker, + ); + + marker = listContainersResponse.marker; + for (const container of listContainersResponse.containerItems) { + console.log(`Container: ${container.name}`); + } + } while (marker); +} + + +/* Create containers +* @serviceURL: URL for Azure Storage endpoint (required) - created using createServiceURL +* @containerName: Container Name +* Returns: containerURL +*/ +const createContainer = async (serviceURL, containerName) => { + const containerURL = ContainerURL.fromServiceURL(serviceURL, containerName) + + const createContainerResponse = await containerURL.create(Aborter.None) + + console.log( + `Created container ${containerName} successfully`, + await createContainerResponse.requestId + ) + return containerURL +} + +/* Create containers +* @containerURL: continer URL (required) - created using createContainer +* @blobName: Blob Name +* Returns: blobURL +*/ +const createBlob = async (containerURL, blobName) => { + const blobURL = Azure.BlobURL.fromContainerURL(containerURL, blobName) + console.log(`created blob successfully`, await blobURL) + return blobURL +} + +/* Upload Blob +* @blobURL: blobURL (required) - created using createBlob +* @blobContent: Blob Content +* Returns: uploadBlobResponse +*/ +const uploadBlob = async (blobURL, blobContent) => { + const blockBlobURL = Azure.BlockBlobURL.fromBlobURL(blobURL) + const uploadBlobResponse = await blockBlobURL.upload( + Azure.Aborter.None, + blobContent, + blobContent.length + ); + console.log(`Upload block blob ${blobName} successfully`, await uploadBlobResponse) + return uploadBlobResponse +} + +/* Download Blob +* @blobURL: blobURL (required) - created using createBlob +* @blobContent: Blob Content +* Returns: downloadBlockBlobResponse +*/ +const downloadBlob = async (blobURL, blobContent) => { + const downloadBlockBlobResponse = await blobURL.download(Azure.Aborter.None, 0) + console.log( + "Downloaded blob content", + downloadBlockBlobResponse.readableStreamBody.read(content.length).toString() + ) + console.log(`BlockBlobResponse: ${downloadBlockBlobResponse}`) + return downloadBlockBlobResponse +} + +/* Delete Blob +* @blobURL: blobURL (required) - created using createBlob +* Returns: bool +*/ +const deleteBlob = async (blobrURL) => { + await blobrURL.delete(Azure.Aborter.None); + console.log("deleted blob", blobrURL); + return true +} + +/* Delete Container +* @containerURL: continer URL (required) - created using createContainer +* Returns: bool +*/ +const deleteContainer = async (containerURL) => { + await containerURL.delete(Azure.Aborter.None); + console.log("deleted container", containerURL); + return true +} + +module.exports = { + createStoragePipline, + createServiceURL, + listContainers, + createContainer, + createBlob, + uploadBlob, + downloadBlob, + deleteBlob, + deleteContainer +} diff --git a/client/package-lock.json b/client/package-lock.json index 219ddf2b8..52252110b 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -4,6 +4,14 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@azure/storage-blob": { + "version": "10.0.0-preview", + "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-10.0.0-preview.tgz", + "integrity": "sha512-PFXKm+gipKDfg5h08hPiEr0Za4RMiFzzte+ewh4ACZeRQa0XZK55NAZxW67ZytGBd7WXdQq6pcAgo5dBnwQANQ==", + "requires": { + "ms-rest-js": "0.21.413" + } + }, "@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", @@ -2204,6 +2212,56 @@ "integrity": "sha512-Benr3i5odUkvpFkOpzGqrltGdbSs+EVCkEBGXbuR7uT0VzhXKIkhem6PDzHdx5EonA+rfbB3QvP6aDOw5+zp5Q==", "optional": true }, + "@types/body-parser": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", + "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.32", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", + "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", + "requires": { + "@types/node": "*" + } + }, + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, + "@types/express": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz", + "integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz", + "integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==", + "requires": { + "@types/events": "*", + "@types/node": "*", + "@types/range-parser": "*" + } + }, + "@types/form-data": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz", + "integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==", + "requires": { + "@types/node": "*" + } + }, "@types/graphql": { "version": "0.12.6", "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.12.6.tgz", @@ -2218,11 +2276,15 @@ "indefinite-observable": "^1.0.1" } }, + "@types/mime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", + "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" + }, "@types/node": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.0.tgz", - "integrity": "sha512-hWzNviaVFIr1TqcRA8ou49JaSHp+Rfabmnqg2kNvusKqLhPU0rIsGPUj5WJJ7ld4Bb7qdgLmIhLfCD1qS08IVA==", - "dev": true + "integrity": "sha512-hWzNviaVFIr1TqcRA8ou49JaSHp+Rfabmnqg2kNvusKqLhPU0rIsGPUj5WJJ7ld4Bb7qdgLmIhLfCD1qS08IVA==" }, "@types/prop-types": { "version": "15.5.5", @@ -2232,6 +2294,11 @@ "@types/react": "*" } }, + "@types/range-parser": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz", + "integrity": "sha512-HtKGu+qG1NPvYe1z7ezLsyIaXYyi8SoAVqWDZgDQ8dLrsZvSzUNCwZyfX33uhWxL/SU0ZDQZ3nwZ0nimt507Kw==" + }, "@types/react": { "version": "16.4.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.4.14.tgz", @@ -2249,6 +2316,15 @@ "@types/react": "*" } }, + "@types/serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, "@types/tapable": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-0.2.5.tgz", @@ -2272,6 +2348,14 @@ } } }, + "@types/uuid": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz", + "integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==", + "requires": { + "@types/node": "*" + } + }, "@types/webpack": { "version": "3.8.12", "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-3.8.12.tgz", @@ -3230,6 +3314,15 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.18.0", + "resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz", + "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=", + "requires": { + "follow-redirects": "^1.3.0", + "is-buffer": "^1.1.5" + } + }, "axobject-query": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.1.tgz", @@ -4645,6 +4738,11 @@ "safe-buffer": "^5.1.1" } }, + "blob-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", + "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==" + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -7670,6 +7768,14 @@ "readable-stream": "^2.0.4" } }, + "follow-redirects": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.8.tgz", + "integrity": "sha512-sy1mXPmv7kLAMKW/8XofG7o9T+6gAjzdZK4AJF6ryqQYUa/hnzgiypoeUecZ53x7XiqKNEpNqLtS97MshW2nxg==", + "requires": { + "debug": "=3.1.0" + } + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -9408,8 +9514,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", @@ -11565,6 +11670,53 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "ms-rest-js": { + "version": "0.21.413", + "resolved": "https://registry.npmjs.org/ms-rest-js/-/ms-rest-js-0.21.413.tgz", + "integrity": "sha512-eX+M98Y9s+zo85Unt83TYkpuJkW4d0wuiHrpWjAxx/7YzZd3uVq8HRhJHXGDqCd22nlEvtwlchfgwILmBcWnOg==", + "requires": { + "@types/express": "^4.11.1", + "@types/form-data": "^2.2.1", + "@types/node": "^9.4.6", + "@types/uuid": "^3.4.3", + "axios": "^0.18.0", + "form-data": "^2.3.2", + "tough-cookie": "^2.4.3", + "tslib": "^1.9.2", + "uuid": "^3.2.1", + "xml2js": "^0.4.19" + }, + "dependencies": { + "@types/node": { + "version": "9.6.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.31.tgz", + "integrity": "sha512-kIVlvUBizL51ALNMPbmcZoM7quHyB7J6fLRwQe22JsMp39nrVSHdBeVVS3fnQCK1orxI3O8LScmb8cuiihkAfA==" + }, + "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" + } + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" + } + } + }, "multimatch": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", @@ -13579,6 +13731,11 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, "public-encrypt": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", @@ -14565,8 +14722,7 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "schedule": { "version": "0.3.0", @@ -15735,8 +15891,7 @@ "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", - "dev": true + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, "tty-browserify": { "version": "0.0.0", diff --git a/client/package.json b/client/package.json index 3fb9b227e..f40fe138f 100644 --- a/client/package.json +++ b/client/package.json @@ -67,6 +67,7 @@ "workbox-cli": "^3.4.1" }, "dependencies": { + "@azure/storage-blob": "^10.0.0-preview", "@material-ui/core": "^3.0.3", "@material-ui/icons": "^3.0.1", "apollo-cache-inmemory": "^1.2.9", @@ -80,6 +81,7 @@ "auth0-lock": "^11.9.0", "azure-storage": "^2.10.1", "babel-polyfill": "^6.26.0", + "blob-util": "^2.0.2", "classnames": "^2.2.6", "cross-fetch": "^2.2.2", "dotenv-webpack": "^1.5.7", diff --git a/client/src/graphql/teams/GetAzureSASMutation.js b/client/src/graphql/teams/GetAzureSASMutation.js new file mode 100644 index 000000000..abb9ffef3 --- /dev/null +++ b/client/src/graphql/teams/GetAzureSASMutation.js @@ -0,0 +1,10 @@ +/* eslint-disable no-unused-vars */ +import gql from 'graphql-tag' + +export const GET_AZURE_SAS = gql` + mutation getAzureSAS($teamSlug: String!) { + getAzureSAS(teamSlug: $teamSlug) + } +` + +export default GET_AZURE_SAS diff --git a/client/src/views/common/UploadImage.js b/client/src/views/common/UploadImage.js index f5b625c8f..e9662db08 100644 --- a/client/src/views/common/UploadImage.js +++ b/client/src/views/common/UploadImage.js @@ -1,9 +1,10 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' +import { Mutation } from 'react-apollo' import Dropzone from 'react-dropzone' -// import ReactCrop from 'react-image-crop' import { Cropper } from 'react-image-cropper' -// import azure from 'azure-storage' +import * as Azure from '@azure/storage-blob' +import { imgSrcToBlob } from 'blob-util' import { withStyles } from '@material-ui/core/styles' import Dialog from '@material-ui/core/Dialog' @@ -11,6 +12,8 @@ import DialogActions from '@material-ui/core/DialogActions' import DialogContent from '@material-ui/core/DialogContent' import Button from '@material-ui/core/Button' +import GET_AZURE_SAS from '../../graphql/teams/GetAzureSASMutation' + const styles = theme => ({ dropzoneContainer: { display: 'block', @@ -54,6 +57,8 @@ class UploadImage extends Component { this.getCroppedImg = this.getCroppedImg.bind(this) this.handleClickOpen = this.handleClickOpen.bind(this) this.handleClose = this.handleClose.bind(this) + this.handleSubmit = this.handleSubmit.bind(this) + this.saveAvatar = this.saveAvatar.bind(this) this.state = { open: false, @@ -86,7 +91,21 @@ class UploadImage extends Component { )} {this.state.cropped !== null && ( - Crop Preview + + {(getAzureSAS, { loading, error, data }) => { + console.log('getAzureSAS: ', error, data) + console.log('getAzureSAS keys: ', process.env.AZURE_STORAGE_URL, process.env.AZURE_SAS) + if (data !== undefined && data.getAzureSAS !== null) { + this.saveAvatar(data.getAzureSAS, team.slug) + } + return ( +
+ Crop Preview + +
+ ) + }} +
)} {this.state.src !== null && ( { - if (error) return (

{error}

) - return 'Success' - } - ) - xhr.send() + await uploadBrowserDataToBlockBlob(Aborter.None, file, blockBlobURL, { + blockSize: 4 * 1024 * 1024, // 4MB block size + parallelism: 20, // 20 concurrency + progress: ev => console.log(ev) + }); } */ }