From 3f21a6ba6fd52b3828dee5975f319304fb475d09 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 29 Mar 2021 15:00:40 +0100 Subject: [PATCH 01/65] Starting worker instance as part of the stack, some changes to how environment handled for worker. --- hosting/docker-compose.yaml | 2 +- packages/worker/package.json | 10 +- packages/worker/scripts/dev/manage.js | 42 ++ packages/worker/src/api/controllers/deploy.js | 2 +- packages/worker/src/environment.js | 18 +- packages/worker/src/index.js | 2 +- packages/worker/yarn.lock | 647 +++++++++++++++++- 7 files changed, 710 insertions(+), 13 deletions(-) create mode 100644 packages/worker/scripts/dev/manage.js diff --git a/hosting/docker-compose.yaml b/hosting/docker-compose.yaml index 8de5e9fcdd..7b5a7612a9 100644 --- a/hosting/docker-compose.yaml +++ b/hosting/docker-compose.yaml @@ -37,7 +37,7 @@ services: PORT: 4003 MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY} MINIO_SECRET_KEY: ${MINIO_SECRET_KEY} - RAW_MINIO_URL: http://minio-service:9000 + MINIO_URL: http://minio-service:9000 COUCH_DB_USERNAME: ${COUCH_DB_USER} COUCH_DB_PASSWORD: ${COUCH_DB_PASSWORD} COUCH_DB_URL: http://${COUCH_DB_USER}:${COUCH_DB_PASSWORD}@couchdb-service:5984 diff --git a/packages/worker/package.json b/packages/worker/package.json index 7d88654a88..43deb14a50 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,5 +1,5 @@ { - "name": "@budibase/deployment", + "name": "@budibase/worker", "email": "hi@budibase.com", "version": "0.8.9", "description": "Budibase Deployment Server", @@ -12,13 +12,16 @@ "budibase" ], "scripts": { - "run:docker": "node src/index.js" + "run:docker": "node src/index.js", + "dev:stack:init": "node ./scripts/dev/manage.js init", + "dev:builder": "npm run dev:stack:init && nodemon src/index.js" }, "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { "@koa/router": "^8.0.0", "aws-sdk": "^2.811.0", + "dotenv": "^8.2.0", "got": "^11.8.1", "joi": "^17.2.1", "koa": "^2.7.0", @@ -33,5 +36,8 @@ "pouchdb": "^7.2.2", "pouchdb-all-dbs": "^1.0.2", "server-destroy": "^1.0.1" + }, + "devDependencies": { + "nodemon": "^2.0.7" } } diff --git a/packages/worker/scripts/dev/manage.js b/packages/worker/scripts/dev/manage.js new file mode 100644 index 0000000000..b7e92f6d15 --- /dev/null +++ b/packages/worker/scripts/dev/manage.js @@ -0,0 +1,42 @@ +#!/usr/bin/env node +const path = require("path") +const fs = require("fs") + +async function init() { + const envFilePath = path.join(process.cwd(), ".env") + if (fs.existsSync(envFilePath)) { + return + } + const envFileJson = { + SELF_HOSTED: 1, + PORT: 4002, + MINIO_ACCESS_KEY: "budibase", + MINIO_SECRET_KEY: "budibase", + COUCH_DB_USER: "budibase", + COUCH_DB_PASSWORD: "budibase", + MINIO_URL: "http://localhost:10000/", + COUCH_DB_URL: "http://budibase:budibase@localhost:10000/db/", + } + let envFile = "" + Object.keys(envFileJson).forEach(key => { + envFile += `${key}=${envFileJson[key]}\n` + }) + fs.writeFileSync(envFilePath, envFile) +} + +// if more than init required use this to determine the command type +//const managementCommand = process.argv.slice(2)[0] + +// for now only one command +let command = init + +command() + .then(() => { + console.log("Done! 🎉") + }) + .catch(err => { + console.error( + "Something went wrong while managing budibase dev worker:", + err.message + ) + }) diff --git a/packages/worker/src/api/controllers/deploy.js b/packages/worker/src/api/controllers/deploy.js index 207be71c90..cbaf842083 100644 --- a/packages/worker/src/api/controllers/deploy.js +++ b/packages/worker/src/api/controllers/deploy.js @@ -43,7 +43,7 @@ async function getMinioSession() { // make sure the bucket exists const objClient = new AWS.S3({ - endpoint: env.RAW_MINIO_URL, + endpoint: env.MINIO_URL, region: REGION, s3ForcePathStyle: true, // needed with minio? params: { diff --git a/packages/worker/src/environment.js b/packages/worker/src/environment.js index 0cd7860869..b857dc6098 100644 --- a/packages/worker/src/environment.js +++ b/packages/worker/src/environment.js @@ -1,16 +1,28 @@ +function isDev() { + return process.env.NODE_ENV !== "production" +} + +let LOADED = false +if (!LOADED && isDev()) { + require("dotenv").config() + LOADED = true +} + module.exports = { SELF_HOSTED: process.env.SELF_HOSTED, PORT: process.env.PORT, MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY, MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY, - RAW_MINIO_URL: process.env.RAW_MINIO_URL, - MINIO_PORT: process.env.MINIO_PORT, + MINIO_URL: process.env.MINIO_URL, + COUCH_DB_URL: process.env.COUCH_DB_URL, + LOG_LEVEL: process.env.LOG_LEVEL, + /* TODO: to remove - once deployment removed */ SELF_HOST_KEY: process.env.SELF_HOST_KEY, COUCH_DB_USERNAME: process.env.COUCH_DB_USERNAME, COUCH_DB_PASSWORD: process.env.COUCH_DB_PASSWORD, - COUCH_DB_URL: process.env.COUCH_DB_URL, _set(key, value) { process.env[key] = value module.exports[key] = value }, + isDev, } diff --git a/packages/worker/src/index.js b/packages/worker/src/index.js index 2cc78cce2d..2426b39411 100644 --- a/packages/worker/src/index.js +++ b/packages/worker/src/index.js @@ -32,7 +32,7 @@ destroyable(server) server.on("close", () => console.log("Server Closed")) -module.exports = server.listen(env.PORT || 4002, async () => { +module.exports = server.listen(parseInt(env.PORT || 4002), async () => { console.log(`Worker running on ${JSON.stringify(server.address())}`) }) diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index d88e560173..70bea3b7ea 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -48,11 +48,23 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + "@sindresorhus/is@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" integrity sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ== +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + "@szmarczak/http-timer@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.5.tgz#bfbd50211e9dfa51ba07da58a14cdfd333205152" @@ -107,6 +119,11 @@ dependencies: "@types/node" "*" +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + abort-controller@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -159,6 +176,23 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +ansi-align@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" + integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + dependencies: + string-width "^3.0.0" + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -178,6 +212,14 @@ any-promise@^1.1.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + args@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/args/-/args-5.0.1.tgz#4bf298df90a4799a09521362c579278cc2fdd761" @@ -243,6 +285,25 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +boxen@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" + integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^5.3.1" + chalk "^3.0.0" + cli-boxes "^2.2.0" + string-width "^4.1.0" + term-size "^2.1.0" + type-fest "^0.8.1" + widest-line "^3.1.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -251,6 +312,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + buffer-from@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -291,6 +359,19 @@ cacheable-lookup@^5.0.3: resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + cacheable-request@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.1.tgz#062031c2856232782ed694a257fa35da93942a58" @@ -309,6 +390,11 @@ camelcase@5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + chalk@2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -318,6 +404,14 @@ chalk@2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -326,6 +420,31 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chokidar@^3.2.2: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +cli-boxes@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + clone-buffer@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -409,6 +528,18 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +configstore@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" + integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== + dependencies: + dot-prop "^5.2.0" + graceful-fs "^4.1.2" + make-dir "^3.0.0" + unique-string "^2.0.0" + write-file-atomic "^3.0.0" + xdg-basedir "^4.0.0" + content-disposition@~0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -441,12 +572,24 @@ crc@^3.4.4: dependencies: buffer "^5.1.0" +crypto-random-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" + integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== + dateformat@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@^3.1.0: +debug@^2.2.0: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.1.0, debug@^3.2.6: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -467,6 +610,13 @@ debug@~3.1.0: dependencies: ms "2.0.0" +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + decompress-response@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" @@ -479,6 +629,16 @@ deep-equal@~1.0.1: resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + defer-to-connect@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" @@ -525,16 +685,43 @@ detective@^4.3.1: acorn "^5.2.1" defined "^1.0.0" +dot-prop@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== + dependencies: + is-obj "^2.0.0" + +dotenv@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" + integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== + double-ended-queue@2.1.0-0: version "2.1.0-0" resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw= +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + encodeurl@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -589,6 +776,11 @@ es3ify@^0.2.2: jstransform "~11.0.0" through "~2.3.4" +escape-goat@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" + integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== + escape-html@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -673,6 +865,13 @@ fetch-cookie@0.10.1: dependencies: tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + flatstr@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" @@ -693,6 +892,18 @@ fresh@~0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -700,6 +911,13 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" +glob-parent@~5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob@^5.0.15: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" @@ -711,6 +929,13 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" +global-dirs@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d" + integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ== + dependencies: + ini "1.3.7" + got@^11.8.1: version "11.8.1" resolved "https://registry.yarnpkg.com/got/-/got-11.8.1.tgz#df04adfaf2e782babb3daabc79139feec2f7e85d" @@ -728,6 +953,23 @@ got@^11.8.1: p-cancelable "^2.0.0" responselike "^2.0.0" +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + graceful-fs@^4.1.2: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -743,6 +985,11 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-yarn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" + integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== + http-assert@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.1.tgz#c5f725d677aa7e873ef736199b89686cceb37878" @@ -813,6 +1060,11 @@ ieee754@^1.1.13, ieee754@^1.1.4: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + immediate@3.3.0, immediate@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" @@ -823,6 +1075,16 @@ immediate@~3.0.5: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + inflation@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/inflation/-/inflation-2.0.0.tgz#8b417e47c28f925a45133d914ca1fd389107f30f" @@ -846,6 +1108,16 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +ini@1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" + integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + inline-process-browser@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/inline-process-browser/-/inline-process-browser-1.0.0.tgz#46a61b153dd3c9b1624b1a00626edb4f7f414f22" @@ -854,16 +1126,80 @@ inline-process-browser@^1.0.0: falafel "^1.0.1" through2 "^0.6.5" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + is-class-hotfix@~0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz#a527d31fb23279281dde5f385c77b5de70a72435" integrity sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ== +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-generator-function@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" + integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== + dependencies: + global-dirs "^2.0.1" + is-path-inside "^3.0.1" + +is-npm@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" + integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-path-inside@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-type-of@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/is-type-of/-/is-type-of-1.2.1.tgz#e263ec3857aceb4f28c47130ec78db09a920f8c5" @@ -873,6 +1209,16 @@ is-type-of@^1.0.0: is-class-hotfix "~0.0.6" isstream "~0.1.2" +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-yarn-global@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" + integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -909,6 +1255,11 @@ joycon@^2.2.5: resolved "https://registry.yarnpkg.com/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" integrity sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ== +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + json-buffer@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" @@ -941,6 +1292,13 @@ keygrip@~1.1.0: dependencies: tsscmp "1.0.6" +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + keyv@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.3.tgz#4f3aa98de254803cafcd2896734108daa35e4254" @@ -1056,6 +1414,13 @@ koa@^2.7.0: type-is "^1.6.16" vary "^1.1.2" +latest-version@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + level-codec@9.0.2, level-codec@^9.0.0: version "9.0.2" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" @@ -1160,6 +1525,11 @@ lie@3.0.4: inline-process-browser "^1.0.0" unreachable-branch-transform "^0.3.0" +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + lowercase-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" @@ -1170,6 +1540,13 @@ ltgt@2.2.1, ltgt@^2.1.2: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -1197,7 +1574,7 @@ mime-types@^2.1.18, mime-types@~2.1.24: dependencies: mime-db "1.44.0" -mimic-response@^1.0.0: +mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== @@ -1207,14 +1584,14 @@ mimic-response@^3.1.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -"minimatch@2 || 3": +"minimatch@2 || 3", minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" -minimist@^1.2.5: +minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -1271,6 +1648,34 @@ node-gyp-build@~4.1.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" integrity sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ== +nodemon@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.7.tgz#6f030a0a0ebe3ea1ba2a38f71bf9bab4841ced32" + integrity sha512-XHzK69Awgnec9UzHr1kc8EomQh4sjTQ8oRf8TsGrSmHDx9/UmiGG9E/mM3BuTfNeFwdNBvrqQq/RHL0xIeyFOA== + dependencies: + chokidar "^3.2.2" + debug "^3.2.6" + ignore-by-default "^1.0.1" + minimatch "^3.0.4" + pstree.remy "^1.1.7" + semver "^5.7.1" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.3" + update-notifier "^4.1.0" + +nopt@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + dependencies: + abbrev "1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-url@^4.1.0: version "4.5.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" @@ -1305,11 +1710,26 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + p-cancelable@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + parseurl@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -1327,6 +1747,11 @@ path-to-regexp@1.x: dependencies: isarray "0.0.1" +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + pino-http@^5.0.1: version "5.3.0" resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-5.3.0.tgz#8ad9c296a60220b8d7067800a63c8716a622c661" @@ -1414,6 +1839,11 @@ pouchdb@^7.2.2: uuid "8.1.0" vuvuzela "1.0.3" +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + private@^0.1.6, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -1429,6 +1859,11 @@ psl@^1.1.33: resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +pstree.remy@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -1452,6 +1887,13 @@ punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +pupa@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" + integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== + dependencies: + escape-goat "^2.0.0" + q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -1487,6 +1929,16 @@ raw-body@^2.2.0: iconv-lite "0.4.24" unpipe "1.0.0" +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + readable-stream@1.1.14: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -1521,6 +1973,13 @@ readable-stream@~0.0.2: resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d" integrity sha1-8y124/uGM0SlSNeZIwBxc2ZbO40= +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + recast@^0.10.1: version "0.10.43" resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f" @@ -1541,6 +2000,20 @@ recast@^0.11.17: private "~0.1.5" source-map "~0.5.0" +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + resolve-alpn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c" @@ -1554,6 +2027,13 @@ resolve-path@^1.4.0: http-errors "~1.6.2" path-is-absolute "1.0.1" +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + responselike@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" @@ -1586,6 +2066,23 @@ sax@>=0.6.0: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +semver-diff@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" + integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== + dependencies: + semver "^6.3.0" + +semver@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + server-destroy@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" @@ -1606,6 +2103,11 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== +signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + sonic-boom@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.3.0.tgz#5c77c846ce6c395dddf2eb8e8e65f9cc576f2e76" @@ -1655,6 +2157,24 @@ statuses@^2.0.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.0.tgz#aa7b107e018eb33e08e8aee2e7337e762dda1028" integrity sha512-w9jNUUQdpuVoYqXxnyOakhckBbOxRaoYqJscyIBYCS5ixyCnO7nQn7zBZvP9zf5QOPZcz2DLUpE3KsNPbJBOFA== +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.0.0, string-width@^4.1.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" + integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -1667,12 +2187,31 @@ string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= +strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -supports-color@^5.3.0: +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -1686,6 +2225,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +term-size@^2.1.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" + integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== + through2@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" @@ -1712,11 +2256,30 @@ tiny-queue@^0.2.0: resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046" integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY= +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +touch@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== + dependencies: + nopt "~1.0.10" + "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" @@ -1731,6 +2294,11 @@ tsscmp@1.0.6: resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@^1.6.14, type-is@^1.6.16: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -1739,6 +2307,27 @@ type-is@^1.6.14, type-is@^1.6.16: media-typer "0.3.0" mime-types "~2.1.24" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +undefsafe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae" + integrity sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== + dependencies: + debug "^2.2.0" + +unique-string@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" + integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== + dependencies: + crypto-random-string "^2.0.0" + universalify@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -1758,11 +2347,37 @@ unreachable-branch-transform@^0.3.0: recast "^0.10.1" through2 "^0.6.2" +update-notifier@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" + integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== + dependencies: + boxen "^4.2.0" + chalk "^3.0.0" + configstore "^5.0.1" + has-yarn "^2.1.0" + import-lazy "^2.1.0" + is-ci "^2.0.0" + is-installed-globally "^0.3.1" + is-npm "^4.0.0" + is-yarn-global "^0.3.0" + latest-version "^5.0.0" + pupa "^2.0.1" + semver-diff "^3.1.1" + xdg-basedir "^4.0.0" + urijs@^1.19.2: version "1.19.2" resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.2.tgz#f9be09f00c4c5134b7cb3cf475c1dd394526265a" integrity sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w== +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + url@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" @@ -1801,11 +2416,28 @@ vuvuzela@1.0.3: resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b" integrity sha1-O+FF5YJxxzylUnndhR8SpoIRSws= +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + write-stream@~0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/write-stream/-/write-stream-0.4.3.tgz#83cc8c0347d0af6057a93862b4e3ae01de5c81c1" @@ -1813,6 +2445,11 @@ write-stream@~0.4.3: dependencies: readable-stream "~0.0.2" +xdg-basedir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" + integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== + xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" From 76f330fc3624816312ef9c02a19fbbed444ff8ef Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 29 Mar 2021 15:06:00 +0100 Subject: [PATCH 02/65] Replacing deprecated symbols. --- packages/server/src/api/index.js | 4 ++-- packages/worker/src/api/index.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js index aeceb65039..ef8deb36cc 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.js @@ -13,10 +13,10 @@ router compress({ threshold: 2048, gzip: { - flush: zlib.Z_SYNC_FLUSH, + flush: zlib.constants.Z_SYNC_FLUSH, }, deflate: { - flush: zlib.Z_SYNC_FLUSH, + flush: zlib.constants.Z_SYNC_FLUSH, }, br: false, }) diff --git a/packages/worker/src/api/index.js b/packages/worker/src/api/index.js index 8b77669c95..0568d79a68 100644 --- a/packages/worker/src/api/index.js +++ b/packages/worker/src/api/index.js @@ -10,10 +10,10 @@ router compress({ threshold: 2048, gzip: { - flush: zlib.Z_SYNC_FLUSH, + flush: zlib.constants.Z_SYNC_FLUSH, }, deflate: { - flush: zlib.Z_SYNC_FLUSH, + flush: zlib.constants.Z_SYNC_FLUSH, }, br: false, }) From 942312836991554775a1c9843dbd35c54a4c4ab2 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 29 Mar 2021 17:31:41 +0100 Subject: [PATCH 03/65] Updating worker package with the various parts of server that needed moved over. --- packages/worker/package.json | 3 +- .../worker/src/api/controllers/admin/index.js | 79 ++++++++++++++++ .../worker/src/api/controllers/admin/utils.js | 13 +++ packages/worker/src/api/controllers/deploy.js | 92 ------------------- packages/worker/src/api/routes/admin/index.js | 12 +++ packages/worker/src/api/routes/deploy.js | 9 -- packages/worker/src/api/routes/index.js | 4 +- packages/worker/src/constants/index.js | 4 + packages/worker/src/db/utils.js | 32 +++++++ packages/worker/src/environment.js | 2 + packages/worker/src/middleware/authorized.js | 7 ++ packages/worker/yarn.lock | 7 +- 12 files changed, 159 insertions(+), 105 deletions(-) create mode 100644 packages/worker/src/api/controllers/admin/index.js create mode 100644 packages/worker/src/api/controllers/admin/utils.js delete mode 100644 packages/worker/src/api/controllers/deploy.js create mode 100644 packages/worker/src/api/routes/admin/index.js delete mode 100644 packages/worker/src/api/routes/deploy.js create mode 100644 packages/worker/src/constants/index.js create mode 100644 packages/worker/src/db/utils.js create mode 100644 packages/worker/src/middleware/authorized.js diff --git a/packages/worker/package.json b/packages/worker/package.json index 43deb14a50..73b417c580 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -21,6 +21,7 @@ "dependencies": { "@koa/router": "^8.0.0", "aws-sdk": "^2.811.0", + "bcryptjs": "^2.4.3", "dotenv": "^8.2.0", "got": "^11.8.1", "joi": "^17.2.1", @@ -33,7 +34,7 @@ "koa-static": "^5.0.0", "node-fetch": "^2.6.1", "pino-pretty": "^4.0.0", - "pouchdb": "^7.2.2", + "pouchdb": "^7.2.1", "pouchdb-all-dbs": "^1.0.2", "server-destroy": "^1.0.1" }, diff --git a/packages/worker/src/api/controllers/admin/index.js b/packages/worker/src/api/controllers/admin/index.js new file mode 100644 index 0000000000..f94cf39fc4 --- /dev/null +++ b/packages/worker/src/api/controllers/admin/index.js @@ -0,0 +1,79 @@ +const CouchDB = require("../../../db") +const { StaticDatabases, generateUserID, getUserParams } = require("../../../db/utils") +const { hash } = require("./utils") +const { UserStatus } = require("../../../constants") + +const USER_DB = StaticDatabases.USER.name + +exports.userSave = async ctx => { + const db = new CouchDB(USER_DB) + const { email, password, _id } = ctx.request.body + const hashedPassword = password ? await hash(password) : null + let user = { + ...ctx.request.body, + _id: generateUserID(email), + password: hashedPassword, + }, dbUser + // in-case user existed already + if (_id) { + dbUser = await db.get(_id) + } + // add the active status to a user if its not provided + if (user.status == null) { + user.status = UserStatus.ACTIVE + } + try { + const response = await db.post({ + password: hashedPassword || dbUser.password, + ...user, + }) + ctx.body = { + _id: response.id, + _rev: response.rev, + email, + } + } catch (err) { + if (err.status === 409) { + ctx.throw(400, "User exists already") + } else { + ctx.throw(err.status, err) + } + } +} + +exports.userDelete = async ctx => { + const db = new CouchDB(USER_DB) + await db.destroy(generateUserID(ctx.params.email)) + ctx.body = { + message: `User ${ctx.params.email} deleted.`, + } +} + +// called internally by app server user fetch +exports.userFetch = async ctx => { + const db = new CouchDB(USER_DB) + const users = ( + await db.allDocs( + getUserParams(null, { + include_docs: true, + }) + ) + ).rows.map(row => row.doc) + // user hashed password shouldn't ever be returned + for (let user of users) { + if (user) { + delete user.password + } + } + ctx.body = users +} + +// called internally by app server user find +exports.userFind = async ctx => { + const db = new CouchDB(USER_DB) + const user = await db.get(generateUserID(ctx.params.email)) + if (user) { + delete user.password + } + ctx.body = user +} diff --git a/packages/worker/src/api/controllers/admin/utils.js b/packages/worker/src/api/controllers/admin/utils.js new file mode 100644 index 0000000000..4af0a52c46 --- /dev/null +++ b/packages/worker/src/api/controllers/admin/utils.js @@ -0,0 +1,13 @@ +const bcrypt = require("bcryptjs") +const env = require("../environment") + +const SALT_ROUNDS = env.SALT_ROUNDS || 10 + +exports.hash = async data => { + const salt = await bcrypt.genSalt(SALT_ROUNDS) + return bcrypt.hash(data, salt) +} + +exports.compare = async (data, encrypted) => { + return bcrypt.compare(data, encrypted) +} \ No newline at end of file diff --git a/packages/worker/src/api/controllers/deploy.js b/packages/worker/src/api/controllers/deploy.js deleted file mode 100644 index cbaf842083..0000000000 --- a/packages/worker/src/api/controllers/deploy.js +++ /dev/null @@ -1,92 +0,0 @@ -const env = require("../../environment") -const got = require("got") -const AWS = require("aws-sdk") - -const APP_BUCKET = "app-assets" -// this doesn't matter in self host -const REGION = "eu-west-1" -const PUBLIC_READ_POLICY = { - Version: "2012-10-17", - Statement: [ - { - Effect: "Allow", - Principal: { - AWS: ["*"], - }, - Action: "s3:GetObject", - Resource: [`arn:aws:s3:::${APP_BUCKET}/*`], - }, - ], -} - -async function getCouchSession() { - // fetch session token for the api user - const session = await got.post(`${env.COUCH_DB_URL}/_session`, { - responseType: "json", - credentials: "include", - json: { - username: env.COUCH_DB_USERNAME, - password: env.COUCH_DB_PASSWORD, - }, - }) - - const cookie = session.headers["set-cookie"][0] - // Get the session cookie value only - return cookie.split(";")[0] -} - -async function getMinioSession() { - AWS.config.update({ - accessKeyId: env.MINIO_ACCESS_KEY, - secretAccessKey: env.MINIO_SECRET_KEY, - }) - - // make sure the bucket exists - const objClient = new AWS.S3({ - endpoint: env.MINIO_URL, - region: REGION, - s3ForcePathStyle: true, // needed with minio? - params: { - Bucket: APP_BUCKET, - }, - }) - // make sure the bucket exists - try { - await objClient - .headBucket({ - Bucket: APP_BUCKET, - }) - .promise() - } catch (err) { - // bucket doesn't exist create it - if (err.statusCode === 404) { - await objClient - .createBucket({ - Bucket: APP_BUCKET, - }) - .promise() - } else { - throw err - } - } - // always make sure policy is correct - await objClient - .putBucketPolicy({ - Bucket: APP_BUCKET, - Policy: JSON.stringify(PUBLIC_READ_POLICY), - }) - .promise() - // Ideally want to send back some pre-signed URLs for files that are to be uploaded - return { - accessKeyId: env.MINIO_ACCESS_KEY, - secretAccessKey: env.MINIO_SECRET_KEY, - } -} - -exports.deploy = async ctx => { - ctx.body = { - couchDbSession: await getCouchSession(), - bucket: APP_BUCKET, - objectStoreSession: await getMinioSession(), - } -} diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js new file mode 100644 index 0000000000..9d85927900 --- /dev/null +++ b/packages/worker/src/api/routes/admin/index.js @@ -0,0 +1,12 @@ +const Router = require("@koa/router") +const controller = require("../../controllers/admin") +const authorized = require("../../../middleware/authorized") + +const router = Router() + +router.post("/api/admin/users", authorized, controller.userSave) + .delete("/api/admin/users/:email", authorized, controller.userDelete) + .get("/api/admin/users", authorized, controller.userFetch) + .get("/api/admin/users/:email", authorized, controller.userFind) + +module.exports = router diff --git a/packages/worker/src/api/routes/deploy.js b/packages/worker/src/api/routes/deploy.js deleted file mode 100644 index 97c5439752..0000000000 --- a/packages/worker/src/api/routes/deploy.js +++ /dev/null @@ -1,9 +0,0 @@ -const Router = require("@koa/router") -const controller = require("../controllers/deploy") -const checkKey = require("../../middleware/check-key") - -const router = Router() - -router.post("/api/deploy", checkKey, controller.deploy) - -module.exports = router diff --git a/packages/worker/src/api/routes/index.js b/packages/worker/src/api/routes/index.js index 7ad619c2b7..076710b21b 100644 --- a/packages/worker/src/api/routes/index.js +++ b/packages/worker/src/api/routes/index.js @@ -1,4 +1,4 @@ -const deployRoutes = require("./deploy") +const adminRoutes = require("./admin") const appRoutes = require("./app") -exports.routes = [deployRoutes, appRoutes] +exports.routes = [adminRoutes, appRoutes] diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js new file mode 100644 index 0000000000..77a6aedca0 --- /dev/null +++ b/packages/worker/src/constants/index.js @@ -0,0 +1,4 @@ +exports.UserStatus = { + ACTIVE: "active", + INACTIVE: "inactive", +} diff --git a/packages/worker/src/db/utils.js b/packages/worker/src/db/utils.js new file mode 100644 index 0000000000..aa274eff3b --- /dev/null +++ b/packages/worker/src/db/utils.js @@ -0,0 +1,32 @@ +exports.StaticDatabases = { + USER: { + name: "user-db", + } +} + +const DocumentTypes = { + USER: "us" +} + +const UNICODE_MAX = "\ufff0" +const SEPARATOR = "_" + +/** + * Generates a new user ID based on the passed in email. + * @param {string} email The email which the ID is going to be built up of. + * @returns {string} The new user ID which the user doc can be stored under. + */ +exports.generateUserID = email => { + return `${DocumentTypes.USER}${SEPARATOR}${email}` +} + +/** + * Gets parameters for retrieving users, this is a utility function for the getDocParams function. + */ +exports.getUserParams = (email = "", otherProps = {}) => { + return { + ...otherProps, + startkey: `${DocumentTypes.USER}${SEPARATOR}${email}`, + endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`, + } +} \ No newline at end of file diff --git a/packages/worker/src/environment.js b/packages/worker/src/environment.js index b857dc6098..bf399fade5 100644 --- a/packages/worker/src/environment.js +++ b/packages/worker/src/environment.js @@ -16,6 +16,8 @@ module.exports = { MINIO_URL: process.env.MINIO_URL, COUCH_DB_URL: process.env.COUCH_DB_URL, LOG_LEVEL: process.env.LOG_LEVEL, + JWT_SECRET: process.env.JWT_SECRET, + SALT_ROUNDS: process.env.SALT_ROUNDS, /* TODO: to remove - once deployment removed */ SELF_HOST_KEY: process.env.SELF_HOST_KEY, COUCH_DB_USERNAME: process.env.COUCH_DB_USERNAME, diff --git a/packages/worker/src/middleware/authorized.js b/packages/worker/src/middleware/authorized.js new file mode 100644 index 0000000000..86a5ab27db --- /dev/null +++ b/packages/worker/src/middleware/authorized.js @@ -0,0 +1,7 @@ +/** + * Check the user token, used when creating admin resources, like for example + * a global user record. + */ +module.exports = async (ctx, next) => { + next() +} diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 70bea3b7ea..d969c67ceb 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -285,6 +285,11 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bcryptjs@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" + integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -1813,7 +1818,7 @@ pouchdb-promise@5.4.3: dependencies: lie "3.0.4" -pouchdb@^7.2.2: +pouchdb@^7.2.1: version "7.2.2" resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-7.2.2.tgz#fcae82862db527e4cf7576ed8549d1384961f364" integrity sha512-5gf5nw5XH/2H/DJj8b0YkvG9fhA/4Jt6kL0Y8QjtztVjb1y4J19Rg4rG+fUbXu96gsUrlyIvZ3XfM0b4mogGmw== From ae8dd1ec786f959d8f8b6784f8801a7590017c1c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 29 Mar 2021 17:32:05 +0100 Subject: [PATCH 04/65] Removing use of the , replacing to ctx.appId to make it clear appId not part of the auth. --- packages/server/src/api/controllers/auth.js | 2 +- .../server/src/api/controllers/automation.js | 40 ++++++++++++------- .../server/src/api/controllers/datasource.js | 8 ++-- .../src/api/controllers/deploy/index.js | 6 +-- packages/server/src/api/controllers/layout.js | 4 +- packages/server/src/api/controllers/query.js | 12 +++--- packages/server/src/api/controllers/role.js | 8 ++-- packages/server/src/api/controllers/row.js | 20 +++++----- packages/server/src/api/controllers/screen.js | 6 +-- .../src/api/controllers/search/index.js | 2 +- .../src/api/controllers/static/index.js | 6 +-- .../server/src/api/controllers/table/index.js | 8 ++-- .../server/src/api/controllers/table/utils.js | 7 ++-- packages/server/src/api/controllers/user.js | 13 +++--- .../server/src/api/controllers/view/index.js | 8 ++-- .../server/src/api/controllers/webhook.js | 8 ++-- .../server/src/api/routes/tests/misc.spec.js | 10 +++-- .../server/src/middleware/authenticated.js | 4 +- packages/server/src/middleware/usageQuota.js | 2 +- packages/server/src/utilities/bcrypt.js | 2 + 20 files changed, 96 insertions(+), 80 deletions(-) diff --git a/packages/server/src/api/controllers/auth.js b/packages/server/src/api/controllers/auth.js index fc486bcb50..fab46bd05e 100644 --- a/packages/server/src/api/controllers/auth.js +++ b/packages/server/src/api/controllers/auth.js @@ -48,7 +48,7 @@ exports.authenticate = async ctx => { // if in prod add the user api key, unless self hosted /* istanbul ignore next */ if (env.isProd() && !env.SELF_HOSTED) { - const { apiKey } = await getAPIKey(ctx.user.appId) + const { apiKey } = await getAPIKey(ctx.appId) payload.apiKey = apiKey } diff --git a/packages/server/src/api/controllers/automation.js b/packages/server/src/api/controllers/automation.js index df17371f92..d3ed836bc9 100644 --- a/packages/server/src/api/controllers/automation.js +++ b/packages/server/src/api/controllers/automation.js @@ -34,13 +34,14 @@ function cleanAutomationInputs(automation) { /** * This function handles checking if any webhooks need to be created or deleted for automations. + * @param {string} appId The ID of the app in which we are checking for webhooks * @param {object} user The user object, including all auth info * @param {object|undefined} oldAuto The old automation object if updating/deleting * @param {object|undefined} newAuto The new automation object if creating/updating * @returns {Promise} After this is complete the new automation object may have been updated and should be * written to DB (this does not write to DB as it would be wasteful to repeat). */ -async function checkForWebhooks({ user, oldAuto, newAuto }) { +async function checkForWebhooks({ appId, user, oldAuto, newAuto }) { const oldTrigger = oldAuto ? oldAuto.definition.trigger : null const newTrigger = newAuto ? newAuto.definition.trigger : null function isWebhookTrigger(auto) { @@ -56,7 +57,7 @@ async function checkForWebhooks({ user, oldAuto, newAuto }) { !isWebhookTrigger(newAuto) && oldTrigger.webhookId ) { - let db = new CouchDB(user.appId) + let db = new CouchDB(appId) // need to get the webhook to get the rev const webhook = await db.get(oldTrigger.webhookId) const ctx = { @@ -86,17 +87,17 @@ async function checkForWebhooks({ user, oldAuto, newAuto }) { const id = ctx.body.webhook._id newTrigger.webhookId = id newTrigger.inputs = { - schemaUrl: `api/webhooks/schema/${user.appId}/${id}`, - triggerUrl: `api/webhooks/trigger/${user.appId}/${id}`, + schemaUrl: `api/webhooks/schema/${appId}/${id}`, + triggerUrl: `api/webhooks/trigger/${appId}/${id}`, } } return newAuto } exports.create = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) let automation = ctx.request.body - automation.appId = ctx.user.appId + automation.appId = ctx.appId // call through to update if already exists if (automation._id && automation._rev) { @@ -107,7 +108,11 @@ exports.create = async function(ctx) { automation.type = "automation" automation = cleanAutomationInputs(automation) - automation = await checkForWebhooks({ user: ctx.user, newAuto: automation }) + automation = await checkForWebhooks({ + appId: ctx.appId, + user: ctx.user, + newAuto: automation, + }) const response = await db.put(automation) automation._rev = response.rev @@ -122,12 +127,13 @@ exports.create = async function(ctx) { } exports.update = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) let automation = ctx.request.body - automation.appId = ctx.user.appId + automation.appId = ctx.appId const oldAutomation = await db.get(automation._id) automation = cleanAutomationInputs(automation) automation = await checkForWebhooks({ + appId: ctx.appId, user: ctx.user, oldAuto: oldAutomation, newAuto: automation, @@ -147,7 +153,7 @@ exports.update = async function(ctx) { } exports.fetch = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const response = await db.allDocs( getAutomationParams(null, { include_docs: true, @@ -157,14 +163,18 @@ exports.fetch = async function(ctx) { } exports.find = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) ctx.body = await db.get(ctx.params.id) } exports.destroy = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const oldAutomation = await db.get(ctx.params.id) - await checkForWebhooks({ user: ctx.user, oldAuto: oldAutomation }) + await checkForWebhooks({ + appId: ctx.appId, + user: ctx.user, + oldAuto: oldAutomation, + }) ctx.body = await db.remove(ctx.params.id, ctx.params.rev) } @@ -195,11 +205,11 @@ module.exports.getDefinitionList = async function(ctx) { *********************/ exports.trigger = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) let automation = await db.get(ctx.params.id) await triggers.externalTrigger(automation, { ...ctx.request.body, - appId: ctx.user.appId, + appId: ctx.appId, }) ctx.status = 200 ctx.body = { diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 678c56a14c..b5a207dbbe 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -6,7 +6,7 @@ const { } = require("../../db/utils") exports.fetch = async function(ctx) { - const database = new CouchDB(ctx.user.appId) + const database = new CouchDB(ctx.appId) ctx.body = ( await database.allDocs( getDatasourceParams(null, { @@ -17,7 +17,7 @@ exports.fetch = async function(ctx) { } exports.save = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const datasource = { _id: generateDatasourceID(), @@ -34,7 +34,7 @@ exports.save = async function(ctx) { } exports.destroy = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) // Delete all queries for the datasource const rows = await db.allDocs(getQueryParams(ctx.params.datasourceId, null)) @@ -48,6 +48,6 @@ exports.destroy = async function(ctx) { } exports.find = async function(ctx) { - const database = new CouchDB(ctx.user.appId) + const database = new CouchDB(ctx.appId) ctx.body = await database.get(ctx.params.datasourceId) } diff --git a/packages/server/src/api/controllers/deploy/index.js b/packages/server/src/api/controllers/deploy/index.js index 026ce5c85b..490fb3c72e 100644 --- a/packages/server/src/api/controllers/deploy/index.js +++ b/packages/server/src/api/controllers/deploy/index.js @@ -93,7 +93,7 @@ async function deployApp(deployment) { exports.fetchDeployments = async function(ctx) { try { - const db = new PouchDB(ctx.user.appId) + const db = new PouchDB(ctx.appId) const deploymentDoc = await db.get("_local/deployments") const { updated, deployments } = await checkAllDeployments( deploymentDoc, @@ -110,7 +110,7 @@ exports.fetchDeployments = async function(ctx) { exports.deploymentProgress = async function(ctx) { try { - const db = new PouchDB(ctx.user.appId) + const db = new PouchDB(ctx.appId) const deploymentDoc = await db.get("_local/deployments") ctx.body = deploymentDoc[ctx.params.deploymentId] } catch (err) { @@ -128,7 +128,7 @@ exports.deployApp = async function(ctx) { hostingInfo.type === HostingTypes.CLOUD ? require("./awsDeploy") : require("./selfDeploy") - let deployment = new Deployment(ctx.user.appId) + let deployment = new Deployment(ctx.appId) deployment.setStatus(DeploymentStatus.PENDING) deployment = await storeLocalDeploymentHistory(deployment) diff --git a/packages/server/src/api/controllers/layout.js b/packages/server/src/api/controllers/layout.js index f270e95bec..86c324d178 100644 --- a/packages/server/src/api/controllers/layout.js +++ b/packages/server/src/api/controllers/layout.js @@ -3,7 +3,7 @@ const CouchDB = require("../../db") const { generateLayoutID, getScreenParams } = require("../../db/utils") exports.save = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) let layout = ctx.request.body if (!layout.props) { @@ -22,7 +22,7 @@ exports.save = async function(ctx) { } exports.destroy = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const layoutId = ctx.params.layoutId, layoutRev = ctx.params.layoutRev diff --git a/packages/server/src/api/controllers/query.js b/packages/server/src/api/controllers/query.js index b9b7c85427..ddf88e925f 100644 --- a/packages/server/src/api/controllers/query.js +++ b/packages/server/src/api/controllers/query.js @@ -28,7 +28,7 @@ function formatResponse(resp) { } exports.fetch = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const body = await db.allDocs( getQueryParams(null, { @@ -39,7 +39,7 @@ exports.fetch = async function(ctx) { } exports.save = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const query = ctx.request.body if (!query._id) { @@ -90,7 +90,7 @@ async function enrichQueryFields(fields, parameters) { } exports.find = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const query = enrichQueries(await db.get(ctx.params.queryId)) // remove properties that could be dangerous in real app if (env.isProd()) { @@ -102,7 +102,7 @@ exports.find = async function(ctx) { } exports.preview = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const datasource = await db.get(ctx.request.body.datasourceId) @@ -130,7 +130,7 @@ exports.preview = async function(ctx) { } exports.execute = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const query = await db.get(ctx.params.queryId) const datasource = await db.get(query.datasourceId) @@ -153,7 +153,7 @@ exports.execute = async function(ctx) { } exports.destroy = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) await db.remove(ctx.params.queryId, ctx.params.revId) ctx.message = `Query deleted.` ctx.status = 200 diff --git a/packages/server/src/api/controllers/role.js b/packages/server/src/api/controllers/role.js index 2c29d1030e..11f81c1219 100644 --- a/packages/server/src/api/controllers/role.js +++ b/packages/server/src/api/controllers/role.js @@ -51,7 +51,7 @@ async function updateRolesOnUserTable(db, roleId, updateOption) { } exports.fetch = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const body = await db.allDocs( getRoleParams(null, { include_docs: true, @@ -79,11 +79,11 @@ exports.fetch = async function(ctx) { } exports.find = async function(ctx) { - ctx.body = await getRole(ctx.user.appId, ctx.params.roleId) + ctx.body = await getRole(ctx.appId, ctx.params.roleId) } exports.save = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) let { _id, name, inherits, permissionId } = ctx.request.body if (!_id) { _id = generateRoleID() @@ -104,7 +104,7 @@ exports.save = async function(ctx) { } exports.destroy = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const roleId = ctx.params.roleId if (isBuiltin(roleId)) { ctx.throw(400, "Cannot delete builtin role.") diff --git a/packages/server/src/api/controllers/row.js b/packages/server/src/api/controllers/row.js index 7540cc1894..fe293e9318 100644 --- a/packages/server/src/api/controllers/row.js +++ b/packages/server/src/api/controllers/row.js @@ -60,7 +60,7 @@ async function findRow(db, appId, tableId, rowId) { } exports.patch = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) let dbRow = await db.get(ctx.params.rowId) let dbTable = await db.get(dbRow.tableId) @@ -121,7 +121,7 @@ exports.patch = async function(ctx) { } exports.save = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) let inputs = ctx.request.body inputs.tableId = ctx.params.tableId @@ -197,7 +197,7 @@ exports.save = async function(ctx) { } exports.fetchView = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const viewName = ctx.params.viewName // if this is a table view being looked for just transfer to that @@ -256,7 +256,7 @@ exports.fetchView = async function(ctx) { } exports.search = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) const { query, @@ -303,7 +303,7 @@ exports.search = async function(ctx) { } exports.fetchTableRows = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) // special case for users, fetch through the user controller @@ -324,7 +324,7 @@ exports.fetchTableRows = async function(ctx) { } exports.find = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) try { const table = await db.get(ctx.params.tableId) @@ -336,7 +336,7 @@ exports.find = async function(ctx) { } exports.destroy = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) const row = await db.get(ctx.params.rowId) if (row.tableId !== ctx.params.tableId) { @@ -358,7 +358,7 @@ exports.destroy = async function(ctx) { exports.validate = async function(ctx) { const errors = await validate({ - appId: ctx.user.appId, + appId: ctx.appId, tableId: ctx.params.tableId, row: ctx.request.body, }) @@ -388,7 +388,7 @@ async function validate({ appId, tableId, row, table }) { } exports.fetchEnrichedRow = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) const tableId = ctx.params.tableId const rowId = ctx.params.rowId @@ -433,7 +433,7 @@ exports.fetchEnrichedRow = async function(ctx) { } async function bulkDelete(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const { rows } = ctx.request.body const db = new CouchDB(appId) diff --git a/packages/server/src/api/controllers/screen.js b/packages/server/src/api/controllers/screen.js index 8f9baa8172..6095d00c95 100644 --- a/packages/server/src/api/controllers/screen.js +++ b/packages/server/src/api/controllers/screen.js @@ -3,7 +3,7 @@ const { getScreenParams, generateScreenID } = require("../../db/utils") const { AccessController } = require("../../utilities/security/roles") exports.fetch = async ctx => { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) const screens = ( @@ -21,7 +21,7 @@ exports.fetch = async ctx => { } exports.save = async ctx => { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) let screen = ctx.request.body @@ -39,7 +39,7 @@ exports.save = async ctx => { } exports.destroy = async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) await db.remove(ctx.params.screenId, ctx.params.screenRev) ctx.body = { message: "Screen deleted successfully", diff --git a/packages/server/src/api/controllers/search/index.js b/packages/server/src/api/controllers/search/index.js index 1810f07198..be431b62a7 100644 --- a/packages/server/src/api/controllers/search/index.js +++ b/packages/server/src/api/controllers/search/index.js @@ -2,7 +2,7 @@ const { QueryBuilder, buildSearchUrl, search } = require("./utils") exports.rowSearch = async ctx => { // this can't be done through pouch, have to reach for trusty node-fetch - const appId = ctx.user.appId + const appId = ctx.appId const bookmark = ctx.params.bookmark let url if (ctx.params.query) { diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js index 7caf6d0f7f..afb1d908ae 100644 --- a/packages/server/src/api/controllers/static/index.js +++ b/packages/server/src/api/controllers/static/index.js @@ -84,7 +84,7 @@ exports.uploadFile = async function(ctx) { return prepareUpload({ file, - s3Key: `assets/${ctx.user.appId}/attachments/${processedFileName}`, + s3Key: `assets/${ctx.appId}/attachments/${processedFileName}`, bucket: "prod-budi-app-assets", }) }) @@ -120,7 +120,7 @@ exports.serveApp = async function(ctx) { exports.serveAttachment = async function(ctx) { await returnObjectStoreFile( ctx, - join(ctx.user.appId, "attachments", ctx.file) + join(ctx.appId, "attachments", ctx.file) ) } @@ -128,7 +128,7 @@ exports.serveAppAsset = async function(ctx) { if (env.isDev() || env.isTest()) { return send(ctx, ctx.file, { root: budibaseTempDir() }) } - await returnObjectStoreFile(ctx, join(ctx.user.appId, "public", ctx.file)) + await returnObjectStoreFile(ctx, join(ctx.appId, "public", ctx.file)) } exports.serveComponentLibrary = async function(ctx) { diff --git a/packages/server/src/api/controllers/table/index.js b/packages/server/src/api/controllers/table/index.js index 4cb1d16146..995ba8f72c 100644 --- a/packages/server/src/api/controllers/table/index.js +++ b/packages/server/src/api/controllers/table/index.js @@ -10,7 +10,7 @@ const { FieldTypes } = require("../../../constants") const { TableSaveFunctions } = require("./utils") exports.fetch = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const body = await db.allDocs( getTableParams(null, { include_docs: true, @@ -20,12 +20,12 @@ exports.fetch = async function(ctx) { } exports.find = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) ctx.body = await db.get(ctx.params.id) } exports.save = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) const { dataImport, ...rest } = ctx.request.body let tableToSave = { @@ -127,7 +127,7 @@ exports.save = async function(ctx) { } exports.destroy = async function(ctx) { - const appId = ctx.user.appId + const appId = ctx.appId const db = new CouchDB(appId) const tableToDelete = await db.get(ctx.params.tableId) diff --git a/packages/server/src/api/controllers/table/utils.js b/packages/server/src/api/controllers/table/utils.js index 66b3651ccf..0302ca18a3 100644 --- a/packages/server/src/api/controllers/table/utils.js +++ b/packages/server/src/api/controllers/table/utils.js @@ -57,8 +57,8 @@ exports.makeSureTableUpToDate = (table, tableToSave) => { return tableToSave } -exports.handleDataImport = async (user, table, dataImport) => { - const db = new CouchDB(user.appId) +exports.handleDataImport = async (appId, user, table, dataImport) => { + const db = new CouchDB(appId) if (dataImport && dataImport.csvString) { // Populate the table with rows imported from CSV in a bulk update const data = await csvParser.transform(dataImport) @@ -152,7 +152,7 @@ class TableSaveFunctions { this.db = db this.ctx = ctx if (this.ctx && this.ctx.user) { - this.appId = this.ctx.user.appId + this.appId = this.ctx.appId } this.oldTable = oldTable this.dataImport = dataImport @@ -184,6 +184,7 @@ class TableSaveFunctions { async after(table) { table = await exports.handleSearchIndexes(this.appId, table) table = await exports.handleDataImport( + this.appId, this.ctx.user, table, this.dataImport diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index 3dd28284be..d9a4af9719 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -5,7 +5,7 @@ const { getRole } = require("../../utilities/security/roles") const { UserStatus } = require("../../constants") exports.fetch = async function(ctx) { - const database = new CouchDB(ctx.user.appId) + const database = new CouchDB(ctx.appId) const users = ( await database.allDocs( getUserParams(null, { @@ -20,15 +20,16 @@ exports.fetch = async function(ctx) { ctx.body = users } +// TODO: need to replace this with something that purely manages metadata exports.create = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const { email, password, roleId } = ctx.request.body if (!email || !password) { ctx.throw(400, "email and Password Required.") } - const role = await getRole(ctx.user.appId, roleId) + const role = await getRole(ctx.appId, roleId) if (!role) ctx.throw(400, "Invalid Role") @@ -67,7 +68,7 @@ exports.create = async function(ctx) { } exports.update = async function(ctx) { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const user = ctx.request.body let dbUser if (user.email && !user._id) { @@ -94,7 +95,7 @@ exports.update = async function(ctx) { } exports.destroy = async function(ctx) { - const database = new CouchDB(ctx.user.appId) + const database = new CouchDB(ctx.appId) await database.destroy(generateUserID(ctx.params.email)) ctx.body = { message: `User ${ctx.params.email} deleted.`, @@ -103,7 +104,7 @@ exports.destroy = async function(ctx) { } exports.find = async function(ctx) { - const database = new CouchDB(ctx.user.appId) + const database = new CouchDB(ctx.appId) let lookup = ctx.params.email ? generateUserID(ctx.params.email) : ctx.params.userId diff --git a/packages/server/src/api/controllers/view/index.js b/packages/server/src/api/controllers/view/index.js index 0f6f008a1b..3d0f236fce 100644 --- a/packages/server/src/api/controllers/view/index.js +++ b/packages/server/src/api/controllers/view/index.js @@ -7,7 +7,7 @@ const { ViewNames } = require("../../../db/utils") const controller = { fetch: async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const designDoc = await db.get("_design/database") const response = [] @@ -25,7 +25,7 @@ const controller = { ctx.body = response }, save: async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const { originalName, ...viewToSave } = ctx.request.body const designDoc = await db.get("_design/database") const view = viewTemplate(viewToSave) @@ -66,7 +66,7 @@ const controller = { } }, destroy: async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const designDoc = await db.get("_design/database") const viewName = decodeURI(ctx.params.viewName) const view = designDoc.views[viewName] @@ -81,7 +81,7 @@ const controller = { ctx.body = view }, exportView: async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const designDoc = await db.get("_design/database") const viewName = decodeURI(ctx.query.view) diff --git a/packages/server/src/api/controllers/webhook.js b/packages/server/src/api/controllers/webhook.js index 5b76f86190..c810f85004 100644 --- a/packages/server/src/api/controllers/webhook.js +++ b/packages/server/src/api/controllers/webhook.js @@ -22,7 +22,7 @@ exports.WebhookType = { } exports.fetch = async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const response = await db.allDocs( getWebhookParams(null, { include_docs: true, @@ -32,9 +32,9 @@ exports.fetch = async ctx => { } exports.save = async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) const webhook = ctx.request.body - webhook.appId = ctx.user.appId + webhook.appId = ctx.appId // check that the webhook exists if (webhook._id) { @@ -51,7 +51,7 @@ exports.save = async ctx => { } exports.destroy = async ctx => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) ctx.body = await db.remove(ctx.params.id, ctx.params.rev) } diff --git a/packages/server/src/api/routes/tests/misc.spec.js b/packages/server/src/api/routes/tests/misc.spec.js index 2957e42d90..f9608c0d49 100644 --- a/packages/server/src/api/routes/tests/misc.spec.js +++ b/packages/server/src/api/routes/tests/misc.spec.js @@ -41,10 +41,12 @@ describe("run misc tests", () => { const dataImport = { csvString: "a,b,c,d\n1,2,3,4" } - await tableUtils.handleDataImport({ - appId: config.getAppId(), - userId: "test", - }, table, dataImport) + await tableUtils.handleDataImport( + config.getAppId(), + { userId: "test" }, + table, + dataImport + ) const rows = await config.getRows() expect(rows[0].a).toEqual("1") expect(rows[0].b).toEqual("2") diff --git a/packages/server/src/middleware/authenticated.js b/packages/server/src/middleware/authenticated.js index 32ed3f63d0..d27b88ae96 100644 --- a/packages/server/src/middleware/authenticated.js +++ b/packages/server/src/middleware/authenticated.js @@ -41,7 +41,6 @@ module.exports = async (ctx, next) => { ctx.auth.authenticated = false ctx.appId = appId ctx.user = { - appId, role: builtinRoles.PUBLIC, } await next() @@ -55,9 +54,10 @@ module.exports = async (ctx, next) => { ctx.auth.apiKey = jwtPayload.apiKey ctx.user = { ...jwtPayload, - appId: appId, role: await getRole(appId, jwtPayload.roleId), } + // appId no longer carried in user, make sure + delete ctx.user.appId } catch (err) { console.log(err) if (authType === AuthTypes.BUILDER) { diff --git a/packages/server/src/middleware/usageQuota.js b/packages/server/src/middleware/usageQuota.js index 1bc829fbcf..a37f089a65 100644 --- a/packages/server/src/middleware/usageQuota.js +++ b/packages/server/src/middleware/usageQuota.js @@ -27,7 +27,7 @@ function getProperty(url) { } module.exports = async (ctx, next) => { - const db = new CouchDB(ctx.user.appId) + const db = new CouchDB(ctx.appId) let usage = METHOD_MAP[ctx.req.method] const property = getProperty(ctx.req.url) if (usage == null || property == null) { diff --git a/packages/server/src/utilities/bcrypt.js b/packages/server/src/utilities/bcrypt.js index 58a37c06a9..6c52d2c2c7 100644 --- a/packages/server/src/utilities/bcrypt.js +++ b/packages/server/src/utilities/bcrypt.js @@ -1,3 +1,5 @@ +// TODO: REMOVE + const bcrypt = require("bcryptjs") const env = require("../environment") From 3f1c18e7dd854b19008a135f990a3da872a997c0 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 1 Apr 2021 20:34:43 +0100 Subject: [PATCH 05/65] basic couchDB authentication using passport --- packages/worker/package.json | 4 + .../worker/src/api/controllers/admin/auth.js | 14 ++ .../worker/src/api/controllers/admin/index.js | 17 +- packages/worker/src/api/routes/admin/auth.js | 8 + packages/worker/src/api/routes/admin/index.js | 5 +- packages/worker/src/db/utils.js | 6 +- packages/worker/src/index.js | 6 + packages/worker/src/middleware/auth/google.js | 13 ++ packages/worker/src/middleware/auth/index.js | 20 ++ packages/worker/src/middleware/auth/jwt.js | 38 ++++ packages/worker/src/middleware/auth/local.js | 58 ++++++ .../src/{api/controllers/admin => }/utils.js | 4 +- packages/worker/yarn.lock | 186 +++++++++++++++++- 13 files changed, 365 insertions(+), 14 deletions(-) create mode 100644 packages/worker/src/api/controllers/admin/auth.js create mode 100644 packages/worker/src/api/routes/admin/auth.js create mode 100644 packages/worker/src/middleware/auth/google.js create mode 100644 packages/worker/src/middleware/auth/index.js create mode 100644 packages/worker/src/middleware/auth/jwt.js create mode 100644 packages/worker/src/middleware/auth/local.js rename packages/worker/src/{api/controllers/admin => }/utils.js (87%) diff --git a/packages/worker/package.json b/packages/worker/package.json index 73b417c580..8f9e301399 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -28,11 +28,15 @@ "koa": "^2.7.0", "koa-body": "^4.2.0", "koa-compress": "^4.0.1", + "koa-passport": "^4.1.4", "koa-pino-logger": "^3.0.0", "koa-send": "^5.0.0", "koa-session": "^5.12.0", "koa-static": "^5.0.0", "node-fetch": "^2.6.1", + "passport-google-oauth": "^2.0.0", + "passport-jwt": "^4.0.0", + "passport-local": "^1.0.0", "pino-pretty": "^4.0.0", "pouchdb": "^7.2.1", "pouchdb-all-dbs": "^1.0.2", diff --git a/packages/worker/src/api/controllers/admin/auth.js b/packages/worker/src/api/controllers/admin/auth.js new file mode 100644 index 0000000000..f6b25091ac --- /dev/null +++ b/packages/worker/src/api/controllers/admin/auth.js @@ -0,0 +1,14 @@ +const jwt = require("jsonwebtoken") +const CouchDB = require("../../../db") +const passport = require("koa-passport") + +exports.authenticate = async (ctx, next) => { + return passport.authenticate("local", (err, user, info, status) => { + ctx.body = { + err, + user, + info, + status, + } + })(ctx, next) +} diff --git a/packages/worker/src/api/controllers/admin/index.js b/packages/worker/src/api/controllers/admin/index.js index f94cf39fc4..b6531174bd 100644 --- a/packages/worker/src/api/controllers/admin/index.js +++ b/packages/worker/src/api/controllers/admin/index.js @@ -1,6 +1,10 @@ const CouchDB = require("../../../db") -const { StaticDatabases, generateUserID, getUserParams } = require("../../../db/utils") -const { hash } = require("./utils") +const { + StaticDatabases, + generateUserID, + getUserParams, +} = require("../../../db/utils") +const { hash } = require("../../../utils") const { UserStatus } = require("../../../constants") const USER_DB = StaticDatabases.USER.name @@ -10,10 +14,11 @@ exports.userSave = async ctx => { const { email, password, _id } = ctx.request.body const hashedPassword = password ? await hash(password) : null let user = { - ...ctx.request.body, - _id: generateUserID(email), - password: hashedPassword, - }, dbUser + ...ctx.request.body, + _id: generateUserID(email), + password: hashedPassword, + }, + dbUser // in-case user existed already if (_id) { dbUser = await db.get(_id) diff --git a/packages/worker/src/api/routes/admin/auth.js b/packages/worker/src/api/routes/admin/auth.js new file mode 100644 index 0000000000..ca41e9e19e --- /dev/null +++ b/packages/worker/src/api/routes/admin/auth.js @@ -0,0 +1,8 @@ +// const Router = require("@koa/router") +// const controller = require("../controllers/auth") + +// const router = Router() + +// router.post("/api/authenticate", controller.authenticate) + +// module.exports = router diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js index 9d85927900..cf3a5c021a 100644 --- a/packages/worker/src/api/routes/admin/index.js +++ b/packages/worker/src/api/routes/admin/index.js @@ -1,10 +1,13 @@ const Router = require("@koa/router") const controller = require("../../controllers/admin") +const authController = require("../../controllers/admin/auth") const authorized = require("../../../middleware/authorized") const router = Router() -router.post("/api/admin/users", authorized, controller.userSave) +router + .post("/api/admin/users", authorized, controller.userSave) + .post("/api/admin/authenticate", authController.authenticate) .delete("/api/admin/users/:email", authorized, controller.userDelete) .get("/api/admin/users", authorized, controller.userFetch) .get("/api/admin/users/:email", authorized, controller.userFind) diff --git a/packages/worker/src/db/utils.js b/packages/worker/src/db/utils.js index aa274eff3b..cda7708825 100644 --- a/packages/worker/src/db/utils.js +++ b/packages/worker/src/db/utils.js @@ -1,11 +1,11 @@ exports.StaticDatabases = { USER: { name: "user-db", - } + }, } const DocumentTypes = { - USER: "us" + USER: "us", } const UNICODE_MAX = "\ufff0" @@ -29,4 +29,4 @@ exports.getUserParams = (email = "", otherProps = {}) => { startkey: `${DocumentTypes.USER}${SEPARATOR}${email}`, endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`, } -} \ No newline at end of file +} diff --git a/packages/worker/src/index.js b/packages/worker/src/index.js index 2426b39411..199bb1d31b 100644 --- a/packages/worker/src/index.js +++ b/packages/worker/src/index.js @@ -1,6 +1,7 @@ const Koa = require("koa") const destroyable = require("server-destroy") const koaBody = require("koa-body") +const passport = require("koa-passport") const logger = require("koa-pino-logger") const http = require("http") const api = require("./api") @@ -24,6 +25,11 @@ app.use( }) ) +// authentication +require("./middleware/auth") +app.use(passport.initialize()) +app.use(passport.session()) + // api routes app.use(api.routes()) diff --git a/packages/worker/src/middleware/auth/google.js b/packages/worker/src/middleware/auth/google.js new file mode 100644 index 0000000000..fd33bc89a3 --- /dev/null +++ b/packages/worker/src/middleware/auth/google.js @@ -0,0 +1,13 @@ +// const GoogleStrategy = require("passport-google-auth").Strategy + +exports.options = { + clientId: "your-client-id", + clientSecret: "your-secret", + callbackURL: + "http://localhost:" + (process.env.PORT || 3000) + "/auth/google/callback", +} + +exports.authenticate = async function(token, tokenSecret, profile, done) { + // retrieve user ... + // fetchUser().then(user => done(null, user)) +} diff --git a/packages/worker/src/middleware/auth/index.js b/packages/worker/src/middleware/auth/index.js new file mode 100644 index 0000000000..3eac2badbf --- /dev/null +++ b/packages/worker/src/middleware/auth/index.js @@ -0,0 +1,20 @@ +const passport = require("koa-passport") +const LocalStrategy = require("passport-local").Strategy +const JwtStrategy = require("passport-jwt").Strategy +const GoogleStrategy = require("passport-google-oauth").Strategy +const jwt = require("./jwt") +const local = require("./local") +const google = require("./google") + +// Strategies +passport.use(new LocalStrategy(local.options, local.authenticate)) +passport.use(new JwtStrategy(jwt.options, jwt.authenticate)) +// passport.use(new GoogleStrategy(google.options, google.authenticate)) + +// exports.middleware = async (ctx, next) => { +// if (ctx.isAuthenticated()) { +// return next() +// } else { +// ctx.throw(403, "Not Authenticated") +// } +// } diff --git a/packages/worker/src/middleware/auth/jwt.js b/packages/worker/src/middleware/auth/jwt.js new file mode 100644 index 0000000000..8313d5abca --- /dev/null +++ b/packages/worker/src/middleware/auth/jwt.js @@ -0,0 +1,38 @@ +const jwt = require("passport-jwt") +const env = require("../../environment") +const { getCookieName } = require("../../../../server/src/utilities") + +const ExtractJWT = jwt.ExtractJwt + +exports.options = { + jwtFromRequest: function(ctx) { + return ctx.cookies.get("budibase") + }, + // TODO: fix + secretOrKey: env.JWT_SECRET || "funky", +} + +exports.authenticate = async function(jwt, done) { + console.log(jwt) + done({ name: "joe" }) + // const appId = ctx.appId + // if (!appId) ctx.throw(400, "No appId") + + // const { email, password } = ctx.request.body + + // if (!email) ctx.throw(400, "Email Required.") + // if (!password) ctx.throw(400, "Password Required.") + + // // Check the user exists in the instance DB by email + // const db = new CouchDB(appId) + // const app = await db.get(appId) + + // let dbUser + // try { + // dbUser = await db.get(generateUserID(email)) + // } catch (_) { + // // do not want to throw a 404 - as this could be + // // used to determine valid emails + // ctx.throw(401, INVALID_ERR) + // } +} diff --git a/packages/worker/src/middleware/auth/local.js b/packages/worker/src/middleware/auth/local.js new file mode 100644 index 0000000000..413ab1c8fb --- /dev/null +++ b/packages/worker/src/middleware/auth/local.js @@ -0,0 +1,58 @@ +const jwt = require("jsonwebtoken") +const { UserStatus } = require("../../constants") +const CouchDB = require("../../db") +const { StaticDatabases, generateUserID } = require("../../db/utils") +const { compare } = require("../../utils") +const env = require("../../environment") + +const INVALID_ERR = "Invalid Credentials" + +exports.options = {} + +/** + * Passport Local Authentication Middleware. + * @param {*} username - username to login with + * @param {*} password - plain text password to log in with + * @param {*} done - callback from passport to return user information and errors + * @returns The authenticated user, or errors if they occur + */ +exports.authenticate = async function(username, password, done) { + if (!username) return done(null, false, "Email Required.") + if (!password) return done(null, false, "Password Required.") + + // Check the user exists in the instance DB by email + const db = new CouchDB(StaticDatabases.USER.name) + + let dbUser + try { + dbUser = await db.get(generateUserID(username)) + } catch { + console.error("User not found") + return done(null, false, { message: "User not found" }) + } + + // check that the user is currently inactive, if this is the case throw invalid + if (dbUser.status === UserStatus.INACTIVE) { + return done(null, false, { message: INVALID_ERR }) + } + + // authenticate + if (await compare(password, dbUser.password)) { + const payload = { + userId: dbUser._id, + } + + const token = jwt.sign(payload, env.JWT_SECRET, { + expiresIn: "1 day", + }) + + // TODO: remove and use cookie + dbUser.token = token + // setCookie(ctx, token, appId) + + delete dbUser.password + return done(null, dbUser) + } else { + done(new Error(INVALID_ERR), false) + } +} diff --git a/packages/worker/src/api/controllers/admin/utils.js b/packages/worker/src/utils.js similarity index 87% rename from packages/worker/src/api/controllers/admin/utils.js rename to packages/worker/src/utils.js index 4af0a52c46..0711ae67bf 100644 --- a/packages/worker/src/api/controllers/admin/utils.js +++ b/packages/worker/src/utils.js @@ -1,5 +1,5 @@ const bcrypt = require("bcryptjs") -const env = require("../environment") +const env = require("./environment") const SALT_ROUNDS = env.SALT_ROUNDS || 10 @@ -10,4 +10,4 @@ exports.hash = async data => { exports.compare = async (data, encrypted) => { return bcrypt.compare(data, encrypted) -} \ No newline at end of file +} diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index d969c67ceb..df8965f515 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -285,6 +285,11 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +base64url@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== + bcryptjs@^2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" @@ -324,6 +329,11 @@ braces@~3.0.2: dependencies: fill-range "^7.0.1" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + buffer-from@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -712,6 +722,13 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1270,6 +1287,22 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +jsonwebtoken@^8.2.0: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + 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" + semver "^5.6.0" + jstransform@~11.0.0: version "11.0.3" resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-11.0.3.tgz#09a78993e0ae4d4ef4487f6155a91f6190cb4223" @@ -1290,6 +1323,23 @@ jstransform@~3.0.0: esprima-fb "~3001.1.0-dev-harmony-fb" source-map "0.1.31" +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + keygrip@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" @@ -1356,6 +1406,13 @@ koa-is-json@^1.0.0: resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14" integrity sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ= +koa-passport@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/koa-passport/-/koa-passport-4.1.4.tgz#5f1665c1c2a37ace79af9f970b770885ca30ccfa" + integrity sha512-dJBCkl4X+zdYxbI2V2OtoGy0PUenpvp2ZLLWObc8UJhsId0iQpTFT8RVcuA0709AL2txGwRHnSPoT1bYNGa6Kg== + dependencies: + passport "^0.4.0" + koa-pino-logger@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/koa-pino-logger/-/koa-pino-logger-3.0.0.tgz#27600b4f3639e8767dfc6b66493109c5457f53ba" @@ -1530,6 +1587,41 @@ lie@3.0.4: inline-process-browser "^1.0.0" unreachable-branch-transform "^0.3.0" +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -1686,6 +1778,11 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== +oauth@0.9.x: + version "0.9.15" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE= + object-assign@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" @@ -1740,6 +1837,76 @@ parseurl@^1.3.2: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +passport-google-oauth1@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth1/-/passport-google-oauth1-1.0.0.tgz#af74a803df51ec646f66a44d82282be6f108e0cc" + integrity sha1-r3SoA99R7GRvZqRNgigr5vEI4Mw= + dependencies: + passport-oauth1 "1.x.x" + +passport-google-oauth20@2.x.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef" + integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ== + dependencies: + passport-oauth2 "1.x.x" + +passport-google-oauth@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth/-/passport-google-oauth-2.0.0.tgz#f6eb4bc96dd6c16ec0ecfdf4e05ec48ca54d4dae" + integrity sha512-JKxZpBx6wBQXX1/a1s7VmdBgwOugohH+IxCy84aPTZNq/iIPX6u7Mqov1zY7MKRz3niFPol0KJz8zPLBoHKtYA== + dependencies: + passport-google-oauth1 "1.x.x" + passport-google-oauth20 "2.x.x" + +passport-jwt@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/passport-jwt/-/passport-jwt-4.0.0.tgz#7f0be7ba942e28b9f5d22c2ebbb8ce96ef7cf065" + integrity sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg== + dependencies: + jsonwebtoken "^8.2.0" + passport-strategy "^1.0.0" + +passport-local@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" + integrity sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4= + dependencies: + passport-strategy "1.x.x" + +passport-oauth1@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/passport-oauth1/-/passport-oauth1-1.1.0.tgz#a7de988a211f9cf4687377130ea74df32730c918" + integrity sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg= + dependencies: + oauth "0.9.x" + passport-strategy "1.x.x" + utils-merge "1.x.x" + +passport-oauth2@1.x.x: + version "1.5.0" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108" + integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ== + dependencies: + base64url "3.x.x" + oauth "0.9.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x.x, passport-strategy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ= + +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + path-is-absolute@1.0.1, path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1752,6 +1919,11 @@ path-to-regexp@1.x: dependencies: isarray "0.0.1" +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= + picomatch@^2.0.4, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" @@ -2051,7 +2223,7 @@ safe-buffer@5.1.2: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -2078,7 +2250,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver@^5.7.1: +semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2319,6 +2491,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +uid2@0.0.x: + version "0.0.3" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" + integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= + undefsafe@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae" @@ -2396,6 +2573,11 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= +utils-merge@1.x.x: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + uuid@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" From a4b1f2390ead8ad2361cfc65a2ce60f4d57f1429 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 6 Apr 2021 18:08:07 +0100 Subject: [PATCH 06/65] Formatting. --- packages/server/src/api/controllers/static/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js index afb1d908ae..e05327d9f1 100644 --- a/packages/server/src/api/controllers/static/index.js +++ b/packages/server/src/api/controllers/static/index.js @@ -118,10 +118,7 @@ exports.serveApp = async function(ctx) { } exports.serveAttachment = async function(ctx) { - await returnObjectStoreFile( - ctx, - join(ctx.appId, "attachments", ctx.file) - ) + await returnObjectStoreFile(ctx, join(ctx.appId, "attachments", ctx.file)) } exports.serveAppAsset = async function(ctx) { From cf073a1e55e869e94f852070f652566136a099bb Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 7 Apr 2021 11:33:16 +0100 Subject: [PATCH 07/65] groundwork for budibase auth lib --- packages/auth/.gitignore | 117 ++ packages/auth/README.md | 1 + packages/auth/package.json | 18 + packages/auth/src/constants.js | 9 + packages/auth/src/db/index.js | 11 + packages/auth/src/db/utils.js | 32 + packages/auth/src/hashing.js | 12 + packages/auth/src/index.js | 31 + packages/auth/src/middleware/authenticated.js | 73 ++ packages/auth/src/middleware/google.js | 13 + packages/auth/src/middleware/index.js | 9 + packages/auth/src/middleware/jwt.js | 19 + .../auth => auth/src/middleware}/local.js | 22 +- packages/auth/yarn.lock | 950 ++++++++++++++ packages/server/package.json | 1 - packages/server/yarn.lock | 1116 +---------------- packages/worker/package.json | 1 + .../worker/src/api/controllers/admin/auth.js | 10 +- packages/worker/src/api/routes/admin/auth.js | 8 - packages/worker/src/api/routes/admin/index.js | 11 +- packages/worker/src/index.js | 3 +- packages/worker/src/middleware/auth/google.js | 13 - packages/worker/src/middleware/auth/index.js | 20 - packages/worker/src/middleware/auth/jwt.js | 38 - packages/worker/src/middleware/authorized.js | 2 +- 25 files changed, 1330 insertions(+), 1210 deletions(-) create mode 100644 packages/auth/.gitignore create mode 100644 packages/auth/README.md create mode 100644 packages/auth/package.json create mode 100644 packages/auth/src/constants.js create mode 100644 packages/auth/src/db/index.js create mode 100644 packages/auth/src/db/utils.js create mode 100644 packages/auth/src/hashing.js create mode 100644 packages/auth/src/index.js create mode 100644 packages/auth/src/middleware/authenticated.js create mode 100644 packages/auth/src/middleware/google.js create mode 100644 packages/auth/src/middleware/index.js create mode 100644 packages/auth/src/middleware/jwt.js rename packages/{worker/src/middleware/auth => auth/src/middleware}/local.js (74%) create mode 100644 packages/auth/yarn.lock delete mode 100644 packages/worker/src/api/routes/admin/auth.js delete mode 100644 packages/worker/src/middleware/auth/google.js delete mode 100644 packages/worker/src/middleware/auth/index.js delete mode 100644 packages/worker/src/middleware/auth/jwt.js diff --git a/packages/auth/.gitignore b/packages/auth/.gitignore new file mode 100644 index 0000000000..2528ad91a4 --- /dev/null +++ b/packages/auth/.gitignore @@ -0,0 +1,117 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + diff --git a/packages/auth/README.md b/packages/auth/README.md new file mode 100644 index 0000000000..bbe704026a --- /dev/null +++ b/packages/auth/README.md @@ -0,0 +1 @@ +# Budibase Authentication Library \ No newline at end of file diff --git a/packages/auth/package.json b/packages/auth/package.json new file mode 100644 index 0000000000..ff59eeb7ba --- /dev/null +++ b/packages/auth/package.json @@ -0,0 +1,18 @@ +{ + "name": "@budibase/auth", + "version": "0.0.1", + "description": "Authentication middlewares for budibase builder and apps", + "main": "src/index.js", + "author": "Budibase", + "license": "AGPL-3.0", + "dependencies": { + "bcryptjs": "^2.4.3", + "jsonwebtoken": "^8.5.1", + "koa-passport": "^4.1.4", + "passport-google-auth": "^1.0.2", + "passport-google-oauth": "^2.0.0", + "passport-jwt": "^4.0.0", + "passport-local": "^1.0.0", + "pouchdb": "^7.2.2" + } +} diff --git a/packages/auth/src/constants.js b/packages/auth/src/constants.js new file mode 100644 index 0000000000..b6946a543b --- /dev/null +++ b/packages/auth/src/constants.js @@ -0,0 +1,9 @@ +exports.UserStatus = { + ACTIVE: "active", + INACTIVE: "inactive", +} + +exports.Cookies = { + CurrentApp: "budibase:currentapp", + Auth: "budibase:auth", +} diff --git a/packages/auth/src/db/index.js b/packages/auth/src/db/index.js new file mode 100644 index 0000000000..4db890f01e --- /dev/null +++ b/packages/auth/src/db/index.js @@ -0,0 +1,11 @@ +const PouchDB = require("pouchdb") + +// level option is purely for testing (development) +const COUCH_DB_URL = + process.env.COUCH_DB_URL || "http://budibase:budibase@localhost:10000/db/" + +const Pouch = PouchDB.defaults({ + prefix: COUCH_DB_URL, +}) + +module.exports = Pouch diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js new file mode 100644 index 0000000000..cda7708825 --- /dev/null +++ b/packages/auth/src/db/utils.js @@ -0,0 +1,32 @@ +exports.StaticDatabases = { + USER: { + name: "user-db", + }, +} + +const DocumentTypes = { + USER: "us", +} + +const UNICODE_MAX = "\ufff0" +const SEPARATOR = "_" + +/** + * Generates a new user ID based on the passed in email. + * @param {string} email The email which the ID is going to be built up of. + * @returns {string} The new user ID which the user doc can be stored under. + */ +exports.generateUserID = email => { + return `${DocumentTypes.USER}${SEPARATOR}${email}` +} + +/** + * Gets parameters for retrieving users, this is a utility function for the getDocParams function. + */ +exports.getUserParams = (email = "", otherProps = {}) => { + return { + ...otherProps, + startkey: `${DocumentTypes.USER}${SEPARATOR}${email}`, + endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`, + } +} diff --git a/packages/auth/src/hashing.js b/packages/auth/src/hashing.js new file mode 100644 index 0000000000..8c81e39d95 --- /dev/null +++ b/packages/auth/src/hashing.js @@ -0,0 +1,12 @@ +const bcrypt = require("bcryptjs") + +const SALT_ROUNDS = process.env.SALT_ROUNDS || 10 + +exports.hash = async data => { + const salt = await bcrypt.genSalt(SALT_ROUNDS) + return bcrypt.hash(data, salt) +} + +exports.compare = async (data, encrypted) => { + return bcrypt.compare(data, encrypted) +} diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js new file mode 100644 index 0000000000..778d4fb32e --- /dev/null +++ b/packages/auth/src/index.js @@ -0,0 +1,31 @@ +const passport = require("koa-passport") +const LocalStrategy = require("passport-local").Strategy +const JwtStrategy = require("passport-jwt").Strategy +// const GoogleStrategy = require("passport-google-oauth").Strategy +const CouchDB = require("./db") +const { StaticDatabases } = require("./db/utils") +const { jwt, local, google } = require("./middleware") +const hashing = require("./hashing") + +// Strategies +passport.use(new LocalStrategy(local.options, local.authenticate)) +passport.use(new JwtStrategy(jwt.options, jwt.authenticate)) +// passport.use(new GoogleStrategy(google.options, google.authenticate)) + +passport.serializeUser((user, done) => done(null, user)) + +passport.deserializeUser(async (user, done) => { + const db = new CouchDB(StaticDatabases.USER.name) + + try { + const user = await db.get(user._id) + return done(null, user) + } catch (err) { + console.error("User not found", err) + return done(null, false, { message: "User not found" }) + } +}) + +// exports.hashing = hashing + +module.exports = passport diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js new file mode 100644 index 0000000000..f7ff086b67 --- /dev/null +++ b/packages/auth/src/middleware/authenticated.js @@ -0,0 +1,73 @@ +const jwt = require("jsonwebtoken") +const STATUS_CODES = require("../utilities/statusCodes") +const { getRole, getBuiltinRoles } = require("../utilities/security/roles") +const { AuthTypes, Cookies } = require("../constants") +const { + getAppId, + getCookieName, + clearCookie, + setCookie, + isClient, +} = require("../utilities") + +module.exports = async (ctx, next) => { + // if (ctx.path === "/_builder") { + // await next() + // return + // } + + // do everything we can to make sure the appId is held correctly + // we hold it in state as a + let appId = getAppId(ctx) + const cookieAppId = ctx.cookies.get(Cookies.CurrentApp) + // const builtinRoles = getBuiltinRoles() + if (appId && cookieAppId !== appId) { + setCookie(ctx, appId, "currentapp") + } else if (cookieAppId) { + appId = cookieAppId + } + let token, authType + // if (!isClient(ctx)) { + // token = ctx.cookies.get(getCookieName()) + // authType = AuthTypes.BUILDER + // } + + if (!token && appId) { + token = ctx.cookies.get(getCookieName(appId)) + // authType = AuthTypes.APP + } + + // if (!token) { + // ctx.auth.authenticated = false + // ctx.appId = appId + // ctx.user = { + // role: builtinRoles.PUBLIC, + // } + // await next() + // return + // } + + try { + // ctx.auth.authenticated = authType + const jwtPayload = jwt.verify(token, ctx.config.jwtSecret) + ctx.appId = appId + // ctx.auth.apiKey = jwtPayload.apiKey + ctx.user = { + ...jwtPayload, + role: await getRole(appId, jwtPayload.roleId), + } + // appId no longer carried in user, make sure + delete ctx.user.appId + } catch (err) { + console.log(err) + // if (authType === AuthTypes.BUILDER) { + // clearCookie(ctx) + // ctx.status = 200 + // return + // } else { + ctx.throw(err.status || STATUS_CODES.FORBIDDEN, err.text) + // } + } + + await next() +} diff --git a/packages/auth/src/middleware/google.js b/packages/auth/src/middleware/google.js new file mode 100644 index 0000000000..008d4a6816 --- /dev/null +++ b/packages/auth/src/middleware/google.js @@ -0,0 +1,13 @@ +const CouchDB = require("../db") + +exports.options = { + clientId: process.env.GOOGLE_CLIENT_ID, + clientSecret: process.env.GOOGLE_CLIENT_SECRET, + callbackURL: process.env.GOOGLE_AUTH_CALLBACK_URL, + // "http://localhost:" + (process.env.PORT || 3000) + "/auth/google/callback", +} + +exports.authenticate = async function(token, tokenSecret, profile, done) { + // retrieve user ... + // fetchUser().then(user => done(null, user)) +} diff --git a/packages/auth/src/middleware/index.js b/packages/auth/src/middleware/index.js new file mode 100644 index 0000000000..a9d07516ed --- /dev/null +++ b/packages/auth/src/middleware/index.js @@ -0,0 +1,9 @@ +const jwt = require("./jwt") +const local = require("./local") +const google = require("./google") + +module.exports = { + google, + jwt, + local, +} diff --git a/packages/auth/src/middleware/jwt.js b/packages/auth/src/middleware/jwt.js new file mode 100644 index 0000000000..5d36f0b91e --- /dev/null +++ b/packages/auth/src/middleware/jwt.js @@ -0,0 +1,19 @@ +// const jwt = require("passport-jwt") +const { Cookies } = require("../constants") + +// const ExtractJWT = jwt.ExtractJwt + +exports.options = { + jwtFromRequest: function(ctx) { + return ctx.cookies.get(Cookies.Auth) + }, + secretOrKey: process.env.JWT_SECRET, +} + +exports.authenticate = async function(jwt, done) { + try { + return done(null, jwt) + } catch (err) { + return done(new Error("JWT invalid."), false) + } +} diff --git a/packages/worker/src/middleware/auth/local.js b/packages/auth/src/middleware/local.js similarity index 74% rename from packages/worker/src/middleware/auth/local.js rename to packages/auth/src/middleware/local.js index 413ab1c8fb..85a68af87c 100644 --- a/packages/worker/src/middleware/auth/local.js +++ b/packages/auth/src/middleware/local.js @@ -1,9 +1,8 @@ const jwt = require("jsonwebtoken") -const { UserStatus } = require("../../constants") -const CouchDB = require("../../db") -const { StaticDatabases, generateUserID } = require("../../db/utils") -const { compare } = require("../../utils") -const env = require("../../environment") +const { UserStatus } = require("../constants") +const CouchDB = require("../db") +const { StaticDatabases, generateUserID } = require("../db/utils") +const { compare } = require("../hashing") const INVALID_ERR = "Invalid Credentials" @@ -26,8 +25,8 @@ exports.authenticate = async function(username, password, done) { let dbUser try { dbUser = await db.get(generateUserID(username)) - } catch { - console.error("User not found") + } catch (err) { + console.error("User not found", err) return done(null, false, { message: "User not found" }) } @@ -39,18 +38,17 @@ exports.authenticate = async function(username, password, done) { // authenticate if (await compare(password, dbUser.password)) { const payload = { - userId: dbUser._id, + _id: dbUser._id, } - const token = jwt.sign(payload, env.JWT_SECRET, { + const token = jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: "1 day", }) - // TODO: remove and use cookie dbUser.token = token - // setCookie(ctx, token, appId) - + // Remove users password in payload delete dbUser.password + return done(null, dbUser) } else { done(new Error(INVALID_ERR), false) diff --git a/packages/auth/yarn.lock b/packages/auth/yarn.lock new file mode 100644 index 0000000000..cde01d2106 --- /dev/null +++ b/packages/auth/yarn.lock @@ -0,0 +1,950 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abort-controller@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-leveldown@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a" + integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +abstract-leveldown@~6.2.1, abstract-leveldown@~6.2.3: + version "6.2.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb" + integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +argsarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb" + integrity sha1-bnIHtOzbObCviDA/pa4ivajfYcs= + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +async@~2.1.4: + version "2.1.5" + resolved "https://registry.yarnpkg.com/async/-/async-2.1.5.tgz#e587c68580994ac67fc56ff86d3ac56bdbe810bc" + integrity sha1-5YfGhYCZSsZ/xW/4bTrFa9voELw= + dependencies: + lodash "^4.14.0" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base64url@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bcryptjs@^2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" + integrity sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms= + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + +buffer-from@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +clone-buffer@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" + integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +deferred-leveldown@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058" + integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw== + dependencies: + abstract-leveldown "~6.2.1" + inherits "^2.0.3" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +double-ended-queue@2.1.0-0: + version "2.1.0-0" + resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" + integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw= + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +encoding-down@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" + integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw== + dependencies: + abstract-leveldown "^6.2.1" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + +end-stream@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/end-stream/-/end-stream-0.1.0.tgz#32003f3f438a2b0143168137f8fa6e9866c81ed5" + integrity sha1-MgA/P0OKKwFDFoE3+PpumGbIHtU= + dependencies: + write-stream "~0.4.3" + +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fetch-cookie@0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-0.10.1.tgz#5ea88f3d36950543c87997c27ae2aeafb4b5c4d4" + integrity sha512-beB+VEd4cNeVG1PY+ee74+PkuCQnik78pgLi5Ah/7qdUfov8IctU0vLUbBT8/10Ma5GMBeI4wtxhGrEfKNYs2g== + dependencies: + tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +google-auth-library@~0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-0.10.0.tgz#6e15babee85fd1dd14d8d128a295b6838d52136e" + integrity sha1-bhW6vuhf0d0U2NEoopW2g41SE24= + dependencies: + gtoken "^1.2.1" + jws "^3.1.4" + lodash.noop "^3.0.1" + request "^2.74.0" + +google-p12-pem@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-0.1.2.tgz#33c46ab021aa734fa0332b3960a9a3ffcb2f3177" + integrity sha1-M8RqsCGqc0+gMys5YKmj/8svMXc= + dependencies: + node-forge "^0.7.1" + +googleapis@^16.0.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/googleapis/-/googleapis-16.1.0.tgz#0f19f2d70572d918881a0f626e3b1a2fa8629576" + integrity sha1-Dxny1wVy2RiIGg9ibjsaL6hilXY= + dependencies: + async "~2.1.4" + google-auth-library "~0.10.0" + string-template "~1.0.0" + +gtoken@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-1.2.3.tgz#5509571b8afd4322e124cf66cf68115284c476d8" + integrity sha512-wQAJflfoqSgMWrSBk9Fg86q+sd6s7y6uJhIvvIPz++RElGlMtEqsdAR2oWwZ/WTEtp7P9xFbJRrT976oRgzJ/w== + dependencies: + google-p12-pem "^0.1.0" + jws "^3.0.0" + mime "^1.4.1" + request "^2.72.0" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +immediate@3.3.0, immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +jsonwebtoken@^8.2.0, jsonwebtoken@^8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + 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" + semver "^5.6.0" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.0.0, jws@^3.1.4, jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +koa-passport@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/koa-passport/-/koa-passport-4.1.4.tgz#5f1665c1c2a37ace79af9f970b770885ca30ccfa" + integrity sha512-dJBCkl4X+zdYxbI2V2OtoGy0PUenpvp2ZLLWObc8UJhsId0iQpTFT8RVcuA0709AL2txGwRHnSPoT1bYNGa6Kg== + dependencies: + passport "^0.4.0" + +level-codec@9.0.2, level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-concat-iterator@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" + integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw== + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-iterator-stream@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c" + integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q== + dependencies: + inherits "^2.0.4" + readable-stream "^3.4.0" + xtend "^4.0.2" + +level-js@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/level-js/-/level-js-5.0.2.tgz#5e280b8f93abd9ef3a305b13faf0b5397c969b55" + integrity sha512-SnBIDo2pdO5VXh02ZmtAyPP6/+6YTJg2ibLtl9C34pWvmtMEmRTWpra+qO/hifkUtBTOtfx6S9vLDjBsBK4gRg== + dependencies: + abstract-leveldown "~6.2.3" + buffer "^5.5.0" + inherits "^2.0.3" + ltgt "^2.1.2" + +level-packager@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939" + integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ== + dependencies: + encoding-down "^6.3.0" + levelup "^4.3.2" + +level-supports@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" + integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg== + dependencies: + xtend "^4.0.2" + +level-write-stream@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-write-stream/-/level-write-stream-1.0.0.tgz#3f7fbb679a55137c0feb303dee766e12ee13c1dc" + integrity sha1-P3+7Z5pVE3wP6zA97nZuEu4Twdw= + dependencies: + end-stream "~0.1.0" + +level@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/level/-/level-6.0.1.tgz#dc34c5edb81846a6de5079eac15706334b0d7cd6" + integrity sha512-psRSqJZCsC/irNhfHzrVZbmPYXDcEYhA5TVNwr+V92jF44rbf86hqGp8fiT702FyiArScYIlPSBTDUASCVNSpw== + dependencies: + level-js "^5.0.0" + level-packager "^5.1.0" + leveldown "^5.4.0" + +leveldown@5.6.0, leveldown@^5.4.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-5.6.0.tgz#16ba937bb2991c6094e13ac5a6898ee66d3eee98" + integrity sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ== + dependencies: + abstract-leveldown "~6.2.1" + napi-macros "~2.0.0" + node-gyp-build "~4.1.0" + +levelup@4.4.0, levelup@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" + integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ== + dependencies: + deferred-leveldown "~5.3.0" + level-errors "~2.0.0" + level-iterator-stream "~4.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + +lodash.noop@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-3.0.1.tgz#38188f4d650a3a474258439b96ec45b32617133c" + integrity sha1-OBiPTWUKOkdCWEObluxFsyYXEzw= + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + +lodash@^4.14.0: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +ltgt@2.2.1, ltgt@^2.1.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= + +mime-db@1.47.0: + version "1.47.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" + integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.30" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" + integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== + dependencies: + mime-db "1.47.0" + +mime@^1.4.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +napi-macros@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" + integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== + +node-fetch@2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + +node-forge@^0.7.1: + version "0.7.6" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" + integrity sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw== + +node-gyp-build@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" + integrity sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +oauth@0.9.x: + version "0.9.15" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + integrity sha1-vR/vr2hslrdUda7VGWQS/2DPucE= + +passport-google-auth@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/passport-google-auth/-/passport-google-auth-1.0.2.tgz#8b300b5aa442ef433de1d832ed3112877d0b2938" + integrity sha1-izALWqRC70M94dgy7TESh30LKTg= + dependencies: + googleapis "^16.0.0" + passport-strategy "1.x" + +passport-google-oauth1@1.x.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth1/-/passport-google-oauth1-1.0.0.tgz#af74a803df51ec646f66a44d82282be6f108e0cc" + integrity sha1-r3SoA99R7GRvZqRNgigr5vEI4Mw= + dependencies: + passport-oauth1 "1.x.x" + +passport-google-oauth20@2.x.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz#0d241b2d21ebd3dc7f2b60669ec4d587e3a674ef" + integrity sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ== + dependencies: + passport-oauth2 "1.x.x" + +passport-google-oauth@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth/-/passport-google-oauth-2.0.0.tgz#f6eb4bc96dd6c16ec0ecfdf4e05ec48ca54d4dae" + integrity sha512-JKxZpBx6wBQXX1/a1s7VmdBgwOugohH+IxCy84aPTZNq/iIPX6u7Mqov1zY7MKRz3niFPol0KJz8zPLBoHKtYA== + dependencies: + passport-google-oauth1 "1.x.x" + passport-google-oauth20 "2.x.x" + +passport-jwt@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/passport-jwt/-/passport-jwt-4.0.0.tgz#7f0be7ba942e28b9f5d22c2ebbb8ce96ef7cf065" + integrity sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg== + dependencies: + jsonwebtoken "^8.2.0" + passport-strategy "^1.0.0" + +passport-local@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-local/-/passport-local-1.0.0.tgz#1fe63268c92e75606626437e3b906662c15ba6ee" + integrity sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4= + dependencies: + passport-strategy "1.x.x" + +passport-oauth1@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/passport-oauth1/-/passport-oauth1-1.1.0.tgz#a7de988a211f9cf4687377130ea74df32730c918" + integrity sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg= + dependencies: + oauth "0.9.x" + passport-strategy "1.x.x" + utils-merge "1.x.x" + +passport-oauth2@1.x.x: + version "1.5.0" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108" + integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ== + dependencies: + base64url "3.x.x" + oauth "0.9.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x, passport-strategy@1.x.x, passport-strategy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + integrity sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ= + +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +pouchdb@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-7.2.2.tgz#fcae82862db527e4cf7576ed8549d1384961f364" + integrity sha512-5gf5nw5XH/2H/DJj8b0YkvG9fhA/4Jt6kL0Y8QjtztVjb1y4J19Rg4rG+fUbXu96gsUrlyIvZ3XfM0b4mogGmw== + dependencies: + abort-controller "3.0.0" + argsarray "0.0.1" + buffer-from "1.1.1" + clone-buffer "1.0.0" + double-ended-queue "2.1.0-0" + fetch-cookie "0.10.1" + immediate "3.3.0" + inherits "2.0.4" + level "6.0.1" + level-codec "9.0.2" + level-write-stream "1.0.0" + leveldown "5.6.0" + levelup "4.4.0" + ltgt "2.2.1" + node-fetch "2.6.0" + readable-stream "1.1.14" + spark-md5 "3.0.1" + through2 "3.0.2" + uuid "8.1.0" + vuvuzela "1.0.3" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +psl@^1.1.28, psl@^1.1.33: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +readable-stream@1.1.14: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +"readable-stream@2 || 3", readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~0.0.2: + version "0.0.4" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d" + integrity sha1-8y124/uGM0SlSNeZIwBxc2ZbO40= + +request@^2.72.0, request@^2.74.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + 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.3" + 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.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +spark-md5@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.1.tgz#83a0e255734f2ab4e5c466e5a2cfc9ba2aa2124d" + integrity sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig== + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + 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" + +string-template@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96" + integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y= + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +through2@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" + integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== + dependencies: + inherits "^2.0.4" + readable-stream "2 || 3" + +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" + integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.1.2" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +uid2@0.0.x: + version "0.0.3" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" + integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= + +universalify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +utils-merge@1.x.x: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" + integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vuvuzela@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b" + integrity sha1-O+FF5YJxxzylUnndhR8SpoIRSws= + +write-stream@~0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/write-stream/-/write-stream-0.4.3.tgz#83cc8c0347d0af6057a93862b4e3ae01de5c81c1" + integrity sha1-g8yMA0fQr2BXqThitOOuAd5cgcE= + dependencies: + readable-stream "~0.0.2" + +xtend@^4.0.2, xtend@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== diff --git a/packages/server/package.json b/packages/server/package.json index 36cd215423..cdaa94b7cf 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -43,7 +43,6 @@ "electron": "electron src/electron.js", "build:electron": "electron-builder --dir", "publish:electron": "electron-builder -mwl --publish always", - "postinstall": "electron-builder install-app-deps", "lint": "eslint --fix src/", "initialise": "node scripts/initialise.js" }, diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 599b64ca60..919dccf1a1 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -7,11 +7,6 @@ resolved "https://registry.yarnpkg.com/7zip-bin/-/7zip-bin-5.0.3.tgz#bc5b5532ecafd923a61f2fb097e3b108c0106a3f" integrity sha512-GLyWIFBbGvpKPGo55JyRZAo4lVbnBiD52cKlw/0Vt+wnmKvWJkpZvsjVoaIolyBXDeAQKSicRtqFNPem9w0WYA== -"@adobe/spectrum-css-workflow-icons@^1.1.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@adobe/spectrum-css-workflow-icons/-/spectrum-css-workflow-icons-1.2.0.tgz#cda8bbe873ba9317160458858ae979e5393e5550" - integrity sha512-STSQQHvoBM0kf1JrNL3KEt88RklIctaGyGOzwUTnhtTkT1jHLaF4FgxrPDCvr1AT8VOq1nGplKUCeyZ9vdUUmA== - "@azure/ms-rest-azure-env@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@azure/ms-rest-azure-env/-/ms-rest-azure-env-1.1.2.tgz#8505873afd4a1227ec040894a64fdd736b4a101f" @@ -254,110 +249,6 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@budibase/bbui@^1.58.13": - version "1.58.13" - resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.58.13.tgz#59df9c73def2d81c75dcbd2266c52c19db88dbd7" - integrity sha512-Zk6CKXdBfKsTVzA1Xs5++shdSSZLfphVpZuKVbjfzkgtuhyH7ruucexuSHEpFsxjW5rEKgKIBoRFzCK5vPvN0w== - dependencies: - markdown-it "^12.0.2" - quill "^1.3.7" - sirv-cli "^0.4.6" - svelte-flatpickr "^2.4.0" - svelte-portal "^1.0.0" - turndown "^7.0.0" - -"@budibase/client@^0.8.9": - version "0.8.10" - resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.8.10.tgz#18cd929dddfd2fa65c15e23871a26bccaa03049f" - integrity sha512-C/25rBAspQDk7Lp8w9icEcytgMAm8+7l+A4Lp7egpDJvrH+5jq2kVNuRRi3emAddCSTBmM0amIoS+PHUGvAa9Q== - dependencies: - "@budibase/string-templates" "^0.8.10" - regexparam "^1.3.0" - shortid "^2.2.15" - svelte-spa-router "^3.0.5" - -"@budibase/handlebars-helpers@^0.11.3": - version "0.11.3" - resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.3.tgz#b6e5c91b83e8906e7d7ff10ddde277a3d561016e" - integrity sha512-MS1ptZEYq8o9J3tNLM7cZ2RGSSJIer4GiMIUHtbBI3sC9UKqZebao1JYNfmZKpNjntuqhZKgjqc5GfnVIEjsYQ== - dependencies: - arr-flatten "^1.1.0" - array-sort "^0.1.4" - define-property "^1.0.0" - extend-shallow "^3.0.2" - "falsey" "^0.3.2" - for-in "^1.0.2" - for-own "^1.0.0" - get-object "^0.2.0" - get-value "^2.0.6" - handlebars "^4.0.11" - handlebars-utils "^1.0.6" - has-value "^1.0.0" - helper-date "^1.0.1" - helper-markdown "^1.0.0" - helper-md "^0.2.2" - html-tag "^2.0.0" - is-even "^1.0.0" - is-glob "^4.0.0" - is-number "^4.0.0" - kind-of "^6.0.0" - logging-helpers "^1.0.0" - micromatch "^3.1.4" - relative "^3.0.2" - striptags "^3.1.0" - to-gfm-code-block "^0.1.1" - year "^0.2.1" - -"@budibase/standard-components@^0.8.9": - version "0.8.10" - resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.8.10.tgz#ffde4e3bfe5afe14c242d7066328066500333b62" - integrity sha512-zXE9SbMFxrZ8tpYmTaBQEPwT+3xJ8p4QtDkSRfnEcxbWojNghh5ikn0897FpgnP7q9x+63tDQ0UCiUcNoiOk7w== - dependencies: - "@adobe/spectrum-css-workflow-icons" "^1.1.0" - "@budibase/bbui" "^1.58.13" - "@budibase/svelte-ag-grid" "^1.0.4" - "@spectrum-css/actionbutton" "^1.0.0-beta.1" - "@spectrum-css/button" "^3.0.0-beta.6" - "@spectrum-css/checkbox" "^3.0.0-beta.6" - "@spectrum-css/fieldlabel" "^3.0.0-beta.7" - "@spectrum-css/icon" "^3.0.0-beta.2" - "@spectrum-css/inputgroup" "^3.0.0-beta.7" - "@spectrum-css/menu" "^3.0.0-beta.5" - "@spectrum-css/page" "^3.0.0-beta.0" - "@spectrum-css/picker" "^1.0.0-beta.3" - "@spectrum-css/popover" "^3.0.0-beta.6" - "@spectrum-css/stepper" "^3.0.0-beta.7" - "@spectrum-css/textfield" "^3.0.0-beta.6" - "@spectrum-css/vars" "^3.0.0-beta.2" - apexcharts "^3.22.1" - flatpickr "^4.6.6" - loadicons "^1.0.0" - lodash.debounce "^4.0.8" - markdown-it "^12.0.2" - quill "^1.3.7" - remixicon "^2.5.0" - svelte-apexcharts "^1.0.2" - svelte-flatpickr "^3.1.0" - turndown "^7.0.0" - -"@budibase/string-templates@^0.8.10", "@budibase/string-templates@^0.8.9": - version "0.8.10" - resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.8.10.tgz#57b1cfb44d4bdac0ab3ef9a4912a6185e972711b" - integrity sha512-YUtbbAvLcxpeEiCs36cF5bkEDgpLaklvpuG/pcUIOxAPr1feqcN1KyFbuoSPihZOWXjXLgsujQerQ5xn8MUrhg== - dependencies: - "@budibase/handlebars-helpers" "^0.11.3" - dayjs "^1.10.4" - handlebars "^4.7.6" - handlebars-utils "^1.0.6" - lodash "^4.17.20" - -"@budibase/svelte-ag-grid@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@budibase/svelte-ag-grid/-/svelte-ag-grid-1.0.4.tgz#41cceec4bde2c4aea8b9da8f610fe36055c7709f" - integrity sha512-JZm6qujxnZpqw7Twbegr6se4sHhyWzN0Cibrk5bVBH32hBgzD6dd33fxwrjHKkWFxjys9wRT+cqYgYVlSt9E3w== - dependencies: - ag-grid-community "^24.0.0" - "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -885,11 +776,6 @@ path-to-regexp "^1.1.1" urijs "^1.19.0" -"@polka/url@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-0.5.0.tgz#b21510597fd601e5d7c95008b76bf0d254ebfd31" - integrity sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw== - "@sendgrid/client@^7.1.1": version "7.4.2" resolved "https://registry.yarnpkg.com/@sendgrid/client/-/client-7.4.2.tgz#204a9fbb5dc05a721a5d8cd8930f57f9f8e612b1" @@ -1002,73 +888,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== -"@spectrum-css/actionbutton@^1.0.0-beta.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/actionbutton/-/actionbutton-1.0.1.tgz#9c75da37ea6915919fb574c74bd60dacc03b6577" - integrity sha512-AUqtyNabHF451Aj9i3xz82TxS5Z6k1dttA68/1hMeU9kbPCSS4P6Viw3vaRGs9CSspuR8xnnhDgrq+F+zMy2Hw== - -"@spectrum-css/button@^3.0.0-beta.6": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/button/-/button-3.0.1.tgz#6db8c3e851baecd0f1c2d88fef37d49d01c6e643" - integrity sha512-YXrBtjIYisk4Vaxnp0RiE4gdElQX04P2mc4Pi2GlQ27dJKlHmufYcF+kAqGdtiyK5yjdN/vKRcC8y13aA4rusA== - -"@spectrum-css/checkbox@^3.0.0-beta.6": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/checkbox/-/checkbox-3.0.1.tgz#6f36377d8bd556989ddd1dec2506dc295c5fcda8" - integrity sha512-fI0q2Cp6yU4ORyE6JWUSMYNgEtGf6AjYViZ2Weg3UPTYBQuWdQd8J0ZTcH38pDMyARFPRdiXgQ3KnyX5Hk5huw== - -"@spectrum-css/fieldlabel@^3.0.0-beta.7": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/fieldlabel/-/fieldlabel-3.0.1.tgz#39f7c0f25cc2ff402afeff005341b0832f7c588c" - integrity sha512-LMfwrwIq8wEEvxFLobdLvXRwKrp8o9Fty4iJ9aYl2Rj1uXkfRd8qLz9HGZjLEE1OuJgoTBgamYABl7EvoA5PLw== - -"@spectrum-css/icon@^3.0.0-beta.2": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/icon/-/icon-3.0.1.tgz#e300a6fc353c85c6b5d6e7a364408a940c31b177" - integrity sha512-cGFtIrcQ/7tthdkHK1npuEFiCdYVHLqwmLxghUYQw8Tb8KgJaw3OBO1tpjgsUizexNgu26BjVRIbGxNWuBXIHQ== - -"@spectrum-css/inputgroup@^3.0.0-beta.7": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/inputgroup/-/inputgroup-3.0.1.tgz#8c5b257b57b3b2cf04e99355709365fa0d6838cc" - integrity sha512-asBRa1jTlld6plkcq4ySO+xl+OJlCMSOLoAFdSSIJowcSlCV0yDy7oeOhf5YQv9mMHFWTKlWUSoAKDZTguIPxA== - -"@spectrum-css/menu@^3.0.0-beta.5": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/menu/-/menu-3.0.1.tgz#2a376f991acc24e12ec892bb6b9db2650fc41fbe" - integrity sha512-Qjg0+1O0eC89sb/bRFq2AGnQ8XqhVy23TUXHyffNM8qdcMssnlny3QmhzjURCZKvx/Y5UytCpzhedPQqSpQwZg== - -"@spectrum-css/page@^3.0.0-beta.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/page/-/page-3.0.1.tgz#5e1c3dd5b1a1ee591f9d636b75f03665f542d846" - integrity sha512-LAlKF8km5BlsGPpZ2SNtwKOQIHn1lz0X93aczGZVZceOg73O4gyeoT5cx4vi1z+KtBRY5VMDWx3XgGtUwwjqwA== - dependencies: - "@spectrum-css/vars" "^3.0.1" - -"@spectrum-css/picker@^1.0.0-beta.3": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/picker/-/picker-1.0.1.tgz#98991198576d26bd14160824e7b6f3c278ff930b" - integrity sha512-Rv4/UBOdNW1gs7WVBCJnPD5VFly8MqP++psDX6kcugUIcfJy0GC3acvElotmKRlCDk8Qxks2W2A0jKeSgphTmA== - -"@spectrum-css/popover@^3.0.0-beta.6": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/popover/-/popover-3.0.1.tgz#5863c1efc53f98f9aba2de9186666780041303fc" - integrity sha512-LmOSj/yCwQQ9iGmCYnHiJsJR/HfPiGqI1Jl7pkKxBOCxYBMS/5+ans9vfCN2Qnd0eK7WSbfPg72S6mjye7db2Q== - -"@spectrum-css/stepper@^3.0.0-beta.7": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/stepper/-/stepper-3.0.1.tgz#7f270f53505e7dbe082591e8ea1c4c8f397e045a" - integrity sha512-IvZlGFJ8QPr9tUz5xvVN4hASaTRDPdKu9IIp25q/x0ecgSrKAM55e3EBWEYWy1H1JI3h+zlPnNRuK0VLhDbCYA== - -"@spectrum-css/textfield@^3.0.0-beta.6": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/textfield/-/textfield-3.0.1.tgz#e875b8e37817378ad08fc4af7d53026df38911e5" - integrity sha512-MUV5q87CVxbkNdSNoxGrFbgyKc51ft/WWf3aVEoPdPw5yBnXqFe1w1YmAit5zYDOOhhs58sCLAlUcCMlOpkgrA== - -"@spectrum-css/vars@^3.0.0-beta.2", "@spectrum-css/vars@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.1.tgz#561fd69098f896a647242dd8d6108af603bfa31e" - integrity sha512-l4oRcCOqInChYXZN6OQhpe3isk6l4OE6Ys8cgdlsiKp53suNoQxyyd9p/eGRbCjZgH3xQ8nK0t4DHa7QYC0S6w== - "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -1353,11 +1172,6 @@ adal-node@^0.1.28: xmldom ">= 0.1.x" xpath.js "~1.1.0" -ag-grid-community@^24.0.0: - version "24.1.0" - resolved "https://registry.yarnpkg.com/ag-grid-community/-/ag-grid-community-24.1.0.tgz#1e3cab51211822e08d56f03a491b7c0deaa398e6" - integrity sha512-pWnWphuDcejZ8ahf6C734EpCx3XQ6dHEZWMWTlCdHNT0mZBLJ4YKCGACX+ttAEtSX2MGM3G13JncvuratUlYag== - agent-base@6: version "6.0.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" @@ -1403,130 +1217,6 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" -ansi-bgblack@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bgblack/-/ansi-bgblack-0.1.1.tgz#a68ba5007887701b6aafbe3fa0dadfdfa8ee3ca2" - integrity sha1-poulAHiHcBtqr74/oNrf36juPKI= - dependencies: - ansi-wrap "0.1.0" - -ansi-bgblue@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bgblue/-/ansi-bgblue-0.1.1.tgz#67bdc04edc9b9b5278969da196dea3d75c8c3613" - integrity sha1-Z73ATtybm1J4lp2hlt6j11yMNhM= - dependencies: - ansi-wrap "0.1.0" - -ansi-bgcyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bgcyan/-/ansi-bgcyan-0.1.1.tgz#58489425600bde9f5507068dd969ebfdb50fe768" - integrity sha1-WEiUJWAL3p9VBwaN2Wnr/bUP52g= - dependencies: - ansi-wrap "0.1.0" - -ansi-bggreen@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bggreen/-/ansi-bggreen-0.1.1.tgz#4e3191248529943f4321e96bf131d1c13816af49" - integrity sha1-TjGRJIUplD9DIelr8THRwTgWr0k= - dependencies: - ansi-wrap "0.1.0" - -ansi-bgmagenta@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bgmagenta/-/ansi-bgmagenta-0.1.1.tgz#9b28432c076eaa999418672a3efbe19391c2c7a1" - integrity sha1-myhDLAduqpmUGGcqPvvhk5HCx6E= - dependencies: - ansi-wrap "0.1.0" - -ansi-bgred@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bgred/-/ansi-bgred-0.1.1.tgz#a76f92838382ba43290a6c1778424f984d6f1041" - integrity sha1-p2+Sg4OCukMpCmwXeEJPmE1vEEE= - dependencies: - ansi-wrap "0.1.0" - -ansi-bgwhite@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bgwhite/-/ansi-bgwhite-0.1.1.tgz#6504651377a58a6ececd0331994e480258e11ba8" - integrity sha1-ZQRlE3elim7OzQMxmU5IAljhG6g= - dependencies: - ansi-wrap "0.1.0" - -ansi-bgyellow@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bgyellow/-/ansi-bgyellow-0.1.1.tgz#c3fe2eb08cd476648029e6874d15a0b38f61d44f" - integrity sha1-w/4usIzUdmSAKeaHTRWgs49h1E8= - dependencies: - ansi-wrap "0.1.0" - -ansi-black@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-black/-/ansi-black-0.1.1.tgz#f6185e889360b2545a1ec50c0bf063fc43032453" - integrity sha1-9hheiJNgslRaHsUMC/Bj/EMDJFM= - dependencies: - ansi-wrap "0.1.0" - -ansi-blue@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-blue/-/ansi-blue-0.1.1.tgz#15b804990e92fc9ca8c5476ce8f699777c21edbf" - integrity sha1-FbgEmQ6S/JyoxUds6PaZd3wh7b8= - dependencies: - ansi-wrap "0.1.0" - -ansi-bold@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-bold/-/ansi-bold-0.1.1.tgz#3e63950af5acc2ae2e670e6f67deb115d1a5f505" - integrity sha1-PmOVCvWswq4uZw5vZ96xFdGl9QU= - dependencies: - ansi-wrap "0.1.0" - -ansi-colors@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-0.2.0.tgz#72c31de2a0d9a2ccd0cac30cc9823eeb2f6434b5" - integrity sha1-csMd4qDZoszQysMMyYI+6y9kNLU= - dependencies: - ansi-bgblack "^0.1.1" - ansi-bgblue "^0.1.1" - ansi-bgcyan "^0.1.1" - ansi-bggreen "^0.1.1" - ansi-bgmagenta "^0.1.1" - ansi-bgred "^0.1.1" - ansi-bgwhite "^0.1.1" - ansi-bgyellow "^0.1.1" - ansi-black "^0.1.1" - ansi-blue "^0.1.1" - ansi-bold "^0.1.1" - ansi-cyan "^0.1.1" - ansi-dim "^0.1.1" - ansi-gray "^0.1.1" - ansi-green "^0.1.1" - ansi-grey "^0.1.1" - ansi-hidden "^0.1.1" - ansi-inverse "^0.1.1" - ansi-italic "^0.1.1" - ansi-magenta "^0.1.1" - ansi-red "^0.1.1" - ansi-reset "^0.1.1" - ansi-strikethrough "^0.1.1" - ansi-underline "^0.1.1" - ansi-white "^0.1.1" - ansi-yellow "^0.1.1" - lazy-cache "^2.0.1" - -ansi-cyan@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" - integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= - dependencies: - ansi-wrap "0.1.0" - -ansi-dim@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-dim/-/ansi-dim-0.1.1.tgz#40de4c603aa8086d8e7a86b8ff998d5c36eefd6c" - integrity sha1-QN5MYDqoCG2Oeoa4/5mNXDbu/Ww= - dependencies: - ansi-wrap "0.1.0" - ansi-escapes@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -1539,62 +1229,6 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.11.0" -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-green@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-green/-/ansi-green-0.1.1.tgz#8a5d9a979e458d57c40e33580b37390b8e10d0f7" - integrity sha1-il2al55FjVfEDjNYCzc5C44Q0Pc= - dependencies: - ansi-wrap "0.1.0" - -ansi-grey@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-grey/-/ansi-grey-0.1.1.tgz#59d98b6ac2ba19f8a51798e9853fba78339a33c1" - integrity sha1-WdmLasK6GfilF5jphT+6eDOaM8E= - dependencies: - ansi-wrap "0.1.0" - -ansi-hidden@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-hidden/-/ansi-hidden-0.1.1.tgz#ed6a4c498d2bb7cbb289dbf2a8d1dcc8567fae0f" - integrity sha1-7WpMSY0rt8uyidvyqNHcyFZ/rg8= - dependencies: - ansi-wrap "0.1.0" - -ansi-inverse@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-inverse/-/ansi-inverse-0.1.1.tgz#b6af45826fe826bfb528a6c79885794355ccd269" - integrity sha1-tq9Fgm/oJr+1KKbHmIV5Q1XM0mk= - dependencies: - ansi-wrap "0.1.0" - -ansi-italic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-italic/-/ansi-italic-0.1.1.tgz#104743463f625c142a036739cf85eda688986f23" - integrity sha1-EEdDRj9iXBQqA2c5z4XtpoiYbyM= - dependencies: - ansi-wrap "0.1.0" - -ansi-magenta@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-magenta/-/ansi-magenta-0.1.1.tgz#063b5ba16fb3f23e1cfda2b07c0a89de11e430ae" - integrity sha1-BjtboW+z8j4c/aKwfAqJ3hHkMK4= - dependencies: - ansi-wrap "0.1.0" - -ansi-red@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" - integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= - dependencies: - ansi-wrap "0.1.0" - ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -1615,20 +1249,6 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== -ansi-reset@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-reset/-/ansi-reset-0.1.1.tgz#e7e71292c3c7ddcd4d62ef4a6c7c05980911c3b7" - integrity sha1-5+cSksPH3c1NYu9KbHwFmAkRw7c= - dependencies: - ansi-wrap "0.1.0" - -ansi-strikethrough@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-strikethrough/-/ansi-strikethrough-0.1.1.tgz#d84877140b2cff07d1c93ebce69904f68885e568" - integrity sha1-2Eh3FAss/wfRyT685pkE9oiF5Wg= - dependencies: - ansi-wrap "0.1.0" - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -1643,32 +1263,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-underline@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-underline/-/ansi-underline-0.1.1.tgz#dfc920f4c97b5977ea162df8ffb988308aaa71a4" - integrity sha1-38kg9Ml7WXfqFi34/7mIMIqqcaQ= - dependencies: - ansi-wrap "0.1.0" - -ansi-white@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-white/-/ansi-white-0.1.1.tgz#9c77b7c193c5ee992e6011d36ec4c921b4578944" - integrity sha1-nHe3wZPF7pkuYBHTbsTJIbRXiUQ= - dependencies: - ansi-wrap "0.1.0" - -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -ansi-yellow@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-yellow/-/ansi-yellow-0.1.1.tgz#cb9356f2f46c732f0e3199e6102955a77da83c1d" - integrity sha1-y5NW8vRscy8OMZnmEClVp32oPB0= - dependencies: - ansi-wrap "0.1.0" - any-base@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe" @@ -1695,18 +1289,6 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -apexcharts@^3.19.2, apexcharts@^3.22.1: - version "3.26.0" - resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.26.0.tgz#a78abc108b2e1b3086a738f0ec7c98e292f4a14b" - integrity sha512-zdYHs3k3tgmCn1BpYLj7rhGEndBYF33Pq1+g0ora37xAr+3act5CJrpdXM2jx2boVUyXgavoSp6sa8WpK7RkSA== - dependencies: - svg.draggable.js "^2.2.2" - svg.easing.js "^2.0.0" - svg.filter.js "^2.0.2" - svg.pathmorphing.js "^0.1.3" - svg.resize.js "^1.4.3" - svg.select.js "^3.0.1" - app-builder-bin@3.5.10: version "3.5.10" resolved "https://registry.yarnpkg.com/app-builder-bin/-/app-builder-bin-3.5.10.tgz#4a7f9999fccc0c435b6284ae1366bc76a17c4a7d" @@ -1758,18 +1340,13 @@ archive-type@^4.0.0: dependencies: file-type "^4.2.0" -argparse@^1.0.10, argparse@^1.0.7: +argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - args@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/args/-/args-5.0.1.tgz#4bf298df90a4799a09521362c579278cc2fdd761" @@ -1805,15 +1382,6 @@ array-equal@^1.0.0: resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= -array-sort@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-0.1.4.tgz#662855eaeb671b4188df4451b2f24a0753992b23" - integrity sha512-BNcM+RXxndPxiZ2rd76k6nyQLRZr2/B/sdi8pQ+Joafr5AH279L40dfokSUTp8O+AaqYjXWhblBWa2st2nc4fQ== - dependencies: - default-compare "^1.0.0" - get-value "^2.0.6" - kind-of "^5.0.2" - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1891,13 +1459,6 @@ atomic-sleep@^1.0.0: resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== -autolinker@~0.28.0: - version "0.28.1" - resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.28.1.tgz#0652b491881879f0775dace0cdca3233942a4e47" - integrity sha1-BlK0kYgYefB3XazgzcoyM5QqTkc= - dependencies: - gulp-header "^1.7.1" - aws-sdk@^2.767.0: version "2.771.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.771.0.tgz#ff4beb0a04d6ab1ae962c85dfb42e3e9bfe2b93b" @@ -2493,11 +2054,6 @@ clone-response@1.0.2, clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" -clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - co-body@^5.1.1: version "5.2.0" resolved "https://registry.yarnpkg.com/co-body/-/co-body-5.2.0.tgz#5a0a658c46029131e0e3a306f67647302f71c124" @@ -2562,11 +2118,6 @@ commander@^2.5.0, commander@^2.8.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - commoner@^0.10.1: version "0.10.8" resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5" @@ -2609,13 +2160,6 @@ concat-stream@^1.6.2: readable-stream "^2.2.2" typedarray "^0.0.6" -concat-with-sourcemaps@*: - version "1.1.0" - resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" - integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== - dependencies: - source-map "^0.6.1" - config-chain@^1.1.11: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" @@ -2636,11 +2180,6 @@ configstore@^5.0.1: write-file-atomic "^3.0.0" xdg-basedir "^4.0.0" -console-clear@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/console-clear/-/console-clear-1.1.1.tgz#995e20cbfbf14dd792b672cde387bd128d674bf7" - integrity sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ== - content-disposition@^0.5.2, content-disposition@~0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -2719,15 +2258,6 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" @@ -2775,23 +2305,11 @@ date-utils@*: resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64" integrity sha1-YfsWzcEnSzyayq/+n8ad+HIKK2Q= -date.js@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/date.js/-/date.js-0.3.3.tgz#ef1e92332f507a638795dbb985e951882e50bbda" - integrity sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw== - dependencies: - debug "~3.1.0" - dateformat@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -dayjs@^1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" - integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== - debug@4, debug@^4.0.1: version "4.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" @@ -2897,18 +2415,6 @@ decompress@^4.2.1: pify "^2.3.0" strip-dirs "^2.0.0" -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" @@ -2929,13 +2435,6 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -default-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" - integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== - dependencies: - kind-of "^5.0.2" - default-shell@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/default-shell/-/default-shell-1.0.1.tgz#752304bddc6174f49eb29cb988feea0b8813c8bc" @@ -3085,11 +2584,6 @@ domexception@^1.0.1: dependencies: webidl-conversions "^4.0.2" -domino@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.6.tgz#fe4ace4310526e5e7b9d12c7de01b7f485a57ffe" - integrity sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ== - dot-prop@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -3306,24 +2800,6 @@ ensure-error@^2.0.0: resolved "https://registry.yarnpkg.com/ensure-error/-/ensure-error-2.1.0.tgz#f11fbe383c0cf4a54850ac77acceb7bc06e0f99d" integrity sha512-+BMSJHw9gxiJAAp2ZR1E0TNcL09dD3lOvkl7WVm4+Y6xnes/pMetP/TzCHiDduh8ihNDjbGfuYxl7l4PA1xZ8A== -ent@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= - -entities@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" - integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== - -env-cmd@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/env-cmd/-/env-cmd-10.1.0.tgz#c7f5d3b550c9519f137fdac4dd8fb6866a8c8c4b" - integrity sha512-mMdWTT9XKN7yNth/6N6g2GuKuJTsKMDHlQFUDacb/heQRRWOTIZ42t1rMHnQu4jYxU1ajdTeJM+9eEETlqToMA== - dependencies: - commander "^4.0.0" - cross-spawn "^7.0.0" - env-paths@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" @@ -3348,11 +2824,6 @@ error-inject@^1.0.0: resolved "https://registry.yarnpkg.com/error-inject/-/error-inject-1.0.0.tgz#e2b3d91b54aed672f309d950d154850fa11d4f37" integrity sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc= -error-symbol@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/error-symbol/-/error-symbol-0.1.0.tgz#0a4dae37d600d15a29ba453d8ef920f1844333f6" - integrity sha1-Ck2uN9YA0VopukU9jvkg8YRDM/Y= - es-abstract@^1.18.0-next.2: version "1.18.0-next.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.3.tgz#56bc8b5cc36b2cca25a13be07f3c02c2343db6b7" @@ -3595,11 +3066,6 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -eventemitter3@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba" - integrity sha1-teEHm1n7XhuidxwKmTvgYKWMmbo= - events@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -3701,7 +3167,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@^3.0.2, extend@~3.0.2: +extend@^3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -3759,23 +3225,11 @@ falafel@^1.0.1: isarray "0.0.1" object-keys "^1.0.6" -"falsey@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/falsey/-/falsey-0.3.2.tgz#b21c90c5c34660fc192bf909575db95b6880d597" - integrity sha512-lxEuefF5MBIVDmE6XeqCdM4BWk1+vYmGZtkbKZ/VFcg6uBBw6fXNEbWmxCjDdQlFc9hy450nkiWwM3VAW6G1qg== - dependencies: - kind-of "^5.0.2" - fast-deep-equal@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" - integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig== - fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -3955,11 +3409,6 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" -flatpickr@^4.5.2, flatpickr@^4.6.6: - version "4.6.9" - resolved "https://registry.yarnpkg.com/flatpickr/-/flatpickr-4.6.9.tgz#9a13383e8a6814bda5d232eae3fcdccb97dc1499" - integrity sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw== - flatstr@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" @@ -3989,18 +3438,11 @@ for-each@^0.3.3: dependencies: is-callable "^1.1.3" -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= - dependencies: - for-in "^1.0.1" - foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -4059,11 +3501,6 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-exists-sync@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" - integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= - fs-extra@8.1.0, fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -4140,19 +3577,6 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" -get-object@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/get-object/-/get-object-0.2.0.tgz#d92ff7d5190c64530cda0543dac63a3d47fe8c0c" - integrity sha1-2S/31RkMZFMM2gVD2sY6PUf+jAw= - dependencies: - is-number "^2.0.2" - isobject "^0.2.0" - -get-port@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= - get-stream@3.0.0, get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -4350,35 +3774,6 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gulp-header@^1.7.1: - version "1.8.12" - resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" - integrity sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ== - dependencies: - concat-with-sourcemaps "*" - lodash.template "^4.4.0" - through2 "^2.0.0" - -handlebars-utils@^1.0.2, handlebars-utils@^1.0.4, handlebars-utils@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/handlebars-utils/-/handlebars-utils-1.0.6.tgz#cb9db43362479054782d86ffe10f47abc76357f9" - integrity sha512-d5mmoQXdeEqSKMtQQZ9WkiUcO1E3tPbWxluCK9hVgIDPzQa9WsKo3Lbe/sGflTe7TomHEeZaOgwIkyIr1kfzkw== - dependencies: - kind-of "^6.0.0" - typeof-article "^0.1.1" - -handlebars@^4.0.11, handlebars@^4.7.6: - version "4.7.7" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" - integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== - dependencies: - minimist "^1.2.5" - neo-async "^2.6.0" - source-map "^0.6.1" - wordwrap "^1.0.0" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -4467,39 +3862,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -helper-date@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/helper-date/-/helper-date-1.0.1.tgz#12fedea3ad8e44a7ca4c4efb0ff4104a5120cffb" - integrity sha512-wU3VOwwTJvGr/w5rZr3cprPHO+hIhlblTJHD6aFBrKLuNbf4lAmkawd2iK3c6NbJEvY7HAmDpqjOFSI5/+Ey2w== - dependencies: - date.js "^0.3.1" - handlebars-utils "^1.0.4" - moment "^2.18.1" - -helper-markdown@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/helper-markdown/-/helper-markdown-1.0.0.tgz#ee7e9fc554675007d37eb90f7853b13ce74f3e10" - integrity sha512-AnDqMS4ejkQK0MXze7pA9TM3pu01ZY+XXsES6gEE0RmCGk5/NIfvTn0NmItfyDOjRAzyo9z6X7YHbHX4PzIvOA== - dependencies: - handlebars-utils "^1.0.2" - highlight.js "^9.12.0" - remarkable "^1.7.1" - -helper-md@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/helper-md/-/helper-md-0.2.2.tgz#c1f59d7e55bbae23362fd8a0e971607aec69d41f" - integrity sha1-wfWdflW7riM2L9ig6XFgeuxp1B8= - dependencies: - ent "^2.2.0" - extend-shallow "^2.0.1" - fs-exists-sync "^0.1.0" - remarkable "^1.6.2" - -highlight.js@^9.12.0: - version "9.18.5" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" - integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== - hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" @@ -4529,14 +3891,6 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== -html-tag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/html-tag/-/html-tag-2.0.0.tgz#36c3bc8d816fd30b570d5764a497a641640c2fed" - integrity sha512-XxzooSo6oBoxBEUazgjdXj7VwTn/iSTSZzTYKzYY6I916tkaYzypHxy+pbVU1h+0UQ9JlVf5XkNQyxOAiiQO1g== - dependencies: - is-self-closing "^1.0.1" - kind-of "^6.0.0" - http-assert@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.1.tgz#c5f725d677aa7e873ef736199b89686cceb37878" @@ -4694,11 +4048,6 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -info-symbol@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/info-symbol/-/info-symbol-0.1.0.tgz#27841d72867ddb4242cd612d79c10633881c6a78" - integrity sha1-J4QdcoZ920JCzWEtecEGM4gcang= - inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" @@ -4775,13 +4124,6 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-arguments@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" - integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== - dependencies: - call-bind "^1.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -4877,13 +4219,6 @@ is-docker@^2.0.0: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== -is-even@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-even/-/is-even-1.0.0.tgz#76b5055fbad8d294a86b6a949015e1c97b717c06" - integrity sha1-drUFX7rY0pSoa2qUkBXhyXtxfAY= - dependencies: - is-odd "^0.1.2" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -4961,13 +4296,6 @@ is-number-object@^1.0.4: resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== -is-number@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -4975,11 +4303,6 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4995,13 +4318,6 @@ is-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= -is-odd@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-0.1.2.tgz#bc573b5ce371ef2aad6e6f49799b72bef13978a7" - integrity sha1-vFc7XONx7yqtbm9JeZtyvvE5eKc= - dependencies: - is-number "^3.0.0" - is-path-inside@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" @@ -5019,7 +4335,7 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-regex@^1.0.4, is-regex@^1.1.2: +is-regex@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== @@ -5032,13 +4348,6 @@ is-retry-allowed@^1.1.0: resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== -is-self-closing@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-self-closing/-/is-self-closing-1.0.1.tgz#5f406b527c7b12610176320338af0fa3896416e4" - integrity sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg== - dependencies: - self-closing-tags "^1.0.1" - is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -5117,11 +4426,6 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isobject@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-0.2.0.tgz#a3432192f39b910b5f02cc989487836ec70aa85e" - integrity sha1-o0MhkvObkQtfAsyYlIeDbscKqF4= - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -5798,7 +5102,7 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= @@ -5812,7 +5116,7 @@ kind-of@^4.0.0: dependencies: is-buffer "^1.1.5" -kind-of@^5.0.0, kind-of@^5.0.2: +kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== @@ -5822,7 +5126,7 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== -kleur@^3.0.0, kleur@^3.0.3: +kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== @@ -5953,13 +5257,6 @@ latest-version@^5.0.0: dependencies: package-json "^6.3.0" -lazy-cache@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" - integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ= - dependencies: - set-getter "^0.1.0" - lazy-val@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65" @@ -6131,13 +5428,6 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= -linkify-it@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8" - integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ== - dependencies: - uc.micro "^1.0.1" - load-bmfont@^1.3.1, load-bmfont@^1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.1.tgz#c0f5f4711a1e2ccff725a7b6078087ccfcddd3e9" @@ -6162,16 +5452,6 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -loadicons@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/loadicons/-/loadicons-1.0.0.tgz#79fd9b08ef2933988c94068cbd246ef3f21cbd04" - integrity sha512-KSywiudfuOK5sTdhNMM8hwRpMxZ5TbQlU4ZijMxUFwRW7jpxUmb9YJoLIzDn7+xuxeLzCZWBmLJS2JDjDWCpsw== - -local-access@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/local-access/-/local-access-1.1.0.tgz#e007c76ba2ca83d5877ba1a125fc8dfe23ba4798" - integrity sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw== - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -6187,11 +5467,6 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -6262,21 +5537,6 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash.template@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" - integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" - integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.without@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" @@ -6297,40 +5557,11 @@ lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.3: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@^4.17.19, lodash@^4.17.20: +lodash@^4.17.19: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-ok@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/log-ok/-/log-ok-0.1.1.tgz#bea3dd36acd0b8a7240d78736b5b97c65444a334" - integrity sha1-vqPdNqzQuKckDXhza1uXxlREozQ= - dependencies: - ansi-green "^0.1.1" - success-symbol "^0.1.0" - -log-utils@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/log-utils/-/log-utils-0.2.1.tgz#a4c217a0dd9a50515d9b920206091ab3d4e031cf" - integrity sha1-pMIXoN2aUFFdm5ICBgkas9TgMc8= - dependencies: - ansi-colors "^0.2.0" - error-symbol "^0.1.0" - info-symbol "^0.1.0" - log-ok "^0.1.1" - success-symbol "^0.1.0" - time-stamp "^1.0.1" - warning-symbol "^0.1.0" - -logging-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/logging-helpers/-/logging-helpers-1.0.0.tgz#b5a37b32ad53eb0137c58c7898a47b175ddb7c36" - integrity sha512-qyIh2goLt1sOgQQrrIWuwkRjUx4NUcEqEGAcYqD8VOnOC6ItwkrVE8/tA4smGpjzyp4Svhc6RodDp9IO5ghpyA== - dependencies: - isobject "^3.0.0" - log-utils "^0.2.1" - loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -6426,17 +5657,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -markdown-it@^12.0.2: - version "12.0.4" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.4.tgz#eec8247d296327eac3ba9746bdeec9cfcc751e33" - integrity sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q== - dependencies: - argparse "^2.0.1" - entities "~2.1.0" - linkify-it "^3.0.1" - mdurl "^1.0.1" - uc.micro "^1.0.5" - matcher@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" @@ -6444,11 +5664,6 @@ matcher@^3.0.0: dependencies: escape-string-regexp "^4.0.0" -mdurl@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -6558,11 +5773,6 @@ mime@^1.3.4, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.3.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== - mime@^2.4.6: version "2.4.6" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" @@ -6617,11 +5827,6 @@ mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4: dependencies: minimist "^1.2.5" -moment@^2.18.1: - version "2.29.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== - mongodb@3.6.3: version "3.6.3" resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.6.3.tgz#eddaed0cc3598474d7a15f0f2a5b04848489fd05" @@ -6640,11 +5845,6 @@ mri@1.1.4: resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w== -mri@^1.1.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6" - integrity sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6706,11 +5906,6 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^2.1.0: - version "2.1.11" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" - integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -6758,11 +5953,6 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.6.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" - integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== - new-github-issue-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/new-github-issue-url/-/new-github-issue-url-0.2.1.tgz#e17be1f665a92de465926603e44b9f8685630c1d" @@ -6927,14 +6117,6 @@ object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -7145,11 +6327,6 @@ pako@^1.0.5: resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== -parchment@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/parchment/-/parchment-1.1.4.tgz#aeded7ab938fe921d4c34bc339ce1168bc2ffde5" - integrity sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -7233,11 +6410,6 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -7823,27 +6995,6 @@ quick-format-unescaped@^4.0.1: resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz#437a5ea1a0b61deb7605f8ab6a8fd3858dbeb701" integrity sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A== -quill-delta@^3.6.2: - version "3.6.3" - resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-3.6.3.tgz#b19fd2b89412301c60e1ff213d8d860eac0f1032" - integrity sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg== - dependencies: - deep-equal "^1.0.1" - extend "^3.0.2" - fast-diff "1.1.2" - -quill@^1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.7.tgz#da5b2f3a2c470e932340cdbf3668c9f21f9286e8" - integrity sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g== - dependencies: - clone "^2.1.1" - deep-equal "^1.0.1" - eventemitter3 "^2.0.3" - extend "^3.0.2" - parchment "^1.1.4" - quill-delta "^3.6.2" - raw-body@^2.2.0: version "2.4.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" @@ -8020,19 +7171,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp.prototype.flags@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" - integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexparam@1.3.0, regexparam@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f" - integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g== - regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -8052,26 +7190,6 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" -relative@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/relative/-/relative-3.0.2.tgz#0dcd8ec54a5d35a3c15e104503d65375b5a5367f" - integrity sha1-Dc2OxUpdNaPBXhBFA9ZTdbWlNn8= - dependencies: - isobject "^2.0.0" - -remarkable@^1.6.2, remarkable@^1.7.1: - version "1.7.4" - resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.4.tgz#19073cb960398c87a7d6546eaa5e50d2022fcd00" - integrity sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg== - dependencies: - argparse "^1.0.10" - autolinker "~0.28.0" - -remixicon@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/remixicon/-/remixicon-2.5.0.tgz#b5e245894a1550aa23793f95daceadbf96ad1a41" - integrity sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww== - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -8258,13 +7376,6 @@ rxjs@^6.6.0: dependencies: tslib "^1.9.0" -sade@^1.4.0: - version "1.7.4" - resolved "https://registry.yarnpkg.com/sade/-/sade-1.7.4.tgz#ea681e0c65d248d2095c90578c03ca0bb1b54691" - integrity sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA== - dependencies: - mri "^1.1.0" - safe-buffer@*, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -8343,11 +7454,6 @@ seek-bzip@^1.0.5: dependencies: commander "^2.8.1" -self-closing-tags@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/self-closing-tags/-/self-closing-tags-1.0.1.tgz#6c5fa497994bb826b484216916371accee490a5d" - integrity sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA== - semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" @@ -8399,13 +7505,6 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= -set-getter@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" - integrity sha1-12nBgsnVpR9AkUXy+6guXoboA3Y= - dependencies: - to-object-path "^0.3.0" - set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" @@ -8438,23 +7537,11 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - shell-env@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/shell-env/-/shell-env-0.3.0.tgz#2250339022989165bda4eb7bf383afeaaa92dc34" @@ -8476,39 +7563,11 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shortid@^2.2.15: - version "2.2.16" - resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.16.tgz#b742b8f0cb96406fd391c76bfc18a67a57fe5608" - integrity sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g== - dependencies: - nanoid "^2.1.0" - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== -sirv-cli@^0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/sirv-cli/-/sirv-cli-0.4.6.tgz#c28ab20deb3b34637f5a60863dc350f055abca04" - integrity sha512-/Vj85/kBvPL+n9ibgX6FicLE8VjidC1BhlX67PYPBfbBAphzR6i0k0HtU5c2arejfU3uzq8l3SYPCwl1x7z6Ww== - dependencies: - console-clear "^1.1.0" - get-port "^3.2.0" - kleur "^3.0.0" - local-access "^1.0.1" - sade "^1.4.0" - sirv "^0.4.6" - tinydate "^1.0.0" - -sirv@^0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-0.4.6.tgz#185e44eb93d24009dd183b7494285c5180b81f22" - integrity sha512-rYpOXlNbpHiY4nVXxuDf4mXPvKz1reZGap/LkWp9TvcZ84qD/nPBjjH/6GZsgIjVMbOslnY8YYULAyP8jMn1GQ== - dependencies: - "@polka/url" "^0.5.0" - mime "^2.3.1" - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -8899,11 +7958,6 @@ strip-outer@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -striptags@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.1.1.tgz#c8c3e7fdd6fb4bb3a32a3b752e5b5e3e38093ebd" - integrity sha1-yMPn/db7S7OjKjt1LltePjgJPr0= - sublevel-pouchdb@7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/sublevel-pouchdb/-/sublevel-pouchdb-7.2.2.tgz#49e46cd37883bf7ff5006d7c5b9bcc7bcc1f422f" @@ -8914,11 +7968,6 @@ sublevel-pouchdb@7.2.2: ltgt "2.2.1" readable-stream "1.1.14" -success-symbol@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897" - integrity sha1-JAIuSG878c3KCUKDt2nEctO3KJc= - sumchecker@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42" @@ -8971,99 +8020,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -svelte-apexcharts@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/svelte-apexcharts/-/svelte-apexcharts-1.0.2.tgz#4e000f8b8f7c901c05658c845457dfc8314d54c1" - integrity sha512-6qlx4rE+XsonZ0FZudfwqOQ34Pq+3wpxgAD75zgEmGoYhYBJcwmikTuTf3o8ZBsZue9U/pAwhNy3ed1Bkq1gmA== - dependencies: - apexcharts "^3.19.2" - -svelte-flatpickr@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/svelte-flatpickr/-/svelte-flatpickr-2.4.0.tgz#190871fc3305956c8c8fd3601cd036b8ac71ef49" - integrity sha512-UUC5Te+b0qi4POg7VDwfGh0m5W3Hf64OwkfOTj6FEe/dYZN4cBzpQ82EuuQl0CTbbBAsMkcjJcixV1d2V6EHCQ== - dependencies: - flatpickr "^4.5.2" - -svelte-flatpickr@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/svelte-flatpickr/-/svelte-flatpickr-3.1.0.tgz#ad83588430dbd55196a1a258b8ba27e7f9c1ee37" - integrity sha512-zKyV+ukeVuJ8CW0Ing3T19VSekc4bPkou/5Riutt1yATrLvSsanNqcgqi7Q5IePvIoOF9GJ5OtHvn1qK9Wx9BQ== - dependencies: - flatpickr "^4.5.2" - -svelte-portal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/svelte-portal/-/svelte-portal-1.0.0.tgz#36a47c5578b1a4d9b4dc60fa32a904640ec4cdd3" - integrity sha512-nHf+DS/jZ6jjnZSleBMSaZua9JlG5rZv9lOGKgJuaZStfevtjIlUJrkLc3vbV8QdBvPPVmvcjTlazAzfKu0v3Q== - -svelte-spa-router@^3.0.5: - version "3.1.0" - resolved "https://registry.yarnpkg.com/svelte-spa-router/-/svelte-spa-router-3.1.0.tgz#a929f0def7e12c41f32bc356f91685aeadcd75bf" - integrity sha512-jlM/xwjn57mylr+pzHYCOOy+IPQauT46gOucNGTBu6jHcFXu3F+oaojN4PXC1LYizRGxFB6QA0qnYbZnRfX7Sg== - dependencies: - regexparam "1.3.0" - svelte@3.30.0: version "3.30.0" resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.30.0.tgz#cbde341e96bf34f4ac73c8f14f8a014e03bfb7d6" integrity sha512-z+hdIACb9TROGvJBQWcItMtlr4s0DBUgJss6qWrtFkOoIInkG+iAMo/FJZQFyDBQZc+dul2+TzYSi/tpTT5/Ag== -svg.draggable.js@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/svg.draggable.js/-/svg.draggable.js-2.2.2.tgz#c514a2f1405efb6f0263e7958f5b68fce50603ba" - integrity sha512-JzNHBc2fLQMzYCZ90KZHN2ohXL0BQJGQimK1kGk6AvSeibuKcIdDX9Kr0dT9+UJ5O8nYA0RB839Lhvk4CY4MZw== - dependencies: - svg.js "^2.0.1" - -svg.easing.js@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/svg.easing.js/-/svg.easing.js-2.0.0.tgz#8aa9946b0a8e27857a5c40a10eba4091e5691f12" - integrity sha1-iqmUawqOJ4V6XEChDrpAkeVpHxI= - dependencies: - svg.js ">=2.3.x" - -svg.filter.js@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/svg.filter.js/-/svg.filter.js-2.0.2.tgz#91008e151389dd9230779fcbe6e2c9a362d1c203" - integrity sha1-kQCOFROJ3ZIwd5/L5uLJo2LRwgM= - dependencies: - svg.js "^2.2.5" - -svg.js@>=2.3.x, svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/svg.js/-/svg.js-2.7.1.tgz#eb977ed4737001eab859949b4a398ee1bb79948d" - integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA== - -svg.pathmorphing.js@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/svg.pathmorphing.js/-/svg.pathmorphing.js-0.1.3.tgz#c25718a1cc7c36e852ecabc380e758ac09bb2b65" - integrity sha512-49HWI9X4XQR/JG1qXkSDV8xViuTLIWm/B/7YuQELV5KMOPtXjiwH4XPJvr/ghEDibmLQ9Oc22dpWpG0vUDDNww== - dependencies: - svg.js "^2.4.0" - -svg.resize.js@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/svg.resize.js/-/svg.resize.js-1.4.3.tgz#885abd248e0cd205b36b973c4b578b9a36f23332" - integrity sha512-9k5sXJuPKp+mVzXNvxz7U0uC9oVMQrrf7cFsETznzUDDm0x8+77dtZkWdMfRlmbkEEYvUn9btKuZ3n41oNA+uw== - dependencies: - svg.js "^2.6.5" - svg.select.js "^2.1.2" - -svg.select.js@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/svg.select.js/-/svg.select.js-2.1.2.tgz#e41ce13b1acff43a7441f9f8be87a2319c87be73" - integrity sha512-tH6ABEyJsAOVAhwcCjF8mw4crjXSI1aa7j2VQR8ZuJ37H2MBUbyeqYr5nEO7sSN3cy9AR9DUwNg0t/962HlDbQ== - dependencies: - svg.js "^2.2.5" - -svg.select.js@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/svg.select.js/-/svg.select.js-3.0.1.tgz#a4198e359f3825739226415f82176a90ea5cc917" - integrity sha512-h5IS/hKkuVCbKSieR9uQCj9w+zLHoPh+ce19bBYyqF53g6mnPB8sAtIbe1s9dh2S2fCmYX2xel1Ln3PJBbK4kw== - dependencies: - svg.js "^2.6.5" - symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -9218,11 +8179,6 @@ through@^2.3.6, through@^2.3.8, through@~2.3.4: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -time-stamp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - timed-out@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -9243,11 +8199,6 @@ tinycolor2@^1.4.1: resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803" integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA== -tinydate@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/tinydate/-/tinydate-1.3.0.tgz#e6ca8e5a22b51bb4ea1c3a2a4fd1352dbd4c57fb" - integrity sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w== - tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -9270,11 +8221,6 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= -to-gfm-code-block@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz#25d045a5fae553189e9637b590900da732d8aa82" - integrity sha1-JdBFpfrlUxielje1kJANpzLYqoI= - to-json-schema@0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/to-json-schema/-/to-json-schema-0.2.5.tgz#ef3c3f11ad64460dcfbdbafd0fd525d69d62a98f" @@ -9391,13 +8337,6 @@ tunnel@0.0.6, tunnel@^0.0.6: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== -turndown@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/turndown/-/turndown-7.0.0.tgz#19b2a6a2d1d700387a1e07665414e4af4fec5225" - integrity sha512-G1FfxfR0mUNMeGjszLYl3kxtopC4O9DRRiMlMDDVHvU1jaBkGFg4qxIyjIk2aiKLHyDyZvZyu4qBO2guuYBy3Q== - dependencies: - domino "^2.1.6" - tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -9450,23 +8389,6 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typeof-article@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/typeof-article/-/typeof-article-0.1.1.tgz#9f07e733c3fbb646ffa9e61c08debacd460e06af" - integrity sha1-nwfnM8P7tkb/qeYcCN66zUYOBq8= - dependencies: - kind-of "^3.1.0" - -uc.micro@^1.0.1, uc.micro@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" - integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== - -uglify-js@^3.1.4: - version "3.13.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.2.tgz#fe10319861bccc8682bfe2e8151fbdd8aa921c44" - integrity sha512-SbMu4D2Vo95LMC/MetNaso1194M1htEA+JrqE9Hk+G2DhI+itfS9TRu9ZKeCahLDNa/J3n4MqUJ/fOHMzQpRWw== - unbox-primitive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.0.tgz#eeacbc4affa28e9b3d36b5eaeccc50b3251b1d3f" @@ -9711,11 +8633,6 @@ walker@^1.0.7, walker@~1.0.5: dependencies: makeerror "1.0.x" -warning-symbol@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/warning-symbol/-/warning-symbol-0.1.0.tgz#bb31dd11b7a0f9d67ab2ed95f457b65825bbad21" - integrity sha1-uzHdEbeg+dZ6su2V9Fe2WCW7rSE= - webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -9774,13 +8691,6 @@ which@^1.2.9, which@^1.3.0: dependencies: isexe "^2.0.0" -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - widest-line@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" @@ -9793,11 +8703,6 @@ word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - worker-farm@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" @@ -10036,11 +8941,6 @@ yauzl@^2.10.0, yauzl@^2.4.2: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" -year@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/year/-/year-0.2.1.tgz#4083ae520a318b23ec86037f3000cb892bdf9bb0" - integrity sha1-QIOuUgoxiyPshgN/MADLiSvfm7A= - ylru@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" diff --git a/packages/worker/package.json b/packages/worker/package.json index 8f9e301399..5ab414dab1 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -19,6 +19,7 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { + "@budibase/auth": "0.0.1", "@koa/router": "^8.0.0", "aws-sdk": "^2.811.0", "bcryptjs": "^2.4.3", diff --git a/packages/worker/src/api/controllers/admin/auth.js b/packages/worker/src/api/controllers/admin/auth.js index f6b25091ac..07b08c7d1f 100644 --- a/packages/worker/src/api/controllers/admin/auth.js +++ b/packages/worker/src/api/controllers/admin/auth.js @@ -1,9 +1,15 @@ const jwt = require("jsonwebtoken") const CouchDB = require("../../../db") -const passport = require("koa-passport") +const passport = require("@budibase/auth") exports.authenticate = async (ctx, next) => { - return passport.authenticate("local", (err, user, info, status) => { + return passport.authenticate("local", async (err, user, info, status) => { + // TODO: better + if (err) { + ctx.throw(err) + } + + // await ctx.login(user) ctx.body = { err, user, diff --git a/packages/worker/src/api/routes/admin/auth.js b/packages/worker/src/api/routes/admin/auth.js deleted file mode 100644 index ca41e9e19e..0000000000 --- a/packages/worker/src/api/routes/admin/auth.js +++ /dev/null @@ -1,8 +0,0 @@ -// const Router = require("@koa/router") -// const controller = require("../controllers/auth") - -// const router = Router() - -// router.post("/api/authenticate", controller.authenticate) - -// module.exports = router diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js index cf3a5c021a..5a6aaf77e6 100644 --- a/packages/worker/src/api/routes/admin/index.js +++ b/packages/worker/src/api/routes/admin/index.js @@ -1,15 +1,16 @@ const Router = require("@koa/router") +const passport = require("@budibase/auth") const controller = require("../../controllers/admin") const authController = require("../../controllers/admin/auth") -const authorized = require("../../../middleware/authorized") +const authenticated = require("../../../middleware/authenticated") const router = Router() router - .post("/api/admin/users", authorized, controller.userSave) + .post("/api/admin/users", authenticated, controller.userSave) .post("/api/admin/authenticate", authController.authenticate) - .delete("/api/admin/users/:email", authorized, controller.userDelete) - .get("/api/admin/users", authorized, controller.userFetch) - .get("/api/admin/users/:email", authorized, controller.userFind) + .delete("/api/admin/users/:email", authenticated, controller.userDelete) + .get("/api/admin/users", passport.authenticate("jwt"), controller.userFetch) + .get("/api/admin/users/:email", authenticated, controller.userFind) module.exports = router diff --git a/packages/worker/src/index.js b/packages/worker/src/index.js index 199bb1d31b..aad8bf54f7 100644 --- a/packages/worker/src/index.js +++ b/packages/worker/src/index.js @@ -1,7 +1,7 @@ const Koa = require("koa") const destroyable = require("server-destroy") const koaBody = require("koa-body") -const passport = require("koa-passport") +const passport = require("@budibase/auth") const logger = require("koa-pino-logger") const http = require("http") const api = require("./api") @@ -26,7 +26,6 @@ app.use( ) // authentication -require("./middleware/auth") app.use(passport.initialize()) app.use(passport.session()) diff --git a/packages/worker/src/middleware/auth/google.js b/packages/worker/src/middleware/auth/google.js deleted file mode 100644 index fd33bc89a3..0000000000 --- a/packages/worker/src/middleware/auth/google.js +++ /dev/null @@ -1,13 +0,0 @@ -// const GoogleStrategy = require("passport-google-auth").Strategy - -exports.options = { - clientId: "your-client-id", - clientSecret: "your-secret", - callbackURL: - "http://localhost:" + (process.env.PORT || 3000) + "/auth/google/callback", -} - -exports.authenticate = async function(token, tokenSecret, profile, done) { - // retrieve user ... - // fetchUser().then(user => done(null, user)) -} diff --git a/packages/worker/src/middleware/auth/index.js b/packages/worker/src/middleware/auth/index.js deleted file mode 100644 index 3eac2badbf..0000000000 --- a/packages/worker/src/middleware/auth/index.js +++ /dev/null @@ -1,20 +0,0 @@ -const passport = require("koa-passport") -const LocalStrategy = require("passport-local").Strategy -const JwtStrategy = require("passport-jwt").Strategy -const GoogleStrategy = require("passport-google-oauth").Strategy -const jwt = require("./jwt") -const local = require("./local") -const google = require("./google") - -// Strategies -passport.use(new LocalStrategy(local.options, local.authenticate)) -passport.use(new JwtStrategy(jwt.options, jwt.authenticate)) -// passport.use(new GoogleStrategy(google.options, google.authenticate)) - -// exports.middleware = async (ctx, next) => { -// if (ctx.isAuthenticated()) { -// return next() -// } else { -// ctx.throw(403, "Not Authenticated") -// } -// } diff --git a/packages/worker/src/middleware/auth/jwt.js b/packages/worker/src/middleware/auth/jwt.js deleted file mode 100644 index 8313d5abca..0000000000 --- a/packages/worker/src/middleware/auth/jwt.js +++ /dev/null @@ -1,38 +0,0 @@ -const jwt = require("passport-jwt") -const env = require("../../environment") -const { getCookieName } = require("../../../../server/src/utilities") - -const ExtractJWT = jwt.ExtractJwt - -exports.options = { - jwtFromRequest: function(ctx) { - return ctx.cookies.get("budibase") - }, - // TODO: fix - secretOrKey: env.JWT_SECRET || "funky", -} - -exports.authenticate = async function(jwt, done) { - console.log(jwt) - done({ name: "joe" }) - // const appId = ctx.appId - // if (!appId) ctx.throw(400, "No appId") - - // const { email, password } = ctx.request.body - - // if (!email) ctx.throw(400, "Email Required.") - // if (!password) ctx.throw(400, "Password Required.") - - // // Check the user exists in the instance DB by email - // const db = new CouchDB(appId) - // const app = await db.get(appId) - - // let dbUser - // try { - // dbUser = await db.get(generateUserID(email)) - // } catch (_) { - // // do not want to throw a 404 - as this could be - // // used to determine valid emails - // ctx.throw(401, INVALID_ERR) - // } -} diff --git a/packages/worker/src/middleware/authorized.js b/packages/worker/src/middleware/authorized.js index 86a5ab27db..716f55fbd5 100644 --- a/packages/worker/src/middleware/authorized.js +++ b/packages/worker/src/middleware/authorized.js @@ -3,5 +3,5 @@ * a global user record. */ module.exports = async (ctx, next) => { - next() + return next() } From f135aa9db439aa3a94d9ac236777aab9ca17d4c9 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 7 Apr 2021 15:15:05 +0100 Subject: [PATCH 08/65] JWT auth on admin endpoints --- packages/auth/src/index.js | 3 +-- packages/auth/src/middleware/authenticated.js | 2 +- packages/auth/src/middleware/index.js | 6 ++--- .../src/middleware/{ => passport}/google.js | 2 +- .../auth/src/middleware/{ => passport}/jwt.js | 5 +--- .../src/middleware/{ => passport}/local.js | 8 +++--- .../worker/src/api/controllers/admin/auth.js | 25 ++++++++++--------- packages/worker/src/api/routes/admin/index.js | 15 ++++++++--- 8 files changed, 35 insertions(+), 31 deletions(-) rename packages/auth/src/middleware/{ => passport}/google.js (91%) rename packages/auth/src/middleware/{ => passport}/jwt.js (71%) rename packages/auth/src/middleware/{ => passport}/local.js (88%) diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 778d4fb32e..3088008086 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -5,7 +5,6 @@ const JwtStrategy = require("passport-jwt").Strategy const CouchDB = require("./db") const { StaticDatabases } = require("./db/utils") const { jwt, local, google } = require("./middleware") -const hashing = require("./hashing") // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) @@ -26,6 +25,6 @@ passport.deserializeUser(async (user, done) => { } }) -// exports.hashing = hashing +// exports.Cookies = Cookies module.exports = passport diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js index f7ff086b67..7797649b18 100644 --- a/packages/auth/src/middleware/authenticated.js +++ b/packages/auth/src/middleware/authenticated.js @@ -22,7 +22,7 @@ module.exports = async (ctx, next) => { const cookieAppId = ctx.cookies.get(Cookies.CurrentApp) // const builtinRoles = getBuiltinRoles() if (appId && cookieAppId !== appId) { - setCookie(ctx, appId, "currentapp") + setCookie(ctx, appId, Cookies.CurrentApp) } else if (cookieAppId) { appId = cookieAppId } diff --git a/packages/auth/src/middleware/index.js b/packages/auth/src/middleware/index.js index a9d07516ed..9d822e5937 100644 --- a/packages/auth/src/middleware/index.js +++ b/packages/auth/src/middleware/index.js @@ -1,6 +1,6 @@ -const jwt = require("./jwt") -const local = require("./local") -const google = require("./google") +const jwt = require("./passport/jwt") +const local = require("./passport/local") +const google = require("./passport/google") module.exports = { google, diff --git a/packages/auth/src/middleware/google.js b/packages/auth/src/middleware/passport/google.js similarity index 91% rename from packages/auth/src/middleware/google.js rename to packages/auth/src/middleware/passport/google.js index 008d4a6816..1ee6583b59 100644 --- a/packages/auth/src/middleware/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -1,4 +1,4 @@ -const CouchDB = require("../db") +// const CouchDB = require("../db") exports.options = { clientId: process.env.GOOGLE_CLIENT_ID, diff --git a/packages/auth/src/middleware/jwt.js b/packages/auth/src/middleware/passport/jwt.js similarity index 71% rename from packages/auth/src/middleware/jwt.js rename to packages/auth/src/middleware/passport/jwt.js index 5d36f0b91e..a619ab994b 100644 --- a/packages/auth/src/middleware/jwt.js +++ b/packages/auth/src/middleware/passport/jwt.js @@ -1,7 +1,4 @@ -// const jwt = require("passport-jwt") -const { Cookies } = require("../constants") - -// const ExtractJWT = jwt.ExtractJwt +const { Cookies } = require("../../constants") exports.options = { jwtFromRequest: function(ctx) { diff --git a/packages/auth/src/middleware/local.js b/packages/auth/src/middleware/passport/local.js similarity index 88% rename from packages/auth/src/middleware/local.js rename to packages/auth/src/middleware/passport/local.js index 85a68af87c..379ec58dbb 100644 --- a/packages/auth/src/middleware/local.js +++ b/packages/auth/src/middleware/passport/local.js @@ -1,8 +1,8 @@ const jwt = require("jsonwebtoken") -const { UserStatus } = require("../constants") -const CouchDB = require("../db") -const { StaticDatabases, generateUserID } = require("../db/utils") -const { compare } = require("../hashing") +const { UserStatus } = require("../../constants") +const CouchDB = require("../../db") +const { StaticDatabases, generateUserID } = require("../../db/utils") +const { compare } = require("../../hashing") const INVALID_ERR = "Invalid Credentials" diff --git a/packages/worker/src/api/controllers/admin/auth.js b/packages/worker/src/api/controllers/admin/auth.js index 07b08c7d1f..2c41c1f47d 100644 --- a/packages/worker/src/api/controllers/admin/auth.js +++ b/packages/worker/src/api/controllers/admin/auth.js @@ -1,20 +1,21 @@ -const jwt = require("jsonwebtoken") -const CouchDB = require("../../../db") const passport = require("@budibase/auth") exports.authenticate = async (ctx, next) => { - return passport.authenticate("local", async (err, user, info, status) => { - // TODO: better + return passport.authenticate("local", async (err, user) => { if (err) { - ctx.throw(err) + return ctx.throw(err) } - // await ctx.login(user) - ctx.body = { - err, - user, - info, - status, - } + const expires = new Date() + expires.setDate(expires.getDate() + 1) + + ctx.cookies.set("budibase:auth", user.token, { + expires, + path: "/", + httpOnly: false, + overwrite: true, + }) + + ctx.body = { success: true } })(ctx, next) } diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js index 5a6aaf77e6..c87e395a22 100644 --- a/packages/worker/src/api/routes/admin/index.js +++ b/packages/worker/src/api/routes/admin/index.js @@ -2,15 +2,22 @@ const Router = require("@koa/router") const passport = require("@budibase/auth") const controller = require("../../controllers/admin") const authController = require("../../controllers/admin/auth") -const authenticated = require("../../../middleware/authenticated") const router = Router() router - .post("/api/admin/users", authenticated, controller.userSave) + .post("/api/admin/users", passport.authenticate("jwt"), controller.userSave) .post("/api/admin/authenticate", authController.authenticate) - .delete("/api/admin/users/:email", authenticated, controller.userDelete) + .delete( + "/api/admin/users/:email", + passport.authenticate("jwt"), + controller.userDelete + ) .get("/api/admin/users", passport.authenticate("jwt"), controller.userFetch) - .get("/api/admin/users/:email", authenticated, controller.userFind) + .get( + "/api/admin/users/:email", + passport.authenticate("jwt"), + controller.userFind + ) module.exports = router From c7f4070ff5462e8995f7ebb3a50978f883960919 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 8 Apr 2021 11:20:37 +0100 Subject: [PATCH 09/65] encapsulate more auth functionality into shared module and use in worker --- packages/auth/src/db/utils.js | 2 + packages/auth/src/index.js | 15 +++- packages/auth/src/middleware/authenticated.js | 73 ----------------- packages/auth/src/utils.js | 79 ++++++++++++++++++ .../src/api/controllers/search/index.js | 2 +- .../worker/src/api/controllers/admin/auth.js | 2 +- packages/worker/src/api/routes/admin/index.js | 17 ++-- packages/worker/src/db/utils.js | 3 + packages/worker/src/index.js | 2 +- .../worker/src/middleware/authenticated.js | 44 ++++++++++ packages/worker/src/utils.js | 81 +++++++++++++++++-- 11 files changed, 222 insertions(+), 98 deletions(-) delete mode 100644 packages/auth/src/middleware/authenticated.js create mode 100644 packages/auth/src/utils.js create mode 100644 packages/worker/src/middleware/authenticated.js diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index cda7708825..17d09ceaeb 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -8,6 +8,8 @@ const DocumentTypes = { USER: "us", } +exports.DocumentTypes = DocumentTypes + const UNICODE_MAX = "\ufff0" const SEPARATOR = "_" diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 3088008086..84e3fe6595 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -5,6 +5,9 @@ const JwtStrategy = require("passport-jwt").Strategy const CouchDB = require("./db") const { StaticDatabases } = require("./db/utils") const { jwt, local, google } = require("./middleware") +const { Cookies, UserStatus } = require("./constants") +const { hash, compare } = require("./hashing") +const { getAppId, setCookie } = require("./utils") // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) @@ -25,6 +28,12 @@ passport.deserializeUser(async (user, done) => { } }) -// exports.Cookies = Cookies - -module.exports = passport +module.exports = { + passport, + Cookies, + UserStatus, + hash, + compare, + getAppId, + setCookie, +} diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js deleted file mode 100644 index 7797649b18..0000000000 --- a/packages/auth/src/middleware/authenticated.js +++ /dev/null @@ -1,73 +0,0 @@ -const jwt = require("jsonwebtoken") -const STATUS_CODES = require("../utilities/statusCodes") -const { getRole, getBuiltinRoles } = require("../utilities/security/roles") -const { AuthTypes, Cookies } = require("../constants") -const { - getAppId, - getCookieName, - clearCookie, - setCookie, - isClient, -} = require("../utilities") - -module.exports = async (ctx, next) => { - // if (ctx.path === "/_builder") { - // await next() - // return - // } - - // do everything we can to make sure the appId is held correctly - // we hold it in state as a - let appId = getAppId(ctx) - const cookieAppId = ctx.cookies.get(Cookies.CurrentApp) - // const builtinRoles = getBuiltinRoles() - if (appId && cookieAppId !== appId) { - setCookie(ctx, appId, Cookies.CurrentApp) - } else if (cookieAppId) { - appId = cookieAppId - } - let token, authType - // if (!isClient(ctx)) { - // token = ctx.cookies.get(getCookieName()) - // authType = AuthTypes.BUILDER - // } - - if (!token && appId) { - token = ctx.cookies.get(getCookieName(appId)) - // authType = AuthTypes.APP - } - - // if (!token) { - // ctx.auth.authenticated = false - // ctx.appId = appId - // ctx.user = { - // role: builtinRoles.PUBLIC, - // } - // await next() - // return - // } - - try { - // ctx.auth.authenticated = authType - const jwtPayload = jwt.verify(token, ctx.config.jwtSecret) - ctx.appId = appId - // ctx.auth.apiKey = jwtPayload.apiKey - ctx.user = { - ...jwtPayload, - role: await getRole(appId, jwtPayload.roleId), - } - // appId no longer carried in user, make sure - delete ctx.user.appId - } catch (err) { - console.log(err) - // if (authType === AuthTypes.BUILDER) { - // clearCookie(ctx) - // ctx.status = 200 - // return - // } else { - ctx.throw(err.status || STATUS_CODES.FORBIDDEN, err.text) - // } - } - - await next() -} diff --git a/packages/auth/src/utils.js b/packages/auth/src/utils.js new file mode 100644 index 0000000000..7eb39a3005 --- /dev/null +++ b/packages/auth/src/utils.js @@ -0,0 +1,79 @@ +const { DocumentTypes, SEPARATOR } = require("./db/utils") + +const APP_PREFIX = DocumentTypes.APP + SEPARATOR + +function confirmAppId(possibleAppId) { + return possibleAppId && possibleAppId.startsWith(APP_PREFIX) + ? possibleAppId + : undefined +} + +/** + * Given a request tries to find the appId, which can be located in various places + * @param {object} ctx The main request body to look through. + * @returns {string|undefined} If an appId was found it will be returned. + */ +exports.getAppId = ctx => { + const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId] + if (ctx.subdomains) { + options.push(ctx.subdomains[1]) + } + let appId + for (let option of options) { + appId = confirmAppId(option) + if (appId) { + break + } + } + + // look in body if can't find it in subdomain + if (!appId && ctx.request.body && ctx.request.body.appId) { + appId = confirmAppId(ctx.request.body.appId) + } + let appPath = + ctx.request.headers.referrer || + ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX)) + if (!appId && appPath.length !== 0) { + appId = confirmAppId(appPath[0]) + } + return appId +} + +/** + * Store a cookie for the request, has a hardcoded expiry. + * @param {object} ctx The request which is to be manipulated. + * @param {string} name The name of the cookie to set. + * @param {string|object} value The value of cookie which will be set. + */ +exports.setCookie = (ctx, value, name = "builder") => { + const expires = new Date() + expires.setDate(expires.getDate() + 1) + + if (!value) { + ctx.cookies.set(name) + } else { + ctx.cookies.set(name, value, { + expires, + path: "/", + httpOnly: false, + overwrite: true, + }) + } +} + +/** + * Utility function, simply calls setCookie with an empty string for value + */ +exports.clearCookie = (ctx, name) => { + exports.setCookie(ctx, "", name) +} + +/** + * Checks if the API call being made (based on the provided ctx object) is from the client. If + * the call is not from a client app then it is from the builder. + * @param {object} ctx The koa context object to be tested. + * @return {boolean} returns true if the call is from the client lib (a built app rather than the builder). + */ +exports.isClient = ctx => { + return ctx.headers["x-budibase-type"] === "client" +} diff --git a/packages/server/src/api/controllers/search/index.js b/packages/server/src/api/controllers/search/index.js index d3c588d079..234c7eb258 100644 --- a/packages/server/src/api/controllers/search/index.js +++ b/packages/server/src/api/controllers/search/index.js @@ -1,7 +1,7 @@ const { QueryBuilder, buildSearchUrl, search } = require("./utils") exports.rowSearch = async ctx => { - const appId = ctx.user.appId + const appId = ctx.appId const { tableId } = ctx.params const { bookmark, query, raw } = ctx.request.body let url diff --git a/packages/worker/src/api/controllers/admin/auth.js b/packages/worker/src/api/controllers/admin/auth.js index 2c41c1f47d..62128efedf 100644 --- a/packages/worker/src/api/controllers/admin/auth.js +++ b/packages/worker/src/api/controllers/admin/auth.js @@ -1,4 +1,4 @@ -const passport = require("@budibase/auth") +const { passport } = require("@budibase/auth") exports.authenticate = async (ctx, next) => { return passport.authenticate("local", async (err, user) => { diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js index c87e395a22..1c64110d2a 100644 --- a/packages/worker/src/api/routes/admin/index.js +++ b/packages/worker/src/api/routes/admin/index.js @@ -2,22 +2,15 @@ const Router = require("@koa/router") const passport = require("@budibase/auth") const controller = require("../../controllers/admin") const authController = require("../../controllers/admin/auth") +const authenticated = require("../../../middleware/authenticated") const router = Router() router - .post("/api/admin/users", passport.authenticate("jwt"), controller.userSave) + .post("/api/admin/users", authenticated, controller.userSave) .post("/api/admin/authenticate", authController.authenticate) - .delete( - "/api/admin/users/:email", - passport.authenticate("jwt"), - controller.userDelete - ) - .get("/api/admin/users", passport.authenticate("jwt"), controller.userFetch) - .get( - "/api/admin/users/:email", - passport.authenticate("jwt"), - controller.userFind - ) + .delete("/api/admin/users/:email", authenticated, controller.userDelete) + .get("/api/admin/users", authenticated, controller.userFetch) + .get("/api/admin/users/:email", authenticated, controller.userFind) module.exports = router diff --git a/packages/worker/src/db/utils.js b/packages/worker/src/db/utils.js index cda7708825..b250b895bb 100644 --- a/packages/worker/src/db/utils.js +++ b/packages/worker/src/db/utils.js @@ -6,8 +6,11 @@ exports.StaticDatabases = { const DocumentTypes = { USER: "us", + APP: "app", } +exports.DocumentTypes = DocumentTypes + const UNICODE_MAX = "\ufff0" const SEPARATOR = "_" diff --git a/packages/worker/src/index.js b/packages/worker/src/index.js index aad8bf54f7..2e031b9f64 100644 --- a/packages/worker/src/index.js +++ b/packages/worker/src/index.js @@ -1,7 +1,7 @@ const Koa = require("koa") const destroyable = require("server-destroy") const koaBody = require("koa-body") -const passport = require("@budibase/auth") +const { passport } = require("@budibase/auth") const logger = require("koa-pino-logger") const http = require("http") const api = require("./api") diff --git a/packages/worker/src/middleware/authenticated.js b/packages/worker/src/middleware/authenticated.js new file mode 100644 index 0000000000..8701da7316 --- /dev/null +++ b/packages/worker/src/middleware/authenticated.js @@ -0,0 +1,44 @@ +const { passport, getAppId, setCookie, Cookies } = require("@budibase/auth") + +module.exports = async (ctx, next) => { + // do everything we can to make sure the appId is held correctly + let appId = getAppId(ctx) + const cookieAppId = ctx.cookies.get(Cookies.CurrentApp) + // const builtinRoles = getBuiltinRoles() + if (appId && cookieAppId !== appId) { + setCookie(ctx, appId, Cookies.CurrentApp) + } else if (cookieAppId) { + appId = cookieAppId + } + + let token + if (appId) { + token = ctx.cookies.get(Cookies.Auth) + } + + if (!token) { + ctx.auth = { + authenticated: true, + } + ctx.appId = appId + // ctx.user = { + // // TODO: introduce roles again + // // role: builtinRoles.PUBLIC, + // } + return await next() + } + + return passport.authenticate("jwt", async (err, user) => { + if (err) { + return ctx.throw(err) + } + + try { + ctx.user = user + await next() + } catch (err) { + console.log(err) + ctx.throw(err.status || 403, err.text) + } + })(ctx, next) +} diff --git a/packages/worker/src/utils.js b/packages/worker/src/utils.js index 0711ae67bf..260a64cda5 100644 --- a/packages/worker/src/utils.js +++ b/packages/worker/src/utils.js @@ -1,13 +1,80 @@ -const bcrypt = require("bcryptjs") const env = require("./environment") +const { DocumentTypes, SEPARATOR } = require("./db/utils") -const SALT_ROUNDS = env.SALT_ROUNDS || 10 +const APP_PREFIX = DocumentTypes.APP + SEPARATOR -exports.hash = async data => { - const salt = await bcrypt.genSalt(SALT_ROUNDS) - return bcrypt.hash(data, salt) +function confirmAppId(possibleAppId) { + return possibleAppId && possibleAppId.startsWith(APP_PREFIX) + ? possibleAppId + : undefined } -exports.compare = async (data, encrypted) => { - return bcrypt.compare(data, encrypted) +/** + * Given a request tries to find the appId, which can be located in various places + * @param {object} ctx The main request body to look through. + * @returns {string|undefined} If an appId was found it will be returned. + */ +exports.getAppId = ctx => { + const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId] + if (ctx.subdomains) { + options.push(ctx.subdomains[1]) + } + let appId + for (let option of options) { + appId = confirmAppId(option) + if (appId) { + break + } + } + + // look in body if can't find it in subdomain + if (!appId && ctx.request.body && ctx.request.body.appId) { + appId = confirmAppId(ctx.request.body.appId) + } + let appPath = + ctx.request.headers.referrer || + ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX)) + if (!appId && appPath.length !== 0) { + appId = confirmAppId(appPath[0]) + } + return appId +} + +/** + * Store a cookie for the request, has a hardcoded expiry. + * @param {object} ctx The request which is to be manipulated. + * @param {string} name The name of the cookie to set. + * @param {string|object} value The value of cookie which will be set. + */ +exports.setCookie = (ctx, value, name = "builder") => { + const expires = new Date() + expires.setDate(expires.getDate() + 1) + + if (!value) { + ctx.cookies.set(name) + } else { + ctx.cookies.set(name, value, { + expires, + path: "/", + httpOnly: false, + overwrite: true, + }) + } +} + +/** + * Utility function, simply calls setCookie with an empty string for value + */ +exports.clearCookie = (ctx, name) => { + exports.setCookie(ctx, "", name) +} + +/** + * Checks if the API call being made (based on the provided ctx object) is from the client. If + * the call is not from a client app then it is from the builder. + * @param {object} ctx The koa context object to be tested. + * @return {boolean} returns true if the call is from the client lib (a built app rather than the builder). + */ +exports.isClient = ctx => { + return ctx.headers["x-budibase-type"] === "client" } From 6aa7a38442ddf2796edcdcea75a3756a5f473ac7 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 8 Apr 2021 11:21:52 +0100 Subject: [PATCH 10/65] flip auth boolean --- hosting/generated-envoy.dev.yaml | 125 ++++++++++++++++++ .../worker/src/middleware/authenticated.js | 2 +- 2 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 hosting/generated-envoy.dev.yaml diff --git a/hosting/generated-envoy.dev.yaml b/hosting/generated-envoy.dev.yaml new file mode 100644 index 0000000000..72cad34104 --- /dev/null +++ b/hosting/generated-envoy.dev.yaml @@ -0,0 +1,125 @@ +static_resources: + listeners: + - name: main_listener + address: + socket_address: { address: 0.0.0.0, port_value: 10000 } + filter_chains: + - filters: + - name: envoy.filters.network.http_connection_manager + typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager + stat_prefix: ingress + codec_type: auto + route_config: + name: local_route + virtual_hosts: + - name: local_services + domains: ["*"] + routes: + - match: { prefix: "/db/" } + route: + cluster: couchdb-service + prefix_rewrite: "/" + + - match: { prefix: "/cache/" } + route: + cluster: redis-service + prefix_rewrite: "/" + + - match: { prefix: "/api/" } + route: + cluster: server-dev + + - match: { prefix: "/app_" } + route: + cluster: server-dev + + - match: { prefix: "/builder/" } + route: + cluster: builder-dev + + - match: { prefix: "/builder" } + route: + cluster: builder-dev + prefix_rewrite: "/builder/" + + # minio is on the default route because this works + # best, minio + AWS SDK doesn't handle path proxy + - match: { prefix: "/" } + route: + cluster: minio-service + + http_filters: + - name: envoy.filters.http.router + + clusters: + - name: minio-service + connect_timeout: 0.25s + type: strict_dns + lb_policy: round_robin + load_assignment: + cluster_name: minio-service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: minio-service + port_value: 9000 + + - name: couchdb-service + connect_timeout: 0.25s + type: strict_dns + lb_policy: round_robin + load_assignment: + cluster_name: couchdb-service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: couchdb-service + port_value: 5984 + + - name: redis-service + connect_timeout: 0.25s + type: strict_dns + lb_policy: round_robin + load_assignment: + cluster_name: redis-service + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: redis-service + port_value: 6379 + + - name: server-dev + connect_timeout: 0.25s + type: strict_dns + lb_policy: round_robin + load_assignment: + cluster_name: server-dev + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: host.docker.internal + port_value: 4001 + + - name: builder-dev + connect_timeout: 15s + type: strict_dns + lb_policy: round_robin + load_assignment: + cluster_name: builder-dev + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: host.docker.internal + port_value: 3000 + diff --git a/packages/worker/src/middleware/authenticated.js b/packages/worker/src/middleware/authenticated.js index 8701da7316..dd7e1d974d 100644 --- a/packages/worker/src/middleware/authenticated.js +++ b/packages/worker/src/middleware/authenticated.js @@ -18,7 +18,7 @@ module.exports = async (ctx, next) => { if (!token) { ctx.auth = { - authenticated: true, + authenticated: false, } ctx.appId = appId // ctx.user = { From fb2fda4055f85b3dc71713ca8c8752fa7f7fcc61 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 8 Apr 2021 11:26:08 +0100 Subject: [PATCH 11/65] encapsulate db ID generation functions --- packages/auth/src/index.js | 4 + .../worker/src/api/controllers/admin/index.js | 6 +- packages/worker/src/utils.js | 80 ------------------- 3 files changed, 7 insertions(+), 83 deletions(-) delete mode 100644 packages/worker/src/utils.js diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 84e3fe6595..51431e4241 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -8,6 +8,7 @@ const { jwt, local, google } = require("./middleware") const { Cookies, UserStatus } = require("./constants") const { hash, compare } = require("./hashing") const { getAppId, setCookie } = require("./utils") +const { generateUserID, getUserParams } = require("./db/utils") // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) @@ -32,6 +33,9 @@ module.exports = { passport, Cookies, UserStatus, + StaticDatabases, + generateUserID, + getUserParams, hash, compare, getAppId, diff --git a/packages/worker/src/api/controllers/admin/index.js b/packages/worker/src/api/controllers/admin/index.js index b6531174bd..515feb8420 100644 --- a/packages/worker/src/api/controllers/admin/index.js +++ b/packages/worker/src/api/controllers/admin/index.js @@ -1,10 +1,10 @@ const CouchDB = require("../../../db") const { - StaticDatabases, + hash, generateUserID, getUserParams, -} = require("../../../db/utils") -const { hash } = require("../../../utils") + StaticDatabases, +} = require("@budibase/auth") const { UserStatus } = require("../../../constants") const USER_DB = StaticDatabases.USER.name diff --git a/packages/worker/src/utils.js b/packages/worker/src/utils.js deleted file mode 100644 index 260a64cda5..0000000000 --- a/packages/worker/src/utils.js +++ /dev/null @@ -1,80 +0,0 @@ -const env = require("./environment") -const { DocumentTypes, SEPARATOR } = require("./db/utils") - -const APP_PREFIX = DocumentTypes.APP + SEPARATOR - -function confirmAppId(possibleAppId) { - return possibleAppId && possibleAppId.startsWith(APP_PREFIX) - ? possibleAppId - : undefined -} - -/** - * Given a request tries to find the appId, which can be located in various places - * @param {object} ctx The main request body to look through. - * @returns {string|undefined} If an appId was found it will be returned. - */ -exports.getAppId = ctx => { - const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId] - if (ctx.subdomains) { - options.push(ctx.subdomains[1]) - } - let appId - for (let option of options) { - appId = confirmAppId(option) - if (appId) { - break - } - } - - // look in body if can't find it in subdomain - if (!appId && ctx.request.body && ctx.request.body.appId) { - appId = confirmAppId(ctx.request.body.appId) - } - let appPath = - ctx.request.headers.referrer || - ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX)) - if (!appId && appPath.length !== 0) { - appId = confirmAppId(appPath[0]) - } - return appId -} - -/** - * Store a cookie for the request, has a hardcoded expiry. - * @param {object} ctx The request which is to be manipulated. - * @param {string} name The name of the cookie to set. - * @param {string|object} value The value of cookie which will be set. - */ -exports.setCookie = (ctx, value, name = "builder") => { - const expires = new Date() - expires.setDate(expires.getDate() + 1) - - if (!value) { - ctx.cookies.set(name) - } else { - ctx.cookies.set(name, value, { - expires, - path: "/", - httpOnly: false, - overwrite: true, - }) - } -} - -/** - * Utility function, simply calls setCookie with an empty string for value - */ -exports.clearCookie = (ctx, name) => { - exports.setCookie(ctx, "", name) -} - -/** - * Checks if the API call being made (based on the provided ctx object) is from the client. If - * the call is not from a client app then it is from the builder. - * @param {object} ctx The koa context object to be tested. - * @return {boolean} returns true if the call is from the client lib (a built app rather than the builder). - */ -exports.isClient = ctx => { - return ctx.headers["x-budibase-type"] === "client" -} From 4abe6192dc56bf7bb2f30d56a61afdbabae0e04c Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 8 Apr 2021 11:53:40 +0100 Subject: [PATCH 12/65] further simplification of jwt auth --- .../worker/src/middleware/authenticated.js | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/worker/src/middleware/authenticated.js b/packages/worker/src/middleware/authenticated.js index dd7e1d974d..751e10ee9a 100644 --- a/packages/worker/src/middleware/authenticated.js +++ b/packages/worker/src/middleware/authenticated.js @@ -11,29 +11,15 @@ module.exports = async (ctx, next) => { appId = cookieAppId } - let token - if (appId) { - token = ctx.cookies.get(Cookies.Auth) - } - - if (!token) { - ctx.auth = { - authenticated: false, - } - ctx.appId = appId - // ctx.user = { - // // TODO: introduce roles again - // // role: builtinRoles.PUBLIC, - // } - return await next() - } - return passport.authenticate("jwt", async (err, user) => { if (err) { - return ctx.throw(err) + return ctx.throw(err.status || 403, err) } try { + ctx.appId = appId + ctx.isAuthenticated = true + // TODO: introduce roles again ctx.user = user await next() } catch (err) { From 2077073986bab894df20ca2c02b1238fec485efd Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 8 Apr 2021 11:57:23 +0100 Subject: [PATCH 13/65] move auth controller into it's own dir --- packages/worker/src/api/controllers/{admin => }/auth.js | 0 packages/worker/src/api/routes/admin/index.js | 3 --- packages/worker/src/api/routes/auth.js | 8 ++++++++ packages/worker/src/api/routes/index.js | 3 ++- 4 files changed, 10 insertions(+), 4 deletions(-) rename packages/worker/src/api/controllers/{admin => }/auth.js (100%) create mode 100644 packages/worker/src/api/routes/auth.js diff --git a/packages/worker/src/api/controllers/admin/auth.js b/packages/worker/src/api/controllers/auth.js similarity index 100% rename from packages/worker/src/api/controllers/admin/auth.js rename to packages/worker/src/api/controllers/auth.js diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js index 1c64110d2a..2c56f67f3f 100644 --- a/packages/worker/src/api/routes/admin/index.js +++ b/packages/worker/src/api/routes/admin/index.js @@ -1,14 +1,11 @@ const Router = require("@koa/router") -const passport = require("@budibase/auth") const controller = require("../../controllers/admin") -const authController = require("../../controllers/admin/auth") const authenticated = require("../../../middleware/authenticated") const router = Router() router .post("/api/admin/users", authenticated, controller.userSave) - .post("/api/admin/authenticate", authController.authenticate) .delete("/api/admin/users/:email", authenticated, controller.userDelete) .get("/api/admin/users", authenticated, controller.userFetch) .get("/api/admin/users/:email", authenticated, controller.userFind) diff --git a/packages/worker/src/api/routes/auth.js b/packages/worker/src/api/routes/auth.js new file mode 100644 index 0000000000..d40071b774 --- /dev/null +++ b/packages/worker/src/api/routes/auth.js @@ -0,0 +1,8 @@ +const Router = require("@koa/router") +const authController = require("../controllers/auth") + +const router = Router() + +router.post("/api/auth/authenticate", authController.authenticate) + +module.exports = router diff --git a/packages/worker/src/api/routes/index.js b/packages/worker/src/api/routes/index.js index 076710b21b..c6bacc81e5 100644 --- a/packages/worker/src/api/routes/index.js +++ b/packages/worker/src/api/routes/index.js @@ -1,4 +1,5 @@ const adminRoutes = require("./admin") +const authRoutes = require("./auth") const appRoutes = require("./app") -exports.routes = [adminRoutes, appRoutes] +exports.routes = [adminRoutes, authRoutes, appRoutes] From 8cde219db9106a41a6d6fb020b49a33870bec3ee Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 8 Apr 2021 16:58:33 +0100 Subject: [PATCH 14/65] First pass of global user configuration through existing user API with role mappings. --- hosting/envoy.dev.yaml.hbs | 18 ++ hosting/envoy.yaml | 5 + packages/auth/src/db/utils.js | 4 + packages/auth/src/index.js | 3 +- packages/server/package.json | 1 + packages/server/src/api/controllers/auth.js | 2 +- packages/server/src/api/controllers/row.js | 8 +- packages/server/src/api/controllers/user.js | 170 ++++++++++-------- packages/server/src/api/routes/user.js | 20 +-- .../src/automations/steps/createUser.js | 2 +- packages/server/src/constants/index.js | 8 +- packages/server/src/db/utils.js | 6 +- .../src/tests/utilities/TestConfiguration.js | 6 +- packages/worker/package.json | 2 +- packages/worker/src/api/routes/admin/index.js | 19 +- .../worker/src/middleware/joi-validator.js | 28 +++ packages/worker/yarn.lock | 8 +- 17 files changed, 206 insertions(+), 104 deletions(-) create mode 100644 packages/worker/src/middleware/joi-validator.js diff --git a/hosting/envoy.dev.yaml.hbs b/hosting/envoy.dev.yaml.hbs index f7f642a244..c2795fdb5f 100644 --- a/hosting/envoy.dev.yaml.hbs +++ b/hosting/envoy.dev.yaml.hbs @@ -26,6 +26,10 @@ static_resources: cluster: redis-service prefix_rewrite: "/" + - match: { prefix: "/api/admin" } + route: + cluster: worker-dev + - match: { prefix: "/api/" } route: cluster: server-dev @@ -123,3 +127,17 @@ static_resources: address: {{ address }} port_value: 3000 + - name: worker-dev + connect_timeout: 0.25s + type: strict_dns + lb_policy: round_robin + load_assignment: + cluster_name: worker-dev + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: {{ address }} + port_value: 4002 + diff --git a/hosting/envoy.yaml b/hosting/envoy.yaml index 8c6081d1a7..1fbd2070ff 100644 --- a/hosting/envoy.yaml +++ b/hosting/envoy.yaml @@ -25,6 +25,11 @@ static_resources: - match: { path: "/" } route: cluster: app-service + + # special case for worker admin API + - match: { path: "/api/admin" } + route: + cluster: worker-service # special case for when API requests are made, can just forward, not to minio - match: { prefix: "/api/" } diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 17d09ceaeb..9b6f5d7103 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -32,3 +32,7 @@ exports.getUserParams = (email = "", otherProps = {}) => { endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`, } } + +exports.getEmailFromUserID = id => { + return id.split(`${DocumentTypes.USER}${SEPARATOR}`)[1] +} \ No newline at end of file diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 51431e4241..b65690b064 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -8,7 +8,7 @@ const { jwt, local, google } = require("./middleware") const { Cookies, UserStatus } = require("./constants") const { hash, compare } = require("./hashing") const { getAppId, setCookie } = require("./utils") -const { generateUserID, getUserParams } = require("./db/utils") +const { generateUserID, getUserParams, getEmailFromUserID } = require("./db/utils") // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) @@ -36,6 +36,7 @@ module.exports = { StaticDatabases, generateUserID, getUserParams, + getEmailFromUserID, hash, compare, getAppId, diff --git a/packages/server/package.json b/packages/server/package.json index 42ecbe39e0..3ff5997985 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -79,6 +79,7 @@ "author": "Budibase", "license": "AGPL-3.0-or-later", "dependencies": { + "@budibase/auth": "^0.0.1", "@budibase/client": "^0.8.9", "@budibase/string-templates": "^0.8.9", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/server/src/api/controllers/auth.js b/packages/server/src/api/controllers/auth.js index 43f7878108..da68aa485b 100644 --- a/packages/server/src/api/controllers/auth.js +++ b/packages/server/src/api/controllers/auth.js @@ -7,7 +7,7 @@ const { generateUserID } = require("../../db/utils") const { setCookie } = require("../../utilities") const { outputProcessing } = require("../../utilities/rowProcessor") const { ViewNames } = require("../../db/utils") -const { UserStatus } = require("../../constants") +const { UserStatus } = require("@budibase/auth") const setBuilderToken = require("../../utilities/builder/setBuilderToken") const INVALID_ERR = "Invalid Credentials" diff --git a/packages/server/src/api/controllers/row.js b/packages/server/src/api/controllers/row.js index 3f531d7e5c..1b3e795f83 100644 --- a/packages/server/src/api/controllers/row.js +++ b/packages/server/src/api/controllers/row.js @@ -48,7 +48,7 @@ async function findRow(db, appId, tableId, rowId) { appId, }, } - await usersController.find(ctx) + await usersController.findMetadata(ctx) row = ctx.body } else { row = await db.get(rowId) @@ -103,7 +103,7 @@ exports.patch = async function(ctx) { ...row, password: ctx.request.body.password, } - await usersController.update(ctx) + await usersController.updateMetadata(ctx) return } @@ -179,7 +179,7 @@ exports.save = async function(ctx) { if (row.tableId === ViewNames.USERS) { // the row has been updated, need to put it into the ctx ctx.request.body = row - await usersController.create(ctx) + await usersController.createMetadata(ctx) return } @@ -310,7 +310,7 @@ exports.fetchTableRows = async function(ctx) { let rows, table = await db.get(ctx.params.tableId) if (ctx.params.tableId === ViewNames.USERS) { - await usersController.fetch(ctx) + await usersController.fetchMetadata(ctx) rows = ctx.body } else { const response = await db.allDocs( diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index d9a4af9719..92b038d05e 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -1,109 +1,137 @@ const CouchDB = require("../../db") -const bcrypt = require("../../utilities/bcrypt") -const { generateUserID, getUserParams, ViewNames } = require("../../db/utils") +const { + generateUserID, + getUserParams, + getEmailFromUserID, +} = require("@budibase/auth") +const { InternalTables } = require("../../db/utils") const { getRole } = require("../../utilities/security/roles") -const { UserStatus } = require("../../constants") +const { checkSlashesInUrl } = require("../../utilities") +const env = require("../../environment") +const fetch = require("node-fetch") -exports.fetch = async function(ctx) { +async function deleteGlobalUser(email) { + const endpoint = `/api/admin/users/${email}` + const reqCfg = { method: "DELETE" } + const response = await fetch( + checkSlashesInUrl(env.WORKER_URL + endpoint), + reqCfg + ) + return response.json() +} + +async function getGlobalUsers(email = null) { + const endpoint = email ? `/api/admin/users/${email}` : `/api/admin/users` + const reqCfg = { method: "GET" } + const response = await fetch( + checkSlashesInUrl(env.WORKER_URL + endpoint), + reqCfg + ) + return response.json() +} + +async function saveGlobalUser(appId, email, body) { + const globalUser = await getGlobalUsers(email) + const roles = globalUser.roles || {} + if (body.roleId) { + roles.appId = body.roleId + } + const endpoint = `/api/admin/users` + const reqCfg = { + method: "POST", + body: { + ...globalUser, + email, + password: body.password, + status: body.status, + roles, + }, + } + + const response = await fetch( + checkSlashesInUrl(env.WORKER_URL + endpoint), + reqCfg + ) + await response.json() + delete body.email + delete body.password + delete body.roleId + delete body.status + return body +} + +exports.fetchMetadata = async function(ctx) { const database = new CouchDB(ctx.appId) - const users = ( + const global = await getGlobalUsers() + const metadata = ( await database.allDocs( getUserParams(null, { include_docs: true, }) ) ).rows.map(row => row.doc) - // user hashed password shouldn't ever be returned - for (let user of users) { - delete user.password + const users = [] + for (let user of global) { + const info = metadata.find(meta => meta._id.includes(user.email)) + users.push({ + ...user, + ...info, + }) } ctx.body = users } -// TODO: need to replace this with something that purely manages metadata -exports.create = async function(ctx) { - const db = new CouchDB(ctx.appId) - const { email, password, roleId } = ctx.request.body - - if (!email || !password) { - ctx.throw(400, "email and Password Required.") - } - - const role = await getRole(ctx.appId, roleId) +exports.createMetadata = async function(ctx) { + const appId = ctx.appId + const db = new CouchDB(appId) + const { email, roleId } = ctx.request.body + // check role valid + const role = await getRole(appId, roleId) if (!role) ctx.throw(400, "Invalid Role") - const hashedPassword = await bcrypt.hash(password) + const metadata = await saveGlobalUser(appId, email, ctx.request.body) + const user = { - ...ctx.request.body, - // these must all be after the object spread, make sure - // any values are overwritten, generateUserID will always - // generate the same ID for the user as it is not UUID based + ...metadata, _id: generateUserID(email), type: "user", - password: hashedPassword, - tableId: ViewNames.USERS, - } - // add the active status to a user if its not provided - if (user.status == null) { - user.status = UserStatus.ACTIVE + tableId: InternalTables.USER_METADATA, } - try { - const response = await db.post(user) - ctx.status = 200 - ctx.message = "User created successfully." - ctx.userId = response.id - ctx.body = { - _rev: response.rev, - email, - } - } catch (err) { - if (err.status === 409) { - ctx.throw(400, "User exists already") - } else { - ctx.throw(err.status, err) - } + const response = await db.post(user) + ctx.body = { + _rev: response.rev, + email, } } -exports.update = async function(ctx) { - const db = new CouchDB(ctx.appId) +exports.updateMetadata = async function(ctx) { + const appId = ctx.appId + const db = new CouchDB(appId) const user = ctx.request.body - let dbUser - if (user.email && !user._id) { - user._id = generateUserID(user.email) - } - // get user incase password removed - if (user._id) { - dbUser = await db.get(user._id) - } - if (user.password) { - user.password = await bcrypt.hash(user.password) - } else { - delete user.password - } + let email = user.email || getEmailFromUserID(user._id) + const metadata = await saveGlobalUser(appId, email, ctx.request.body) - const response = await db.put({ - password: dbUser.password, - ...user, + if (!metadata._id) { + user._id = generateUserID(email) + } + ctx.body = await db.put({ + ...metadata, }) - user._rev = response.rev - - ctx.status = 200 - ctx.body = response } -exports.destroy = async function(ctx) { - const database = new CouchDB(ctx.appId) - await database.destroy(generateUserID(ctx.params.email)) +exports.destroyMetadata = async function(ctx) { + const db = new CouchDB(ctx.appId) + const email = ctx.params.email + await deleteGlobalUser(email) + await db.destroy(generateUserID(email)) ctx.body = { message: `User ${ctx.params.email} deleted.`, } - ctx.status = 200 } -exports.find = async function(ctx) { +exports.findMetadata = async function(ctx) { const database = new CouchDB(ctx.appId) let lookup = ctx.params.email ? generateUserID(ctx.params.email) diff --git a/packages/server/src/api/routes/user.js b/packages/server/src/api/routes/user.js index cdaab0cc5b..b0450b72cc 100644 --- a/packages/server/src/api/routes/user.js +++ b/packages/server/src/api/routes/user.js @@ -11,31 +11,31 @@ const router = Router() router .get( - "/api/users", + "/api/users/metadata", authorized(PermissionTypes.USER, PermissionLevels.READ), - controller.fetch + controller.fetchMetadata ) .get( - "/api/users/:email", + "/api/users/metadata/:email", authorized(PermissionTypes.USER, PermissionLevels.READ), - controller.find + controller.findMetadata ) .put( - "/api/users", + "/api/users/metadata", authorized(PermissionTypes.USER, PermissionLevels.WRITE), - controller.update + controller.updateMetadata ) .post( - "/api/users", + "/api/users/metadata", authorized(PermissionTypes.USER, PermissionLevels.WRITE), usage, - controller.create + controller.createMetadata ) .delete( - "/api/users/:email", + "/api/users/metadata/:email", authorized(PermissionTypes.USER, PermissionLevels.WRITE), usage, - controller.destroy + controller.destroyMetadata ) module.exports = router diff --git a/packages/server/src/automations/steps/createUser.js b/packages/server/src/automations/steps/createUser.js index 147a3f7868..8849415c5a 100644 --- a/packages/server/src/automations/steps/createUser.js +++ b/packages/server/src/automations/steps/createUser.js @@ -75,7 +75,7 @@ module.exports.run = async function({ inputs, appId, apiKey, emitter }) { if (env.isProd()) { await usage.update(apiKey, usage.Properties.USER, 1) } - await userController.create(ctx) + await userController.createMetadata(ctx) return { response: ctx.body, // internal property not returned through the API diff --git a/packages/server/src/constants/index.js b/packages/server/src/constants/index.js index 1e8ebb2721..940c1100dd 100644 --- a/packages/server/src/constants/index.js +++ b/packages/server/src/constants/index.js @@ -1,4 +1,5 @@ const { BUILTIN_ROLE_IDS } = require("../utilities/security/roles") +const { UserStatus } = require("@budibase/auth") exports.LOGO_URL = "https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg" @@ -27,11 +28,6 @@ exports.AuthTypes = { EXTERNAL: "external", } -exports.UserStatus = { - ACTIVE: "active", - INACTIVE: "inactive", -} - exports.USERS_TABLE_SCHEMA = { _id: "ta_users", type: "table", @@ -68,7 +64,7 @@ exports.USERS_TABLE_SCHEMA = { constraints: { type: exports.FieldTypes.STRING, presence: false, - inclusion: Object.values(exports.UserStatus), + inclusion: Object.values(UserStatus), }, }, }, diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index 4c31f0398e..8623b99f2c 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -34,7 +34,10 @@ const DocumentTypes = { const ViewNames = { LINK: "by_link", ROUTING: "screen_routes", - USERS: "ta_users", +} + +const InternalTables = { + USER_METADATA: "ta_users", } const SearchIndexes = { @@ -43,6 +46,7 @@ const SearchIndexes = { exports.StaticDatabases = StaticDatabases exports.ViewNames = ViewNames +exports.InternalTables = InternalTables exports.DocumentTypes = DocumentTypes exports.SEPARATOR = SEPARATOR exports.UNICODE_MAX = UNICODE_MAX diff --git a/packages/server/src/tests/utilities/TestConfiguration.js b/packages/server/src/tests/utilities/TestConfiguration.js index 433cec4a0a..002cf4d004 100644 --- a/packages/server/src/tests/utilities/TestConfiguration.js +++ b/packages/server/src/tests/utilities/TestConfiguration.js @@ -279,7 +279,7 @@ class TestConfiguration { roleId, }, null, - controllers.user.create + controllers.user.createMetadata ) } @@ -289,7 +289,7 @@ class TestConfiguration { { email, }, - controllers.user.find + controllers.user.findMetadata ) return this._req( { @@ -297,7 +297,7 @@ class TestConfiguration { status: "inactive", }, null, - controllers.user.update + controllers.user.updateMetadata ) } diff --git a/packages/worker/package.json b/packages/worker/package.json index 5ab414dab1..37b7435066 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -25,7 +25,7 @@ "bcryptjs": "^2.4.3", "dotenv": "^8.2.0", "got": "^11.8.1", - "joi": "^17.2.1", + "joi": "^17.4.0", "koa": "^2.7.0", "koa-body": "^4.2.0", "koa-compress": "^4.0.1", diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js index 1c64110d2a..97924ce7cb 100644 --- a/packages/worker/src/api/routes/admin/index.js +++ b/packages/worker/src/api/routes/admin/index.js @@ -3,11 +3,28 @@ const passport = require("@budibase/auth") const controller = require("../../controllers/admin") const authController = require("../../controllers/admin/auth") const authenticated = require("../../../middleware/authenticated") +const joiValidator = require("../../../middleware/joi-validator") +const Joi = require("joi") const router = Router() +function buildUserSaveValidation() { + // prettier-ignore + return joiValidator.body(Joi.object({ + _id: Joi.string(), + _rev: Joi.string(), + email: Joi.string(), + password: Joi.string(), + // maps appId -> roleId for the user + roles: Joi.object() + .pattern(/.*/, Joi.string()) + .required() + .unknown(true) + }).required().unknown(true)) +} + router - .post("/api/admin/users", authenticated, controller.userSave) + .post("/api/admin/users", buildUserSaveValidation(), authenticated, controller.userSave) .post("/api/admin/authenticate", authController.authenticate) .delete("/api/admin/users/:email", authenticated, controller.userDelete) .get("/api/admin/users", authenticated, controller.userFetch) diff --git a/packages/worker/src/middleware/joi-validator.js b/packages/worker/src/middleware/joi-validator.js new file mode 100644 index 0000000000..1686b0e727 --- /dev/null +++ b/packages/worker/src/middleware/joi-validator.js @@ -0,0 +1,28 @@ +function validate(schema, property) { + // Return a Koa middleware function + return (ctx, next) => { + if (!schema) { + return next() + } + let params = null + if (ctx[property] != null) { + params = ctx[property] + } else if (ctx.request[property] != null) { + params = ctx.request[property] + } + const { error } = schema.validate(params) + if (error) { + ctx.throw(400, `Invalid ${property} - ${error.message}`) + return + } + return next() + } +} + +module.exports.body = schema => { + return validate(schema, "body") +} + +module.exports.params = schema => { + return validate(schema, "params") +} diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index df8965f515..6515c5967f 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -1261,10 +1261,10 @@ jmespath@0.15.0, jmespath@^0.15.0: resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= -joi@^17.2.1: - version "17.3.0" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.3.0.tgz#f1be4a6ce29bc1716665819ac361dfa139fff5d2" - integrity sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg== +joi@^17.4.0: + version "17.4.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.0.tgz#b5c2277c8519e016316e49ababd41a1908d9ef20" + integrity sha512-F4WiW2xaV6wc1jxete70Rw4V/VuMd6IN+a5ilZsxG4uYtUXWu2kq9W5P2dz30e7Gmw8RCbY/u/uk+dMPma9tAg== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" From 15900efc35e61f1f0e406e92f1ebb96d1830892b Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 8 Apr 2021 17:39:46 +0100 Subject: [PATCH 15/65] Some changes after trying system for first time. --- hosting/docker-compose.yaml | 1 + hosting/envoy.dev.yaml.hbs | 4 ++++ packages/server/scripts/dev/manage.js | 3 --- packages/server/src/app.js | 3 ++- packages/worker/scripts/dev/manage.js | 4 +--- packages/worker/src/index.js | 3 ++- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/hosting/docker-compose.yaml b/hosting/docker-compose.yaml index 49f8cddccd..5e21cc9efd 100644 --- a/hosting/docker-compose.yaml +++ b/hosting/docker-compose.yaml @@ -35,6 +35,7 @@ services: environment: SELF_HOSTED: 1 PORT: 4003 + JWT_SECRET: ${JWT_SECRET} MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY} MINIO_SECRET_KEY: ${MINIO_SECRET_KEY} MINIO_URL: http://minio-service:9000 diff --git a/hosting/envoy.dev.yaml.hbs b/hosting/envoy.dev.yaml.hbs index c2795fdb5f..40cfc551ef 100644 --- a/hosting/envoy.dev.yaml.hbs +++ b/hosting/envoy.dev.yaml.hbs @@ -46,6 +46,10 @@ static_resources: route: cluster: builder-dev prefix_rewrite: "/builder/" + + # special case in dev to redirect no path to builder + - match: { path: "/" } + redirect: { path_redirect: "/builder/" } # minio is on the default route because this works # best, minio + AWS SDK doesn't handle path proxy diff --git a/packages/server/scripts/dev/manage.js b/packages/server/scripts/dev/manage.js index 7a318ff6ff..20037c7e3c 100644 --- a/packages/server/scripts/dev/manage.js +++ b/packages/server/scripts/dev/manage.js @@ -33,9 +33,6 @@ async function init() { fs.writeFileSync(envoyOutputPath, processStringSync(contents, config)) const envFilePath = path.join(process.cwd(), ".env") - if (fs.existsSync(envFilePath)) { - return - } const envFileJson = { PORT: 4001, MINIO_URL: "http://localhost:10000/", diff --git a/packages/server/src/app.js b/packages/server/src/app.js index e5e9b77084..88776fadac 100644 --- a/packages/server/src/app.js +++ b/packages/server/src/app.js @@ -1,3 +1,5 @@ +// need to load environment first +const env = require("./environment") const Koa = require("koa") const destroyable = require("server-destroy") const electron = require("electron") @@ -5,7 +7,6 @@ const koaBody = require("koa-body") const logger = require("koa-pino-logger") const http = require("http") const api = require("./api") -const env = require("./environment") const eventEmitter = require("./events") const automations = require("./automations/index") const Sentry = require("@sentry/node") diff --git a/packages/worker/scripts/dev/manage.js b/packages/worker/scripts/dev/manage.js index b7e92f6d15..f363bd05ac 100644 --- a/packages/worker/scripts/dev/manage.js +++ b/packages/worker/scripts/dev/manage.js @@ -4,12 +4,10 @@ const fs = require("fs") async function init() { const envFilePath = path.join(process.cwd(), ".env") - if (fs.existsSync(envFilePath)) { - return - } const envFileJson = { SELF_HOSTED: 1, PORT: 4002, + JWT_SECRET: "testsecret", MINIO_ACCESS_KEY: "budibase", MINIO_SECRET_KEY: "budibase", COUCH_DB_USER: "budibase", diff --git a/packages/worker/src/index.js b/packages/worker/src/index.js index 2e031b9f64..55f2705ed1 100644 --- a/packages/worker/src/index.js +++ b/packages/worker/src/index.js @@ -1,3 +1,5 @@ +// need to load environment first +const env = require("./environment") const Koa = require("koa") const destroyable = require("server-destroy") const koaBody = require("koa-body") @@ -5,7 +7,6 @@ const { passport } = require("@budibase/auth") const logger = require("koa-pino-logger") const http = require("http") const api = require("./api") -const env = require("./environment") const app = new Koa() From 0c34f1a108755ad9f98db1d32f1b7e53bce14585 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 8 Apr 2021 18:18:53 +0100 Subject: [PATCH 16/65] Making sure volumes are removed when nuking. --- packages/server/scripts/dev/manage.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/server/scripts/dev/manage.js b/packages/server/scripts/dev/manage.js index 20037c7e3c..4e170d1c63 100644 --- a/packages/server/scripts/dev/manage.js +++ b/packages/server/scripts/dev/manage.js @@ -67,7 +67,11 @@ async function nuke() { console.log( "Clearing down your budibase dev environment, including all containers and volumes... 💥" ) - await compose.down(CONFIG) + await compose.down({ + ...CONFIG, + // stop containers, delete volumes + commandOptions: ["-v", "--remove-orphans"], + }) } const managementCommand = process.argv.slice(2)[0] From 3214abb89a041763a8c661b2983705581acf3a6e Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 9 Apr 2021 15:11:49 +0100 Subject: [PATCH 17/65] Global users now working through the server, all requests proxied. --- package.json | 2 +- packages/auth/src/db/utils.js | 7 +- .../src/components/backend/DataTable/api.js | 5 +- .../components/start/CreateAppModal.svelte | 2 +- .../server/src/api/controllers/application.js | 2 +- packages/server/src/api/controllers/auth.js | 4 +- .../server/src/api/controllers/hosting.js | 2 +- packages/server/src/api/controllers/role.js | 4 +- packages/server/src/api/controllers/row.js | 18 +-- .../src/api/controllers/static/index.js | 2 +- packages/server/src/api/controllers/user.js | 98 ++++----------- packages/server/src/db/utils.js | 21 +++- .../server/src/utilities/builder/hosting.js | 29 +---- .../server/src/utilities/workerRequests.js | 116 ++++++++++++++++++ .../worker/src/api/controllers/admin/index.js | 31 +++-- packages/worker/src/api/routes/app.js | 4 +- .../worker/src/middleware/authenticated.js | 32 ++--- 17 files changed, 219 insertions(+), 160 deletions(-) create mode 100644 packages/server/src/utilities/workerRequests.js diff --git a/package.json b/package.json index b2f572d202..a4b0993fde 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "clean": "lerna clean", "kill-port": "kill-port 4001", "dev": "yarn run kill-port && lerna link && lerna run --parallel dev:builder --concurrency 1", - "dev:noserver": "lerna link && lerna run --parallel dev:builder --concurrency 1 --ignore @budibase/server", + "dev:noserver": "lerna link && lerna run dev:stack:up && lerna run --parallel dev:builder --concurrency 1 --ignore @budibase/server --ignore @budibase/worker", "test": "lerna run test", "lint": "eslint packages", "lint:fix": "eslint --fix packages", diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 9b6f5d7103..871423df03 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -26,13 +26,12 @@ exports.generateUserID = email => { * Gets parameters for retrieving users, this is a utility function for the getDocParams function. */ exports.getUserParams = (email = "", otherProps = {}) => { + if (!email) { + email = "" + } return { ...otherProps, startkey: `${DocumentTypes.USER}${SEPARATOR}${email}`, endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`, } } - -exports.getEmailFromUserID = id => { - return id.split(`${DocumentTypes.USER}${SEPARATOR}`)[1] -} \ No newline at end of file diff --git a/packages/builder/src/components/backend/DataTable/api.js b/packages/builder/src/components/backend/DataTable/api.js index 91ebc19b26..43c6856540 100644 --- a/packages/builder/src/components/backend/DataTable/api.js +++ b/packages/builder/src/components/backend/DataTable/api.js @@ -1,7 +1,7 @@ import api from "builderStore/api" export async function createUser(user) { - const CREATE_USER_URL = `/api/users` + const CREATE_USER_URL = `/api/users/metadata` const response = await api.post(CREATE_USER_URL, user) return await response.json() } @@ -15,8 +15,7 @@ export async function saveRow(row, tableId) { export async function deleteRow(row) { const DELETE_ROWS_URL = `/api/${row.tableId}/rows/${row._id}/${row._rev}` - const response = await api.delete(DELETE_ROWS_URL) - return response + return api.delete(DELETE_ROWS_URL) } export async function fetchDataForView(view) { diff --git a/packages/builder/src/components/start/CreateAppModal.svelte b/packages/builder/src/components/start/CreateAppModal.svelte index babe7bd0df..c727283b29 100644 --- a/packages/builder/src/components/start/CreateAppModal.svelte +++ b/packages/builder/src/components/start/CreateAppModal.svelte @@ -157,7 +157,7 @@ password: $createAppStore.values.password, roleId: $createAppStore.values.roleId, } - const userResp = await api.post(`/api/users`, user) + const userResp = await api.post(`/api/users/metadata`, user) const json = await userResp.json() $goto(`./${appJson._id}`) } catch (error) { diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js index cacde4bb00..042474c5b6 100644 --- a/packages/server/src/api/controllers/application.js +++ b/packages/server/src/api/controllers/application.js @@ -74,7 +74,7 @@ async function getAppUrlIfNotInUse(ctx) { if (!env.SELF_HOSTED) { return url } - const deployedApps = await getDeployedApps() + const deployedApps = await getDeployedApps(ctx) if ( deployedApps[url] != null && deployedApps[url].appId !== ctx.params.appId diff --git a/packages/server/src/api/controllers/auth.js b/packages/server/src/api/controllers/auth.js index da68aa485b..6e662f7b9a 100644 --- a/packages/server/src/api/controllers/auth.js +++ b/packages/server/src/api/controllers/auth.js @@ -3,7 +3,7 @@ const CouchDB = require("../../db") const bcrypt = require("../../utilities/bcrypt") const env = require("../../environment") const { getAPIKey } = require("../../utilities/usageQuota") -const { generateUserID } = require("../../db/utils") +const { generateUserMetadataID } = require("../../db/utils") const { setCookie } = require("../../utilities") const { outputProcessing } = require("../../utilities/rowProcessor") const { ViewNames } = require("../../db/utils") @@ -27,7 +27,7 @@ exports.authenticate = async ctx => { let dbUser try { - dbUser = await db.get(generateUserID(email)) + dbUser = await db.get(generateUserMetadataID(email)) } catch (_) { // do not want to throw a 404 - as this could be // used to determine valid emails diff --git a/packages/server/src/api/controllers/hosting.js b/packages/server/src/api/controllers/hosting.js index 4b070cf75b..8b7b31e00a 100644 --- a/packages/server/src/api/controllers/hosting.js +++ b/packages/server/src/api/controllers/hosting.js @@ -40,5 +40,5 @@ exports.fetchUrls = async ctx => { } exports.getDeployedApps = async ctx => { - ctx.body = await getDeployedApps() + ctx.body = await getDeployedApps(ctx) } diff --git a/packages/server/src/api/controllers/role.js b/packages/server/src/api/controllers/role.js index 11f81c1219..d27272a21a 100644 --- a/packages/server/src/api/controllers/role.js +++ b/packages/server/src/api/controllers/role.js @@ -10,7 +10,7 @@ const { const { generateRoleID, getRoleParams, - getUserParams, + getUserMetadataParams, ViewNames, } = require("../../db/utils") @@ -112,7 +112,7 @@ exports.destroy = async function(ctx) { // first check no users actively attached to role const users = ( await db.allDocs( - getUserParams(null, { + getUserMetadataParams(null, { include_docs: true, }) ) diff --git a/packages/server/src/api/controllers/row.js b/packages/server/src/api/controllers/row.js index 1b3e795f83..8b4a461d2c 100644 --- a/packages/server/src/api/controllers/row.js +++ b/packages/server/src/api/controllers/row.js @@ -6,8 +6,8 @@ const { generateRowID, DocumentTypes, SEPARATOR, - ViewNames, - generateUserID, + InternalTables, + generateUserMetadataID, } = require("../../db/utils") const usersController = require("./user") const { @@ -39,7 +39,7 @@ validateJs.extend(validateJs.validators.datetime, { async function findRow(db, appId, tableId, rowId) { let row - if (tableId === ViewNames.USERS) { + if (tableId === InternalTables.USER_METADATA) { let ctx = { params: { userId: rowId, @@ -97,7 +97,7 @@ exports.patch = async function(ctx) { }) // Creation of a new user goes to the user controller - if (row.tableId === ViewNames.USERS) { + if (row.tableId === InternalTables.USER_METADATA) { // the row has been updated, need to put it into the ctx ctx.request.body = { ...row, @@ -142,8 +142,8 @@ exports.save = async function(ctx) { } if (!inputs._rev && !inputs._id) { - if (inputs.tableId === ViewNames.USERS) { - inputs._id = generateUserID(inputs.email) + if (inputs.tableId === InternalTables.USER_METADATA) { + inputs._id = generateUserMetadataID(inputs.email) } else { inputs._id = generateRowID(inputs.tableId) } @@ -176,7 +176,7 @@ exports.save = async function(ctx) { }) // Creation of a new user goes to the user controller - if (row.tableId === ViewNames.USERS) { + if (row.tableId === InternalTables.USER_METADATA) { // the row has been updated, need to put it into the ctx ctx.request.body = row await usersController.createMetadata(ctx) @@ -289,7 +289,7 @@ exports.search = async function(ctx) { const response = await search(searchString) // delete passwords from users - if (tableId === ViewNames.USERS) { + if (tableId === InternalTables.USER_METADATA) { for (let row of response.rows) { delete row.password } @@ -309,7 +309,7 @@ exports.fetchTableRows = async function(ctx) { // special case for users, fetch through the user controller let rows, table = await db.get(ctx.params.tableId) - if (ctx.params.tableId === ViewNames.USERS) { + if (ctx.params.tableId === InternalTables.USER_METADATA) { await usersController.fetchMetadata(ctx) rows = ctx.body } else { diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js index 69a12d573b..71e20923a8 100644 --- a/packages/server/src/api/controllers/static/index.js +++ b/packages/server/src/api/controllers/static/index.js @@ -22,7 +22,7 @@ const { objectStoreUrl, clientLibraryPath } = require("../../../utilities") async function checkForSelfHostedURL(ctx) { // the "appId" component of the URL may actually be a specific self hosted URL let possibleAppUrl = `/${encodeURI(ctx.params.appId).toLowerCase()}` - const apps = await getDeployedApps() + const apps = await getDeployedApps(ctx) if (apps[possibleAppUrl] && apps[possibleAppUrl].appId) { return apps[possibleAppUrl].appId } else { diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index 92b038d05e..c526050cde 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -1,71 +1,23 @@ const CouchDB = require("../../db") const { - generateUserID, - getUserParams, - getEmailFromUserID, -} = require("@budibase/auth") + generateUserMetadataID, + getUserMetadataParams, + getEmailFromUserMetadataID, +} = require("../../db/utils") const { InternalTables } = require("../../db/utils") const { getRole } = require("../../utilities/security/roles") -const { checkSlashesInUrl } = require("../../utilities") -const env = require("../../environment") -const fetch = require("node-fetch") - -async function deleteGlobalUser(email) { - const endpoint = `/api/admin/users/${email}` - const reqCfg = { method: "DELETE" } - const response = await fetch( - checkSlashesInUrl(env.WORKER_URL + endpoint), - reqCfg - ) - return response.json() -} - -async function getGlobalUsers(email = null) { - const endpoint = email ? `/api/admin/users/${email}` : `/api/admin/users` - const reqCfg = { method: "GET" } - const response = await fetch( - checkSlashesInUrl(env.WORKER_URL + endpoint), - reqCfg - ) - return response.json() -} - -async function saveGlobalUser(appId, email, body) { - const globalUser = await getGlobalUsers(email) - const roles = globalUser.roles || {} - if (body.roleId) { - roles.appId = body.roleId - } - const endpoint = `/api/admin/users` - const reqCfg = { - method: "POST", - body: { - ...globalUser, - email, - password: body.password, - status: body.status, - roles, - }, - } - - const response = await fetch( - checkSlashesInUrl(env.WORKER_URL + endpoint), - reqCfg - ) - await response.json() - delete body.email - delete body.password - delete body.roleId - delete body.status - return body -} +const { + getGlobalUsers, + saveGlobalUser, + deleteGlobalUser, +} = require("../../utilities/workerRequests") exports.fetchMetadata = async function(ctx) { const database = new CouchDB(ctx.appId) - const global = await getGlobalUsers() + const global = await getGlobalUsers(ctx, ctx.appId) const metadata = ( await database.allDocs( - getUserParams(null, { + getUserMetadataParams(null, { include_docs: true, }) ) @@ -90,11 +42,11 @@ exports.createMetadata = async function(ctx) { const role = await getRole(appId, roleId) if (!role) ctx.throw(400, "Invalid Role") - const metadata = await saveGlobalUser(appId, email, ctx.request.body) + const metadata = await saveGlobalUser(ctx, appId, email, ctx.request.body) const user = { ...metadata, - _id: generateUserID(email), + _id: generateUserMetadataID(email), type: "user", tableId: InternalTables.USER_METADATA, } @@ -110,11 +62,11 @@ exports.updateMetadata = async function(ctx) { const appId = ctx.appId const db = new CouchDB(appId) const user = ctx.request.body - let email = user.email || getEmailFromUserID(user._id) - const metadata = await saveGlobalUser(appId, email, ctx.request.body) + let email = user.email || getEmailFromUserMetadataID(user._id) + const metadata = await saveGlobalUser(ctx, appId, email, ctx.request.body) if (!metadata._id) { - user._id = generateUserID(email) + user._id = generateUserMetadataID(email) } ctx.body = await db.put({ ...metadata, @@ -124,8 +76,8 @@ exports.updateMetadata = async function(ctx) { exports.destroyMetadata = async function(ctx) { const db = new CouchDB(ctx.appId) const email = ctx.params.email - await deleteGlobalUser(email) - await db.destroy(generateUserID(email)) + await deleteGlobalUser(ctx, email) + await db.destroy(generateUserMetadataID(email)) ctx.body = { message: `User ${ctx.params.email} deleted.`, } @@ -133,12 +85,12 @@ exports.destroyMetadata = async function(ctx) { exports.findMetadata = async function(ctx) { const database = new CouchDB(ctx.appId) - let lookup = ctx.params.email - ? generateUserID(ctx.params.email) - : ctx.params.userId - const user = await database.get(lookup) - if (user) { - delete user.password + const email = + ctx.params.email || getEmailFromUserMetadataID(ctx.params.userId) + const global = await getGlobalUsers(ctx, ctx.appId, email) + const user = await database.get(generateUserMetadataID(email)) + ctx.body = { + ...global, + ...user, } - ctx.body = user } diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index 8623b99f2c..63d4e30d65 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -116,16 +116,18 @@ exports.getRowParams = (tableId = null, rowId = null, otherProps = {}) => { /** * Gets a new row ID for the specified table. * @param {string} tableId The table which the row is being created for. + * @param {string|null} id If an ID is to be used then the UUID can be substituted for this. * @returns {string} The new ID which a row doc can be stored under. */ -exports.generateRowID = tableId => { - return `${DocumentTypes.ROW}${SEPARATOR}${tableId}${SEPARATOR}${newid()}` +exports.generateRowID = (tableId, id = null) => { + id = id || newid() + return `${DocumentTypes.ROW}${SEPARATOR}${tableId}${SEPARATOR}${id}` } /** * Gets parameters for retrieving users, this is a utility function for the getDocParams function. */ -exports.getUserParams = (email = "", otherProps = {}) => { +exports.getUserMetadataParams = (email = "", otherProps = {}) => { return exports.getRowParams(ViewNames.USERS, email, otherProps) } @@ -134,8 +136,17 @@ exports.getUserParams = (email = "", otherProps = {}) => { * @param {string} email The email which the ID is going to be built up of. * @returns {string} The new user ID which the user doc can be stored under. */ -exports.generateUserID = email => { - return `${DocumentTypes.ROW}${SEPARATOR}${ViewNames.USERS}${SEPARATOR}${DocumentTypes.USER}${SEPARATOR}${email}` +exports.generateUserMetadataID = email => { + return exports.generateRowID(InternalTables.USER_METADATA, email) +} + +/** + * Breaks up the ID to get the email address back out of it. + */ +exports.getEmailFromUserMetadataID = id => { + return id.split( + `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}` + )[1] } /** diff --git a/packages/server/src/utilities/builder/hosting.js b/packages/server/src/utilities/builder/hosting.js index f852cefec1..328e98ee98 100644 --- a/packages/server/src/utilities/builder/hosting.js +++ b/packages/server/src/utilities/builder/hosting.js @@ -2,6 +2,7 @@ const CouchDB = require("../../db") const { StaticDatabases } = require("../../db/utils") const fetch = require("node-fetch") const env = require("../../environment") +const { getDeployedApps } = require("../../utilities/workerRequests") const PROD_HOSTING_URL = "app.budi.live" @@ -84,30 +85,4 @@ exports.getTemplatesUrl = async (appId, type, name) => { return `${protocol}${hostingInfo.templatesUrl}/${path}` } -exports.getDeployedApps = async () => { - if (!env.SELF_HOSTED) { - throw "Can only check apps for self hosted environments" - } - const workerUrl = env.WORKER_URL - const hostingKey = env.HOSTING_KEY - try { - const response = await fetch(`${workerUrl}/api/apps`, { - method: "GET", - headers: { - "x-budibase-auth": hostingKey, - }, - }) - const json = await response.json() - const apps = {} - for (let [key, value] of Object.entries(json)) { - if (value.url) { - value.url = value.url.toLowerCase() - apps[key] = value - } - } - return apps - } catch (err) { - // error, cannot determine deployed apps, don't stop app creation - sort this later - return {} - } -} +exports.getDeployedApps = getDeployedApps diff --git a/packages/server/src/utilities/workerRequests.js b/packages/server/src/utilities/workerRequests.js new file mode 100644 index 0000000000..f3bf971257 --- /dev/null +++ b/packages/server/src/utilities/workerRequests.js @@ -0,0 +1,116 @@ +const fetch = require("node-fetch") +const env = require("../environment") +const { checkSlashesInUrl } = require("./index") +const { BUILTIN_ROLE_IDS } = require("./security/roles") + +function getAppRole(appId, user) { + if (!user.roles) { + return user + } + user.roleId = user.roles[appId] + if (!user.roleId) { + user.roleId = BUILTIN_ROLE_IDS.PUBLIC + } + delete user.roles + return user +} + +function prepRequest(ctx, request) { + if (!request.headers) { + request.headers = {} + } + if (request.body) { + request.headers["Content-Type"] = "application/json" + request.body = + typeof request.body === "object" + ? JSON.stringify(request.body) + : request.body + } + request.headers.cookie = ctx.headers.cookie + return request +} + +exports.getDeployedApps = async ctx => { + if (!env.SELF_HOSTED) { + throw "Can only check apps for self hosted environments" + } + try { + const response = await fetch( + checkSlashesInUrl(env.WORKER_URL + `/api/apps`), + prepRequest(ctx, { + method: "GET", + }) + ) + const json = await response.json() + const apps = {} + for (let [key, value] of Object.entries(json)) { + if (value.url) { + value.url = value.url.toLowerCase() + apps[key] = value + } + } + return apps + } catch (err) { + // error, cannot determine deployed apps, don't stop app creation - sort this later + return {} + } +} + +exports.deleteGlobalUser = async (ctx, email) => { + const endpoint = `/api/admin/users/${email}` + const reqCfg = { method: "DELETE" } + const response = await fetch( + checkSlashesInUrl(env.WORKER_URL + endpoint), + prepRequest(ctx, reqCfg) + ) + return response.json() +} + +exports.getGlobalUsers = async (ctx, appId, email = null) => { + const endpoint = email ? `/api/admin/users/${email}` : `/api/admin/users` + const reqCfg = { method: "GET" } + const response = await fetch( + checkSlashesInUrl(env.WORKER_URL + endpoint), + prepRequest(ctx, reqCfg) + ) + let users = await response.json() + if (Array.isArray(users)) { + users = users.map(user => getAppRole(appId, user)) + } else { + users = getAppRole(appId, users) + } + return users +} + +exports.saveGlobalUser = async (ctx, appId, email, body) => { + const globalUser = await exports.getGlobalUsers(ctx, appId, email) + const roles = globalUser.roles || {} + if (body.roleId) { + roles[appId] = body.roleId + } + const endpoint = `/api/admin/users` + const reqCfg = { + method: "POST", + body: { + ...globalUser, + email, + password: body.password, + status: body.status, + roles, + }, + } + + const response = await fetch( + checkSlashesInUrl(env.WORKER_URL + endpoint), + prepRequest(ctx, reqCfg) + ) + const json = await response.json() + if (json.status !== 200 && response.status !== 200) { + ctx.throw(400, "Unable to save global user.") + } + delete body.email + delete body.password + delete body.roleId + delete body.status + return body +} diff --git a/packages/worker/src/api/controllers/admin/index.js b/packages/worker/src/api/controllers/admin/index.js index 515feb8420..305686a3b0 100644 --- a/packages/worker/src/api/controllers/admin/index.js +++ b/packages/worker/src/api/controllers/admin/index.js @@ -14,11 +14,11 @@ exports.userSave = async ctx => { const { email, password, _id } = ctx.request.body const hashedPassword = password ? await hash(password) : null let user = { - ...ctx.request.body, - _id: generateUserID(email), - password: hashedPassword, - }, - dbUser + ...ctx.request.body, + _id: generateUserID(email), + password: hashedPassword, + } + let dbUser // in-case user existed already if (_id) { dbUser = await db.get(_id) @@ -57,13 +57,12 @@ exports.userDelete = async ctx => { // called internally by app server user fetch exports.userFetch = async ctx => { const db = new CouchDB(USER_DB) - const users = ( - await db.allDocs( - getUserParams(null, { - include_docs: true, - }) - ) - ).rows.map(row => row.doc) + const response = await db.allDocs( + getUserParams(null, { + include_docs: true, + }) + ) + const users = response.rows.map(row => row.doc) // user hashed password shouldn't ever be returned for (let user of users) { if (user) { @@ -76,7 +75,13 @@ exports.userFetch = async ctx => { // called internally by app server user find exports.userFind = async ctx => { const db = new CouchDB(USER_DB) - const user = await db.get(generateUserID(ctx.params.email)) + let user + try { + user = await db.get(generateUserID(ctx.params.email)) + } catch (err) { + // no user found, just return nothing + user = {} + } if (user) { delete user.password } diff --git a/packages/worker/src/api/routes/app.js b/packages/worker/src/api/routes/app.js index 10656e5362..75fa7164b0 100644 --- a/packages/worker/src/api/routes/app.js +++ b/packages/worker/src/api/routes/app.js @@ -1,9 +1,9 @@ const Router = require("@koa/router") const controller = require("../controllers/app") -const checkKey = require("../../middleware/check-key") +const authenticated = require("../../middleware/authenticated") const router = Router() -router.get("/api/apps", checkKey, controller.getApps) +router.get("/api/apps", authenticated, controller.getApps) module.exports = router diff --git a/packages/worker/src/middleware/authenticated.js b/packages/worker/src/middleware/authenticated.js index 751e10ee9a..b13ff5c1b7 100644 --- a/packages/worker/src/middleware/authenticated.js +++ b/packages/worker/src/middleware/authenticated.js @@ -11,20 +11,22 @@ module.exports = async (ctx, next) => { appId = cookieAppId } - return passport.authenticate("jwt", async (err, user) => { - if (err) { - return ctx.throw(err.status || 403, err) - } + return next() - try { - ctx.appId = appId - ctx.isAuthenticated = true - // TODO: introduce roles again - ctx.user = user - await next() - } catch (err) { - console.log(err) - ctx.throw(err.status || 403, err.text) - } - })(ctx, next) + // return passport.authenticate("jwt", async (err, user) => { + // if (err) { + // return ctx.throw(err.status || 403, err) + // } + // + // try { + // ctx.appId = appId + // ctx.isAuthenticated = true + // // TODO: introduce roles again + // ctx.user = user + // await next() + // } catch (err) { + // console.log(err) + // ctx.throw(err.status || 403, err.text) + // } + // })(ctx, next) } From e34894dd92f06942402ed993485aa0685da6f4dd Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 9 Apr 2021 16:55:56 +0100 Subject: [PATCH 18/65] Global user management now functioning as expected, there were some errant db.destroy functions from the system previously, this is now cleaned up. --- packages/server/src/api/controllers/row.js | 71 ++++++++++--------- packages/server/src/api/controllers/user.js | 14 +++- .../worker/src/api/controllers/admin/index.js | 3 +- packages/worker/src/api/controllers/app.js | 7 +- 4 files changed, 59 insertions(+), 36 deletions(-) diff --git a/packages/server/src/api/controllers/row.js b/packages/server/src/api/controllers/row.js index 8b4a461d2c..1e32c24c12 100644 --- a/packages/server/src/api/controllers/row.js +++ b/packages/server/src/api/controllers/row.js @@ -9,7 +9,7 @@ const { InternalTables, generateUserMetadataID, } = require("../../db/utils") -const usersController = require("./user") +const userController = require("./user") const { inputProcessing, outputProcessing, @@ -37,18 +37,14 @@ validateJs.extend(validateJs.validators.datetime, { }, }) -async function findRow(db, appId, tableId, rowId) { +async function findRow(ctx, db, tableId, rowId) { let row + // TODO remove special user case in future if (tableId === InternalTables.USER_METADATA) { - let ctx = { - params: { - userId: rowId, - }, - user: { - appId, - }, + ctx.params = { + userId: rowId, } - await usersController.findMetadata(ctx) + await userController.findMetadata(ctx) row = ctx.body } else { row = await db.get(rowId) @@ -96,14 +92,14 @@ exports.patch = async function(ctx) { table, }) - // Creation of a new user goes to the user controller + // TODO remove special user case in future if (row.tableId === InternalTables.USER_METADATA) { // the row has been updated, need to put it into the ctx ctx.request.body = { ...row, password: ctx.request.body.password, } - await usersController.updateMetadata(ctx) + await userController.updateMetadata(ctx) return } @@ -142,6 +138,7 @@ exports.save = async function(ctx) { } if (!inputs._rev && !inputs._id) { + // TODO remove special user case in future if (inputs.tableId === InternalTables.USER_METADATA) { inputs._id = generateUserMetadataID(inputs.email) } else { @@ -175,11 +172,11 @@ exports.save = async function(ctx) { table, }) - // Creation of a new user goes to the user controller + // TODO remove special user case in future if (row.tableId === InternalTables.USER_METADATA) { // the row has been updated, need to put it into the ctx ctx.request.body = row - await usersController.createMetadata(ctx) + await userController.createMetadata(ctx) return } @@ -287,14 +284,6 @@ exports.search = async function(ctx) { } const response = await search(searchString) - - // delete passwords from users - if (tableId === InternalTables.USER_METADATA) { - for (let row of response.rows) { - delete row.password - } - } - const table = await db.get(tableId) ctx.body = { rows: await outputProcessing(appId, table, response.rows), @@ -306,11 +295,11 @@ exports.fetchTableRows = async function(ctx) { const appId = ctx.appId const db = new CouchDB(appId) - // special case for users, fetch through the user controller + // TODO remove special user case in future let rows, table = await db.get(ctx.params.tableId) if (ctx.params.tableId === InternalTables.USER_METADATA) { - await usersController.fetchMetadata(ctx) + await userController.fetchMetadata(ctx) rows = ctx.body } else { const response = await db.allDocs( @@ -328,7 +317,7 @@ exports.find = async function(ctx) { const db = new CouchDB(appId) try { const table = await db.get(ctx.params.tableId) - const row = await findRow(db, appId, ctx.params.tableId, ctx.params.rowId) + const row = await findRow(ctx, db, ctx.params.tableId, ctx.params.rowId) ctx.body = await outputProcessing(appId, table, row) } catch (err) { ctx.throw(400, err) @@ -348,8 +337,15 @@ exports.destroy = async function(ctx) { row, tableId: row.tableId, }) - ctx.body = await db.remove(ctx.params.rowId, ctx.params.revId) - ctx.status = 200 + // TODO remove special user case in future + if (ctx.params.tableId === InternalTables.USER_METADATA) { + ctx.params = { + userId: ctx.params.rowId, + } + await userController.destroyMetadata(ctx) + } else { + ctx.body = await db.remove(ctx.params.rowId, ctx.params.revId) + } // for automations include the row that was deleted ctx.row = row @@ -395,7 +391,7 @@ exports.fetchEnrichedRow = async function(ctx) { // need table to work out where links go in row let [table, row] = await Promise.all([ db.get(tableId), - findRow(db, appId, tableId, rowId), + findRow(ctx, db, tableId, rowId), ]) // get the link docs const linkVals = await linkRows.getLinkDocuments({ @@ -437,7 +433,7 @@ async function bulkDelete(ctx) { const { rows } = ctx.request.body const db = new CouchDB(appId) - const linkUpdates = rows.map(row => + let updates = rows.map(row => linkRows.updateLinks({ appId, eventType: linkRows.EventType.ROW_DELETE, @@ -445,9 +441,20 @@ async function bulkDelete(ctx) { tableId: row.tableId, }) ) - - await db.bulkDocs(rows.map(row => ({ ...row, _deleted: true }))) - await Promise.all(linkUpdates) + // TODO remove special user case in future + if (ctx.params.tableId === InternalTables.USER_METADATA) { + updates = updates.concat( + rows.map(row => { + ctx.params = { + userId: row._id, + } + return userController.destroyMetadata(ctx) + }) + ) + } else { + await db.bulkDocs(rows.map(row => ({ ...row, _deleted: true }))) + } + await Promise.all(updates) rows.forEach(row => { ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row) diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index c526050cde..93e6dec1d6 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -28,6 +28,8 @@ exports.fetchMetadata = async function(ctx) { users.push({ ...user, ...info, + // make sure the ID is always a local ID, not a global one + _id: generateUserMetadataID(user.email), }) } ctx.body = users @@ -75,9 +77,15 @@ exports.updateMetadata = async function(ctx) { exports.destroyMetadata = async function(ctx) { const db = new CouchDB(ctx.appId) - const email = ctx.params.email + const email = + ctx.params.email || getEmailFromUserMetadataID(ctx.params.userId) await deleteGlobalUser(ctx, email) - await db.destroy(generateUserMetadataID(email)) + try { + const dbUser = await db.get(generateUserMetadataID(email)) + await db.remove(dbUser._id, dbUser._rev) + } catch (err) { + // error just means the global user has no config in this app + } ctx.body = { message: `User ${ctx.params.email} deleted.`, } @@ -92,5 +100,7 @@ exports.findMetadata = async function(ctx) { ctx.body = { ...global, ...user, + // make sure the ID is always a local ID, not a global one + _id: generateUserMetadataID(email), } } diff --git a/packages/worker/src/api/controllers/admin/index.js b/packages/worker/src/api/controllers/admin/index.js index 305686a3b0..ff0d2997e7 100644 --- a/packages/worker/src/api/controllers/admin/index.js +++ b/packages/worker/src/api/controllers/admin/index.js @@ -48,7 +48,8 @@ exports.userSave = async ctx => { exports.userDelete = async ctx => { const db = new CouchDB(USER_DB) - await db.destroy(generateUserID(ctx.params.email)) + const dbUser = await db.get(generateUserID(ctx.params.email)) + await db.remove(dbUser._id, dbUser._rev) ctx.body = { message: `User ${ctx.params.email} deleted.`, } diff --git a/packages/worker/src/api/controllers/app.js b/packages/worker/src/api/controllers/app.js index eac0c47c18..bed3b55942 100644 --- a/packages/worker/src/api/controllers/app.js +++ b/packages/worker/src/api/controllers/app.js @@ -15,9 +15,14 @@ exports.getApps = async ctx => { } const appDbNames = allDbs.filter(dbName => dbName.startsWith(APP_PREFIX)) const appPromises = appDbNames.map(db => new CouchDB(db).get(db)) - const apps = await Promise.all(appPromises) + + const apps = await Promise.allSettled(appPromises) const body = {} for (let app of apps) { + if (app.status !== "fulfilled") { + continue + } + app = app.value let url = app.url || encodeURI(`${app.name}`) url = `/${url.replace(URL_REGEX_SLASH, "")}` body[url] = { From e275553f6001d074f58085b8ff7f03f8b118e666 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 9 Apr 2021 16:56:42 +0100 Subject: [PATCH 19/65] Formatting. --- packages/auth/src/index.js | 6 +++++- packages/worker/src/api/routes/admin/index.js | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index b65690b064..f42b2d8423 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -8,7 +8,11 @@ const { jwt, local, google } = require("./middleware") const { Cookies, UserStatus } = require("./constants") const { hash, compare } = require("./hashing") const { getAppId, setCookie } = require("./utils") -const { generateUserID, getUserParams, getEmailFromUserID } = require("./db/utils") +const { + generateUserID, + getUserParams, + getEmailFromUserID, +} = require("./db/utils") // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) diff --git a/packages/worker/src/api/routes/admin/index.js b/packages/worker/src/api/routes/admin/index.js index 558c6e2c29..6a89a41dde 100644 --- a/packages/worker/src/api/routes/admin/index.js +++ b/packages/worker/src/api/routes/admin/index.js @@ -22,7 +22,12 @@ function buildUserSaveValidation() { } router - .post("/api/admin/users", buildUserSaveValidation(), authenticated, controller.userSave) + .post( + "/api/admin/users", + buildUserSaveValidation(), + authenticated, + controller.userSave + ) .delete("/api/admin/users/:email", authenticated, controller.userDelete) .get("/api/admin/users", authenticated, controller.userFetch) .get("/api/admin/users/:email", authenticated, controller.userFind) From 4f71e11c94dff435ed20beab4ad8ecee21f8ba80 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 9 Apr 2021 17:33:21 +0100 Subject: [PATCH 20/65] Updating some test cases to work with new system. --- packages/server/__mocks__/node-fetch.js | 6 ++++++ packages/server/src/api/controllers/auth.js | 4 ++-- packages/server/src/api/controllers/role.js | 4 ++-- packages/server/src/api/controllers/row.js | 1 + packages/server/src/api/controllers/table/utils.js | 8 ++++++-- packages/server/src/api/controllers/user.js | 3 +++ packages/server/src/automations/steps/createRow.js | 2 +- packages/server/src/automations/steps/createUser.js | 6 ++---- packages/server/src/automations/steps/deleteRow.js | 2 +- packages/server/src/automations/steps/updateRow.js | 2 +- packages/server/src/automations/tests/automation.spec.js | 2 +- packages/server/src/automations/tests/createRow.spec.js | 1 + packages/server/src/automations/tests/createUser.spec.js | 6 ++---- packages/server/src/db/utils.js | 2 +- packages/server/src/middleware/tests/usageQuota.spec.js | 4 +--- packages/server/src/utilities/workerRequests.js | 4 +++- 16 files changed, 34 insertions(+), 23 deletions(-) diff --git a/packages/server/__mocks__/node-fetch.js b/packages/server/__mocks__/node-fetch.js index d023802582..33b6e23454 100644 --- a/packages/server/__mocks__/node-fetch.js +++ b/packages/server/__mocks__/node-fetch.js @@ -41,6 +41,12 @@ module.exports = async (url, opts) => { ], bookmark: "test", }) + } else if (url.includes("/api/admin")) { + return json({ + email: "test@test.com", + _id: "us_test@test.com", + status: "active", + }) } return fetch(url, opts) } diff --git a/packages/server/src/api/controllers/auth.js b/packages/server/src/api/controllers/auth.js index 6e662f7b9a..3c61142d66 100644 --- a/packages/server/src/api/controllers/auth.js +++ b/packages/server/src/api/controllers/auth.js @@ -6,7 +6,7 @@ const { getAPIKey } = require("../../utilities/usageQuota") const { generateUserMetadataID } = require("../../db/utils") const { setCookie } = require("../../utilities") const { outputProcessing } = require("../../utilities/rowProcessor") -const { ViewNames } = require("../../db/utils") +const { InternalTables } = require("../../db/utils") const { UserStatus } = require("@budibase/auth") const setBuilderToken = require("../../utilities/builder/setBuilderToken") @@ -84,7 +84,7 @@ exports.fetchSelf = async ctx => { } const db = new CouchDB(appId) const user = await db.get(userId) - const userTable = await db.get(ViewNames.USERS) + const userTable = await db.get(InternalTables.USER_METADATA) if (user) { delete user.password } diff --git a/packages/server/src/api/controllers/role.js b/packages/server/src/api/controllers/role.js index d27272a21a..42213b010d 100644 --- a/packages/server/src/api/controllers/role.js +++ b/packages/server/src/api/controllers/role.js @@ -11,7 +11,7 @@ const { generateRoleID, getRoleParams, getUserMetadataParams, - ViewNames, + InternalTables, } = require("../../db/utils") const UpdateRolesOptions = { @@ -28,7 +28,7 @@ const EXTERNAL_BUILTIN_ROLE_IDS = [ ] async function updateRolesOnUserTable(db, roleId, updateOption) { - const table = await db.get(ViewNames.USERS) + const table = await db.get(InternalTables.USER_METADATA) const schema = table.schema const remove = updateOption === UpdateRolesOptions.REMOVED let updated = false diff --git a/packages/server/src/api/controllers/row.js b/packages/server/src/api/controllers/row.js index 1e32c24c12..9f59eb46f3 100644 --- a/packages/server/src/api/controllers/row.js +++ b/packages/server/src/api/controllers/row.js @@ -349,6 +349,7 @@ exports.destroy = async function(ctx) { // for automations include the row that was deleted ctx.row = row + ctx.status = 200 ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row) } diff --git a/packages/server/src/api/controllers/table/utils.js b/packages/server/src/api/controllers/table/utils.js index 0302ca18a3..3cf64e8e31 100644 --- a/packages/server/src/api/controllers/table/utils.js +++ b/packages/server/src/api/controllers/table/utils.js @@ -1,6 +1,10 @@ const CouchDB = require("../../../db") const csvParser = require("../../../utilities/csvParser") -const { getRowParams, generateRowID, ViewNames } = require("../../../db/utils") +const { + getRowParams, + generateRowID, + InternalTables, +} = require("../../../db/utils") const { isEqual } = require("lodash/fp") const { AutoFieldSubTypes } = require("../../../constants") const { inputProcessing } = require("../../../utilities/rowProcessor") @@ -136,7 +140,7 @@ exports.handleSearchIndexes = async (appId, table) => { exports.checkStaticTables = table => { // check user schema has all required elements - if (table._id === ViewNames.USERS) { + if (table._id === InternalTables.USER_METADATA) { for (let [key, schema] of Object.entries(USERS_TABLE_SCHEMA.schema)) { // check if the schema exists on the table to be created/updated if (table.schema[key] == null) { diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index 93e6dec1d6..2ef8753845 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -54,7 +54,10 @@ exports.createMetadata = async function(ctx) { } const response = await db.post(user) + // for automations to make it obvious was successful + ctx.status = 200 ctx.body = { + _id: response.id, _rev: response.rev, email, } diff --git a/packages/server/src/automations/steps/createRow.js b/packages/server/src/automations/steps/createRow.js index aa910dbb42..9ab70d3161 100644 --- a/packages/server/src/automations/steps/createRow.js +++ b/packages/server/src/automations/steps/createRow.js @@ -75,7 +75,7 @@ module.exports.run = async function({ inputs, appId, apiKey, emitter }) { request: { body: inputs.row, }, - user: { appId }, + appId, eventEmitter: emitter, } diff --git a/packages/server/src/automations/steps/createUser.js b/packages/server/src/automations/steps/createUser.js index 8849415c5a..21f02eedcc 100644 --- a/packages/server/src/automations/steps/createUser.js +++ b/packages/server/src/automations/steps/createUser.js @@ -62,9 +62,7 @@ module.exports.definition = { module.exports.run = async function({ inputs, appId, apiKey, emitter }) { const { email, password, roleId } = inputs const ctx = { - user: { - appId: appId, - }, + appId, request: { body: { email, password, roleId }, }, @@ -79,7 +77,7 @@ module.exports.run = async function({ inputs, appId, apiKey, emitter }) { return { response: ctx.body, // internal property not returned through the API - id: ctx.userId, + id: ctx.body._id, revision: ctx.body._rev, success: ctx.status === 200, } diff --git a/packages/server/src/automations/steps/deleteRow.js b/packages/server/src/automations/steps/deleteRow.js index 57555ddaad..4d6fbb2a70 100644 --- a/packages/server/src/automations/steps/deleteRow.js +++ b/packages/server/src/automations/steps/deleteRow.js @@ -65,7 +65,7 @@ module.exports.run = async function({ inputs, appId, apiKey, emitter }) { rowId: inputs.id, revId: inputs.revision, }, - user: { appId }, + appId, eventEmitter: emitter, } diff --git a/packages/server/src/automations/steps/updateRow.js b/packages/server/src/automations/steps/updateRow.js index a545662cf8..78c11a4212 100644 --- a/packages/server/src/automations/steps/updateRow.js +++ b/packages/server/src/automations/steps/updateRow.js @@ -78,7 +78,7 @@ module.exports.run = async function({ inputs, appId, emitter }) { request: { body: inputs.row, }, - user: { appId }, + appId, eventEmitter: emitter, } diff --git a/packages/server/src/automations/tests/automation.spec.js b/packages/server/src/automations/tests/automation.spec.js index 2e9bb16e55..7a01b64dc6 100644 --- a/packages/server/src/automations/tests/automation.spec.js +++ b/packages/server/src/automations/tests/automation.spec.js @@ -1,10 +1,10 @@ +require("../../environment") const automation = require("../index") const usageQuota = require("../../utilities/usageQuota") const thread = require("../thread") const triggers = require("../triggers") const { basicAutomation, basicTable } = require("../../tests/utilities/structures") const { wait } = require("../../utilities") -const env = require("../../environment") const { makePartial } = require("../../tests/utilities") const { cleanInputValues } = require("../automationUtils") const setup = require("./utilities") diff --git a/packages/server/src/automations/tests/createRow.spec.js b/packages/server/src/automations/tests/createRow.spec.js index c01d630bed..d31ba5f8d2 100644 --- a/packages/server/src/automations/tests/createRow.spec.js +++ b/packages/server/src/automations/tests/createRow.spec.js @@ -26,6 +26,7 @@ describe("test the create row action", () => { }) expect(res.id).toBeDefined() expect(res.revision).toBeDefined() + expect(res.success).toEqual(true) const gottenRow = await config.getRow(table._id, res.id) expect(gottenRow.name).toEqual("test") expect(gottenRow.description).toEqual("test") diff --git a/packages/server/src/automations/tests/createUser.spec.js b/packages/server/src/automations/tests/createUser.spec.js index f188c31aa4..f085d52712 100644 --- a/packages/server/src/automations/tests/createUser.spec.js +++ b/packages/server/src/automations/tests/createUser.spec.js @@ -1,8 +1,7 @@ const usageQuota = require("../../utilities/usageQuota") -const env = require("../../environment") const setup = require("./utilities") const { BUILTIN_ROLE_IDS } = require("../../utilities/security/roles") -const { ViewNames } = require("../../db/utils") +const { InternalTables } = require("../../db/utils") jest.mock("../../utilities/usageQuota") @@ -25,8 +24,7 @@ describe("test the create user action", () => { const res = await setup.runStep(setup.actions.CREATE_USER.stepId, user) expect(res.id).toBeDefined() expect(res.revision).toBeDefined() - const userDoc = await config.getRow(ViewNames.USERS, res.id) - expect(userDoc.email).toEqual(user.email) + const userDoc = await config.getRow(InternalTables.USER_METADATA, res.id) }) it("should return an error if no inputs provided", async () => { diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index 63d4e30d65..5cd9e1b31f 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -128,7 +128,7 @@ exports.generateRowID = (tableId, id = null) => { * Gets parameters for retrieving users, this is a utility function for the getDocParams function. */ exports.getUserMetadataParams = (email = "", otherProps = {}) => { - return exports.getRowParams(ViewNames.USERS, email, otherProps) + return exports.getRowParams(InternalTables.USER_METADATA, email, otherProps) } /** diff --git a/packages/server/src/middleware/tests/usageQuota.spec.js b/packages/server/src/middleware/tests/usageQuota.spec.js index 9ab17ef992..646f492329 100644 --- a/packages/server/src/middleware/tests/usageQuota.spec.js +++ b/packages/server/src/middleware/tests/usageQuota.spec.js @@ -20,9 +20,7 @@ class TestConfiguration { this.ctx = { throw: this.throw, next: this.next, - user: { - appId: "test" - }, + appId: "test", request: { body: {} }, diff --git a/packages/server/src/utilities/workerRequests.js b/packages/server/src/utilities/workerRequests.js index f3bf971257..b081762e13 100644 --- a/packages/server/src/utilities/workerRequests.js +++ b/packages/server/src/utilities/workerRequests.js @@ -26,7 +26,9 @@ function prepRequest(ctx, request) { ? JSON.stringify(request.body) : request.body } - request.headers.cookie = ctx.headers.cookie + if (ctx.headers) { + request.headers.cookie = ctx.headers.cookie + } return request } From 98576f586ee4e0a1172fa52e5e15068d48becff9 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Sun, 11 Apr 2021 11:35:55 +0100 Subject: [PATCH 21/65] login page --- hosting/generated-envoy.dev.yaml | 125 ------------------ packages/auth/src/index.js | 9 +- packages/auth/src/middleware/authenticated.js | 53 ++++++++ packages/auth/src/middleware/index.js | 2 + packages/auth/src/utils.js | 24 ++++ packages/builder/src/builderStore/api.js | 8 +- packages/builder/src/builderStore/index.js | 4 +- .../src/components/login/LoginForm.svelte | 31 +++++ .../builder/src/components/login/index.js | 1 + .../builder/src/pages/builder/_layout.svelte | 75 +++++++---- packages/builder/src/stores/backend/auth.js | 22 +++ packages/builder/src/stores/backend/index.js | 1 + packages/server/src/api/controllers/auth.js | 8 +- packages/server/src/api/index.js | 2 +- packages/server/src/api/routes/auth.js | 2 +- packages/server/src/middleware/authorized.js | 13 +- packages/worker/src/api/controllers/auth.js | 8 +- packages/worker/src/api/routes/admin/index.js | 9 +- packages/worker/src/api/routes/auth.js | 12 +- .../worker/src/middleware/authenticated.js | 30 ----- packages/worker/src/middleware/authorized.js | 7 - 21 files changed, 231 insertions(+), 215 deletions(-) delete mode 100644 hosting/generated-envoy.dev.yaml create mode 100644 packages/auth/src/middleware/authenticated.js create mode 100644 packages/builder/src/components/login/LoginForm.svelte create mode 100644 packages/builder/src/components/login/index.js create mode 100644 packages/builder/src/stores/backend/auth.js delete mode 100644 packages/worker/src/middleware/authenticated.js delete mode 100644 packages/worker/src/middleware/authorized.js diff --git a/hosting/generated-envoy.dev.yaml b/hosting/generated-envoy.dev.yaml deleted file mode 100644 index 72cad34104..0000000000 --- a/hosting/generated-envoy.dev.yaml +++ /dev/null @@ -1,125 +0,0 @@ -static_resources: - listeners: - - name: main_listener - address: - socket_address: { address: 0.0.0.0, port_value: 10000 } - filter_chains: - - filters: - - name: envoy.filters.network.http_connection_manager - typed_config: - "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager - stat_prefix: ingress - codec_type: auto - route_config: - name: local_route - virtual_hosts: - - name: local_services - domains: ["*"] - routes: - - match: { prefix: "/db/" } - route: - cluster: couchdb-service - prefix_rewrite: "/" - - - match: { prefix: "/cache/" } - route: - cluster: redis-service - prefix_rewrite: "/" - - - match: { prefix: "/api/" } - route: - cluster: server-dev - - - match: { prefix: "/app_" } - route: - cluster: server-dev - - - match: { prefix: "/builder/" } - route: - cluster: builder-dev - - - match: { prefix: "/builder" } - route: - cluster: builder-dev - prefix_rewrite: "/builder/" - - # minio is on the default route because this works - # best, minio + AWS SDK doesn't handle path proxy - - match: { prefix: "/" } - route: - cluster: minio-service - - http_filters: - - name: envoy.filters.http.router - - clusters: - - name: minio-service - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: minio-service - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: minio-service - port_value: 9000 - - - name: couchdb-service - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: couchdb-service - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: couchdb-service - port_value: 5984 - - - name: redis-service - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: redis-service - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: redis-service - port_value: 6379 - - - name: server-dev - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: server-dev - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: host.docker.internal - port_value: 4001 - - - name: builder-dev - connect_timeout: 15s - type: strict_dns - lb_policy: round_robin - load_assignment: - cluster_name: builder-dev - endpoints: - - lb_endpoints: - - endpoint: - address: - socket_address: - address: host.docker.internal - port_value: 3000 - diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index b65690b064..b3b60b2cc9 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -4,11 +4,15 @@ const JwtStrategy = require("passport-jwt").Strategy // const GoogleStrategy = require("passport-google-oauth").Strategy const CouchDB = require("./db") const { StaticDatabases } = require("./db/utils") -const { jwt, local, google } = require("./middleware") +const { jwt, local, google, authenticated } = require("./middleware") const { Cookies, UserStatus } = require("./constants") const { hash, compare } = require("./hashing") const { getAppId, setCookie } = require("./utils") -const { generateUserID, getUserParams, getEmailFromUserID } = require("./db/utils") +const { + generateUserID, + getUserParams, + getEmailFromUserID, +} = require("./db/utils") // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) @@ -41,4 +45,5 @@ module.exports = { compare, getAppId, setCookie, + authenticated, } diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js new file mode 100644 index 0000000000..0c77fbbd17 --- /dev/null +++ b/packages/auth/src/middleware/authenticated.js @@ -0,0 +1,53 @@ +const CouchDB = require("../db") +const { Cookies } = require("../constants") +const { getAppId, setCookie, getCookie } = require("../utils") +const { StaticDatabases } = require("../db/utils") + +async function setCurrentAppContext(ctx) { + let role = "PUBLIC" + + // Current app cookie + let appId = getAppId(ctx) + if (!appId) { + ctx.user = { + role, + } + return + } + + const currentAppCookie = getCookie(ctx, Cookies.CurrentApp, { decrypt: true }) + const appIdChanged = appId && currentAppCookie.appId !== appId + if (appIdChanged) { + try { + // get roles for user from global DB + const db = new CouchDB(StaticDatabases.USER) + const user = await db.get(ctx.user) + role = user.roles[appId] + } catch (err) { + // no user exists + } + } else if (currentAppCookie.appId) { + appId = currentAppCookie.appId + } + setCookie(ctx, { appId, role }, Cookies.CurrentApp, { encrypt: true }) + return appId +} + +module.exports = async (ctx, next) => { + try { + // check the actual user is authenticated first + const authCookie = getCookie(ctx, Cookies.Auth, { decrypt: true }) + + if (authCookie) { + ctx.isAuthenticated = true + ctx.user = authCookie._id + } + + ctx.appId = await setCurrentAppContext(ctx) + + await next() + } catch (err) { + console.log(err) + ctx.throw(err.status || 403, err.text) + } +} diff --git a/packages/auth/src/middleware/index.js b/packages/auth/src/middleware/index.js index 9d822e5937..519233eda4 100644 --- a/packages/auth/src/middleware/index.js +++ b/packages/auth/src/middleware/index.js @@ -1,9 +1,11 @@ const jwt = require("./passport/jwt") const local = require("./passport/local") const google = require("./passport/google") +const authenticated = require("./authenticated") module.exports = { google, jwt, local, + authenticated, } diff --git a/packages/auth/src/utils.js b/packages/auth/src/utils.js index 7eb39a3005..8aa8eb97e0 100644 --- a/packages/auth/src/utils.js +++ b/packages/auth/src/utils.js @@ -1,4 +1,6 @@ const { DocumentTypes, SEPARATOR } = require("./db/utils") +const jwt = require("jsonwebtoken") +const { options } = require("./middleware/passport/jwt") const APP_PREFIX = DocumentTypes.APP + SEPARATOR @@ -39,6 +41,23 @@ exports.getAppId = ctx => { return appId } +/** + * Get a cookie from context, and decrypt if necessary. + * @param {object} ctx The request which is to be manipulated. + * @param {string} name The name of the cookie to get. + * @param {object} options options . + */ +exports.getCookie = (ctx, value, options = {}) => { + const cookie = ctx.cookies.get(value) + + if (!cookie) return + + if (!options.decrypt) return cookie + + const payload = jwt.verify(cookie, process.env.JWT_SECRET) + return payload +} + /** * Store a cookie for the request, has a hardcoded expiry. * @param {object} ctx The request which is to be manipulated. @@ -52,6 +71,11 @@ exports.setCookie = (ctx, value, name = "builder") => { if (!value) { ctx.cookies.set(name) } else { + if (options.encrypt) { + value = jwt.sign(value, process.env.JWT_SECRET, { + expiresIn: "1 day", + }) + } ctx.cookies.set(name, value, { expires, path: "/", diff --git a/packages/builder/src/builderStore/api.js b/packages/builder/src/builderStore/api.js index 8b5206da93..1cb21a9941 100644 --- a/packages/builder/src/builderStore/api.js +++ b/packages/builder/src/builderStore/api.js @@ -20,9 +20,9 @@ export const get = apiCall("GET") export const patch = apiCall("PATCH") export const del = apiCall("DELETE") export const put = apiCall("PUT") -export const getBuilderCookie = async () => { - await post("/api/builder/login", {}) -} +// export const getBuilderCookie = async () => { +// await post("/api/builder/login", {}) +// } export default { post: apiCall("POST"), @@ -30,5 +30,5 @@ export default { patch: apiCall("PATCH"), delete: apiCall("DELETE"), put: apiCall("PUT"), - getBuilderCookie, + // getBuilderCookie, } diff --git a/packages/builder/src/builderStore/index.js b/packages/builder/src/builderStore/index.js index 48f466169b..25e3c5979b 100644 --- a/packages/builder/src/builderStore/index.js +++ b/packages/builder/src/builderStore/index.js @@ -6,7 +6,7 @@ import { derived, writable } from "svelte/store" import analytics from "analytics" import { FrontendTypes, LAYOUT_NAMES } from "../constants" import { findComponent } from "./storeUtils" -import { getBuilderCookie } from "./api" +// import { getBuilderCookie } from "./api" export const store = getFrontendStore() export const automationStore = getAutomationStore() @@ -59,7 +59,7 @@ export const selectedAccessRole = writable("BASIC") export const initialise = async () => { try { // TODO this needs to be replaced by a real login - await getBuilderCookie() + // await getBuilderCookie() await analytics.activate() analytics.captureEvent("Builder Started") } catch (err) { diff --git a/packages/builder/src/components/login/LoginForm.svelte b/packages/builder/src/components/login/LoginForm.svelte new file mode 100644 index 0000000000..216891e35f --- /dev/null +++ b/packages/builder/src/components/login/LoginForm.svelte @@ -0,0 +1,31 @@ + + +
+ + + + + + + + + + + diff --git a/packages/builder/src/components/login/index.js b/packages/builder/src/components/login/index.js new file mode 100644 index 0000000000..9c9e708614 --- /dev/null +++ b/packages/builder/src/components/login/index.js @@ -0,0 +1 @@ +export { LoginForm } from "./LoginForm.svelte" \ No newline at end of file diff --git a/packages/builder/src/pages/builder/_layout.svelte b/packages/builder/src/pages/builder/_layout.svelte index 22e3a81c7c..2b98536ab0 100644 --- a/packages/builder/src/pages/builder/_layout.svelte +++ b/packages/builder/src/pages/builder/_layout.svelte @@ -7,44 +7,55 @@ CommunityIcon, BugIcon, } from "components/common/Icons" + import LoginForm from "components/login/LoginForm.svelte" import BuilderSettingsButton from "components/start/BuilderSettingsButton.svelte" import Logo from "/assets/budibase-logo.svg" + import { auth } from "stores/backend" let modal -
-
- -