diff --git a/.eslintrc.json b/.eslintrc.json index 6293ac93..20951b9d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,6 +3,7 @@ "es6": true, "node": true }, + "parser": "@babel/eslint-parser", "parserOptions": { "ecmaVersion": 2017, "sourceType": "module" diff --git a/config/config.md b/config/config.md index 19bf4270..11ce252f 100644 --- a/config/config.md +++ b/config/config.md @@ -41,6 +41,13 @@ The following config option are provided by the OpenHIM. All of these options ha "timeout": 60000 }, "api": { + // The session secret key used for the hashing of signed cookie (used to detect if the client modified the cookie) + // Signed cookie is another cookie of the same name with the .sig suffix appended + "sessionKey": "r8q,+&1LM3)CD*zAGpx1xm{NeQhc;#", + // The session max age is the session cookie expiration time (in milliseconds) + "maxAge": 7200000, + // The number of characters that will be used to generate a random salt for the encryption of passwords + "salt": 10, // The port that the OpenHIM API uses "port": 8080, // The protocol that the OpenHIM API uses @@ -60,7 +67,11 @@ The following config option are provided by the OpenHIM. All of these options ha // A message to append to detail strings that have been truncated "truncateAppend": "\n[truncated ...]", // The types of authentication to use for the API - // Supported types are "token" and "basic" + // Supported types are "token" and "basic" and "local" + // * "local" means through the UI with hitting "/authentication/local" endpoint with username and password, + // this will create a session for the user and set cookies in the browser. + // * "basic" means with basic auth either through browser or postman by giving also username and password. + // * [Deprecated] "token" means that a request should provide in the header an 'auth-token', 'auth-salt' and 'auth-ts' to be authenticated. "authenicationTypes": ["token"] }, "rerun": { diff --git a/config/default.json b/config/default.json index 52cfe0cf..38eadd55 100644 --- a/config/default.json +++ b/config/default.json @@ -31,6 +31,9 @@ "pollPeriodMins": 60 }, "api": { + "sessionKey": "r8q,+&1LM3)CD*zAGpx1xm{NeQhc;#", + "maxAge": 7200000, + "salt": 10, "enabled": true, "protocol": "https", "port": 8080, @@ -39,7 +42,7 @@ "maxPayloadSizeMB": 50, "truncateSize": 15000, "truncateAppend": "\n[truncated ...]", - "authenticationTypes": ["basic", "token"] + "authenticationTypes": ["basic", "local", "token"] }, "rerun": { "httpPort": 7786, diff --git a/config/test.json b/config/test.json index 9a244df6..a642befa 100644 --- a/config/test.json +++ b/config/test.json @@ -26,7 +26,7 @@ "maxPayloadSizeMB": 50, "truncateSize": 10, "truncateAppend": "\n[truncated ...]", - "authenticationTypes": ["token", "basic"] + "authenticationTypes": ["token", "basic", "local"] }, "caching": { "enabled": false diff --git a/package-lock.json b/package-lock.json index 5cfcaecd..6b9284c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,87 +4,90 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "@babel/cli": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.15.4.tgz", - "integrity": "sha512-9RhhQ7tgKRcSO/jI3rNLxalLSk30cHqeM8bb+nGOJTyYBDpkoXw/A9QHZ2SYjlslAt4tr90pZQGIEobwWHSIDw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.20.7.tgz", + "integrity": "sha512-WylgcELHB66WwQqItxNILsMlaTd8/SO6SgTTjMp4uCI7P4QyH1r3nqgFmO3BfM4AtfniHgFMH3EpYFj/zynBkQ==", "dev": true, "requires": { - "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.2", + "@jridgewell/trace-mapping": "^0.3.8", + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", "chokidar": "^3.4.0", "commander": "^4.0.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", + "glob": "^7.2.0", "make-dir": "^2.1.0", - "slash": "^2.0.0", - "source-map": "^0.5.0" + "slash": "^2.0.0" } }, "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dev": true, "requires": { - "@babel/highlight": "^7.10.4" + "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", + "version": "7.20.14", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.14.tgz", + "integrity": "sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw==", "dev": true }, "@babel/core": { - "version": "7.15.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.5.tgz", - "integrity": "sha512-pYgXxiwAgQpgM1bNkZsDEq85f0ggXMA5L7c+o3tskGMh2BunCI9QUwB9Z4jpvXUOuMdyGKiGKQiRe11VS6Jzvg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.4", - "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.5", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4", + "version": "7.20.12", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", + "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.7", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helpers": "^7.20.7", + "@babel/parser": "^7.20.7", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.12", + "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" + "json5": "^2.2.2", + "semver": "^6.3.0" }, "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, + } + } + }, + "@babel/eslint-parser": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz", + "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==", + "dev": true, + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -94,89 +97,118 @@ } }, "@babel/generator": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.4.tgz", - "integrity": "sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==", + "version": "7.20.14", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", + "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", "dev": true, "requires": { - "@babel/types": "^7.15.4", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "^7.20.7", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } } }, "@babel/helper-annotate-as-pure": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.15.4.tgz", - "integrity": "sha512-QwrtdNvUNsPCj2lfNQacsGSQvGX8ee1ttrBrcozUP2Sv/jylewBP/8QFe6ZkBsC8T/GYWonNAWJV4aRR9AL2DA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.15.4.tgz", - "integrity": "sha512-P8o7JP2Mzi0SdC6eWr1zF+AEYvrsZa7GSY1lTayjF5XJhVH0kjLYUZPvTMflP7tBgZoe9gIhTa60QwFpqh/E0Q==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" } }, "@babel/helper-compilation-targets": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", - "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", + "@babel/compat-data": "^7.20.5", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true } } }, "@babel/helper-create-class-features-plugin": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.4.tgz", - "integrity": "sha512-7ZmzFi+DwJx6A7mHRwbuucEYpyBwmh2Ca0RvI6z2+WLZYCqV0JOaLb+u0zbtmDicebgKBZgqbYfLaKNqSgv5Pw==", + "version": "7.20.12", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz", + "integrity": "sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/helper-split-export-declaration": "^7.18.6" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", - "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz", + "integrity": "sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "regexpu-core": "^4.7.1" + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.2.1" } }, "@babel/helper-define-polyfill-provider": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", - "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", + "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", "dev": true, "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2", @@ -191,370 +223,377 @@ } } }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, "@babel/helper-explode-assignable-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.15.4.tgz", - "integrity": "sha512-J14f/vq8+hdC2KoWLIQSsGrC9EFBKE4NFts8pfMpymfApds+fPqR30AOUWc4tyr56h9l/GA1Sxv2q3dLZWbQ/g==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" } }, "@babel/helper-function-name": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", - "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", - "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", + "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/template": "^7.18.10", + "@babel/types": "^7.19.0" } }, "@babel/helper-hoist-variables": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", - "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", - "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz", + "integrity": "sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.20.7" } }, "@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", - "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-simple-access": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - } + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", + "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.10", + "@babel/types": "^7.20.7" } }, "@babel/helper-optimise-call-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", - "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" } }, "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true }, "@babel/helper-remap-async-to-generator": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.15.4.tgz", - "integrity": "sha512-v53MxgvMK/HCwckJ1bZrq6dNKlmwlyRNYM6ypaRTdXWGOE2c1/SCa6dL/HimhPulGhZKw9W0QhREM583F/t0vQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-wrap-function": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/helper-replace-supers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", - "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", + "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/helper-simple-access": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", - "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.20.2" } }, "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.15.4.tgz", - "integrity": "sha512-BMRLsdh+D1/aap19TycS4eD1qELGrCBJwzaY9IE8LrpJtJb+H7rQkPIdsfgnMtLBA6DJls7X9z93Z4U8h7xw0A==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", + "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.20.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", - "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dev": true, "requires": { - "@babel/types": "^7.15.4" + "@babel/types": "^7.18.6" } }, + "@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true + }, "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "dev": true }, "@babel/helper-wrap-function": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.15.4.tgz", - "integrity": "sha512-Y2o+H/hRV5W8QhIfTpRIBwl57y8PrZt6JM3V8FOo5qarjshHItyH5lXlpMfBfmBefOqSCpKZs/6Dxqp0E/U+uw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", + "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/helper-function-name": "^7.19.0", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" } }, "@babel/helpers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", - "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz", + "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==", "dev": true, "requires": { - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.13", + "@babel/types": "^7.20.7" } }, "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.10.4", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.6.tgz", - "integrity": "sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==", + "version": "7.20.15", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", + "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", "dev": true }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.15.4.tgz", - "integrity": "sha512-eBnpsl9tlhPhpI10kU06JHnrYXwg3+V6CaP2idsCXNef0aeslpqyITXQ74Vfk5uHgY7IG7XP0yIH8b42KSzHog==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", + "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.15.4", - "@babel/plugin-proposal-optional-chaining": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.7" } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.15.4.tgz", - "integrity": "sha512-2zt2g5vTXpMC3OmK6uyjvdXptbhBXfA77XGrd3gh93zwG8lZYBLOBImiGBEG0RANu3JqKEACCz5CGk73OJROBw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.15.4", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", "@babel/plugin-syntax-async-generators": "^7.8.4" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", - "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-proposal-class-static-block": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.15.4.tgz", - "integrity": "sha512-M682XWrrLNk3chXCjoPUQWOyYsB93B9z3mRyjtqqYJWDf2mfCdIYgDrA11cgNVhAQieaq6F2fn2f3wI0U4aTjA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz", + "integrity": "sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-class-static-block": "^7.14.5" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", - "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-dynamic-import": "^7.8.3" } }, "@babel/plugin-proposal-export-namespace-from": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", - "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.18.9", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", - "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-json-strings": "^7.8.3" } }, "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", - "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", - "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", - "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.15.6.tgz", - "integrity": "sha512-qtOHo7A1Vt+O23qEAX+GdBpqaIuD3i9VRrWgCJeq7WO6H2d14EK3q11urj5Te2MAeK97nMiIdRpwd/ST4JFbNg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", "dev": true, "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.15.4" + "@babel/plugin-transform-parameters": "^7.20.7" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", - "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-plugin-utils": "^7.18.6", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz", + "integrity": "sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" } }, "@babel/plugin-proposal-private-methods": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", - "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-proposal-private-property-in-object": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.15.4.tgz", - "integrity": "sha512-X0UTixkLf0PCCffxgu5/1RQyGGbgZuKoI+vXP4iSbJSYwPb7hu06omsFGBvQ9lJEvwgrxHdS8B5nbfcd8GyUNA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz", + "integrity": "sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-create-class-features-plugin": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", - "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-syntax-async-generators": { @@ -602,6 +641,15 @@ "@babel/helper-plugin-utils": "^7.8.3" } }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", + "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.19.0" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -684,356 +732,353 @@ } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", - "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", + "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", - "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", + "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5" + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", - "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", - "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", + "version": "7.20.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.15.tgz", + "integrity": "sha512-Vv4DMZ6MiNOhu/LdaZsT/bsLRxgL94d269Mv4R/9sp6+Mp++X/JqypZYypJXLlM4mlL352/Egzbzr98iABH1CA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-classes": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.15.4.tgz", - "integrity": "sha512-Yjvhex8GzBmmPQUvpXRPWQ9WnxXgAFuZSrqOK/eJlOGIXwvv8H3UEdUigl1gb/bnjTrln+e8bkZUYCBt/xYlBg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz", + "integrity": "sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-split-export-declaration": "^7.18.6", "globals": "^11.1.0" } }, "@babel/plugin-transform-computed-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", - "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", + "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7" } }, "@babel/plugin-transform-destructuring": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", - "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", + "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", - "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", - "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", - "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-for-of": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.15.4.tgz", - "integrity": "sha512-DRTY9fA751AFBDh2oxydvVm4SYevs5ILTWLs6xKXps4Re/KG5nfUkr+TdHCrRWB8C69TlzVgA9b3RmGWmgN9LA==", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", + "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", - "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", - "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", - "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", - "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", + "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.4.tgz", - "integrity": "sha512-qg4DPhwG8hKp4BbVDvX1s8cohM8a6Bvptu4l6Iingq5rW+yRUAhe/YRup/YcW2zCOlrysEWVhftIcKzrEZv3sA==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz", + "integrity": "sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.15.4", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-simple-access": "^7.20.2" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.15.4.tgz", - "integrity": "sha512-fJUnlQrl/mezMneR72CKCgtOoahqGJNVKpompKwzv3BrEXdlPspTcyxrZ1XmDTIr9PpULrgEQo3qNKp6dW7ssw==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", + "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - } + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-identifier": "^7.19.1" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", - "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", - "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", + "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-new-target": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", - "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-object-super": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", - "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" } }, "@babel/plugin-transform-parameters": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.15.4.tgz", - "integrity": "sha512-9WB/GUTO6lvJU3XQsSr6J/WKvBC2hcs4Pew8YxZagi6GkTdniyqp8On5kqdK8MN0LMeu0mGbhPN+O049NV/9FQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", + "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-property-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", - "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-regenerator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", - "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", + "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", "dev": true, "requires": { - "regenerator-transform": "^0.14.2" + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", - "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", - "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-spread": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", - "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", + "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", - "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/plugin-transform-template-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", - "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", - "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", - "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.18.9" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", - "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" } }, "@babel/preset-env": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.6.tgz", - "integrity": "sha512-L+6jcGn7EWu7zqaO2uoTDjjMBW+88FXzV8KvrBl2z6MtRNxlsmUNRlZPaNNPUTgqhyC5DHNFk/2Jmra+ublZWw==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.15.4", - "@babel/plugin-proposal-async-generator-functions": "^7.15.4", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-class-static-block": "^7.15.4", - "@babel/plugin-proposal-dynamic-import": "^7.14.5", - "@babel/plugin-proposal-export-namespace-from": "^7.14.5", - "@babel/plugin-proposal-json-strings": "^7.14.5", - "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", - "@babel/plugin-proposal-numeric-separator": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.15.6", - "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", - "@babel/plugin-proposal-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-private-methods": "^7.14.5", - "@babel/plugin-proposal-private-property-in-object": "^7.15.4", - "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", + "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.20.1", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.20.1", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.2", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.20.0", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -1043,44 +1088,44 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.14.5", - "@babel/plugin-transform-async-to-generator": "^7.14.5", - "@babel/plugin-transform-block-scoped-functions": "^7.14.5", - "@babel/plugin-transform-block-scoping": "^7.15.3", - "@babel/plugin-transform-classes": "^7.15.4", - "@babel/plugin-transform-computed-properties": "^7.14.5", - "@babel/plugin-transform-destructuring": "^7.14.7", - "@babel/plugin-transform-dotall-regex": "^7.14.5", - "@babel/plugin-transform-duplicate-keys": "^7.14.5", - "@babel/plugin-transform-exponentiation-operator": "^7.14.5", - "@babel/plugin-transform-for-of": "^7.15.4", - "@babel/plugin-transform-function-name": "^7.14.5", - "@babel/plugin-transform-literals": "^7.14.5", - "@babel/plugin-transform-member-expression-literals": "^7.14.5", - "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.15.4", - "@babel/plugin-transform-modules-systemjs": "^7.15.4", - "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", - "@babel/plugin-transform-new-target": "^7.14.5", - "@babel/plugin-transform-object-super": "^7.14.5", - "@babel/plugin-transform-parameters": "^7.15.4", - "@babel/plugin-transform-property-literals": "^7.14.5", - "@babel/plugin-transform-regenerator": "^7.14.5", - "@babel/plugin-transform-reserved-words": "^7.14.5", - "@babel/plugin-transform-shorthand-properties": "^7.14.5", - "@babel/plugin-transform-spread": "^7.14.6", - "@babel/plugin-transform-sticky-regex": "^7.14.5", - "@babel/plugin-transform-template-literals": "^7.14.5", - "@babel/plugin-transform-typeof-symbol": "^7.14.5", - "@babel/plugin-transform-unicode-escapes": "^7.14.5", - "@babel/plugin-transform-unicode-regex": "^7.14.5", - "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.15.6", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.2", - "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.16.0", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.20.2", + "@babel/plugin-transform-classes": "^7.20.2", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.20.2", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.19.6", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.6", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.20.1", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", "semver": "^6.3.0" }, "dependencies": { @@ -1093,9 +1138,9 @@ } }, "@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", @@ -1106,146 +1151,95 @@ } }, "@babel/register": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.15.3.tgz", - "integrity": "sha512-mj4IY1ZJkorClxKTImccn4T81+UKTo4Ux0+OFSV9hME1ooqS9UV+pJ6BjD0qXPK4T3XW/KNa79XByjeEMZz+fw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz", + "integrity": "sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==", "dev": true, "requires": { "clone-deep": "^4.0.1", "find-cache-dir": "^2.0.0", "make-dir": "^2.1.0", - "pirates": "^4.0.0", + "pirates": "^4.0.5", "source-map-support": "^0.5.16" } }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "@babel/runtime": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", - "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", "dev": true, "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" }, "dependencies": { "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "dev": true } } }, "@babel/template": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", - "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dev": true, "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - } + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" } }, "@babel/traverse": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", - "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4", + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz", + "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.20.7", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.19.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.20.13", + "@babel/types": "^7.20.7", "debug": "^4.1.0", "globals": "^11.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - } } }, "@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", + "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - } } }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" + }, "@coolaj86/urequest": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/@coolaj86/urequest/-/urequest-1.3.7.tgz", "integrity": "sha512-PPrVYra9aWvZjSCKl/x1pJ9ZpXda1652oJrPBYy5rQumJJMkmTBN3ux+sK2xAUwVvv2wnewDlaQaHLxLwSHnIA==" }, "@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "requires": { "colorspace": "1.1.x", "enabled": "2.0.x", @@ -1253,41 +1247,29 @@ } }, "@eslint/eslintrc": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", - "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", "espree": "^7.3.0", - "globals": "^12.1.0", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.19", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - } - }, "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" } } } @@ -1304,9 +1286,9 @@ } }, "@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, "@istanbuljs/load-nyc-config": { @@ -1371,47 +1353,69 @@ } }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, "@nicolo-ribaudo/chokidar-2": { - "version": "2.1.8-no-fsevents.2", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.2.tgz", - "integrity": "sha512-Fb8WxUFOBQVl+CX4MWet5o7eCc6Pj04rXIwVKZ6h1NnqTo45eOQW6aWyhG25NIODvWFwTDMwBsYxrQ3imxpetg==", + "version": "2.1.8-no-fsevents.3", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", + "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", + "dev": true, + "optional": true + }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", "dev": true, - "optional": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^5.1.2", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^4.0.1" - } - } + "eslint-scope": "5.1.1" } }, "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -1438,9 +1442,9 @@ } }, "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, "@tootallnate/once": { @@ -1460,7 +1464,7 @@ "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, "@types/mongodb": { @@ -1473,9 +1477,14 @@ } }, "@types/node": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", - "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + "version": "18.13.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", + "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" + }, + "@types/triple-beam": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -1483,13 +1492,19 @@ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, "acorn": { @@ -1499,9 +1514,9 @@ "dev": true }, "acorn-jsx": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true }, "agenda": { @@ -1552,9 +1567,9 @@ } }, "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -1572,9 +1587,9 @@ } }, "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true }, "ansi-escapes": { @@ -1595,10 +1610,9 @@ } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" }, "ansi-styles": { "version": "3.2.1", @@ -1609,32 +1623,13 @@ "color-convert": "^1.9.0" } }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" - }, "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, "append-transform": { @@ -1649,7 +1644,7 @@ "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, "argparse": { @@ -1664,13 +1659,13 @@ "argv": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", - "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", + "integrity": "sha512-dEamhpPEwRUBpLNHeuCm/v+g0anFByHahxodVO/BbAarHVBBg2MccCwf9K+o1Pof+2btdnkJelYVUWjW/VrATw==", "dev": true }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" }, "arr-flatten": { "version": "1.1.0", @@ -1680,79 +1675,86 @@ "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" }, "array-includes": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", - "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.5" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" } }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" }, "array.prototype.flat": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", - "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" } }, "array.prototype.flatmap": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz", - "integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "function-bind": "^1.1.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" } }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" }, "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" }, "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.6.tgz", + "integrity": "sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==" }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "atna-audit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/atna-audit/-/atna-audit-1.0.1.tgz", - "integrity": "sha1-A7jPtfRgFCQbhUQA9K6ep3si4so=", + "integrity": "sha512-BhzuWFEbjR1ndb+U1yzkl5DCjHySxgSOIEKTRPbo3HJuEZGh+Oi5xBqLpk4BX8TVNSOh8MGkERaQqB1nMkTaDg==", "requires": { "js2xmlparser": "^1.0.0" } @@ -1762,6 +1764,12 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "axios": { "version": "0.21.4", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", @@ -1770,23 +1778,14 @@ "follow-redirects": "^1.14.0" } }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, "babel-plugin-polyfill-corejs2": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", - "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", + "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", "dev": true, "requires": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.2", + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.3", "semver": "^6.1.1" }, "dependencies": { @@ -1799,28 +1798,28 @@ } }, "babel-plugin-polyfill-corejs3": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz", - "integrity": "sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", + "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.2", - "core-js-compat": "^3.14.0" + "@babel/helper-define-polyfill-provider": "^0.3.3", + "core-js-compat": "^3.25.1" } }, "babel-plugin-polyfill-regenerator": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", - "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", + "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", "dev": true, "requires": { - "@babel/helper-define-polyfill-provider": "^0.2.2" + "@babel/helper-define-polyfill-provider": "^0.3.3" } }, "babel-polyfill": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", - "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", "requires": { "babel-runtime": "^6.26.0", "core-js": "^2.5.0", @@ -1830,7 +1829,7 @@ "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", "requires": { "core-js": "^2.4.0", "regenerator-runtime": "^0.11.0" @@ -1844,9 +1843,9 @@ } }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base": { "version": "0.11.2", @@ -1865,7 +1864,7 @@ "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "requires": { "is-descriptor": "^1.0.0" } @@ -1895,14 +1894,14 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "basic-auth": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", @@ -1921,14 +1920,12 @@ "bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" }, "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, "bl": { "version": "2.2.1", @@ -1954,34 +1951,11 @@ } }, "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "fill-range": "^7.0.1" } }, "browser-stdout": { @@ -1991,22 +1965,30 @@ "dev": true }, "browserslist": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.0.tgz", - "integrity": "sha512-g2BJ2a0nEYvEFQC208q8mVAhfNwpZ5Mu8BwgtCdZKO3qx98HChmeg448fPdUzld8aFmfLgVh7yymqV+q1lJZ5g==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001254", - "colorette": "^1.3.0", - "electron-to-chromium": "^1.3.830", - "escalade": "^3.1.1", - "node-releases": "^1.1.75" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" } }, "bson": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", - "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } }, "buffer-alloc": { "version": "1.2.0", @@ -2027,12 +2009,12 @@ "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", "dev": true }, "buffer-from": { @@ -2042,9 +2024,9 @@ "dev": true }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "cache-base": { "version": "1.0.1", @@ -2104,7 +2086,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -2117,15 +2098,14 @@ "dev": true }, "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==" }, "caniuse-lite": { - "version": "1.0.30001257", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz", - "integrity": "sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==", + "version": "1.0.30001453", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001453.tgz", + "integrity": "sha512-R9o/uySW38VViaTrOtwfbFEiBFUh7ST3uIG4OEymIG3/uKdHDO4xk/FaqfUw0d+irSUyFPy3dZszf9VvSTPnsA==", "dev": true }, "chalk": { @@ -2148,12 +2128,12 @@ "charenc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==" }, "chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2163,75 +2143,6 @@ "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - } } }, "chownr": { @@ -2254,7 +2165,7 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "requires": { "is-descriptor": "^0.1.0" } @@ -2283,14 +2194,13 @@ "dev": true }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, "clone-deep": { @@ -2307,7 +2217,7 @@ "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" }, "co-body": { "version": "6.1.0", @@ -2323,7 +2233,7 @@ "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==" }, "codecov": { "version": "3.8.3", @@ -2336,36 +2246,24 @@ "js-yaml": "3.14.1", "teeny-request": "7.1.1", "urlgrey": "1.0.0" - }, - "dependencies": { - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - } } }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" } }, "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "color-convert": "^1.9.3", + "color-string": "^1.6.0" } }, "color-convert": { @@ -2379,29 +2277,23 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", - "dev": true - }, "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", "requires": { - "color": "3.0.x", + "color": "^3.1.3", "text-hex": "1.0.x" } }, @@ -2422,7 +2314,7 @@ "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, "component-emitter": { @@ -2441,60 +2333,36 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "safe-buffer": "5.1.2" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } + "safe-buffer": "5.2.1" } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" }, "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" }, "cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, "cookies": { @@ -2504,52 +2372,44 @@ "requires": { "depd": "~2.0.0", "keygrip": "~1.1.0" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - } } }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==" }, "copy-to": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", - "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=" + "integrity": "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==" }, "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" }, "core-js-compat": { - "version": "3.17.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.17.3.tgz", - "integrity": "sha512-+in61CKYs4hQERiADCJsdgewpdl/X0GhEX77pjKgbeibXviIt2oxEjTc8O2fqHX8mDdBrDvX8MYD/RYsBv4OiA==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.28.0.tgz", + "integrity": "sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg==", "dev": true, "requires": { - "browserslist": "^4.17.0", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } + "browserslist": "^4.21.5" } }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "requires": { + "buffer": "^5.1.0" + } }, "cron": { "version": "1.8.2", @@ -2582,7 +2442,7 @@ "crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==" }, "date.js": { "version": "0.3.3", @@ -2611,49 +2471,58 @@ }, "dependencies": { "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" }, "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==" }, "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==" }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "default-require-extensions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", - "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", + "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", "dev": true, "requires": { "strip-bom": "^4.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + } } }, "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "define-property": { @@ -2696,32 +2565,42 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "dezalgo": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } }, "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "doctrine": { @@ -2749,18 +2628,18 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.3.838", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.838.tgz", - "integrity": "sha512-65O6UJiyohFAdX/nc6KJ0xG/4zOn7XCO03kQNNbCeMRGxlWTLzc6Uyi0tFNQuuGWqySZJi8CD2KXPXySVYmzMA==", + "version": "1.4.299", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.299.tgz", + "integrity": "sha512-lQ7ijJghH6pCGbfWXr6EY+KYCMaRSjgsY925r1p/TlpSfVM1VjHTcn1gAc15VM4uwti283X6QtjPTXdpoSGiZQ==", "dev": true }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "enabled": { @@ -2771,7 +2650,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "end-of-stream": { "version": "1.4.4", @@ -2803,33 +2682,70 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true } } }, "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", + "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", "dev": true, "requires": { + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.4", + "is-array-buffer": "^3.0.1", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + } + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" } }, "es-to-primitive": { @@ -2863,12 +2779,12 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "eslint": { @@ -2928,22 +2844,11 @@ "@babel/highlight": "^7.10.4" } }, - "@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - } + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, "ansi-styles": { "version": "4.3.0", @@ -2954,12 +2859,6 @@ "color-convert": "^2.0.1" } }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2991,97 +2890,34 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { - "estraverse": "^5.1.0" + "type-fest": "^0.20.2" } }, - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "file-entry-cache": { + "strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "flat-cache": "^3.0.4" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", - "dev": true - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "ansi-regex": "^5.0.1" } }, "supports-color": { @@ -3092,53 +2928,19 @@ "requires": { "has-flag": "^4.0.0" } - }, - "table": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", - "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", - "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - } - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true } } }, "eslint-config-prettier": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", - "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", + "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", "dev": true }, "eslint-config-standard": { - "version": "16.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", - "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", "dev": true }, "eslint-config-standard-jsx": { @@ -3148,13 +2950,14 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", - "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", "dev": true, "requires": { "debug": "^3.2.7", - "resolve": "^1.20.0" + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" }, "dependencies": { "debug": { @@ -3175,13 +2978,12 @@ } }, "eslint-module-utils": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", - "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", "dev": true, "requires": { - "debug": "^3.2.7", - "pkg-dir": "^2.0.0" + "debug": "^3.2.7" }, "dependencies": { "debug": { @@ -3193,63 +2995,11 @@ "ms": "^2.1.1" } }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - } } } }, @@ -3264,35 +3014,35 @@ } }, "eslint-plugin-import": { - "version": "2.24.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz", - "integrity": "sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==", + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", "dev": true, "requires": { - "array-includes": "^3.1.3", - "array.prototype.flat": "^1.2.4", - "debug": "^2.6.9", + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.6.2", - "find-up": "^2.0.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", "has": "^1.0.3", - "is-core-module": "^2.6.0", - "minimatch": "^3.0.4", - "object.values": "^1.1.4", - "pkg-up": "^2.0.0", - "read-pkg-up": "^3.0.0", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.11.0" + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" }, "dependencies": { "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "doctrine": { @@ -3304,124 +3054,16 @@ "esutils": "^2.0.2" } }, - "es-abstract": { - "version": "1.18.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.6.tgz", - "integrity": "sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-string": "^1.0.7", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "dev": true - }, - "is-core-module": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", - "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "object.values": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", - "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.2" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -3441,9 +3083,9 @@ }, "dependencies": { "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, "semver": { @@ -3455,37 +3097,39 @@ } }, "eslint-plugin-prettier": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz", - "integrity": "sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" } }, "eslint-plugin-promise": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz", - "integrity": "sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", + "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", "dev": true }, "eslint-plugin-react": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.21.5.tgz", - "integrity": "sha512-8MaEggC2et0wSF6bUeywF7qQ46ER81irOdWS4QWxnnlAEsnzeBevk1sWh7fhpCghPpXb+8Ks7hvaft6L/xsR6g==", + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.25.3.tgz", + "integrity": "sha512-ZMbFvZ1WAYSZKY662MBVEWR45VaBT6KSJCiupjrNlcdakB90juaZeDCbJq19e73JZQubqFtgETohwgAt8u5P6w==", "dev": true, "requires": { - "array-includes": "^3.1.1", - "array.prototype.flatmap": "^1.2.3", + "array-includes": "^3.1.3", + "array.prototype.flatmap": "^1.2.4", "doctrine": "^2.1.0", - "has": "^1.0.3", + "estraverse": "^5.2.0", "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "object.entries": "^1.1.2", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", + "minimatch": "^3.0.4", + "object.entries": "^1.1.4", + "object.fromentries": "^2.0.4", + "object.hasown": "^1.0.0", + "object.values": "^1.1.4", "prop-types": "^15.7.2", - "resolve": "^1.18.1", - "string.prototype.matchall": "^4.0.2" + "resolve": "^2.0.0-next.3", + "string.prototype.matchall": "^4.0.5" }, "dependencies": { "doctrine": { @@ -3496,6 +3140,23 @@ "requires": { "esutils": "^2.0.2" } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } } } }, @@ -3516,12 +3177,20 @@ "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } } }, "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true }, "espree": { @@ -3533,6 +3202,14 @@ "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } } }, "esprima": { @@ -3542,18 +3219,18 @@ "dev": true }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", + "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", "dev": true, "requires": { "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -3568,9 +3245,9 @@ }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -3590,13 +3267,13 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true }, "event-stream": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", "requires": { "duplexer": "~0.1.1", "from": "~0", @@ -3608,14 +3285,14 @@ } }, "eventemitter2": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.4.tgz", - "integrity": "sha512-HLU3NDY6wARrLCEwyGKRBvuWYyvW6mHYv72SJJAH3iJN3a6eVUvkjFkcxah1bcTgGVBBrFdIopBJPhCQFMLyXw==" + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -3637,7 +3314,7 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "requires": { "is-descriptor": "^0.1.0" } @@ -3645,7 +3322,7 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "requires": { "is-extendable": "^0.1.0" } @@ -3655,7 +3332,7 @@ "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -3700,7 +3377,7 @@ "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "requires": { "is-descriptor": "^1.0.0" } @@ -3708,7 +3385,7 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "requires": { "is-extendable": "^0.1.0" } @@ -3738,11 +3415,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" } } }, @@ -3755,7 +3427,7 @@ "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" }, "fast-diff": { "version": "1.2.0", @@ -3780,35 +3452,28 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, "fast-safe-stringify": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true }, "fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", "dev": true, "requires": { "punycode": "^1.3.2" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } } }, "fecha": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", - "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" }, "figures": { "version": "3.2.0", @@ -3820,51 +3485,34 @@ } }, "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { - "flat-cache": "^2.0.1" + "flat-cache": "^3.0.4" } }, "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "to-regex-range": "^5.0.1" } }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dev": true, "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "dependencies": { @@ -3876,6 +3524,12 @@ "requires": { "ms": "2.0.0" } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true } } }, @@ -3906,31 +3560,19 @@ "dev": true }, "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, "fn.name": { @@ -3939,14 +3581,23 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz", - "integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==" + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" }, "foreground-child": { "version": "2.0.0", @@ -3982,7 +3633,7 @@ "normalize-path": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", "requires": { "remove-trailing-separator": "^1.0.1" } @@ -4033,7 +3684,7 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "requires": { "is-extendable": "^0.1.0" } @@ -4041,7 +3692,7 @@ "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -4058,7 +3709,7 @@ "glob-parent": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -4067,7 +3718,7 @@ "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", "requires": { "is-extglob": "^2.1.0" } @@ -4077,7 +3728,7 @@ "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", "requires": { "binary-extensions": "^1.0.0" } @@ -4085,7 +3736,7 @@ "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "requires": { "kind-of": "^3.0.2" } @@ -4093,7 +3744,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } @@ -4111,7 +3762,7 @@ "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -4130,15 +3781,21 @@ } }, "formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", - "dev": true + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dev": true, + "requires": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + } }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", "requires": { "map-cache": "^0.2.2" } @@ -4146,12 +3803,12 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "from": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==" }, "fromentries": { "version": "1.3.2", @@ -4174,7 +3831,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, "fsevents": { @@ -4186,13 +3843,30 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, "gensync": { @@ -4208,14 +3882,13 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dev": true, + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.3" } }, "get-package-type": { @@ -4243,18 +3916,18 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==" }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } @@ -4263,7 +3936,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -4274,15 +3946,33 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, "glossy": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/glossy/-/glossy-0.1.7.tgz", - "integrity": "sha1-dptZhKlvYGarnqdYIkgl7mwhDws=" + "integrity": "sha512-mTCC51QFadK75MvAhrL5nPVIP291NjML1guo10Sa7Yj04tJU4V++Vgm780NIddg9etQD9D8FM67hFGqM8EE2HQ==" + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "growl": { "version": "1.10.5", @@ -4313,34 +4003,46 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } }, "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "dev": true }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, "has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, "requires": { "has-symbols": "^1.0.2" } @@ -4348,7 +4050,7 @@ "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -4358,7 +4060,7 @@ "has-values": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -4367,7 +4069,7 @@ "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "requires": { "kind-of": "^3.0.2" }, @@ -4375,7 +4077,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } @@ -4385,7 +4087,7 @@ "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", "requires": { "is-buffer": "^1.1.5" } @@ -4400,6 +4102,14 @@ "requires": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "he": { @@ -4408,6 +4118,12 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true + }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -4421,44 +4137,30 @@ "dev": true }, "http-assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.4.1.tgz", - "integrity": "sha512-rdw7q6GTlibqVVbXr0CKelfV5iY8G2HqEUkhSk297BMbSpSL8crXC+9rjKoMcZZEsksX30le6f/4ul4E28gegw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", "requires": { "deep-equal": "~1.0.1", - "http-errors": "~1.7.2" - }, - "dependencies": { - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - } + "http-errors": "~1.8.0" } }, "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" }, "dependencies": { - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" } } }, @@ -4474,9 +4176,9 @@ } }, "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "requires": { "agent-base": "6", @@ -4491,7 +4193,7 @@ "humps": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/humps/-/humps-2.0.1.tgz", - "integrity": "sha1-3QLqYIG9BWjcXQcxhEY5V7qe+ao=" + "integrity": "sha512-E0eIbrFWUhwfXJmsbdjRQFQPrl5pTEoKlz163j1mTqqUnU9PgR4AgB8AIITzuB3vLBdxZXyZ9TDIrwB2OASz4g==" }, "iconv-lite": { "version": "0.4.24", @@ -4501,12 +4203,23 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, "ignore-walk": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.4.tgz", @@ -4517,9 +4230,9 @@ } }, "import-fresh": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", - "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -4537,7 +4250,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "indent-string": { @@ -4549,12 +4262,12 @@ "inflation": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", - "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=" + "integrity": "sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==" }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dev": true, "requires": { "once": "^1.3.0", @@ -4592,6 +4305,12 @@ "through": "^2.3.6" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -4617,21 +4336,47 @@ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4644,12 +4389,12 @@ } }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, "requires": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" } @@ -4657,12 +4402,12 @@ "invert-kv": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==" }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", "requires": { "kind-of": "^3.0.2" }, @@ -4670,41 +4415,54 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } } } }, + "is-array-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", + "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-typed-array": "^1.1.10" + } + }, "is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "is-bigint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", - "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", - "dev": true + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } }, "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "^2.0.0" } }, "is-boolean-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", - "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" } }, "is-buffer": { @@ -4713,15 +4471,20 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true }, + "is-class-hotfix": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", + "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==" + }, "is-core-module": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", - "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "requires": { "has": "^1.0.3" @@ -4730,7 +4493,7 @@ "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", "requires": { "kind-of": "^3.0.2" }, @@ -4738,7 +4501,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } @@ -4746,10 +4509,13 @@ } }, "is-date-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", - "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", - "dev": true + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-descriptor": { "version": "0.1.6", @@ -4771,66 +4537,57 @@ "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "requires": { + "number-is-nan": "^1.0.0" + } }, "is-generator-function": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", - "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==" + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { "is-extglob": "^2.1.1" } }, "is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, - "optional": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "has-tostringtag": "^1.0.0" } }, - "is-number-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", - "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", - "dev": true - }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", @@ -4846,25 +4603,37 @@ } }, "is-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", - "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.2" + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" } }, "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, "is-string": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", - "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } }, "is-symbol": { "version": "1.0.4", @@ -4875,12 +4644,44 @@ "has-symbols": "^1.0.2" } }, + "is-type-of": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-type-of/-/is-type-of-1.2.1.tgz", + "integrity": "sha512-uK0kyX9LZYhSDS7H2sVJQJop1UnWPWmo5RvR3q2kFH6AUHYs7sOrVg0b4nyBHw29kRRNFofYN/JbHZDlHiItTA==", + "requires": { + "core-util-is": "^1.0.2", + "is-class-hotfix": "~0.0.6", + "isstream": "~0.1.2" + } + }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", "dev": true }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -4889,22 +4690,27 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true }, "istanbul-lib-hook": { @@ -4937,41 +4743,17 @@ } }, "istanbul-lib-processinfo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", - "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", + "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", "dev": true, "requires": { "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", - "make-dir": "^3.0.0", + "cross-spawn": "^7.0.3", + "istanbul-lib-coverage": "^3.2.0", "p-map": "^3.0.0", "rimraf": "^3.0.0", - "uuid": "^3.3.3" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } + "uuid": "^8.3.2" } }, "istanbul-lib-report": { @@ -5018,9 +4800,9 @@ } }, "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "dev": true, "requires": { "debug": "^4.1.1", @@ -5037,9 +4819,9 @@ } }, "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -5053,9 +4835,9 @@ "dev": true }, "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -5065,7 +4847,7 @@ "js2xmlparser": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-1.0.0.tgz", - "integrity": "sha1-WhcPLo1kds5FQF4EgjJCUTeC/jA=" + "integrity": "sha512-k5U3WB58ZbkCqSyrBrNmGtNU87YudbNGTyJNFlVenzzoaKeRXEpQ3E5pYOIidRgQCzxvWIJQK56W7eYkCQqYQA==" }, "jsesc": { "version": "2.5.2", @@ -5088,17 +4870,14 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true }, "jsonwebtoken": { "version": "8.5.1", @@ -5118,9 +4897,9 @@ }, "dependencies": { "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "semver": { "version": "5.7.1", @@ -5130,13 +4909,13 @@ } }, "jsx-ast-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz", - "integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", "dev": true, "requires": { - "array-includes": "^3.1.2", - "object.assign": "^4.1.2" + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" } }, "just-extend": { @@ -5188,16 +4967,16 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "koa": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.1.tgz", - "integrity": "sha512-Lb2Dloc72auj5vK4X4qqL7B5jyDPQaZucc9sR/71byg7ryoD1NCaCm63CShk9ID9quQvDEi1bGR/iGjCG7As3w==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.14.1.tgz", + "integrity": "sha512-USJFyZgi2l0wDgqkfD27gL4YGno7TfUkcmOe6UOLFOVuN+J7FwnNu4Dydl4CUQzraM1lBAiGed0M9OVJoT0Kqw==", "requires": { "accepts": "^1.3.5", "cache-content-type": "^1.0.0", "content-disposition": "~0.5.2", "content-type": "^1.0.4", "cookies": "~0.8.0", - "debug": "~3.1.0", + "debug": "^4.3.2", "delegates": "^1.0.0", "depd": "^2.0.0", "destroy": "^1.0.4", @@ -5208,7 +4987,7 @@ "http-errors": "^1.6.3", "is-generator-function": "^1.0.7", "koa-compose": "^4.1.0", - "koa-convert": "^1.2.0", + "koa-convert": "^2.0.0", "on-finished": "^2.3.0", "only": "~0.0.2", "parseurl": "^1.3.2", @@ -5218,17 +4997,17 @@ }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "ms": "2.0.0" + "ms": "2.1.2" } }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, @@ -5266,39 +5045,63 @@ } }, "koa-convert": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz", - "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", "requires": { "co": "^4.6.0", - "koa-compose": "^3.0.0" - }, - "dependencies": { - "koa-compose": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz", - "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", - "requires": { - "any-promise": "^1.1.0" - } - } + "koa-compose": "^4.1.0" } }, "koa-is-json": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", - "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=" + "integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw==" + }, + "koa-passport": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/koa-passport/-/koa-passport-4.1.4.tgz", + "integrity": "sha512-dJBCkl4X+zdYxbI2V2OtoGy0PUenpvp2ZLLWObc8UJhsId0iQpTFT8RVcuA0709AL2txGwRHnSPoT1bYNGa6Kg==", + "requires": { + "passport": "^0.4.0" + } }, "koa-route": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/koa-route/-/koa-route-3.2.0.tgz", - "integrity": "sha1-dimLmaa8+p44yrb+XHmocz51i84=", + "integrity": "sha512-8FsuWw/L+CUWJfpgN6vrlYUDNTheEinG8Zkm97GyuLJNyWjCVUs9p10Ih3jTIWwmDVQcz6827l0RKadAS5ibqA==", "requires": { "debug": "*", "methods": "~1.1.0", "path-to-regexp": "^1.2.0" } }, + "koa-session": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/koa-session/-/koa-session-6.4.0.tgz", + "integrity": "sha512-h/dxmSOvNEXpHQPRs4TV03TZVFyZIjmYQiTAW5JBFTYBOZ0VdpZ8QEE6Dud75g8z9JNGXi3m++VqRmqToB+c2A==", + "requires": { + "crc": "^3.8.0", + "debug": "^4.3.3", + "is-type-of": "^1.2.1", + "uuid": "^8.3.2" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -5307,7 +5110,7 @@ "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", "requires": { "invert-kv": "^1.0.0" } @@ -5325,7 +5128,7 @@ "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -5337,13 +5140,7 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true } } @@ -5363,59 +5160,53 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" }, "lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" }, "lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" }, "lodash.merge": { "version": "4.6.2", @@ -5426,12 +5217,12 @@ "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true }, "log-symbols": { @@ -5453,9 +5244,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -5495,26 +5286,22 @@ } }, "logform": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", - "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", + "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", + "@colors/colors": "1.5.0", + "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" }, "dependencies": { - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" } } }, @@ -5556,17 +5343,17 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==" }, "map-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==" }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", "requires": { "object-visit": "^1.0.0" } @@ -5584,7 +5371,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, "memory-pager": { "version": "1.5.0", @@ -5595,7 +5382,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "micromatch": { "version": "3.1.10", @@ -5637,7 +5424,7 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "requires": { "is-extendable": "^0.1.0" } @@ -5647,7 +5434,7 @@ "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -5658,7 +5445,7 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "requires": { "is-extendable": "^0.1.0" } @@ -5668,7 +5455,7 @@ "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", "requires": { "kind-of": "^3.0.2" }, @@ -5676,7 +5463,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } @@ -5686,7 +5473,7 @@ "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -5701,16 +5488,16 @@ "dev": true }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.44.0" + "mime-db": "1.52.0" } }, "mimic-fn": { @@ -5720,17 +5507,17 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "mixin-deep": { "version": "1.3.2", @@ -5752,20 +5539,12 @@ } }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "requires": { - "minimist": "^1.2.5" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - } + "minimist": "^1.2.6" } }, "mocha": { @@ -5801,14 +5580,25 @@ "yargs-unparser": "2.0.0" }, "dependencies": { - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "color-convert": "^2.0.1" } }, "argparse": { @@ -5817,36 +5607,47 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "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" + } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "color-name": "~1.1.4" } }, - "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.3.1", - "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" - } + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "debug": { "version": "4.3.1", @@ -5865,27 +5666,12 @@ } } }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -5896,25 +5682,30 @@ "path-exists": "^4.0.0" } }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, "js-yaml": { @@ -5935,6 +5726,15 @@ "p-locate": "^5.0.0" } }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5974,6 +5774,26 @@ "picomatch": "^2.2.1" } }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -5983,39 +5803,62 @@ "has-flag": "^4.0.0" } }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "requires": { - "is-number": "^7.0.0" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" } } } }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "moment-timezone": { - "version": "0.5.33", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", - "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", + "version": "0.5.40", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.40.tgz", + "integrity": "sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg==", "requires": { "moment": ">= 2.9.0" } }, "mongodb": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.0.tgz", - "integrity": "sha512-JOAYjT9WYeRFkIP6XtDidAr3qvpfLRJhT2iokRWWH0tgqCQr9kmSfOJBZ3Ry0E5A3EqKxVPVhN3MV8Gn03o7pA==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", + "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", "requires": { "bl": "^2.2.1", "bson": "^1.1.4", "denque": "^1.4.1", - "optional-require": "^1.0.3", + "optional-require": "^1.1.8", "safe-buffer": "^5.1.2", "saslprep": "^1.0.0" } @@ -6023,18 +5866,18 @@ "mongodb-uri": { "version": "0.9.7", "resolved": "https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz", - "integrity": "sha1-D3ca0W9IOuZfQoeWlCjp+8SqYYE=" + "integrity": "sha512-s6BdnqNoEYfViPJgkH85X5Nw5NpzxN8hoflKLweNa7vBxt2V7kaS06d74pAtqDxde8fn4r9h4dNdLiFGoNV0KA==" }, "mongoose": { - "version": "5.13.9", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.9.tgz", - "integrity": "sha512-JbLw5ie0LJxm7V9LoNxRY//6cyFJf0cOpON2TWUWvF9pabil6ArfECL3xHV2N+mwwO4gXiIa+c0pwTzDUVTgqw==", + "version": "5.13.15", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz", + "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==", "requires": { "@types/bson": "1.x || 4.0.x", "@types/mongodb": "^3.5.27", "bson": "^1.1.4", "kareem": "2.3.2", - "mongodb": "3.6.11", + "mongodb": "3.7.3", "mongoose-legacy-pluralize": "1.0.2", "mpath": "0.8.4", "mquery": "3.2.5", @@ -6046,19 +5889,6 @@ "sliced": "1.0.1" }, "dependencies": { - "mongodb": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz", - "integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==", - "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" - } - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -6122,7 +5952,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "mute-stream": { "version": "0.0.8", @@ -6157,7 +5987,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "nconf": { @@ -6169,88 +5999,12 @@ "ini": "^1.3.0", "secure-keys": "^1.0.0", "yargs": "^3.19.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "y18n": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", - "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "requires": { - "camelcase": "^2.0.1", - "cliui": "^3.0.3", - "decamelize": "^1.1.1", - "os-locale": "^1.4.0", - "string-width": "^1.0.1", - "window-size": "^0.1.4", - "y18n": "^3.2.0" - } - } } }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "neo-async": { "version": "2.6.2", @@ -6277,16 +6031,13 @@ } }, "node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA==", - "dev": true - }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } }, "node-preload": { "version": "0.2.1", @@ -6298,15 +6049,65 @@ } }, "node-releases": { - "version": "1.1.75", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", - "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "nodemailer": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.3.tgz", - "integrity": "sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew==" + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", + "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==" + }, + "nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "requires": { + "abbrev": "1" + } }, "normalize-package-data": { "version": "2.5.0", @@ -6336,7 +6137,7 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==" }, "nyc": { "version": "15.1.0", @@ -6374,9 +6175,9 @@ }, "dependencies": { "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "ansi-styles": { @@ -6420,16 +6221,10 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -6508,23 +6303,23 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } }, "wrap-ansi": { @@ -6578,13 +6373,13 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true }, "object-copy": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -6594,7 +6389,7 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "requires": { "is-descriptor": "^0.1.0" } @@ -6602,7 +6397,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } @@ -6610,10 +6405,9 @@ } }, "object-inspect": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", - "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", - "dev": true + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" }, "object-keys": { "version": "1.1.1", @@ -6624,71 +6418,78 @@ "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", "requires": { "isobject": "^3.0.0" } }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, "object.entries": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", - "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.1", - "has": "^1.0.3" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "object.fromentries": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz", - "integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "requires": { "isobject": "^3.0.1" } }, "object.values": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", - "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has": "^1.0.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -6696,7 +6497,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "requires": { "wrappy": "1" @@ -6722,12 +6523,12 @@ "only": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", - "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==" }, "optional-require": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.7.tgz", - "integrity": "sha512-cIeRZocXsZnZYn+SevbtSqNlLbeoS4mLzuNn4fvXRMDRNhTGg0sxuKXl0FnZCtnew85LorNxIbZp5OeliILhMw==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", + "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", "requires": { "require-at": "^1.0.6" } @@ -6749,7 +6550,7 @@ "os-locale": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", "requires": { "lcid": "^1.0.0" } @@ -6757,7 +6558,7 @@ "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" }, "p-limit": { "version": "2.3.0", @@ -6816,7 +6617,7 @@ "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "requires": { "error-ex": "^1.3.1", @@ -6831,23 +6632,61 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==" + }, + "passport": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", + "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-custom": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/passport-custom/-/passport-custom-1.1.1.tgz", + "integrity": "sha512-/2m7jUGxmCYvoqenLB9UrmkCgPt64h8ZtV+UtuQklZ/Tn1NpKBeOorCYkB/8lMRoiZ5hUrCoMmDtxCS/d38mlg==", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-http": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/passport-http/-/passport-http-0.3.0.tgz", + "integrity": "sha512-OwK9DkqGVlJfO8oD0Bz1VDIo+ijD3c1ZbGGozIZw+joIP0U60pXY7goB+8wiDWtNqHpkTaQiJ9Ux1jE3Ykmpuw==", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==" }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", "dev": true }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" }, "path-key": { "version": "3.1.1", @@ -6872,7 +6711,7 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" } } }, @@ -6888,23 +6727,28 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true } } }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "pause-stream": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", "requires": { "through": "~2.3" } }, "pem": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/pem/-/pem-1.14.4.tgz", - "integrity": "sha512-v8lH3NpirgiEmbOqhx0vwQTxwi0ExsiWBGYh0jYNq7K6mQuO4gI6UEFlr6fLAdv9TPXRt6GqiwE37puQdIDS8g==", + "version": "1.14.6", + "resolved": "https://registry.npmjs.org/pem/-/pem-1.14.6.tgz", + "integrity": "sha512-I5GKUer2PPv5qzUfxaZ6IGRkhp+357Kyv2t1JJg9vP8hGGI13qU34N2QupmggbpIZGPuudH0jn8KU5hjFpPk3g==", "requires": { "es6-promisify": "^6.0.0", "md5": "^2.2.1", @@ -6912,10 +6756,16 @@ "which": "^2.0.2" } }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pify": { "version": "4.0.1", @@ -6924,13 +6774,10 @@ "dev": true }, "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true }, "pkg-conf": { "version": "3.1.0", @@ -6955,22 +6802,6 @@ "type-fest": "^0.3.0" } }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "type-fest": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", @@ -6991,7 +6822,7 @@ "pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "integrity": "sha512-fjAPuiws93rm7mPUu21RdBnkeZNrbfCFCwfAhPWY+rR3zG0ubpe5cEReHOw5fIbfmsxEV/g2kSxGTATY3Bpnwg==", "dev": true, "requires": { "find-up": "^2.1.0" @@ -7000,7 +6831,7 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "requires": { "locate-path": "^2.0.0" @@ -7009,7 +6840,7 @@ "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "requires": { "p-locate": "^2.0.0", @@ -7028,7 +6859,7 @@ "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "requires": { "p-limit": "^1.1.0" @@ -7037,7 +6868,7 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true } } @@ -7045,7 +6876,7 @@ "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==" }, "prelude-ls": { "version": "1.2.1", @@ -7054,9 +6885,9 @@ "dev": true }, "prettier": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.0.tgz", - "integrity": "sha512-DsEPLY1dE5HF3BxCRBmD4uYZ+5DCbvatnolqTqcxEgKVZnL2kUfyu7b8pPQ5+hTBkdhU9SLUmK0/pHb07RE4WQ==", + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", + "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", "dev": true }, "prettier-linter-helpers": { @@ -7089,14 +6920,14 @@ "dev": true }, "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "react-is": "^16.13.1" } }, "ps-tree": { @@ -7107,6 +6938,12 @@ "event-stream": "=3.3.4" } }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "pump": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", @@ -7118,15 +6955,18 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true }, "qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } }, "randombytes": { "version": "2.1.0", @@ -7144,27 +6984,32 @@ "dev": true }, "raw-body": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz", - "integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.3", + "bytes": "3.1.2", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, "dependencies": { "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" } } }, @@ -7177,7 +7022,7 @@ "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, "requires": { "load-json-file": "^4.0.0", @@ -7188,7 +7033,7 @@ "read-pkg-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", "dev": true, "requires": { "find-up": "^2.0.0", @@ -7198,7 +7043,7 @@ "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "requires": { "locate-path": "^2.0.0" @@ -7207,7 +7052,7 @@ "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "requires": { "p-locate": "^2.0.0", @@ -7226,7 +7071,7 @@ "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "requires": { "p-limit": "^1.1.0" @@ -7235,7 +7080,7 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true } } @@ -7262,15 +7107,11 @@ } }, "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "picomatch": "^2.2.1" } }, "regenerate": { @@ -7280,23 +7121,23 @@ "dev": true }, "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", "dev": true, "requires": { - "regenerate": "^1.4.0" + "regenerate": "^1.4.2" } }, "regenerator-runtime": { "version": "0.10.5", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==" }, "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", + "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", "dev": true, "requires": { "@babel/runtime": "^7.8.4" @@ -7317,13 +7158,14 @@ "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" }, "regexp.prototype.flags": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", - "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" } }, "regexpp": { @@ -7333,29 +7175,23 @@ "dev": true }, "regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.1.tgz", + "integrity": "sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ==", "dev": true, "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" } }, - "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, "regjsparser": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", - "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", "dev": true, "requires": { "jsesc": "~0.5.0" @@ -7364,7 +7200,7 @@ "jsesc": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true } } @@ -7372,7 +7208,7 @@ "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", "dev": true, "requires": { "es6-error": "^4.0.1" @@ -7381,7 +7217,7 @@ "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" }, "repeat-element": { "version": "1.1.4", @@ -7391,7 +7227,7 @@ "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" }, "require-at": { "version": "1.0.6", @@ -7401,7 +7237,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, "require-from-string": { @@ -7433,24 +7269,25 @@ } }, "resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "requires": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-from": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" }, "restore-cursor": { "version": "3.1.0", @@ -7477,9 +7314,15 @@ }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, "cross-spawn": { @@ -7503,6 +7346,12 @@ } } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "eslint": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", @@ -7557,6 +7406,12 @@ "eslint-visitor-keys": "^1.1.0" } }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, "espree": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", @@ -7568,6 +7423,32 @@ "eslint-visitor-keys": "^1.1.0" } }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -7577,10 +7458,16 @@ "type-fest": "^0.8.1" } }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, "requires": { "prelude-ls": "~1.1.2", @@ -7604,13 +7491,13 @@ "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", "dev": true }, "regexpp": { @@ -7619,6 +7506,15 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -7628,7 +7524,7 @@ "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "requires": { "shebang-regex": "^1.0.0" @@ -7637,9 +7533,31 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -7649,15 +7567,33 @@ "ansi-regex": "^4.1.0" } }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, "requires": { "prelude-ls": "~1.1.2" } }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -7701,11 +7637,27 @@ "safe-regex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", "requires": { "ret": "~0.1.10" } }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "safe-stable-stringify": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", + "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==" + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -7728,35 +7680,35 @@ "secure-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", - "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=" + "integrity": "sha512-nZi59hW3Sl5P3+wOO89eHBAAGwmCPd2aE1+dLZV5MO+ItQctIvAqihzaAXIQhvtH4KJPxM080HsnqltR2y8cWg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "requires": { "lru-cache": "^6.0.0" } }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dev": true, "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "2.0.0", "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", + "ms": "2.1.3", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { "debug": { @@ -7771,28 +7723,34 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true } } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dev": true, "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" } }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true } } @@ -7807,21 +7765,21 @@ } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dev": true, "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.18.0" } }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, "set-value": { @@ -7838,7 +7796,7 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "requires": { "is-extendable": "^0.1.0" } @@ -7846,9 +7804,9 @@ } }, "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "shallow-clone": { "version": "3.0.1", @@ -7899,7 +7857,7 @@ "should-format": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", "dev": true, "requires": { "should-type": "^1.3.0", @@ -7909,7 +7867,7 @@ "should-type": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", "dev": true }, "should-type-adaptors": { @@ -7932,7 +7890,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, "requires": { "call-bind": "^1.0.0", "get-intrinsic": "^1.0.2", @@ -7945,19 +7902,36 @@ "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "requires": { "is-arrayish": "^0.3.1" } }, + "simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, "sinon": { "version": "9.2.4", "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", @@ -7972,6 +7946,12 @@ "supports-color": "^7.1.0" }, "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -7996,20 +7976,44 @@ "dev": true }, "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true } } @@ -8017,7 +8021,7 @@ "sliced": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", - "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" }, "snapdragon": { "version": "0.8.2", @@ -8045,7 +8049,7 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "requires": { "is-descriptor": "^0.1.0" } @@ -8053,7 +8057,7 @@ "extend-shallow": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", "requires": { "is-extendable": "^0.1.0" } @@ -8073,7 +8077,7 @@ "define-property": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", "requires": { "is-descriptor": "^1.0.0" } @@ -8117,7 +8121,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } @@ -8127,7 +8131,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" }, "source-map-resolve": { "version": "0.5.3", @@ -8142,9 +8146,9 @@ } }, "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -8167,7 +8171,7 @@ "sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", "optional": true, "requires": { "memory-pager": "^1.0.2" @@ -8231,9 +8235,9 @@ } }, "spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", "dev": true }, "speculate": { @@ -8268,7 +8272,7 @@ "split": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", "requires": { "through": "2" } @@ -8284,7 +8288,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "ssl-root-cas": { @@ -8298,24 +8302,48 @@ "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" }, "standard": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/standard/-/standard-16.0.3.tgz", - "integrity": "sha512-70F7NH0hSkNXosXRltjSv6KpTAOkUkSfyu3ynyM5dtRUiLtR+yX9EGZ7RKwuGUqCJiX/cnkceVM6HTZ4JpaqDg==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/standard/-/standard-16.0.4.tgz", + "integrity": "sha512-2AGI874RNClW4xUdM+bg1LRXVlYLzTNEkHmTG5mhyn45OhbgwA+6znowkOGYy+WMb5HRyELvtNy39kcdMQMcYQ==", "dev": true, "requires": { - "eslint": "~7.13.0", - "eslint-config-standard": "16.0.2", + "eslint": "~7.18.0", + "eslint-config-standard": "16.0.3", "eslint-config-standard-jsx": "10.0.0", - "eslint-plugin-import": "~2.22.1", + "eslint-plugin-import": "~2.24.2", "eslint-plugin-node": "~11.1.0", - "eslint-plugin-promise": "~4.2.1", - "eslint-plugin-react": "~7.21.5", + "eslint-plugin-promise": "~5.1.0", + "eslint-plugin-react": "~7.25.1", "standard-engine": "^14.0.1" }, "dependencies": { + "@eslint/eslintrc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", + "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.20", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -8326,9 +8354,9 @@ } }, "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -8351,13 +8379,13 @@ "dev": true }, "eslint": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.13.0.tgz", - "integrity": "sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ==", + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz", + "integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.1", + "@eslint/eslintrc": "^0.3.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -8367,10 +8395,10 @@ "eslint-scope": "^5.1.1", "eslint-utils": "^2.1.0", "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.0", + "espree": "^7.3.1", "esquery": "^1.2.0", "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", + "file-entry-cache": "^6.0.0", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", "globals": "^12.1.0", @@ -8381,7 +8409,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash": "^4.17.20", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -8390,30 +8418,32 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^5.2.3", + "table": "^6.0.4", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" } }, "eslint-plugin-import": { - "version": "2.22.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", - "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "version": "2.24.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz", + "integrity": "sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==", "dev": true, "requires": { - "array-includes": "^3.1.1", - "array.prototype.flat": "^1.2.3", - "contains-path": "^0.1.0", + "array-includes": "^3.1.3", + "array.prototype.flat": "^1.2.4", "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.4", - "eslint-module-utils": "^2.6.0", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.6.2", + "find-up": "^2.0.0", "has": "^1.0.3", + "is-core-module": "^2.6.0", "minimatch": "^3.0.4", - "object.values": "^1.1.1", - "read-pkg-up": "^2.0.0", - "resolve": "^1.17.0", - "tsconfig-paths": "^3.9.0" + "object.values": "^1.1.4", + "pkg-up": "^2.0.0", + "read-pkg-up": "^3.0.0", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.11.0" }, "dependencies": { "debug": { @@ -8426,69 +8456,26 @@ } }, "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" + "esutils": "^2.0.2" } } } }, "eslint-plugin-promise": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", - "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", - "dev": true - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.1.tgz", + "integrity": "sha512-XgdcdyNzHfmlQyweOPTxmc7pIsS6dE4MvwhXWMQ2Dxs1XAL2GJDilUsjWen6TWik0aSI+zD/PqocZBblcm9rdA==", "dev": true }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, "find-up": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, "requires": { "locate-path": "^2.0.0" @@ -8509,52 +8496,16 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, "locate-path": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", @@ -8567,7 +8518,7 @@ "p-locate": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "requires": { "p-limit": "^1.1.0" @@ -8576,71 +8527,17 @@ "p-try": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, - "regexpp": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", - "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } }, "supports-color": { "version": "7.2.0", @@ -8651,14 +8548,11 @@ "has-flag": "^4.0.0" } }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true } } }, @@ -8677,7 +8571,7 @@ "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -8686,7 +8580,7 @@ "define-property": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", "requires": { "is-descriptor": "^0.1.0" } @@ -8696,12 +8590,12 @@ "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" }, "stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", "requires": { "duplexer": "~0.1.1" } @@ -8716,57 +8610,51 @@ } }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - } + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, "string.prototype.matchall": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.4.tgz", - "integrity": "sha512-pknFIWVachNcyqRfaQSeu/FUfpvJTe4uskUSZ9Wc1RijsPuzbZ8TyYT8WCNnntCjUEqQ3vUHMAfVj2+wLAisPQ==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.2", - "has-symbols": "^1.0.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", - "regexp.prototype.flags": "^1.3.1", + "regexp.prototype.flags": "^1.4.3", "side-channel": "^1.0.4" } }, "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "string_decoder": { @@ -8785,18 +8673,17 @@ } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^2.0.0" } }, "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, "strip-json-comments": { @@ -8808,55 +8695,69 @@ "stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==", "dev": true }, "superagent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-6.1.0.tgz", - "integrity": "sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg==", + "version": "8.0.9", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", + "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", "dev": true, "requires": { "component-emitter": "^1.3.0", - "cookiejar": "^2.1.2", - "debug": "^4.1.1", - "fast-safe-stringify": "^2.0.7", - "form-data": "^3.0.0", - "formidable": "^1.2.2", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", "methods": "^1.1.2", - "mime": "^2.4.6", - "qs": "^6.9.4", - "readable-stream": "^3.6.0", - "semver": "^7.3.2" + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" }, "dependencies": { - "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "dev": true + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, "supertest": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.1.6.tgz", - "integrity": "sha512-0hACYGNJ8OHRg8CRITeZOdbjur7NLuNs0mBjVhdpxi7hP6t3QIbOzLON5RTUmZcy2I9riuII3+Pr2C7yztrIIg==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", "dev": true, "requires": { "methods": "^1.1.2", - "superagent": "^6.1.0" + "superagent": "^8.0.5" } }, "supports-color": { @@ -8868,48 +8769,79 @@ "has-flag": "^3.0.0" } }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", + "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", "dev": true, "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "dependencies": { + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.1" } } } @@ -8985,13 +8917,13 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" }, "tmp": { "version": "0.0.33", @@ -9011,13 +8943,13 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", "requires": { "kind-of": "^3.0.2" }, @@ -9025,7 +8957,7 @@ "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", "requires": { "is-buffer": "^1.1.5" } @@ -9044,20 +8976,32 @@ } }, "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "optional": true, + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "^7.0.0" } }, "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true }, "triple-beam": { "version": "1.3.0", @@ -9065,31 +9009,25 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "tsconfig-paths": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", - "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", "dev": true, "requires": { "@types/json5": "^0.0.29", "json5": "^1.0.1", - "minimist": "^1.2.0", + "minimist": "^1.2.6", "strip-bom": "^3.0.0" }, "dependencies": { "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { "minimist": "^1.2.0" } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true } } }, @@ -9120,9 +9058,9 @@ "dev": true }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, "type-is": { @@ -9134,6 +9072,17 @@ "mime-types": "~2.1.24" } }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -9144,49 +9093,55 @@ } }, "uglify-js": { - "version": "3.13.6", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.6.tgz", - "integrity": "sha512-rRprLwl8RVaS+Qvx3Wh5hPfPBn9++G6xkGlUupya0s5aDmNjI7z3lnRLB3u7sN4OmbB0pWgzhM9BEJyiWAwtAA==", + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "optional": true }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", "dev": true }, "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" } }, "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true }, "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true }, "union-value": { @@ -9203,12 +9158,12 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -9217,7 +9172,7 @@ "has-value": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -9227,7 +9182,7 @@ "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", "requires": { "isarray": "1.0.0" } @@ -9237,7 +9192,7 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==" } } }, @@ -9246,19 +9201,37 @@ "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" }, + "update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "requires": { "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + } } }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" }, "urlgrey": { "version": "1.0.0", @@ -9277,7 +9250,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "uuid": { "version": "8.3.2", @@ -9285,9 +9258,9 @@ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", - "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "validate-npm-package-license": { @@ -9303,7 +9276,23 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } }, "which": { "version": "2.0.2", @@ -9329,9 +9318,23 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", "dev": true }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -9339,66 +9342,35 @@ "dev": true, "requires": { "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } } }, "window-size": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + "integrity": "sha512-2thx4pB0cV3h+Bw7QmMXcEbdmOzv9t0HFplJH/Lz6yu60hXYy5RT8rUu+wlIreVxWsGN20mo+MHeCSfUpQBwPw==" }, "winston": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", + "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", "requires": { + "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", + "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.2.0", + "logform": "^2.4.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" + "winston-transport": "^4.5.0" }, "dependencies": { "async": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", - "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" }, "readable-stream": { "version": "3.6.0", @@ -9413,21 +9385,34 @@ } }, "winston-mongodb": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/winston-mongodb/-/winston-mongodb-5.0.7.tgz", - "integrity": "sha512-6uUdd7IPfzKMth1vbO6zPyLQzn57CTNXbyjZmdD9UgBlY19BliFnYcK7+Aopo0GHIsWDo7xlerpj3x/ZULDIpg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/winston-mongodb/-/winston-mongodb-5.1.1.tgz", + "integrity": "sha512-tlDksYDCsSka6vLzB/cg19B+kRbVH/y9JQdXVXc5r4TSLEgX1Ivj/vHyedYlYzNMAZkSSfexwI/dSDn3f9/Qkg==", "requires": { "mongodb": "^3.6.2", "winston-transport": "^4.4.0" } }, "winston-transport": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", - "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", "requires": { - "readable-stream": "^2.3.7", - "triple-beam": "^1.2.0" + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "word-wrap": { @@ -9439,7 +9424,7 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" }, "workerpool": { "version": "6.1.0", @@ -9448,46 +9433,18 @@ "dev": true }, "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" } }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, "write": { @@ -9548,10 +9505,9 @@ "dev": true }, "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" }, "yallist": { "version": "4.0.0", @@ -9559,26 +9515,17 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha512-ONJZiimStfZzhKamYvR/xvmgW3uEkAUFSP91y2caTEPhzF6uP2JfPiVZcq66b/YR0C3uitxSV7+T1x8p5bkmMg==", "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "dependencies": { - "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", - "dev": true - } + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" } }, "yargs-parser": { @@ -9599,6 +9546,12 @@ "is-plain-obj": "^2.1.0" }, "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, "decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", @@ -9608,9 +9561,9 @@ } }, "ylru": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz", - "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==" + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", + "integrity": "sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==" }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index cf6a3d82..a3262de3 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "test:seed": "node performance/seed.js", "test:seed:ci": "npm run test:seed -- --quiet", "start": "node lib/server.js", + "start:dev": "nodemon lib/server.js", "stop": "pkill -SIGINT Core", "spec": "speculate" }, @@ -56,8 +57,11 @@ "kcors": "2.2.2", "koa": "^2.13.0", "koa-bodyparser": "^4.3.0", + "koa-compose": "^4.1.0", "koa-compress": "^5.1.0", + "koa-passport": "^4.0.0", "koa-route": "3.2.0", + "koa-session": "^6.3.1", "lodash": "^4.17.20", "moment": "^2.29.1", "moment-timezone": "^0.5.31", @@ -67,6 +71,9 @@ "mongoose-patch-history": "^2.0.0", "nconf": "0.10.0", "nodemailer": "^6.6.3", + "passport-custom": "^1.1.1", + "passport-http": "^0.3.0", + "passport-local": "^1.0.0", "pem": "^1.14.4", "raw-body": "^2.4.1", "semver": "^7.3.2", @@ -81,6 +88,7 @@ "devDependencies": { "@babel/cli": "^7.15.4", "@babel/core": "^7.15.5", + "@babel/eslint-parser": "^7.19.1", "@babel/preset-env": "^7.15.6", "@babel/register": "^7.15.3", "codecov": "^3.8.3", @@ -94,6 +102,7 @@ "faker": "^5.5.3", "finalhandler": "^1.1.2", "mocha": "^8.4.0", + "nodemon": "^2.0.20", "nyc": "^15.1.0", "prettier": "^2.4.0", "progress": "2.0.3", diff --git a/src/api/authentication.js b/src/api/authentication.js index fa316899..fd9275bb 100644 --- a/src/api/authentication.js +++ b/src/api/authentication.js @@ -1,15 +1,13 @@ 'use strict' import atna from 'atna-audit' -import basicAuth from 'basic-auth' -import crypto from 'crypto' import logger from 'winston' import os from 'os' import * as auditing from '../auditing' import * as authorisation from './authorisation' -import {UserModelAPI} from '../model/users' -import {caseInsensitiveRegex, logAndSetResponse} from '../utils' +import passport from '../passport' +import {logAndSetResponse} from '../utils' import {config} from '../config' import { BASIC_AUTH_TYPE, @@ -36,108 +34,26 @@ const auditingExemptPaths = [ /\/logs/ ] -const isUndefOrEmpty = string => string == null || string === '' - async function authenticateBasic(ctx) { - const credentials = basicAuth(ctx) - if (credentials == null) { - // No basic auth details found - return null - } - const {name: email, pass: password} = credentials - const user = await UserModelAPI.findOne({ - email: caseInsensitiveRegex(email) - }) - if (user == null) { - // not authenticated - user not found - ctx.throw( - 401, - `No user exists for ${email}, denying access to API, request originated from ${ctx.request.host}`, - {email} - ) - } + // Basic auth using middleware + await passport.authenticate('basic', function (err, user) { + if (user) { + ctx.req.user = user + ctx.body = 'User Authenticated Successfully' + ctx.status = 200 + } + })(ctx, () => {}) - const hash = crypto.createHash(user.passwordAlgorithm) - hash.update(user.passwordSalt) - hash.update(password) - if (user.passwordHash !== hash.digest('hex')) { - // not authenticated - password mismatch - ctx.throw( - 401, - `Password did not match expected value, denying access to API, the request was made by ${email} from ${ctx.request.host}`, - {email} - ) - } - return user + return ctx.req.user || null } +/** + * @deprecated + */ async function authenticateToken(ctx) { - const {header} = ctx.request - const email = header['auth-username'] - const authTS = header['auth-ts'] - const authSalt = header['auth-salt'] - const authToken = header['auth-token'] + await passport.authenticate('token')(ctx, () => {}) - // if any of the required headers aren't present - if ( - isUndefOrEmpty(email) || - isUndefOrEmpty(authTS) || - isUndefOrEmpty(authSalt) || - isUndefOrEmpty(authToken) - ) { - ctx.throw( - 401, - `API request made by ${email} from ${ctx.request.host} is missing required API authentication headers, denying access`, - {email} - ) - } - - // check if request is recent - const requestDate = new Date(Date.parse(authTS)) - - const authWindowSeconds = - config.api.authWindowSeconds != null ? config.api.authWindowSeconds : 10 - const to = new Date() - to.setSeconds(to.getSeconds() + authWindowSeconds) - const from = new Date() - from.setSeconds(from.getSeconds() - authWindowSeconds) - - if (requestDate < from || requestDate > to) { - // request expired - ctx.throw( - 401, - `API request made by ${email} from ${ctx.request.host} has expired, denying access`, - {email} - ) - } - - const user = await UserModelAPI.findOne({ - email: caseInsensitiveRegex(email) - }) - if (user == null) { - // not authenticated - user not found - ctx.throw( - 401, - `No user exists for ${email}, denying access to API, request originated from ${ctx.request.host}`, - {email} - ) - } - - const hash = crypto.createHash('sha512') - hash.update(user.passwordHash) - hash.update(authSalt) - hash.update(authTS) - - if (authToken !== hash.digest('hex')) { - // not authenticated - token mismatch - ctx.throw( - 401, - `API token did not match expected value, denying access to API, the request was made by ${email} from ${ctx.request.host}`, - {email} - ) - } - - return user + return ctx.req.user || null } function getEnabledAuthenticationTypesFromConfig(config) { @@ -160,20 +76,26 @@ function getEnabledAuthenticationTypesFromConfig(config) { return [] } -function isAuthenticationTypeEnabled(type) { +export function isAuthenticationTypeEnabled(type) { return getEnabledAuthenticationTypesFromConfig(config).includes(type) } async function authenticateRequest(ctx) { - let user - // First attempt basic authentication if enabled - if (user == null && isAuthenticationTypeEnabled('basic')) { - user = await authenticateBasic(ctx) + let user = null + + // First attempt local authentication if enabled + if (ctx.req.user) { + user = ctx.req.user } - // Otherwise try token based authentication if enabled - if (user == null && isAuthenticationTypeEnabled('token')) { + // Otherwise try token based authentication if enabled (@deprecated) + if (user == null) { user = await authenticateToken(ctx) } + // Otherwise try basic based authentication if enabled + if (user == null) { + // Basic auth using middleware + user = await authenticateBasic(ctx) + } // User could not be authenticated if (user == null) { const enabledTypes = @@ -195,9 +117,50 @@ function handleAuditResponse(err) { } export async function authenticate(ctx, next) { - let user try { - user = await authenticateRequest(ctx) + // Authenticate Request either by basic or local or token + const user = await authenticateRequest(ctx) + + if (ctx.isAuthenticated()) { + // Set the user on the context for consumption by other middleware + ctx.authenticated = user + + // Deal with paths exempt from audit + if (ctx.path === '/transactions') { + if ( + !ctx.query.filterRepresentation || + ctx.query.filterRepresentation !== 'full' + ) { + // exempt from auditing success + return next() + } + } else { + for (const pathTest of auditingExemptPaths) { + if (pathTest.test(ctx.path)) { + // exempt from auditing success + return next() + } + } + } + // Send an auth success audit event + let audit = atna.construct.userLoginAudit( + atna.constants.OUTCOME_SUCCESS, + himSourceID, + os.hostname(), + ctx.authenticated.email, + ctx.authenticated.groups.join(','), + ctx.authenticated.groups.join(',') + ) + audit = atna.construct.wrapInSyslog(audit) + auditing.sendAuditEvent(audit, handleAuditResponse) + + return next() + } else { + ctx.throw( + 401, + `Denying access for an API request from ${ctx.request.host}` + ) + } } catch (err) { // Handle authentication errors if (err.status === 401) { @@ -210,7 +173,7 @@ export async function authenticate(ctx, next) { atna.constants.OUTCOME_SERIOUS_FAILURE, himSourceID, os.hostname(), - err.email + `Unknown with ip ${ctx.request.ip}` ) audit = atna.construct.wrapInSyslog(audit) auditing.sendAuditEvent(audit, handleAuditResponse) @@ -219,41 +182,6 @@ export async function authenticate(ctx, next) { // Rethrow other errors throw err } - - // Set the user on the context for consumption by other middleware - ctx.authenticated = user - - // Deal with paths exempt from audit - if (ctx.path === '/transactions') { - if ( - !ctx.query.filterRepresentation || - ctx.query.filterRepresentation !== 'full' - ) { - // exempt from auditing success - return next() - } - } else { - for (const pathTest of auditingExemptPaths) { - if (pathTest.test(ctx.path)) { - // exempt from auditing success - return next() - } - } - } - - // Send an auth success audit event - let audit = atna.construct.userLoginAudit( - atna.constants.OUTCOME_SUCCESS, - himSourceID, - os.hostname(), - user.email, - user.groups.join(','), - user.groups.join(',') - ) - audit = atna.construct.wrapInSyslog(audit) - auditing.sendAuditEvent(audit, handleAuditResponse) - - return next() } export async function getEnabledAuthenticationTypes(ctx, next) { diff --git a/src/api/transactions.js b/src/api/transactions.js index 26af5b62..77506554 100644 --- a/src/api/transactions.js +++ b/src/api/transactions.js @@ -200,7 +200,10 @@ export async function getTransactions(ctx) { filters = parseTransactionFilters(filters) // execute the query - let transactions = await TransactionModelAPI.find(filters, projectionFiltersObject) + let transactions = await TransactionModelAPI.find( + filters, + projectionFiltersObject + ) .skip(filterSkip) .limit(parseInt(filterLimit, 10)) .sort({'request.timestamp': -1}) @@ -264,13 +267,21 @@ export async function rerunTransactions(ctx) { filters = parseTransactionFilters(filters) const count = await TransactionModelAPI.count(filters).exec() - const pages = Math.floor(count/taskTransactionsLength) - - createRerunTasks(filters, batchSize, ctx.authenticated.email, 0, pages, pauseQueue, taskTransactionsLength) + const pages = Math.floor(count / taskTransactionsLength) + + createRerunTasks( + filters, + batchSize, + ctx.authenticated.email, + 0, + pages, + pauseQueue, + taskTransactionsLength + ) ctx.body = { success: true, - message: "Tasks created for bulk rerun of transactions" + message: 'Tasks created for bulk rerun of transactions' } } catch (e) { utils.logAndSetResponse( @@ -284,9 +295,17 @@ export async function rerunTransactions(ctx) { let transactionsToRerun, taskObject, task -async function createRerunTasks(filters, batchSize, email, page, pages, pauseQueue, filterLimit) { +async function createRerunTasks( + filters, + batchSize, + email, + page, + pages, + pauseQueue, + filterLimit +) { transactionsToRerun = await TransactionModelAPI.find(filters, {_id: 1}) - .skip(filterLimit*page) + .skip(filterLimit * page) .limit(parseInt(filterLimit, 10)) .sort({'request.timestamp': -1}) .exec() @@ -296,7 +315,8 @@ async function createRerunTasks(filters, batchSize, email, page, pages, pauseQue transactionsToRerun = transactionsToRerun.map(trans => { return { tid: trans._id - }}) + } + }) taskObject = {} taskObject.remainingTransactions = transactionsToRerun.length @@ -314,7 +334,15 @@ async function createRerunTasks(filters, batchSize, email, page, pages, pauseQue logger.info(`Rerun task with id ${task._id} created!`) if (page < pages) { - return createRerunTasks(filters, batchSize, email, ++page, pages, pauseQueue, filterLimit) + return createRerunTasks( + filters, + batchSize, + email, + ++page, + pages, + pauseQueue, + filterLimit + ) } else { transactionsToRerun = null task = null @@ -323,7 +351,7 @@ async function createRerunTasks(filters, batchSize, email, page, pages, pauseQue } } -function parseTransactionFilters (filters) { +function parseTransactionFilters(filters) { filters = Object.assign({}, filters) // parse date to get it into the correct format for querying @@ -794,6 +822,5 @@ export async function removeTransaction(ctx, transactionId) { if (process.env.NODE_ENV === 'test') { exports.calculateTransactionBodiesByteLength = calculateTransactionBodiesByteLength - exports.createRerunTasks = - createRerunTasks + exports.createRerunTasks = createRerunTasks } diff --git a/src/api/users.js b/src/api/users.js index a30fe598..25c07ebd 100644 --- a/src/api/users.js +++ b/src/api/users.js @@ -11,7 +11,12 @@ import * as auditing from '../auditing' import * as authorisation from './authorisation' import * as contact from '../contact' import * as utils from '../utils' -import {UserModelAPI} from '../model/users' +import { + UserModelAPI, + updateUser as apiUpdateUser, + updateTokenUser +} from '../model/users' +import {PassportModelAPI, createPassport} from '../model/passport' import {config} from '../config' config.newUserExpiry = config.get('newUserExpiry') @@ -23,11 +28,42 @@ const himSourceID = config.get('auditing').auditEvents.auditSourceID /* * Get authentication details */ +export function me(ctx) { + if (ctx.req.user) { + ctx.body = {user: ctx.req.user} + ctx.status = 200 + } else { + ctx.body = 'Not authenticated' + ctx.status = 404 + } +} -export async function authenticate(ctx, email) { - email = unescape(email) +export async function authenticate(ctx) { + if (!ctx.req.user) { + utils.logAndSetResponse(ctx, 404, `Could not be authenticaticated`, 'info') + } else { + ctx.body = { + result: 'User authenticated successfully', + user: ctx.req.user + } + ctx.status = 200 + } +} + +/** + * @deprecated + * + * Using token auth type, the user is authenticated in the next middeleware, here we just return the salt and timestamp + * so the client can generate the password hash + */ +export async function authenticateToken(ctx, email) { + logger.warn( + 'Token authentication strategy is deprecated. Please consider using Local or Basic authentication.' + ) try { + email = unescape(email) + const user = await UserModelAPI.findOne({ email: utils.caseInsensitiveRegex(email) }) @@ -51,9 +87,24 @@ export async function authenticate(ctx, email) { logger.debug('Processed internal audit') ) } else { - ctx.body = { - salt: user.passwordSalt, - ts: new Date() + const passport = await PassportModelAPI.findOne({ + protocol: 'token', + user: user.id + }) + + if (!passport) { + utils.logAndSetResponse( + ctx, + 404, + `Could not find token passport for user ${email}`, + 'info' + ) + } else { + ctx.body = { + salt: passport.passwordSalt, + ts: new Date() + } + ctx.status = 200 } } } catch (e) { @@ -66,6 +117,13 @@ export async function authenticate(ctx, email) { } } +export const logout = async function (ctx) { + ctx.logout() + ctx.session = null + ctx.authenticated = null + ctx.status = 200 +} + /** * Reset password Functions */ @@ -242,7 +300,6 @@ export async function updateUserByToken(ctx, token) { `Could not find user with token ${token} via the API ${error}`, 'error' ) - return } // check to make sure 'msisdn' isnt 'undefined' when saving @@ -253,12 +310,16 @@ export async function updateUserByToken(ctx, token) { // construct user object to prevent other properties from being updated const userUpdateObj = { + id: userDataExpiry._id, token: null, tokenType: null, expiry: null, + password: userData.password, + + // deprecated [token] passwordAlgorithm: userData.passwordAlgorithm, - passwordSalt: userData.passwordSalt, - passwordHash: userData.passwordHash + passwordHash: userData.passwordHash, + passwordSalt: userData.passwordSalt } if (userDataExpiry.tokenType === 'newUser') { @@ -269,9 +330,28 @@ export async function updateUserByToken(ctx, token) { } try { - await UserModelAPI.findOneAndUpdate({token}, userUpdateObj) - ctx.body = 'Successfully set new user password.' - return logger.info(`User updated by token ${token}`) + let user, error + // @deprecated Token user update + if ( + userUpdateObj.passwordAlgorithm && + userUpdateObj.passwordHash && + userUpdateObj.passwordSalt + ) { + logger.warn( + 'Token authentication strategy is deprecated. Please consider using Local or Basic authentication.' + ) + ;({user, error} = await updateTokenUser(userUpdateObj)) + // Other providers + } else { + ;({user, error} = await apiUpdateUser(userUpdateObj)) + } + + if (user) { + ctx.body = 'Successfully set new user password.' + return logger.info(`User updated by token ${token}`) + } else { + ctx.throw(500, error) + } } catch (error) { return utils.logAndSetResponse( ctx, @@ -336,9 +416,41 @@ export async function addUser(ctx) { const setPasswordLink = `${consoleURL}/#!/set-password/${token}` try { + const {passwordHash, passwordAlgorithm, passwordSalt, password} = userData + + // Remove password fields from user object + if (passwordHash || passwordAlgorithm || passwordSalt || password) { + delete userData.passwordHash + delete userData.passwordSalt + delete userData.passwordAlgorithm + delete userData.password + } + const user = new UserModelAPI(userData) await user.save() + let result + // Create passport if password field is provided (to support clients who uses this functionality) + // @deprecated token passport + if (passwordHash || passwordAlgorithm || passwordSalt) { + logger.warn( + 'Token authentication strategy is deprecated. Please consider using Local or Basic authentication.' + ) + result = await createPassport(user, { + passwordHash, + passwordAlgorithm, + passwordSalt + }) + } else { + result = await createPassport(user, { + password + }) + } + + if (!result.user || result.error) { + logger.error(`Error while trying to create a passport for ${user.email}.`) + } + // Send email to new user to set password const plainMessage = plainMessageTemplate( @@ -436,42 +548,86 @@ export async function updateUser(ctx, email) { return } - const userData = ctx.request.body + let userDetails + + try { + // first try get new user details + userDetails = await UserModelAPI.findOne({ + email: utils.caseInsensitiveRegex(email) + }) + + if (!userDetails) { + ctx.body = `User with email ${email} could not be found.` + ctx.status = 404 + return + } + } catch (e) { + utils.logAndSetResponse( + ctx, + 500, + `Could not find user with email ${email} via the API ${e}`, + 'error' + ) + } + + const {_doc: userData} = new UserModelAPI(ctx.request.body) + const {password} = ctx.request.body + + // @deprecated + const {passwordAlgorithm, passwordHash, passwordSalt} = ctx.request.body // reset token/locked/expiry when user is updated and password supplied - if ( - userData.passwordAlgorithm && - userData.passwordHash && - userData.passwordSalt - ) { + if (password || (passwordAlgorithm && passwordHash && passwordSalt)) { userData.token = null userData.tokenType = null userData.locked = false userData.expiry = null } - // Don't allow a non-admin user to change their groups + // Don't allow a non-admin user to change their groups & Update only if groups exist if ( - ctx.authenticated.email === email && - !authorisation.inGroup('admin', ctx.authenticated) + (ctx.authenticated.email === email && + !authorisation.inGroup('admin', ctx.authenticated)) || + ctx.request.body.groups === undefined ) { delete userData.groups } - // Ignore _id if it exists (update is by email) if (userData._id) { delete userData._id } try { - await UserModelAPI.findOneAndUpdate( - {email: utils.caseInsensitiveRegex(email)}, - userData - ) - ctx.body = 'Successfully updated user.' - logger.info( - `User ${ctx.authenticated.email} updated user ${userData.email}` - ) + let user, error + // @deprecated Token user update + if (passwordAlgorithm && passwordHash && passwordSalt) { + logger.warn( + 'Token authentication strategy is deprecated. Please consider using Local or Basic authentication.' + ) + ;({user, error} = await updateTokenUser({ + id: userDetails._id, + passwordAlgorithm, + passwordHash, + passwordSalt, + ...userData + })) + // Other providers + } else { + ;({user, error} = await apiUpdateUser({ + id: userDetails._id, + password, + ...userData + })) + } + + if (user) { + ctx.body = 'Successfully updated user.' + logger.info( + `User ${ctx.authenticated.email} updated user ${userData.email}` + ) + } else { + ctx.throw(500, error) + } } catch (e) { utils.logAndSetResponse( ctx, diff --git a/src/koaApi.js b/src/koaApi.js index e197771a..c53c45b1 100644 --- a/src/koaApi.js +++ b/src/koaApi.js @@ -4,6 +4,8 @@ import Koa from 'koa' import bodyParser from 'koa-bodyparser' import cors from 'kcors' import route from 'koa-route' +import session from 'koa-session' +import compose from 'koa-compose' import * as about from './api/about' import * as audits from './api/audits' @@ -25,15 +27,43 @@ import * as tasks from './api/tasks' import * as transactions from './api/transactions' import * as users from './api/users' import * as visualizers from './api/visualizers' +import passport from './passport' +import MongooseStore from './middleware/sessionStore' import {config} from './config' export function setupApp(done) { - // Create an instance of the koa-server and add a body-parser + // Create an instance of the koa-server const app = new Koa() - app.use(cors({allowMethods: 'GET,HEAD,PUT,POST,DELETE'})) + + // Add cors options + app.use(cors({allowMethods: 'GET,HEAD,PUT,POST,DELETE', credentials: true})) + + // Configure Sessions Middleware + app.keys = [config.api.sessionKey] + app.use( + session( + { + maxAge: config.api.maxAge || 7200000, + resave: false, + secure: true, + httpOnly: true, + sameSite: 'none', + store: new MongooseStore() + }, + app + ) + ) + + // Add a body-parser const limitMB = config.api.maxPayloadSizeMB || 16 app.use(bodyParser({jsonLimit: limitMB * 1024 * 1024})) + app.use(passport.initialize()) + app.use(passport.session()) + + // Passport load strategies: local basic + passport.loadStrategies() + // Expose uptime server stats route before the auth middleware so that it is publicly accessible app.use(route.get('/heartbeat', heartbeat.getHeartbeat)) @@ -44,8 +74,20 @@ export function setupApp(done) { app.use(route.get('/token/:token', users.getUserByToken)) app.use(route.put('/token/:token', users.updateUserByToken)) + // Check of logged in user + app.use(route.get('/me', users.me)) + // Expose the authenticate route before the auth middleware so that it is publicly accessible - app.use(route.get('/authenticate/:username', users.authenticate)) + // Local authentication + app.use( + route.post( + '/authenticate/local', + compose([passport.authenticate('local'), users.authenticate]) + ) + ) + // @deprecated: Token authentication + app.use(route.get('/authenticate/:username', users.authenticateToken)) + // Authenticate the API request app.use(authentication.authenticate) @@ -57,6 +99,9 @@ export function setupApp(done) { ) ) + // Logout route + app.use(route.get('/logout', users.logout)) + // Define the api routes app.use(route.get('/users', users.getUsers)) app.use(route.get('/users/:email', users.getUser)) diff --git a/src/middleware/sessionStore.js b/src/middleware/sessionStore.js new file mode 100644 index 00000000..b407370f --- /dev/null +++ b/src/middleware/sessionStore.js @@ -0,0 +1,55 @@ +import {connectionAPI} from '../config' +import {Schema} from 'mongoose' + +/** + * Session Store + * + * To be able to store the session in a Mongo collection instead of just saving it in memory + * + */ + +const SessionSchema = new Schema({ + _id: String, + data: Object, + updatedAt: { + default: new Date(), + type: Date + } +}) + +class MongooseStore { + constructor() { + this.session = connectionAPI.model('Session', SessionSchema) + } + + /** + * Override of the destroy, get and set functions used in session + * + */ + + async destroy(id) { + const {session} = this + return session.deleteOne({_id: id}) + } + + async get(id) { + const {session} = this + const {data} = (await session.findById(id)) || {} + return data + } + + async set(id, data, maxAge, {changed, rolling}) { + if (changed || rolling) { + const {session} = this + const record = {_id: id, data, updatedAt: new Date()} + await session.findByIdAndUpdate(id, record, {upsert: true, safe: true}) + } + return data + } + + static create() { + return new MongooseStore() + } +} + +export default MongooseStore diff --git a/src/model/index.js b/src/model/index.js index 05294811..58c8b795 100644 --- a/src/model/index.js +++ b/src/model/index.js @@ -19,3 +19,4 @@ export * from './transactions' export * from './users' export * from './visualizer' export * from './metrics' +export * from './passport' diff --git a/src/model/passport.js b/src/model/passport.js new file mode 100644 index 00000000..44b16527 --- /dev/null +++ b/src/model/passport.js @@ -0,0 +1,123 @@ +'use strict' + +import {Schema} from 'mongoose' + +import {connectionAPI, connectionDefault} from '../config' + +/** + * Passport Model + * + * The Passport model handles associating authenticators with users. An authen- + * ticator can be either local (password) or third-party (provider). A single + * user can have multiple passports, allowing them to connect and use several + * third-party strategies in optional conjunction with a password. + * + * Since an application will only need to authenticate a user once per session, + * it makes sense to encapsulate the data specific to the authentication process + * in a model of its own. This allows us to keep the session itself as light- + * weight as possible as the application only needs to serialize and deserialize + * the user, but not the authentication data, to and from the session. + */ + +const PassportSchema = new Schema({ + // Required field: Protocol + // + // Defines the protocol to use for the passport. When employing the local + // strategy, the protocol will be set to 'local'. When using a third-party + // strategy, the protocol will be set to the standard used by the third- + // party service. + // e.g. 'basic', 'openid', 'local', 'token' [token is deprecated] + protocol: { + type: String, + required: true + }, + // Local field: Password + // + // When the local strategy is employed, a password will be used as the + // means of authentication along with an email. + password: String, + // accessToken is used to authenticate API requests. it is generated when a + // passport (with protocol 'local') is created for a user. + accessToken: String, + + // Provider fields: Provider, identifer and tokens + // + // "provider" is the name of the third-party auth service in all lowercase + // (e.g. 'github', 'facebook') whereas "identifier" is a provider-specific + // key, typically an ID. These two fields are used as the main means of + // identifying a passport and tying it to a local user. + // + // The "tokens" field is a JSON object used in the case of the OAuth stan- + // dards. When using OAuth 1.0, a `token` as well as a `tokenSecret` will + // be issued by the provider. In the case of OAuth 2.0, an `accessToken` + // and a `refreshToken` will be issued. + provider: String, + identifier: String, + tokens: Object, + + /* ---- @deprecated ---- */ + // Password fields: passwordAlgorithm, passwordHash and passwordSalt + // + // Used for the token strategy + // The "passwordAlgorithm" is used to identify which algorithm was used when hashing the password + // (e.g 'sha256') "passwordSalt" the random string used for hashing as well and "passwordHash" is the result. + passwordAlgorithm: String, + passwordHash: String, + passwordSalt: String, + /* ---- ------------- ---- */ + + // Associations + // + // Associate every passport with one, and only one, user. + user: {type: Schema.Types.ObjectId, ref: 'User'} +}) + +// compile the Passport Schema into a Model +export const PassportModelAPI = connectionAPI.model('Passport', PassportSchema) +export const PassportModel = connectionDefault.model('Passport', PassportSchema) + +/** + * Register a passport + * + * This method creates a new passport from a specified email, username and password + * and assign it to a newly created user. + * + * @param {*} user user that will be linked to the new passport + * @param {*} passwordInfo either password or password fields (deprecated) which are + * passwordHash, passwordSalt and passwordAlgorithm + */ +export const createPassport = async function (user, passwordInfo) { + let result = {error: null, user: null} + return await PassportModelAPI.create({ + protocol: passwordInfo.password ? 'local' : 'token', + user: user.id, + ...passwordInfo + }) + .then(async function () { + result.user = user + return result + }) + .catch(err => { + result.error = err + return result + }) +} + +/** + * Update a passport + * + * This method updates a passport of a specific user + * + */ +export const updatePassport = async function (user, passport) { + let result = {error: null, user: null} + return PassportModelAPI.findByIdAndUpdate(passport.id, passport) + .then(function () { + result.user = user + return result + }) + .catch(err => { + result.error = err + return result + }) +} diff --git a/src/model/users.js b/src/model/users.js index 56f1226c..dfd105c7 100644 --- a/src/model/users.js +++ b/src/model/users.js @@ -2,7 +2,9 @@ import {Schema} from 'mongoose' +import {PassportModelAPI, createPassport, updatePassport} from './passport' import {connectionAPI, connectionDefault} from '../config' +import {hashPassword} from '../utils' const UserSchema = new Schema({ firstname: { @@ -18,9 +20,17 @@ const UserSchema = new Schema({ required: true, unique: true }, + passports: {type: Schema.Types.ObjectId, ref: 'Passport'}, + /* --- @deprecated --- */ passwordAlgorithm: String, passwordHash: String, passwordSalt: String, + /* --- ----------- --- */ + provider: { + type: String, + enum: ['keycloak', 'local', 'token'], // token is deprecated + default: 'local' + }, groups: [String], msisdn: String, dailyReport: Boolean, @@ -38,3 +48,153 @@ const UserSchema = new Schema({ // compile the User Schema into a Model export const UserModelAPI = connectionAPI.model('User', UserSchema) export const UserModel = connectionDefault.model('User', UserSchema) + +/** + * Register a new user + * + * This method creates a new user from a specified email, username and password + * and assign the newly created user a local Passport. + * + */ +export const createUser = async function (_user) { + // Create a clone to _user + const userToBeCreated = {..._user} + + let result = {error: null, user: null} + + try { + let password = await hashPassword(userToBeCreated.password) + delete userToBeCreated.password + + const {passwordHash, passwordAlgorithm, passwordSalt} = userToBeCreated + + if (passwordHash || passwordAlgorithm || passwordSalt) { + delete userToBeCreated.passwordHash + delete userToBeCreated.passwordSalt + delete userToBeCreated.passwordAlgorithm + } + + return await UserModelAPI.create(userToBeCreated) + .then(async function (user) { + return await createPassport(user, {password}) + }) + .catch(err => { + result.error = err + return result + }) + } catch (err) { + result.error = err + return result + } +} + +/** + * Update user + * + * This method updates an user based on its id or username if id is not present + * and assign the newly created user a local Passport. + * + */ +export const updateUser = async function (_user) { + // Create a clone to _user + const userToBeUpdated = {..._user} + + let result = {user: null, error: null} + + try { + let password + if (userToBeUpdated.password) { + password = await hashPassword(userToBeUpdated.password) + + delete userToBeUpdated.password + } + + await UserModelAPI.findByIdAndUpdate(userToBeUpdated.id, userToBeUpdated, { + new: true + }) + .then(async function (user) { + // Check if password has a string to replace it + if (password) { + await PassportModelAPI.findOne({ + protocol: 'local', + user: user.id + }).then(async function (passport) { + if (passport) { + passport.password = password + result = await updatePassport(user, passport) + } else { + result = await createPassport(user, {password}) + } + }) + } else { + result.user = user + } + }) + .catch(err => { + result.error = err + }) + + return result + } catch (err) { + result.error = err + return result + } +} + +/** + * @deprecated + * Update user (token provider) + * + * Please consider upgrading and use updateUser instead. + * + * This method updates an user based on its id or username if id is not present + * and assign the newly created user a token Passport. + * + */ +export const updateTokenUser = async function (_user) { + // Create a clone to _user + const userToBeUpdated = {..._user, provider: 'token'} + + let result = {user: null, error: null} + + const {passwordHash, passwordAlgorithm, passwordSalt} = userToBeUpdated + + if (passwordHash || passwordAlgorithm || passwordSalt) { + userToBeUpdated.passwordHash = null + userToBeUpdated.passwordSalt = null + userToBeUpdated.passwordAlgorithm = null + } + + await UserModelAPI.findByIdAndUpdate(userToBeUpdated.id, userToBeUpdated, { + new: true + }) + .then(async function (user) { + // Check if password has a string to replace it + if (passwordHash && passwordAlgorithm && passwordSalt) { + await PassportModelAPI.findOne({ + protocol: 'token', + user: user.id + }).then(async function (passport) { + if (passport) { + passport.passwordHash = passwordHash + passport.passwordAlgorithm = passwordAlgorithm + passport.passwordSalt = passwordSalt + result = await updatePassport(user, passport) + } else { + result = await createPassport(user, { + passwordHash, + passwordAlgorithm, + passwordSalt + }) + } + }) + } else { + result.user = user + } + }) + .catch(err => { + result.error = err + }) + + return result +} diff --git a/src/passport.js b/src/passport.js new file mode 100644 index 00000000..27e4c60b --- /dev/null +++ b/src/passport.js @@ -0,0 +1,135 @@ +import _ from 'lodash' +import logger from 'winston' + +import passport from 'koa-passport' +import * as passportLocal from 'passport-local' +import * as passportHttp from 'passport-http' +import * as passportCustom from 'passport-custom' +import {isAuthenticationTypeEnabled} from './api/authentication' +import {local, basic, token} from './protocols' +import {UserModelAPI} from './model' + +const disabledAuthTypeError = strat => + new Error( + `Could not be authenticaticated, ${strat} authentication type is disabled` + ) + +/** + * Handle passport errors with logger + * + */ +const handlePassportError = function (err, user, next) { + if (err) { + logger.error(err.message) + next(null, false) + } else if (!user) { + return next(null, false) + } else { + return next(null, user) + } +} + +/** + * Load Strategies: Local and Basic + * + */ +passport.loadStrategies = function () { + var strategies = { + local: { + strategy: passportLocal.Strategy + }, + basic: { + strategy: passportHttp.BasicStrategy + }, + token: { + strategy: passportCustom.Strategy + } + // TODO: Add openid + } + + _.each( + strategies, + _.bind(async function (strat, key) { + let Strategy + + if (key === 'local') { + Strategy = strat.strategy + passport.use( + new Strategy(async (username, password, next) => { + if (isAuthenticationTypeEnabled(key)) { + return await local.login(username, password, (err, user) => + handlePassportError(err, user, next) + ) + } else { + return handlePassportError( + disabledAuthTypeError(key), + false, + next + ) + } + }) + ) + } else if (key === 'basic') { + Strategy = strat.strategy + passport.use( + new Strategy(async (username, password, next) => { + if (isAuthenticationTypeEnabled(key)) { + return await basic.login(username, password, (err, user) => + handlePassportError(err, user, next) + ) + } else { + return handlePassportError( + disabledAuthTypeError(key), + false, + next + ) + } + }) + ) + } else if (key === 'token') { + Strategy = strat.strategy + passport.use( + 'token', + new Strategy(async (req, next) => { + if (isAuthenticationTypeEnabled(key)) { + return await token.login(req, (err, user) => + handlePassportError(err, user, next) + ) + } else { + return handlePassportError( + disabledAuthTypeError(key), + false, + next + ) + } + }) + ) + } + }, passport) + ) +} + +/** + * Serialize User: used the email to be stored in the session + * + */ +passport.serializeUser(function (user, next) { + next(null, user.email) +}) + +/** + * Deserialize User + * + */ +passport.deserializeUser(async function (email, next) { + try { + const user = await UserModelAPI.findOne({ + email + }) + next(null, user) + } catch (err) { + next(err, null) + } +}) + +export default passport diff --git a/src/protocols/basic.js b/src/protocols/basic.js new file mode 100644 index 00000000..4c765386 --- /dev/null +++ b/src/protocols/basic.js @@ -0,0 +1,14 @@ +import * as local from './local' + +/** + * Basic Authentication Protocol + * + * the application sends a username and password with every request + * + * For more information on basic authentication in Passport.js, check out: + * https://www.passportjs.org/packages/passport-http/ + */ + +export const login = async function (username, password, next) { + return await local.login(username, password, next) +} diff --git a/src/protocols/index.js b/src/protocols/index.js new file mode 100644 index 00000000..24b3a828 --- /dev/null +++ b/src/protocols/index.js @@ -0,0 +1,12 @@ +'use strict' + +export * as local from './local' +export * as basic from './basic' +// export * as openid from './openid' +import * as tokenProtocol from './token' + +/** + * @deprecated + * token protocol is deprecated + */ +export const token = tokenProtocol diff --git a/src/protocols/local.js b/src/protocols/local.js new file mode 100644 index 00000000..242b77bd --- /dev/null +++ b/src/protocols/local.js @@ -0,0 +1,64 @@ +import {UserModelAPI} from '../model' +import {validatePassword} from '../utils' +import {PassportModelAPI} from '../model/passport' + +/** + * Local Authentication Protocol + * + * The most widely used way for websites to authenticate users is via a username + * and/or email as well as a password. This module provides functions both for + * registering entirely new users, assigning passwords to already registered + * users and validating login requesting. + * + * For more information on local authentication in Passport.js, check out: + * http://passportjs.org/guide/username-password/ + */ + +/** + * Validate a login request + * + * Looks up a user using the supplied identifier (email or username) and then + * attempts to find a local Passport associated with the user. If a Passport is + * found, its password is checked against the password supplied in the form. + * + */ +export const login = async function (email, password, next) { + return await UserModelAPI.findOne({email}) + .then(function (user) { + if (!user) { + return next( + new Error(`No user exists for ${email}, denying access to API`), + false + ) + } + return PassportModelAPI.findOne({ + protocol: user.provider === 'token' ? 'token' : 'local', + user: user.id + }) + .then(function (passport) { + if (passport) { + return validatePassword(passport, password, function (err, res) { + if (err || !res) { + return next( + new Error( + `Wrong password entered by ${email}, denying access to API ${ + err ? err : '' + }` + ), + false + ) + } else { + return next(null, user) + } + }) + } else { + return next( + new Error(`Password not set for ${email}, denying access to API`), + false + ) + } + }) + .catch(next) + }) + .catch(next) +} diff --git a/src/protocols/token.js b/src/protocols/token.js new file mode 100644 index 00000000..cb8f13f4 --- /dev/null +++ b/src/protocols/token.js @@ -0,0 +1,116 @@ +import crypto from 'crypto' + +import {PassportModelAPI} from '../model/passport' +import {UserModelAPI} from '../model' +import {config} from '../config' +import {caseInsensitiveRegex} from '../utils' + +/** + * Token Authentication: A passport strategy for authenticating with custom logic + * + * For more information on custom authentication in Passport.js, check out: + * https://www.passportjs.org/packages/passport-custom/ + */ + +const isUndefOrEmpty = string => string == null || string === '' + +/** + * @deprecated + * Validate a login request + * + * Looks up a user using the supplied header info and then + * attempts to find a token Passport associated with the user. If a Passport is + * found, its passwordHash is checked against the token supplied in the header. + * + */ +export const login = async function (req, next) { + try { + const {header} = req + const email = header['auth-username'] + const authTS = header['auth-ts'] + const authSalt = header['auth-salt'] + const authToken = header['auth-token'] + + // if any of the required headers aren't present + if ( + isUndefOrEmpty(email) || + isUndefOrEmpty(authTS) || + isUndefOrEmpty(authSalt) || + isUndefOrEmpty(authToken) + ) { + return next( + new Error( + `API request made by ${email} from ${req.host} is missing required API authentication headers, denying access` + ), + false + ) + } + + // check if request is recent + const requestDate = new Date(Date.parse(authTS)) + + const authWindowSeconds = + config.api.authWindowSeconds != null ? config.api.authWindowSeconds : 10 + const to = new Date() + to.setSeconds(to.getSeconds() + authWindowSeconds) + const from = new Date() + from.setSeconds(from.getSeconds() - authWindowSeconds) + + if (requestDate < from || requestDate > to) { + // request expired + return next( + new Error( + `API request made by ${email} from ${req.host} has expired, denying access` + ), + false + ) + } + + const user = await UserModelAPI.findOne({ + email: caseInsensitiveRegex(email) + }) + + if (user == null) { + // not authenticated - user not found + return next( + new Error( + `No user exists for ${email}, denying access to API, request originated from ${req.host}` + ), + false + ) + } + + const passport = await PassportModelAPI.findOne({ + protocol: 'token', + user: user.id + }) + + if (passport == null) { + // not authenticated - user not found + return next( + new Error( + `Password not set for ${email}, denying access to API, request originated from ${req.host}` + ), + false + ) + } + + const hash = crypto.createHash(passport.passwordAlgorithm) + hash.update(passport.passwordHash) + hash.update(authSalt) + hash.update(authTS) + + if (authToken !== hash.digest('hex')) { + // not authenticated - token mismatch + return next( + new Error( + `API token did not match expected value, denying access to API, the request was made by ${email} from ${req.host}` + ), + false + ) + } + return next(null, user) + } catch (err) { + return next(err, false) + } +} diff --git a/src/server.js b/src/server.js index 9c0d2d17..515c22d8 100644 --- a/src/server.js +++ b/src/server.js @@ -35,7 +35,7 @@ import * as tcpAdapter from './tcpAdapter' import * as tlsAuthentication from './middleware/tlsAuthentication' import * as upgradeDB from './upgradeDB' import {KeystoreModel} from './model/keystore' -import {UserModel} from './model/users' +import {UserModel, createUser, updateTokenUser} from './model/users' import {appRoot, config, connectionAgenda} from './config' mongoose.Promise = Promise @@ -334,13 +334,15 @@ if (cluster.isMaster && !module.parent) { firstname: 'Super', surname: 'User', email: 'root@openhim.org', + password: 'openhim-password', + groups: ['admin'], + // -- @deprecated -- passwordAlgorithm: 'sha512', passwordHash: '943a856bba65aad6c639d5c8d4a11fc8bb7fe9de62ae307aec8cf6ae6c1faab722127964c71db4bdd2ea2cdf60c6e4094dcad54d4522ab2839b65ae98100d0fb', - passwordSalt: 'd9bcb40e-ae65-478f-962e-5e5e5e7d0a01', - groups: ['admin'] + passwordSalt: 'd9bcb40e-ae65-478f-962e-5e5e5e7d0a01' + // -- ----------- -- } - // password = 'openhim-password' // Job scheduler let agenda = null @@ -470,21 +472,28 @@ if (cluster.isMaster && !module.parent) { } // Ensure that a root user always exists - const ensureRootUser = callback => - UserModel.findOne({email: 'root@openhim.org'}, (err, user) => { + const ensureRootUser = async callback => + await UserModel.findOne({email: 'root@openhim.org'}, async (err, user) => { if (err) { return callback(err) } if (!user) { - user = new UserModel(rootUser) - return user.save(err => { - if (err) { - logger.error(`Could not save root user: ${err}`) - return callback(err) + return await createUser(rootUser).then(async res => { + if (res.error) { + logger.error(`Could not save root user: ${res.error}`) + return callback(res.error) } - - logger.info('Root user created.') - return callback() + // deprecated + return await updateTokenUser({...rootUser, id: res.user.id}).then( + async res => { + if (res.error) { + logger.error(`Could not save root user: ${res.error}`) + return callback(res.error) + } + logger.info('Root user created.') + return callback() + } + ) }) } return callback() diff --git a/src/tasks.js b/src/tasks.js index 2c5df6d9..3d188b40 100644 --- a/src/tasks.js +++ b/src/tasks.js @@ -81,6 +81,7 @@ export function isRunning() { return live } +/* eslint-disable no-unused-vars */ async function finalizeTaskRound(task) { const result = await TaskModel.findOne({_id: task._id}, {status: 1}) if (result.status === 'Processing' && task.remainingTransactions !== 0) { @@ -128,9 +129,12 @@ async function processNextTaskRound(task) { logger.info( `Processing of task ${task._id} paused. Remaining transactions = ${task.remainingTransactions}` ) - TaskModel.findByIdAndUpdate({_id: task._id}, { - remainingTransactions: task.remainingTransactions - }) + TaskModel.findByIdAndUpdate( + {_id: task._id}, + { + remainingTransactions: task.remainingTransactions + } + ) return } @@ -166,7 +170,8 @@ async function processNextTaskRound(task) { await Promise.all(promises) logger.info( - `Round completed for rerun task #${task._id} - ${task.remainingTransactions} transactions remainings `, task.batchSize + `Round completed for rerun task #${task._id} - ${task.remainingTransactions} transactions remainings `, + task.batchSize ) if (task.remainingTransactions) { diff --git a/src/upgradeDB.js b/src/upgradeDB.js index 379e65cf..73579642 100644 --- a/src/upgradeDB.js +++ b/src/upgradeDB.js @@ -8,6 +8,7 @@ import {DbVersionModel} from './model/dbVersion' import {KeystoreModel} from './model/keystore' import {UserModel} from './model/users' import {VisualizerModel} from './model/visualizer' +import {PassportModel} from './model/passport' function dedupName(name, names, num) { let newName @@ -230,6 +231,70 @@ upgradeFuncs.push({ } }) +upgradeFuncs.push({ + description: + 'Migrate password properties of token auth strategy from User collection to Passport collection', + func() { + return new Promise((resolve, reject) => { + UserModel.find((err, users) => { + if (err) { + return reject(err) + } + + const promises = [] + users.forEach(user => { + if ( + user.passwordHash != null && + user.passwordAlgorithm != null && + user.passwordSalt != null + ) { + let pass = { + passwordHash: user.passwordHash, + passwordAlgorithm: user.passwordAlgorithm, + passwordSalt: user.passwordSalt, + user: user.id, + protocol: 'token' + } + + const promise = new Promise((resolve, reject) => { + pass = new PassportModel(pass) + logger.debug( + `Migrating passwords fields from user ${user.email} to passport collection` + ) + pass.save(err => { + if (err) { + logger.error( + `Error migrating password fields from user ${user.email}: ${err.stack}` + ) + return reject(err) + } + + // delete the password fields from this user + user.set('passwordHash', null) + user.set('passwordAlgorithm', null) + user.set('passwordSalt', null) + // add the field provider to know that these users are from old version + user.set('provider', 'token') + user.save(err => { + if (err) { + return reject(err) + } + return resolve() + }) + }) + }) + promises.push(promise) + } + }) + + Promise.all(promises) + .then(() => resolve()) + .catch(err => reject(err)) + }) + }) + } +}) + if (process.env.NODE_ENV === 'test') { exports.upgradeFuncs = upgradeFuncs exports.dedupName = dedupName diff --git a/src/utils.js b/src/utils.js index 15f4b913..5be0fd3f 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,7 @@ 'use strict' +import bcrypt from 'bcryptjs' +import crypto from 'crypto' import logger from 'winston' import momentTZ from 'moment-timezone' import _ from 'lodash' @@ -10,6 +12,7 @@ import {config} from './config' config.caching = config.get('caching') config.api = config.get('api') +config.authentication = config.get('authentication') /** * Will take in a string and return a safe regex that will match case insensitive @@ -185,3 +188,43 @@ export function selectAuditFields(authenticated) { name: `${authenticated.firstname} ${authenticated.surname}` } } + +/** + * Validate password by comparing it to the password stored in the passport + */ +export const validatePassword = function (passport, password, next) { + // @deprecated Token strategy + if (passport.protocol === 'token') { + const hash = crypto.createHash(passport.passwordAlgorithm) + hash.update(passport.passwordSalt) + hash.update(password) + if (passport.passwordHash !== hash.digest('hex')) { + // not authenticated - password mismatch + return next(new Error('Password did not match expected value'), false) + } + return next(null, true) + // Local strategy + } else { + bcrypt.compare(password, passport.password, next) + } +} + +/** + * Hash password according to a salt defined in the config file + */ +export async function hashPassword(password) { + var salt = config.api.salt || 10 + + if (password) { + return new Promise((resolve, reject) => { + bcrypt.hash(password, salt, function (err, hash) { + if (err) { + reject(err) + } + resolve(hash) + }) + }) + } else { + return Promise.reject(new Error("Password wasn't provided")) + } +} diff --git a/test/integration/aboutAPITests.js b/test/integration/aboutAPITests.js index 52f1ced7..d1394730 100644 --- a/test/integration/aboutAPITests.js +++ b/test/integration/aboutAPITests.js @@ -11,13 +11,9 @@ import {BASE_URL, SERVER_PORTS} from '../constants' describe('API Integration Tests', () => describe('About Information REST Api Testing', () => { - let authDetails = {} - before(async () => { - await testUtils.setupTestUsers() await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) - - authDetails = testUtils.getAuthDetails() + await testUtils.setupTestUsers() }) after(async () => { @@ -28,25 +24,29 @@ describe('API Integration Tests', () => }) describe('*getAboutInformation', () => { + it('should return status 401 when being unauthenticated', async () => { + await request(BASE_URL).get('/about').expect(401) + }) + it('should fetch core version and return status 200', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + const res = await request(BASE_URL) .get('/about') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', cookie) .expect(200) res.body.should.have.property('currentCoreVersion') }) it('should return 404 if not found', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + await request(BASE_URL) .get('/about/bleh') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', cookie) .expect(404) }) }) diff --git a/test/integration/auditAPITests.js b/test/integration/auditAPITests.js index f0cd68a0..a233eaa8 100644 --- a/test/integration/auditAPITests.js +++ b/test/integration/auditAPITests.js @@ -16,18 +16,32 @@ import {config} from '../../src/config' describe('API Integration Tests', () => { const router = config.get('router') const api = config.get('api') - let authDetails + + let rootCookie = '', + nonRootCookie = '' + before(async () => { - await testUtils.setupTestUsers() await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) - - authDetails = testUtils.getAuthDetails() + await testUtils.setupTestUsers() }) after(async () => { await Promise.all([promisify(server.stop)(), testUtils.cleanupTestUsers()]) }) + beforeEach(async () => { + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) + }) + afterEach(async () => { await Promise.all([ AuditModel.deleteMany({}), @@ -118,10 +132,7 @@ describe('API Integration Tests', () => { it('should add a audit and return status 201 - audit created', async () => { await request(BASE_URL) .post('/audits') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(auditData) .expect(201) @@ -158,13 +169,14 @@ describe('API Integration Tests', () => { it('should only allow admin users to add audits', async () => { await request(BASE_URL) .post('/audits') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(auditData) .expect(403) }) + + it('should allow only authenticated users to add audits and return 401 status', async () => { + await request(BASE_URL).post('/audits').send(auditData).expect(401) + }) }) describe('*getAudits()', () => { @@ -173,10 +185,7 @@ describe('API Integration Tests', () => { await new AuditModel(auditData).save() const res = await request(BASE_URL) .get('/audits?filterPage=0&filterLimit=10&filters={}') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(countBefore + 1) @@ -195,10 +204,7 @@ describe('API Integration Tests', () => { filters )}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(countBefore + 1) @@ -216,10 +222,7 @@ describe('API Integration Tests', () => { filters )}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(400) res.statusCode.should.be.exactly(400) @@ -240,10 +243,7 @@ describe('API Integration Tests', () => { filters )}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.statusCode.should.be.exactly(200) @@ -264,10 +264,7 @@ describe('API Integration Tests', () => { filters )}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(400) res.statusCode.should.be.exactly(400) @@ -278,10 +275,7 @@ describe('API Integration Tests', () => { await request(BASE_URL) .get('/audits?filterRepresentation=full') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) await testUtils.pollCondition(() => @@ -317,15 +311,16 @@ describe('API Integration Tests', () => { await new AuditModel(auditData).save() await request(BASE_URL) .get('/audits') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const auditCount = await AuditModel.countDocuments() auditCount.should.eql(1) }) + + it('should allow only authenticated users to get audits and return 401 status', async () => { + await request(BASE_URL).get('/audits').send(auditData).expect(401) + }) }) describe('*getAuditById (auditId)', () => { @@ -334,10 +329,7 @@ describe('API Integration Tests', () => { const auditId = audit._id const res = await request(BASE_URL) .get(`/audits/${auditId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.eventIdentification.eventDateTime.should.equal( @@ -373,10 +365,7 @@ describe('API Integration Tests', () => { const auditId = audit._id await request(BASE_URL) .get(`/audits/${auditId}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) @@ -385,10 +374,7 @@ describe('API Integration Tests', () => { const auditId = audit._id await request(BASE_URL) .get(`/audits/${auditId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) await testUtils.pollCondition(() => @@ -425,19 +411,13 @@ describe('API Integration Tests', () => { it('should fetch dropdown filter options - admin user', async () => { await request(BASE_URL) .post('/audits') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) .send(auditData) + .set('Cookie', rootCookie) .expect(201) const res = await request(BASE_URL) .get('/audits-filter-options') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.eventType.length.should.equal(1) @@ -450,12 +430,14 @@ describe('API Integration Tests', () => { await new AuditModel(auditData).save() await request(BASE_URL) .get('/audits-filter-options') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) + + it('should return 401 when user is not authenticated', async () => { + await new AuditModel(auditData).save() + await request(BASE_URL).get('/audits-filter-options').expect(401) + }) }) }) }) diff --git a/test/integration/authenticationAPITests.js b/test/integration/authenticationAPITests.js index 1c5b64ee..a505c3d7 100644 --- a/test/integration/authenticationAPITests.js +++ b/test/integration/authenticationAPITests.js @@ -16,19 +16,21 @@ import {ChannelModelAPI} from '../../src/model/channels' import {ClientModelAPI} from '../../src/model/clients' import {KeystoreModelAPI} from '../../src/model/keystore' import {config} from '../../src/config' +import {PassportModelAPI, UserModelAPI} from '../../src/model' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants describe('API Integration Tests', () => { describe('Retrieve Enabled Authentication types', () => { - let authDetails = null const authConfig = config.authentication + let rootCookie = '', + nonRootCookie = '' + before(async () => { - await testUtils.setupTestUsers() - authDetails = testUtils.getAuthDetails() const startPromise = promisify(server.start) await startPromise({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setupTestUsers() await testUtils.setImmediatePromise() await AuditModel.deleteMany({}) }) @@ -37,8 +39,19 @@ describe('API Integration Tests', () => { await AuditModel.deleteMany({}) }) - beforeEach(() => { + beforeEach(async () => { config.authentication = authConfig + + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) after(async () => { @@ -48,25 +61,23 @@ describe('API Integration Tests', () => { ]) }) + it('should return 401 for unauthenticated user', async () => { + await request(BASE_URL).get('/authentication/types').expect(401) + }) + it('should only allow an admin user to retrieve authentication types', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/authentication/types') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('should return an error when the authentication object is invalid', async () => { config.authentication = {} - await request(constants.BASE_URL) + await request(BASE_URL) .get('/authentication/types') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(500) }) @@ -76,12 +87,9 @@ describe('API Integration Tests', () => { config.authentication.enableJWTAuthentication = false config.authentication.enableCustomTokenAuthentication = true - const result = await request(constants.BASE_URL) + const result = await request(BASE_URL) .get('/authentication/types') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) result.body.length.should.be.equal(3) @@ -96,12 +104,9 @@ describe('API Integration Tests', () => { config.authentication.enableJWTAuthentication = true config.authentication.enableCustomTokenAuthentication = true - const result = await request(constants.BASE_URL) + const result = await request(BASE_URL) .get('/authentication/types') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) result.body.length.should.be.equal(4) @@ -113,14 +118,271 @@ describe('API Integration Tests', () => { }) describe('Authentication API tests', () => { - let authDetails = null + const user = { + firstname: 'test', + surname: 'with no password', + email: 'test@doe.net' + } before(async () => { + const startPromise = promisify(server.start) + await startPromise({apiPort: SERVER_PORTS.apiPort}) await testUtils.setupTestUsers() - authDetails = testUtils.getAuthDetails() + await testUtils.setImmediatePromise() + await new UserModelAPI(user).save() + await AuditModel.deleteMany({}) + }) + + afterEach(async () => { + await AuditModel.deleteMany({}) + }) + + after(async () => { + await Promise.all([ + UserModelAPI.deleteMany({}), + PassportModelAPI.deleteMany({}), + testUtils.cleanupTestUsers(), + promisify(server.stop)() + ]) + }) + + it('should audit a successful login on an API endpoint', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL).get('/channels').set('Cookie', cookie).expect(200) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find() + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('0') // success + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.be.equal('root@jembi.org') + }) + + it('should audit a successful login on an API endpoint with basic auth', async () => { + await request(BASE_URL) + .get('/channels') + .set( + 'Authorization', + `Basic ${Buffer.from(`${testUtils.rootUser.email}:password`).toString( + 'base64' + )}` + ) + .expect(200) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find() + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('0') // success + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.be.equal('root@jembi.org') + }) + + it('should audit an unsuccessful login on an API endpoint', async () => { + const user = { + username: 'wrong@email.org', + password: 'password' + } + + await request(BASE_URL).post('/authenticate/local').send(user).expect(401) + + await request(BASE_URL).get('/channels').expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find({}) + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should audit an unsuccessful login when user with no password set yet', async () => { + await request(BASE_URL) + .post('/authenticate/local') + .send({username: user.email, password: 'password'}) + .expect(401) + + await request(BASE_URL).get('/channels').expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find({}) + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should audit an unsuccessful login on an API endpoint with basic auth and incorrect email', async () => { + await request(BASE_URL) + .get('/channels') + .set( + 'Authorization', + `Basic ${Buffer.from(`wrong@email.org:password`).toString('base64')}` + ) + .expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find({}) + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should audit an unsuccessful login on an API endpoint with basic auth and incorrect password', async () => { + await request(BASE_URL) + .get('/channels') + .set( + 'Authorization', + `Basic ${Buffer.from(`${testUtils.rootUser.email}:drowssap`).toString( + 'base64' + )}` + ) + .expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find({}) + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should NOT audit a successful login on an auditing exempt API endpoint', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL).get('/audits').set('Cookie', cookie).expect(200) + const audits = await AuditModel.find({}) + audits.length.should.be.exactly(0) + }) + + it('should audit an unsuccessful login on an auditing exempt API endpoint', async () => { + const user = { + username: 'wrong@email.org', + password: 'password' + } + + await request(BASE_URL).post('/authenticate/local').send(user).expect(401) + + await request(BASE_URL).get('/audits').expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find({}) + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should NOT audit a successful login on /transactions if the view is not full', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL) + .get('/transactions') // default is simple + .set('Cookie', cookie) + .expect(200) + const audits = await AuditModel.find({}) + audits.length.should.be.exactly(0) + }) + + it('should audit a successful login on /transactions if the view is full', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL) + .get('/transactions?filterRepresentation=full') + .set('Cookie', cookie) + .expect(200) + const audits = await AuditModel.find() + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('0') // success + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.be.equal('root@jembi.org') + }) + }) + + // @deprecated token strategy tests + describe('Authentication API token auth type tests', () => { + const user = { + firstname: 'test', + surname: 'with no password', + email: 'test@doe.net' + } + + let authDetails = null + + before(async () => { const startPromise = promisify(server.start) await startPromise({apiPort: SERVER_PORTS.apiPort}) + // Create users with token passport only + await testUtils.setupTestUsersWithToken() + authDetails = testUtils.getAuthDetails() await testUtils.setImmediatePromise() + await new UserModelAPI(user).save() await AuditModel.deleteMany({}) }) @@ -130,13 +392,15 @@ describe('API Integration Tests', () => { after(async () => { await Promise.all([ + UserModelAPI.deleteMany({}), + PassportModelAPI.deleteMany({}), testUtils.cleanupTestUsers(), promisify(server.stop)() ]) }) it('should audit a successful login on an API endpoint', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -161,7 +425,7 @@ describe('API Integration Tests', () => { }) it('should audit a successful login on an API endpoint with basic auth', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') .set( 'Authorization', @@ -188,7 +452,7 @@ describe('API Integration Tests', () => { }) it('should audit an unsuccessful login on an API endpoint', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') .set('auth-username', 'wrong@email.org') .set('auth-ts', authDetails.authTS) @@ -209,11 +473,36 @@ describe('API Integration Tests', () => { ) audits[0].activeParticipant.length.should.be.exactly(2) audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') - audits[0].activeParticipant[1].userID.should.be.equal('wrong@email.org') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should audit an unsuccessful login when user with no password set yet', async () => { + await request(BASE_URL) + .post('/channels') + .set('auth-username', user.email) + .set('auth-ts', authDetails.authTS) + .set('auth-salt', authDetails.authSalt) + .set('auth-token', authDetails.authToken) + .expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find({}) + + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) }) it('should audit an unsuccessful login on an API endpoint with basic auth and incorrect email', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') .set( 'Authorization', @@ -234,11 +523,11 @@ describe('API Integration Tests', () => { ) audits[0].activeParticipant.length.should.be.exactly(2) audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') - audits[0].activeParticipant[1].userID.should.be.equal('wrong@email.org') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) }) it('should audit an unsuccessful login on an API endpoint with basic auth and incorrect password', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') .set( 'Authorization', @@ -261,11 +550,11 @@ describe('API Integration Tests', () => { ) audits[0].activeParticipant.length.should.be.exactly(2) audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') - audits[0].activeParticipant[1].userID.should.be.equal('root@jembi.org') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) }) it('should NOT audit a successful login on an auditing exempt API endpoint', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/audits') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -277,7 +566,7 @@ describe('API Integration Tests', () => { }) it('should audit an unsuccessful login on an auditing exempt API endpoint', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/audits') .set('auth-username', 'wrong@email.org') .set('auth-ts', authDetails.authTS) @@ -298,11 +587,11 @@ describe('API Integration Tests', () => { ) audits[0].activeParticipant.length.should.be.exactly(2) audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') - audits[0].activeParticipant[1].userID.should.be.equal('wrong@email.org') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) }) it('should NOT audit a successful login on /transactions if the view is not full', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/transactions') // default is simple .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -314,7 +603,7 @@ describe('API Integration Tests', () => { }) it('should audit a successful login on /transactions if the view is full', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/transactions?filterRepresentation=full') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -334,6 +623,186 @@ describe('API Integration Tests', () => { }) }) + describe('Authentication API types tests', () => { + afterEach(async () => { + await Promise.all([ + AuditModel.deleteMany({}), + PassportModelAPI.deleteMany({}), + UserModelAPI.deleteMany({}), + testUtils.cleanupTestUsers(), + promisify(server.stop)() + ]) + }) + + after(async () => { + config.api.authenticationTypes = ['local', 'basic', 'token'] + }) + + it('should audit an unsuccessful login with disabled basic auth', async () => { + config.api.authenticationTypes = ['local'] + + await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setupTestUsers() + await testUtils.setImmediatePromise() + await AuditModel.deleteMany({}) + + await request(BASE_URL) + .get('/channels') + .set( + 'Authorization', + `Basic ${Buffer.from(`${testUtils.rootUser.email}:password`).toString( + 'base64' + )}` + ) + .expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find() + + audits.length.should.be.exactly(1) + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should audit an unsuccessful login with disabled local auth', async () => { + config.api.authenticationTypes = ['basic'] + + await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setupTestUsers() + await testUtils.setImmediatePromise() + await AuditModel.deleteMany({}) + + const {email, password} = testUtils.rootUser + + await request(BASE_URL) + .post('/authenticate/local') + .send({username: email, password}) + .expect(401) + + await request(BASE_URL).get('/channels').expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find() + + audits.length.should.be.exactly(1) + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should audit an unsuccessful login with disabled token auth', async () => { + config.api.authenticationTypes = ['basic'] + + await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setImmediatePromise() + await testUtils.setupTestUsersWithToken() + const authDetails = testUtils.getAuthDetails() + await AuditModel.deleteMany({}) + + await request(BASE_URL) + .get(`/authenticate/${testUtils.rootUser.email}`) + .expect(200) + + await request(BASE_URL) + .get('/channels') + .set('auth-username', testUtils.rootUser.email) + .set('auth-ts', authDetails.authTS) + .set('auth-salt', authDetails.authSalt) + .set('auth-token', authDetails.authToken) + .expect(401) + + await testUtils.pollCondition(() => + AuditModel.countDocuments().then(c => c === 1) + ) + const audits = await AuditModel.find() + + audits.length.should.be.exactly(1) + audits.length.should.be.exactly(1) + audits[0].eventIdentification.eventOutcomeIndicator.should.be.equal('8') // failure + audits[0].eventIdentification.eventTypeCode.code.should.be.equal('110122') + audits[0].eventIdentification.eventTypeCode.displayName.should.be.equal( + 'Login' + ) + audits[0].activeParticipant.length.should.be.exactly(2) + audits[0].activeParticipant[0].userID.should.be.equal('OpenHIM') + audits[0].activeParticipant[1].userID.should.match(/Unknown with ip/) + }) + + it('should audit a successful login with enabled basic auth', async () => { + config.api.authenticationTypes = ['basic'] + + await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setupTestUsers() + await testUtils.setImmediatePromise() + await AuditModel.deleteMany({}) + + await request(BASE_URL) + .get('/channels') + .set( + 'Authorization', + `Basic ${Buffer.from(`${testUtils.rootUser.email}:password`).toString( + 'base64' + )}` + ) + .expect(200) + }) + + it('should audit an unsuccessful login with disabled local auth', async () => { + config.api.authenticationTypes = ['local'] + + await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setupTestUsers() + await testUtils.setImmediatePromise() + await AuditModel.deleteMany({}) + + const {email, password} = testUtils.rootUser + + await request(BASE_URL) + .post('/authenticate/local') + .send({username: email, password}) + .expect(200) + }) + + it('should audit an unsuccessful login with disabled token auth', async () => { + config.api.authenticationTypes = ['token'] + + await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setImmediatePromise() + await testUtils.setupTestUsersWithToken() + const authDetails = testUtils.getAuthDetails() + await AuditModel.deleteMany({}) + + await request(BASE_URL) + .get(`/authenticate/${testUtils.rootUser.email}`) + .expect(200) + + await request(BASE_URL) + .get('/channels') + .set('auth-username', testUtils.rootUser.email) + .set('auth-ts', authDetails.authTS) + .set('auth-salt', authDetails.authSalt) + .set('auth-token', authDetails.authToken) + .expect(200) + }) + }) + describe('Authentication and authorisation tests', () => { describe('Mutual TLS', () => { let mockServer = null diff --git a/test/integration/certificateApiTests.js b/test/integration/certificateApiTests.js index 080c57b3..b5fd8975 100644 --- a/test/integration/certificateApiTests.js +++ b/test/integration/certificateApiTests.js @@ -13,16 +13,15 @@ import * as server from '../../src/server' import * as testUtils from '../utils' import {KeystoreModelAPI} from '../../src/model/keystore' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants describe('API Integration Tests', () => { describe('Certificate API Tests', () => { - let authDetails = null + let cookie = '' before(async () => { - await testUtils.setupTestUsers() await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) - authDetails = await testUtils.getAuthDetails() + await testUtils.setupTestUsers() }) after(async () => { @@ -34,6 +33,9 @@ describe('API Integration Tests', () => { beforeEach(async () => { await testUtils.setupTestKeystore() + + const user = testUtils.rootUser + cookie = await testUtils.authenticate(request, BASE_URL, user) }) afterEach(async () => { @@ -53,12 +55,9 @@ describe('API Integration Tests', () => { organizationUnit: 'testOrg unit' } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/certificates') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', cookie) .send(postData) .expect(201) @@ -92,12 +91,9 @@ describe('API Integration Tests', () => { organizationUnit: 'testOrg unit' } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/certificates') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', cookie) .send(postData) .expect(201) @@ -111,5 +107,11 @@ describe('API Integration Tests', () => { result.cert.data.should.not.equal(serverCert.toString()) result.key.should.not.equal(serverKey.toString()) }) + + it('Should return 401 for unanthenticated create request', async () => { + const postData = {} + + await request(BASE_URL).post('/certificates').send(postData).expect(401) + }) }) }) diff --git a/test/integration/channelsAPITests.js b/test/integration/channelsAPITests.js index 5442fb67..fed30b63 100644 --- a/test/integration/channelsAPITests.js +++ b/test/integration/channelsAPITests.js @@ -20,7 +20,7 @@ import {ClientModelAPI} from '../../src/model/clients' import {TransactionModelAPI} from '../../src/model/transactions' import {config} from '../../src/config' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants let sandbox = sinon.createSandbox() describe('API Integration Tests', () => { @@ -65,16 +65,16 @@ describe('API Integration Tests', () => { } } - let authDetails = {} + let rootCookie = '', + nonRootCookie = '' before(async () => { - await testUtils.setupTestUsers() await promisify(server.start)({ apiPort: SERVER_PORTS.apiPort, tcpHttpReceiverPort: SERVER_PORTS.tcpHttpReceiverPort, pollingPort: SERVER_PORTS.pollingPort }) - authDetails = await testUtils.getAuthDetails() + await testUtils.setupTestUsers() await Promise.all([ TransactionModelAPI.deleteMany({}), ChannelModelAPI.deleteMany({}) @@ -105,27 +105,32 @@ describe('API Integration Tests', () => { channel2._id = ch2._id sandbox.stub(tcpAdapter, 'notifyMasterToStartTCPServer') sandbox.stub(tcpAdapter, 'notifyMasterToStopTCPServer') + + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) describe('*getChannels()', () => { it('should fetch all channels', async () => { - const result = await request(constants.BASE_URL) + const result = await request(BASE_URL) .get('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) result.body.length.should.be.eql(2) }) it('should only allow non root user to fetch channel that they are allowed to view', async () => { - const result = await request(constants.BASE_URL) + const result = await request(BASE_URL) .get('/channels') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) result.body.length.should.be.eql(1) result.body[0].name.should.be.eql('TestChannel2') @@ -147,12 +152,9 @@ describe('API Integration Tests', () => { } ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newChannel) .expect(201) const channel = await ChannelModelAPI.findOne({name: 'NewChannel'}) @@ -174,12 +176,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newChannel) .expect(400) }) @@ -200,12 +199,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidChannel) .expect(400) }) @@ -227,12 +223,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidChannel) .expect(400) }) @@ -240,12 +233,9 @@ describe('API Integration Tests', () => { it('should not allow a non admin user to add a channel', async () => { const newChannel = {} - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(newChannel) .expect(403) }) @@ -269,12 +259,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(tcpChannel) .expect(201) @@ -301,12 +288,9 @@ describe('API Integration Tests', () => { status: 'disabled' } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(tcpChannelDisabled) .expect(201) sinon.assert.notCalled(tcpAdapter.notifyMasterToStartTCPServer) @@ -331,12 +315,9 @@ describe('API Integration Tests', () => { const spy = sinon.spy(polling, 'registerPollingChannel') - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(pollChannel) .expect(201) @@ -369,12 +350,9 @@ describe('API Integration Tests', () => { const spy = sinon.spy(polling, 'registerPollingChannel') - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(pollChannelDisabled) .expect(201) spy.restore() @@ -395,12 +373,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newChannel) .expect(400) }) @@ -426,12 +401,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newChannel) .expect(400) }) @@ -458,12 +430,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newChannel) .expect(201) }) @@ -484,12 +453,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newChannel) .expect(400) }) @@ -509,12 +475,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(methodChannelDoc) .expect(201) @@ -540,12 +503,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(methodChannelDocRejected) .expect(400) @@ -571,12 +531,9 @@ describe('API Integration Tests', () => { ] } - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(methodChannelDocRejected) .expect(400) @@ -604,12 +561,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(methodChannelDoc) .expect(400) @@ -635,12 +589,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(methodChannelDoc) .expect(400) @@ -667,12 +618,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(methodChannelDoc) .expect(201) @@ -697,12 +645,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(timeoutChannelDoc) .expect(201) @@ -727,12 +672,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(timeoutChannelDoc) .expect(400) @@ -745,12 +687,9 @@ describe('API Integration Tests', () => { describe('*getChannel(channelId)', () => { it('should fetch a specific channel by id', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('name', 'TestChannel1') res.body.should.have.property('urlPattern', 'test/sample') @@ -758,22 +697,16 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user from fetching a channel they dont have access to by name', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get(`/channels/${channel1._id}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('should allow a non admin user to fetch a channel they have access to by name', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/channels/${channel2._id}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body.should.have.property('name', 'TestChannel2') res.body.should.have.property('urlPattern', 'test/sample') @@ -803,24 +736,18 @@ describe('API Integration Tests', () => { .db() .collection('channels') .insertOne(noMethodChannelDoc) - const resp = await request(constants.BASE_URL) + const resp = await request(BASE_URL) .get(`/channels/${id.toString()}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) resp.body.should.property('methods') }) it('should return a 404 if that channel doesnt exist', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels/999999999999999999999999') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(404) }) }) @@ -917,23 +844,17 @@ describe('API Integration Tests', () => { }) it('should return the patches for the correct channel', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/channels/${channel1._id}/audits`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.eql(expectedPatches) }) it('should return an empty array when the channel does not exist', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/channels/59f6d57b07552f280271efac/audits') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.eql([]) }) @@ -960,12 +881,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) const channel = await ChannelModelAPI.findOne({name: 'TestChannel1'}) @@ -977,12 +895,9 @@ describe('API Integration Tests', () => { it('should not allow a non admin user to update a channel', async () => { const updates = {} - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channel1._id}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(updates) .expect(403) }) @@ -1014,12 +929,9 @@ describe('API Integration Tests', () => { } await httpChannel.save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${httpChannel._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(changeToTCP) .expect(200) @@ -1054,12 +966,9 @@ describe('API Integration Tests', () => { } await httpChannel.save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${httpChannel._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(changeToTCPDisabled) .expect(200) sinon.assert.notCalled(tcpAdapter.notifyMasterToStartTCPServer) @@ -1090,12 +999,9 @@ describe('API Integration Tests', () => { const spy = sinon.spy(polling, 'registerPollingChannel') await pollChannel.save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${pollChannel._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(pollChannel) .expect(200) spy.restore() @@ -1133,12 +1039,9 @@ describe('API Integration Tests', () => { const spy = sinon.spy(polling, 'registerPollingChannel') await pollChannel.save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${pollChannel._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(pollChannel) .expect(200) spy.restore() @@ -1163,12 +1066,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(400) }) @@ -1193,12 +1093,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(400) }) @@ -1224,12 +1121,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) }) @@ -1240,12 +1134,9 @@ describe('API Integration Tests', () => { priority: -1 } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(400) const channel = await ChannelModelAPI.findOne({name: 'TestChannel1'}) @@ -1275,12 +1166,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({type: 'tcp'}) .expect(200) @@ -1312,12 +1200,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({methods: ['GET']}) .expect(400) @@ -1348,12 +1233,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({methods: ['GET']}) .expect(200) @@ -1390,12 +1272,9 @@ describe('API Integration Tests', () => { methodChannelDocRejected ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(methodUpdate) .expect(400) @@ -1432,12 +1311,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({maxBodyAgeDays: 2}) .expect(400) @@ -1468,12 +1344,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({maxBodyAgeDays: 2}) .expect(200) @@ -1504,12 +1377,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({maxBodyAgeDays: -1}) .expect(400) @@ -1540,12 +1410,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({maxBodyAgeDays: 36501}) .expect(400) @@ -1576,12 +1443,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({maxBodyAgeDays: null}) .expect(200) @@ -1615,12 +1479,9 @@ describe('API Integration Tests', () => { methodChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({maxBodyAgeDays: 2}) .expect(200) @@ -1651,12 +1512,9 @@ describe('API Integration Tests', () => { timeoutChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({timeout: 9}) .expect(200) @@ -1687,12 +1545,9 @@ describe('API Integration Tests', () => { timeoutChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({timeout: null}) .expect(200) @@ -1723,12 +1578,9 @@ describe('API Integration Tests', () => { timeoutChannelDoc ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/channels/${channelId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({timeout: -1}) .expect(400) @@ -1743,24 +1595,18 @@ describe('API Integration Tests', () => { // there can't be any linked transactions trx.length.should.be.exactly(0) - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const channels = await ChannelModelAPI.find({name: 'TestChannel1'}) channels.should.have.length(0) }) it('should only allow an admin user to remove a channel', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/channels/${channel1._id}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) @@ -1792,12 +1638,9 @@ describe('API Integration Tests', () => { trx.length.should.be.exactly(0) await pollChannel.save() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/channels/${pollChannel._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) spy.restore() spy.calledOnce.should.be.true() @@ -1820,12 +1663,9 @@ describe('API Integration Tests', () => { }) await trx.save() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/channels/${channel1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const channels = await ChannelModelAPI.find({name: 'TestChannel1'}) channels.should.have.length(1) @@ -1843,12 +1683,9 @@ describe('API Integration Tests', () => { ) config.polling.pollingPort = SERVER_PORTS.pollingPort - await request(constants.BASE_URL) + await request(BASE_URL) .post(`/channels/${channel1._id}/trigger`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) mockServer.close @@ -1857,33 +1694,24 @@ describe('API Integration Tests', () => { it('should fail when polling channel cannot be triggered', async () => { config.polling.pollingPort = 1234 - await request(constants.BASE_URL) + await request(BASE_URL) .post(`/channels/${channel1._id}/trigger`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(500) }) it('should reject a manually polled channel - channel not found', async () => { const invalidId = mongoose.Types.ObjectId('4eeeeeeeeeeeeeeeebbbbbb2') - await request(constants.BASE_URL) + await request(BASE_URL) .post(`/channels/${invalidId}/trigger`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(404) }) it('should not allow a non admin user from manually polling a channel they do not have access to', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post(`/channels/${channel1._id}/trigger`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) diff --git a/test/integration/clientsAPITests.js b/test/integration/clientsAPITests.js index d64cd214..37f9a92f 100644 --- a/test/integration/clientsAPITests.js +++ b/test/integration/clientsAPITests.js @@ -12,7 +12,7 @@ import * as server from '../../src/server' import * as testUtils from '../utils' import {ClientModelAPI} from '../../src/model/clients' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants describe('API Integration Tests', () => { describe('Clients REST Api Testing', () => { @@ -27,11 +27,12 @@ describe('API Integration Tests', () => { '23:37:6A:5E:A9:13:A4:8C:66:C5:BB:9F:0E:0D:68:9B:99:80:10:FC' } - let authDetails = {} + let rootCookie = '', + nonRootCookie = '' before(async () => { - await testUtils.setupTestUsers() await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setupTestUsers() }) after(async () => { @@ -40,7 +41,16 @@ describe('API Integration Tests', () => { }) beforeEach(async () => { - authDetails = await testUtils.getAuthDetails() + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) afterEach(async () => { @@ -49,12 +59,9 @@ describe('API Integration Tests', () => { describe('*addClient', () => { it('should add client to db and return status 201 - client created', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testAppDoc) .expect(201) const client = await ClientModelAPI.findOne({ @@ -80,21 +87,15 @@ describe('API Integration Tests', () => { const clientNoToken2 = Object.assign({}, testAppDoc) clientNoToken2.clientID = 'test2' - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(clientNoToken1) .expect(201) - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(clientNoToken2) .expect(201) @@ -113,35 +114,26 @@ describe('API Integration Tests', () => { clientNoToken2.clientID = 'test2' clientNoToken2.customTokenID = 'test' - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(clientNoToken1) .expect(201) const client1 = await ClientModelAPI.findOne({clientID: 'test1'}) should(client1.customTokenID).equal('test') - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(clientNoToken2) .expect(400) }) it('should only allow an admin user to add a client', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(testAppDoc) .expect(403) }) @@ -151,12 +143,9 @@ describe('API Integration Tests', () => { await client.save() const conflict = await Object.assign({}, testAppDoc) conflict.clientID = 'PoC' - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(conflict) .expect(409) }) @@ -165,12 +154,9 @@ describe('API Integration Tests', () => { const clientWithConflict = Object.assign({}, testAppDoc) clientWithConflict.clientID = 'PoC' - await request(constants.BASE_URL) + await request(BASE_URL) .post('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(clientWithConflict) .expect(400) }) @@ -194,12 +180,9 @@ describe('API Integration Tests', () => { }) it('should get client by clientId and return status 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/clients/${clientId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.clientID.should.equal('testClient') res.body.clientDomain.should.equal('www.zedmusic-unique.co.zw') @@ -216,21 +199,15 @@ describe('API Integration Tests', () => { customTokenID: 'test' } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/clients/${clientId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/clients/${clientId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) should.not.exist(res.body.customTokenID) @@ -238,32 +215,23 @@ describe('API Integration Tests', () => { }) it('should return status 404 if not found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/clients/000000000000000000000000') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(404) }) it('should not allow a non admin user to fetch a client', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get(`/clients/${clientId}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('should allow a non admin user to fetch a limited view of a client', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/clients/${clientId}/clientName`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body.name.should.equal('OpenHIE NodeJs') @@ -286,12 +254,9 @@ describe('API Integration Tests', () => { it('should return client with specified clientDomain', async () => { await new ClientModelAPI(clientTest).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/clients/domain/www.zedmusic-unique.co.zw') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.clientID.should.equal('Zambia_OpenHIE_Instance') res.body.clientDomain.should.equal('www.zedmusic-unique.co.zw') @@ -304,12 +269,9 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user to fetch a client by domain', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/clients/domain/www.zedmusic-unique.co.zw') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) @@ -355,12 +317,9 @@ describe('API Integration Tests', () => { }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/clients') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(4) @@ -371,12 +330,9 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user to fetch all clients', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/clients') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) @@ -402,12 +358,9 @@ describe('API Integration Tests', () => { name: 'Devil_may_Cry' } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/clients/${client._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -427,12 +380,9 @@ describe('API Integration Tests', () => { customTokenID: 'test' } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/clients/${client._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -448,12 +398,9 @@ describe('API Integration Tests', () => { customTokenID: null } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/clients/${client._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -469,12 +416,9 @@ describe('API Integration Tests', () => { passwordHash: null } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/clients/${client._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -493,12 +437,9 @@ describe('API Integration Tests', () => { name: 'Devil_may_Cry' } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/clients/${client._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -512,12 +453,9 @@ describe('API Integration Tests', () => { it('should not allow a non admin user to update a client', async () => { const updates = {} - await request(constants.BASE_URL) + await request(BASE_URL) .put('/clients/000000000000000000000000') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(updates) .expect(403) }) @@ -525,12 +463,9 @@ describe('API Integration Tests', () => { it('should reject a client that conflicts with a role', async () => { const client = await new ClientModelAPI(testAppDoc).save() const conflict = {clientID: 'PoC'} - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/clients/${client._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(conflict) .expect(409) }) @@ -549,12 +484,9 @@ describe('API Integration Tests', () => { const client = await new ClientModelAPI(docTestRemove).save() const countBefore = await ClientModelAPI.countDocuments() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/clients/${client._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const countAfter = await ClientModelAPI.countDocuments() @@ -566,12 +498,9 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user to remove a client', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/clients/000000000000000000000000') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) diff --git a/test/integration/contactGroupsAPITests.js b/test/integration/contactGroupsAPITests.js index 0ce7ebf7..49fa2146 100644 --- a/test/integration/contactGroupsAPITests.js +++ b/test/integration/contactGroupsAPITests.js @@ -14,7 +14,7 @@ import * as testUtils from '../utils' import {ChannelModelAPI} from '../../src/model/channels' import {ContactGroupModelAPI} from '../../src/model/contactGroups' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants describe('API Integration Tests', () => { describe('Contact Groups REST Api Testing', () => { @@ -30,7 +30,21 @@ describe('API Integration Tests', () => { ] } - let authDetails = {} + let rootCookie = '', + nonRootCookie = '' + + beforeEach(async () => { + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) + }) before(async () => { await testUtils.setupTestUsers() @@ -42,22 +56,15 @@ describe('API Integration Tests', () => { await promisify(server.stop)() }) - beforeEach(async () => { - authDetails = await testUtils.getAuthDetails() - }) - afterEach(async () => { await ContactGroupModelAPI.deleteMany({}) }) describe('*addContactGroup', () => { it('should add contact group to db and return status 201 - group created', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/groups') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(contactGroupData) .expect(201) const contactGroup = await ContactGroupModelAPI.findOne({ @@ -69,12 +76,9 @@ describe('API Integration Tests', () => { }) it('should only allow an admin user to add a contacGroup', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/groups') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(contactGroupData) .expect(403) }) @@ -103,12 +107,9 @@ describe('API Integration Tests', () => { }) it('should get contactGroup by contactGroupId and return status 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/groups/${contactGroupId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.group.should.equal('Group 1') res.body.users.length.should.equal(6) @@ -119,22 +120,16 @@ describe('API Integration Tests', () => { }) it('should return status 404 if not found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/groups/000000000000000000000000') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(404) }) it('should not allow a non admin user to fetch a contactGroups', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get(`/groups/${contactGroupId}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) @@ -181,23 +176,17 @@ describe('API Integration Tests', () => { await new ContactGroupModelAPI(contactGroupData2).save() await new ContactGroupModelAPI(contactGroupData3).save() await new ContactGroupModelAPI(contactGroupData4).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/groups') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(4) }) it('should not allow a non admin user to fetch all contact groups', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/groups') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) @@ -227,12 +216,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/groups/${contactGroup._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) contactGroup = await ContactGroupModelAPI.findById(contactGroup._id) @@ -246,12 +232,9 @@ describe('API Integration Tests', () => { it('should not allow a non admin user to update a contactGroup', async () => { const updates = {} - await request(constants.BASE_URL) + await request(BASE_URL) .put('/groups/000000000000000000000000') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(updates) .expect(403) }) @@ -274,12 +257,9 @@ describe('API Integration Tests', () => { contactGroupData ).save() const countBefore = await ContactGroupModelAPI.countDocuments() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/groups/${contactGroup._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const countAfter = await ContactGroupModelAPI.countDocuments() const notFoundDoc = await ContactGroupModelAPI.findOne({ @@ -332,12 +312,9 @@ describe('API Integration Tests', () => { } await new ChannelModelAPI(channel1).save() const countBefore = await ContactGroupModelAPI.countDocuments() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/groups/${contactGroup._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(409) const countAfter = await ContactGroupModelAPI.countDocuments() await ContactGroupModelAPI.findOne({group: 'Group 2'}) @@ -346,12 +323,9 @@ describe('API Integration Tests', () => { it('should not allow a non admin user to remove a contactGroup', async () => { contactGroupData = {} - await request(constants.BASE_URL) + await request(BASE_URL) .del('/groups/000000000000000000000000') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) diff --git a/test/integration/eventsAPITests.js b/test/integration/eventsAPITests.js index 1df24f2a..d746d860 100644 --- a/test/integration/eventsAPITests.js +++ b/test/integration/eventsAPITests.js @@ -18,7 +18,7 @@ import {config} from '../../src/config' config.authentication = config.get('authentication') config.tlsClientLookup = config.get('tlsClientLookup') -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants const {HTTP_BASE_URL: baseUrl} = constants describe('Events API Integration Tests', () => { @@ -28,7 +28,7 @@ describe('Events API Integration Tests', () => { const mediatorPortPlus40 = constants.PORT_START + 40 const mediatorPortPlus41 = constants.PORT_START + 41 const mediatorPortPlus42 = constants.PORT_START + 42 - let authDetails = {} + let rootCookie = '' let slowSpy let sandbox @@ -156,8 +156,13 @@ describe('Events API Integration Tests', () => { httpPort: SERVER_PORTS.httpPort, apiPort: SERVER_PORTS.apiPort }) - authDetails = await testUtils.getAuthDetails() await EventModel.deleteMany({}) + + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) }) afterEach(async () => { @@ -173,12 +178,9 @@ describe('Events API Integration Tests', () => { .auth('testApp', 'password') .expect(200) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/events/${+startTime}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) res.body.should.have.property('events') res.body.events.length.should.be.exactly(6) @@ -207,12 +209,9 @@ describe('Events API Integration Tests', () => { .auth('testApp', 'password') .expect(200) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/events/${+startTime}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) res.body.should.have.property('events') res.body.events.length.should.be.exactly(6) @@ -233,12 +232,9 @@ describe('Events API Integration Tests', () => { .auth('testApp', 'password') .expect(200) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/events/${+startTime}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) res.body.should.have.property('events') res.body.events.length.should.be.exactly(6) @@ -254,12 +250,9 @@ describe('Events API Integration Tests', () => { .auth('testApp', 'password') .expect(200) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/events/${+startTime}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) res.body.should.have.property('events') res.body.events.length.should.be.exactly(6) @@ -287,12 +280,9 @@ describe('Events API Integration Tests', () => { EventModel.countDocuments().then(c => c === 6) ) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/events/${+startTime}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) res.body.should.have.property('events') res.body.events.length.should.be.exactly(6) @@ -325,12 +315,9 @@ describe('Events API Integration Tests', () => { EventModel.countDocuments().then(c => c === 6) ) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/events/${+startTime}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) res.body.should.have.property('events') res.body.events.length.should.be.exactly(6) diff --git a/test/integration/generalAPITests.js b/test/integration/generalAPITests.js index 128a052a..d8c6578f 100644 --- a/test/integration/generalAPITests.js +++ b/test/integration/generalAPITests.js @@ -2,36 +2,45 @@ /* eslint-env mocha */ -import crypto from 'crypto' import request from 'supertest' import {promisify} from 'util' +import * as crypto from 'crypto' import * as constants from '../constants' import * as server from '../../src/server' -import {UserModel} from '../../src/model' +import {UserModel, createUser, updateTokenUser} from '../../src/model' +import {authenticate} from '../utils' +import {config} from '../../src/config' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants describe('API Integration Tests', () => { + const userWithoutPass = { + firstname: 'Test', + surname: 'Test', + email: 'test@test.net', + groups: ['group1', 'group2'] + } + describe('General API tests', () => { const userDoc = { firstname: 'Bill', surname: 'Murray', email: 'bfm@crazy.net', - passwordAlgorithm: 'sha512', - passwordHash: - '669c981d4edccb5ed61f4d77f9fcc4bf594443e2740feb1a23f133bdaf80aae41804d10aa2ce254cfb6aca7c497d1a717f2dd9a794134217219d8755a84b6b4e', - passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0', + password: 'password', groups: ['HISP', 'admin'] } - // password is 'password' + before(async () => { + // Set the authentication maxAge to 1s for the tests + config.api.maxAge = 1000 await Promise.all([ promisify(server.start)({ apiPort: SERVER_PORTS.apiPort, httpsPort: SERVER_PORTS.httpsPort }), - new UserModel(userDoc).save() + createUser(userDoc), + new UserModel(userWithoutPass).save() ]) }) @@ -41,7 +50,104 @@ describe('API Integration Tests', () => { it('should set the cross-origin resource sharing headers', async () => { const origin = 'https://example.com' - await request(constants.BASE_URL) + await request(BASE_URL) + .post('/authenticate/local') + .send({username: userDoc.email, password: userDoc.password}) + .set('Origin', origin) + .set('Access-Control-Request-Method', 'POST') + .expect(200) + .expect('Access-Control-Allow-Origin', origin) + .expect('Access-Control-Allow-Credentials', 'true') + }) + + it('should disallow access for unauthenticated requests', async () => { + await request(BASE_URL).get('/channels').expect(401) + }) + + it('should disallow access if password does not match', async () => { + await request(BASE_URL) + .post('/authenticate/local') + .send({ + username: userDoc.email, + password: `${userDoc.password}incorrect` + }) + .expect(401) + }) + + it("should disallow access if the user's password is not set yet", async () => { + await request(BASE_URL) + .post('/authenticate/local') + .send({username: userWithoutPass.email, password: 'password'}) + .expect(401) + }) + + it('should disallow access if the user is not found', async () => { + // User not found when getting auth info + await request(BASE_URL) + .post('/authenticate/local') + .send({username: 'unexistent-user@test.com', password: 'password'}) + .expect(401) + }) + + it('should disallow access if cookies does not exist', async () => { + await request(BASE_URL) + .post('/authenticate/local') + .send({username: userDoc.email, password: userDoc.password}) + .expect(200) + + await request(BASE_URL).get('/channels').expect(401) + }) + + it('should disallow if cookies are expired', async () => { + const user = {email: userDoc.email, password: userDoc.password} + const cookie = await authenticate(request, BASE_URL, user) + + // Expire the cookies after 1s + await new Promise(resolve => setTimeout(resolve, 1000)) + + await request(BASE_URL).get('/channels').set('Cookie', cookie).expect(401) + }) + + it('should allow access if correct API authentication details are provided', async () => { + const user = {email: userDoc.email, password: userDoc.password} + const cookie = await authenticate(request, BASE_URL, user) + + await request(BASE_URL).get('/channels').set('Cookie', cookie).expect(200) + }) + }) + + describe('General API tests (token auth)', () => { + const userDoc = { + firstname: 'Bill', + surname: 'Murray', + email: 'bfm@crazy.net', + passwordAlgorithm: 'sha512', + passwordHash: + '669c981d4edccb5ed61f4d77f9fcc4bf594443e2740feb1a23f133bdaf80aae41804d10aa2ce254cfb6aca7c497d1a717f2dd9a794134217219d8755a84b6b4e', + passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0', + groups: ['HISP', 'admin'] + } + + let userWithoutPassRes = null + + // password is 'password' + before(async () => { + await promisify(server.start)({ + apiPort: SERVER_PORTS.apiPort, + httpsPort: SERVER_PORTS.httpsPort + }) + const res = await new UserModel(userDoc).save() + await updateTokenUser({id: res.id, ...userDoc}) + userWithoutPassRes = await new UserModel(userWithoutPass).save() + }) + + after(async () => { + await Promise.all([UserModel.deleteMany({}), promisify(server.stop)()]) + }) + + it('should set the cross-origin resource sharing headers', async () => { + const origin = 'https://example.com' + await request(BASE_URL) .options('/authenticate/bfm@crazy.net') .set('Origin', origin) .set('Access-Control-Request-Method', 'GET') @@ -51,11 +157,11 @@ describe('API Integration Tests', () => { }) it('should disallow access if no API authentication details are provided', async () => { - await request(constants.BASE_URL).get('/channels').expect(401) + await request(BASE_URL).get('/channels').expect(401) }) it('should disallow access if token does not match', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/authenticate/bfm@crazy.net') .expect(200) const passwordsalt = res.body.salt @@ -73,7 +179,7 @@ describe('API Integration Tests', () => { await tokenhash.update(requestsalt) await tokenhash.update(authTS) - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') .set('auth-username', 'bfm@crazy.net') .set('auth-ts', authTS) @@ -82,10 +188,79 @@ describe('API Integration Tests', () => { .expect(401) }) - it('should allow access if correct API authentication details are provided', async () => { - const res = await request(constants.BASE_URL) + it('should disallow access if the request is too old', async () => { + const res = await request(BASE_URL) + .get('/authenticate/bfm@crazy.net') + .expect(200) + const passwordsalt = res.body.salt + + // create passwordhash + const passwordhash = await crypto.createHash('sha512') + await passwordhash.update(passwordsalt) + await passwordhash.update('password') + + // create tokenhash + let authTS = await new Date() + await authTS.setSeconds(authTS.getSeconds() - 53) + authTS = await authTS.toISOString() + const requestsalt = '842cd4a0-1a91-45a7-bf76-c292cb36b2e8' + const tokenhash = await crypto.createHash('sha512') + await tokenhash.update(passwordhash.digest('hex')) + await tokenhash.update(requestsalt) + await tokenhash.update(authTS) + + await request(BASE_URL) + .get('/channels') + .set('auth-username', 'bfm@crazy.net') + .set('auth-ts', authTS) + .set('auth-salt', requestsalt) + .set('auth-token', tokenhash.digest('hex')) + .expect(401) + }) + + it("should disallow access if the user's password is not set yet", async () => { + await request(BASE_URL) + .get('/channels') + .set('auth-username', userWithoutPass.email) + .set('auth-ts', new Date()) + .set('auth-salt', 'salt') + .set('auth-token', 'token') + .expect(401) + }) + + it("should disallow access if the user's password algorithm is not defined correctly", async () => { + const passwordfields = { + passwordAlgorithm: 'test', + passwordHash: + '669c981d4edccb5ed61f4d77f9fcc4bf594443e2740feb1a23f133bdaf80aae41804d10aa2ce254cfb6aca7c497d1a717f2dd9a794134217219d8755a84b6b4e', + passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0' + } + await updateTokenUser({ + id: userWithoutPassRes.id, + ...userWithoutPass, + ...passwordfields + }) + + await request(BASE_URL) + .get('/channels') + .set('auth-username', 'test@test.net') + .set('auth-ts', new Date()) + .set('auth-salt', 'salt') + .set('auth-token', 'token') + .expect(401) + }) + + it('should disallow access if the user is not found', async () => { + // User not found when getting auth info + await request(BASE_URL) + .get('/authenticate/unexistent-user@test.org') + .expect(404) + + // User not found when authenticating + const res = await request(BASE_URL) .get('/authenticate/bfm@crazy.net') .expect(200) + const passwordsalt = res.body.salt // create passwordhash @@ -102,17 +277,17 @@ describe('API Integration Tests', () => { await tokenhash.update(requestsalt) await tokenhash.update(authTS) - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') - .set('auth-username', 'bfm@crazy.net') + .set('auth-username', 'non-existent-user@test.org') .set('auth-ts', authTS) .set('auth-salt', requestsalt) .set('auth-token', tokenhash.digest('hex')) - .expect(200) + .expect(401) }) - it('should disallow access if the request is too old', async () => { - const res = await request(constants.BASE_URL) + it('should allow access if correct API authentication details are provided', async () => { + const res = await request(BASE_URL) .get('/authenticate/bfm@crazy.net') .expect(200) const passwordsalt = res.body.salt @@ -123,22 +298,21 @@ describe('API Integration Tests', () => { await passwordhash.update('password') // create tokenhash - let authTS = await new Date() - await authTS.setSeconds(authTS.getSeconds() - 53) - authTS = await authTS.toISOString() + const authTS = await new Date().toISOString() const requestsalt = '842cd4a0-1a91-45a7-bf76-c292cb36b2e8' const tokenhash = await crypto.createHash('sha512') - await tokenhash.update(passwordhash.digest('hex')) + const hashStr = await passwordhash.digest('hex') + await tokenhash.update(hashStr) await tokenhash.update(requestsalt) await tokenhash.update(authTS) - await request(constants.BASE_URL) + await request(BASE_URL) .get('/channels') .set('auth-username', 'bfm@crazy.net') .set('auth-ts', authTS) .set('auth-salt', requestsalt) .set('auth-token', tokenhash.digest('hex')) - .expect(401) + .expect(200) }) }) }) diff --git a/test/integration/heartbeatAPITest.js b/test/integration/heartbeatAPITest.js index ee266000..d77cfe08 100644 --- a/test/integration/heartbeatAPITest.js +++ b/test/integration/heartbeatAPITest.js @@ -11,6 +11,8 @@ import * as server from '../../src/server' import * as testUtils from '../utils' import {MediatorModel} from '../../src/model/mediators' +const {BASE_URL} = constants + describe('API Integration Tests', () => describe('Heartbeat REST API testing', () => { const mediatorDoc = { @@ -28,12 +30,12 @@ describe('API Integration Tests', () => ] } - let authDetails + let rootCookie = '' before(async () => { await Promise.all([ - testUtils.setupTestUsers(), - promisify(server.start)({apiPort: constants.SERVER_PORTS.apiPort}) + promisify(server.start)({apiPort: constants.SERVER_PORTS.apiPort}), + testUtils.setupTestUsers() ]) }) @@ -44,31 +46,26 @@ describe('API Integration Tests', () => ]) }) - beforeEach(async () => { - authDetails = testUtils.getAuthDetails() - }) - afterEach(async () => { await MediatorModel.deleteMany({}) }) + beforeEach(async () => { + const user = testUtils.rootUser + rootCookie = await testUtils.authenticate(request, BASE_URL, user) + }) + const registerMediator = () => - request(constants.BASE_URL) + request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediatorDoc) .expect(201) const sendUptime = () => - request(constants.BASE_URL) + request(BASE_URL) .post(`/mediators/${mediatorDoc.urn}/heartbeat`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ uptime: 200 }) @@ -76,13 +73,11 @@ describe('API Integration Tests', () => describe('*getHeartbeat()', () => { it('should fetch the heartbeat without requiring authentication', async () => { - await request(constants.BASE_URL).get('/heartbeat').expect(200) + await request(BASE_URL).get('/heartbeat').expect(200) }) it('should return core uptime', async () => { - const res = await request(constants.BASE_URL) - .get('/heartbeat') - .expect(200) + const res = await request(BASE_URL).get('/heartbeat').expect(200) res.body.should.have.property('master').and.be.a.Number() }) @@ -90,9 +85,7 @@ describe('API Integration Tests', () => it('should include known mediators in response', async () => { await registerMediator() - const res = await request(constants.BASE_URL) - .get('/heartbeat') - .expect(200) + const res = await request(BASE_URL).get('/heartbeat').expect(200) res.body.should.have.property('mediators') res.body.mediators.should.have.property(mediatorDoc.urn) @@ -100,9 +93,7 @@ describe('API Integration Tests', () => it('should set the uptime to null if no heartbeats received from mediator', async () => { await registerMediator() - const res = await request(constants.BASE_URL) - .get('/heartbeat') - .expect(200) + const res = await request(BASE_URL).get('/heartbeat').expect(200) res.body.should.have.property('mediators') should(res.body.mediators[mediatorDoc.urn]).be.null() @@ -111,9 +102,7 @@ describe('API Integration Tests', () => it('should include the mediator uptime', async () => { await registerMediator() await sendUptime() - const res = await request(constants.BASE_URL) - .get('/heartbeat') - .expect(200) + const res = await request(BASE_URL).get('/heartbeat').expect(200) res.body.should.have.property('mediators') res.body.mediators[mediatorDoc.urn].should.be.exactly(200) @@ -130,9 +119,7 @@ describe('API Integration Tests', () => } await MediatorModel.findOneAndUpdate({urn: mediatorDoc.urn}, update) - const res = await request(constants.BASE_URL) - .get('/heartbeat') - .expect(200) + const res = await request(BASE_URL).get('/heartbeat').expect(200) res.body.should.have.property('mediators') should(res.body.mediators[mediatorDoc.urn]).be.null() diff --git a/test/integration/keystoreAPITests.js b/test/integration/keystoreAPITests.js index 57a1bde1..906fa240 100644 --- a/test/integration/keystoreAPITests.js +++ b/test/integration/keystoreAPITests.js @@ -14,7 +14,10 @@ import {config} from '../../src/config' describe('API Integration Tests', () => { const ORIGINAL_CERTIFICATE_MANAGEMENT = config.certificateManagement - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants + + let rootCookie = '', + nonRootCookie = '' before(() => { config.certificateManagement = config.get('certificateManagement') @@ -25,12 +28,11 @@ describe('API Integration Tests', () => { }) describe('Keystore API Tests', () => { - let authDetails = {} let keystore before(async () => { - await testUtils.setupTestUsers() await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + await testUtils.setupTestUsers() }) after(async () => { @@ -39,8 +41,18 @@ describe('API Integration Tests', () => { }) beforeEach(async () => { - authDetails = await testUtils.getAuthDetails() keystore = await testUtils.setupTestKeystore() + + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) afterEach(async () => { @@ -48,12 +60,9 @@ describe('API Integration Tests', () => { }) it('Should fetch the current HIM server certificate', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/keystore/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.data.should.be.exactly(keystore.cert.data) @@ -61,22 +70,16 @@ describe('API Integration Tests', () => { }) it('Should not allow a non-admin user to fetch the current HIM server certificate', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/keystore/cert') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('Should fetch the current trusted ca certificates', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/keystore/ca') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.be.instanceof(Array).and.have.lengthOf(2) @@ -85,22 +88,16 @@ describe('API Integration Tests', () => { }) it('Should not allow a non-admin user to fetch the current trusted ca certificates', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/keystore/ca') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('Should fetch a ca certificate by id', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/keystore/ca/${keystore.ca[0]._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('commonName', keystore.ca[0].commonName) @@ -108,12 +105,9 @@ describe('API Integration Tests', () => { }) it('Should not allow a non-admin user to fetch a ca certificate by id', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/keystore/ca/1234') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) @@ -122,12 +116,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/server-tls/cert.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(201) @@ -142,12 +133,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/server-tls/cert.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(201) @@ -160,12 +148,9 @@ describe('API Integration Tests', () => { it("Should return a 400 if the server certificate isn't valid", async () => { const postData = {cert: 'junkjunkjunk'} - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(400) }) @@ -175,12 +160,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/server-tls/cert.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/cert') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(postData) .expect(403) }) @@ -191,12 +173,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/server-tls/cert.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(400) }) @@ -206,12 +185,9 @@ describe('API Integration Tests', () => { key: fs.readFileSync('test/resources/server-tls/key.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/key') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(201) @@ -224,12 +200,9 @@ describe('API Integration Tests', () => { key: fs.readFileSync('test/resources/server-tls/key.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/key') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(postData) .expect(403) }) @@ -239,12 +212,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/trust-tls/cert1.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/ca/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(201) @@ -260,12 +230,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/trust-tls/cert1.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/ca/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(201) @@ -278,12 +245,9 @@ describe('API Integration Tests', () => { it('Should respond with a 400 if one or more certs are invalid', async () => { const postData = {cert: 'junkjunkjunk'} - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/ca/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(400) }) @@ -293,12 +257,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/trust-tls/cert1.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/ca/cert') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(postData) .expect(403) }) @@ -308,12 +269,9 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/chain.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/ca/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(201) @@ -328,23 +286,17 @@ describe('API Integration Tests', () => { cert: fs.readFileSync('test/resources/invalid-chain.pem').toString() } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/keystore/ca/cert') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(postData) .expect(400) }) it('Should remove a ca certificate by id', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/keystore/ca/${keystore.ca[0]._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) keystore = await KeystoreModelAPI.findOne({}) @@ -352,22 +304,16 @@ describe('API Integration Tests', () => { }) it('Should not allow a non-admin user to remove a ca certificate by id', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/keystore/ca/1234') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('Should verify that a valid server cert and key match', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/keystore/validity') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.valid.should.be.exactly(true) @@ -377,12 +323,9 @@ describe('API Integration Tests', () => { keystore.key = await fs.readFileSync('test/resources/trust-tls/key1.pem') await keystore.save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/keystore/validity') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.valid.should.be.exactly(false) @@ -392,12 +335,9 @@ describe('API Integration Tests', () => { keystore.key = 'junkjunkjunk' await keystore.save() - await request(constants.BASE_URL) + await request(BASE_URL) .get('/keystore/validity') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(400) }) @@ -407,12 +347,9 @@ describe('API Integration Tests', () => { keystore.passphrase = 'password' await keystore.save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/keystore/validity') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.valid.should.be.exactly(true) @@ -424,12 +361,9 @@ describe('API Integration Tests', () => { keystore.passphrase = undefined await keystore.save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/keystore/validity') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.valid.should.be.exactly(false) diff --git a/test/integration/logsAPITests.js b/test/integration/logsAPITests.js index 5fb04e80..bd9fb2a0 100644 --- a/test/integration/logsAPITests.js +++ b/test/integration/logsAPITests.js @@ -6,17 +6,17 @@ import moment from 'moment' import request from 'supertest' import {promisify} from 'util' -import * as constants from '../constants' import * as server from '../../src/server' import * as testUtils from '../utils' import {connectionDefault} from '../../src/config/connection' +import {SERVER_PORTS, BASE_URL} from '../constants' describe(`API Integration Tests`, () => { describe(`Log REST API`, () => { - let authDetails let beforeTS let middleTS let endTS + let rootCookie = '' before(async () => { beforeTS = moment('2012-01-01 11:00') @@ -24,8 +24,8 @@ describe(`API Integration Tests`, () => { endTS = moment(beforeTS).add(3, 'minutes') await Promise.all([ + promisify(server.start)({apiPort: SERVER_PORTS.apiPort}), testUtils.setupTestUsers(), - promisify(server.start)({apiPort: constants.SERVER_PORTS.apiPort}), connectionDefault.db.collection('log').deleteMany({}) ]) @@ -66,7 +66,8 @@ describe(`API Integration Tests`, () => { }) beforeEach(async () => { - authDetails = testUtils.getAuthDetails() + const user = testUtils.rootUser + rootCookie = await testUtils.authenticate(request, BASE_URL, user) }) after(async () => { @@ -79,14 +80,11 @@ describe(`API Integration Tests`, () => { describe('*getLogs', () => { it('should return latest logs in order', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( `/logs?from=${beforeTS.toISOString()}&until=${endTS.toISOString()}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.equal(5) @@ -98,14 +96,11 @@ describe(`API Integration Tests`, () => { }) it('should limit number of logs returned', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( `/logs?limit=2&from=${beforeTS.toISOString()}&until=${endTS.toISOString()}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.equal(2) @@ -114,14 +109,11 @@ describe(`API Integration Tests`, () => { }) it('should use start after the specified entry', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( `/logs?start=3&from=${beforeTS.toISOString()}&until=${endTS.toISOString()}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.equal(2) @@ -130,14 +122,11 @@ describe(`API Integration Tests`, () => { }) it('should filter by date', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( `/logs?from=${beforeTS.toISOString()}&until=${middleTS.toISOString()}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.equal(3) @@ -147,14 +136,11 @@ describe(`API Integration Tests`, () => { }) it('should filter by level', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( `/logs?level=error&from=${beforeTS.toISOString()}&until=${endTS.toISOString()}` ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.equal(2) @@ -163,13 +149,14 @@ describe(`API Integration Tests`, () => { }) it('should deny access for a non-admin', async () => { - await request(constants.BASE_URL) - .get('/logs') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) - .expect(403) + const user = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL).get('/logs').set('Cookie', cookie).expect(403) + }) + + it('should return 401 for unauthenticated', async () => { + await request(BASE_URL).get('/logs').expect(401) }) }) }) diff --git a/test/integration/mediatorAPITests.js b/test/integration/mediatorAPITests.js index 8f7d5fa2..ffbfb347 100644 --- a/test/integration/mediatorAPITests.js +++ b/test/integration/mediatorAPITests.js @@ -18,7 +18,7 @@ import {TransactionModelAPI} from '../../src/model/transactions' import {config} from '../../src/config' describe('API Integration Tests', () => { - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants const httpPortPlus40 = constants.PORT_START + 40 nconf.set('router', {httpPort: SERVER_PORTS.httpPort}) @@ -101,7 +101,8 @@ describe('API Integration Tests', () => { ] } - let authDetails = {} + let rootCookie = '', + nonRootCookie = '' before(async () => { await testUtils.setupTestUsers() @@ -116,7 +117,16 @@ describe('API Integration Tests', () => { }) beforeEach(async () => { - authDetails = await testUtils.getAuthDetails() + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) afterEach(async () => { @@ -128,24 +138,18 @@ describe('API Integration Tests', () => { it('should fetch all mediators', async () => { await new MediatorModelAPI(mediator1).save() await new MediatorModelAPI(mediator2).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.eql(2) }) it('should not allow non root user to fetch mediators', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/mediators') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) @@ -153,67 +157,49 @@ describe('API Integration Tests', () => { describe('*getMediator()', () => { it('should fetch mediator', async () => { await new MediatorModelAPI(mediator1).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/mediators/${mediator1.urn}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.urn.should.be.exactly(mediator1.urn) }) it('should return status 404 if not found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get(`/mediators/${mediator1.urn}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(404) }) it('should not allow non root user to fetch mediator', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get(`/mediators/${mediator1.urn}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) describe('*addMediator()', () => { it('should return 201', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator1) .expect(201) }) it('should not allow non root user to add mediator', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(mediator1) .expect(403) }) it('should add the mediator to the mediators collection', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator1) .expect(201) @@ -222,21 +208,15 @@ describe('API Integration Tests', () => { }) it('should add multiple mediators without default channel config', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator2) .expect(201) - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator3) .expect(201) }) @@ -250,12 +230,9 @@ describe('API Integration Tests', () => { await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updatedMediator) .expect(201) @@ -272,12 +249,9 @@ describe('API Integration Tests', () => { } await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updatedMediator) .expect(201) @@ -294,12 +268,9 @@ describe('API Integration Tests', () => { } await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updatedMediator) .expect(201) @@ -363,12 +334,9 @@ describe('API Integration Tests', () => { } await new MediatorModelAPI(mediator).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updatedMediator) .expect(201) @@ -394,12 +362,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidMediator) .expect(400) }) @@ -419,12 +384,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidMediator) .expect(400) }) @@ -444,12 +406,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidMediator) .expect(400) }) @@ -470,12 +429,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidMediator) .expect(400) }) @@ -487,12 +443,9 @@ describe('API Integration Tests', () => { version: '0.8.2', description: 'Invalid mediator for testing' } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidMediator) .expect(400) }) @@ -506,12 +459,9 @@ describe('API Integration Tests', () => { endpoints: [] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidMediator) .expect(400) }) @@ -546,12 +496,9 @@ describe('API Integration Tests', () => { } } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(invalidMediator) .expect(400) }) @@ -586,12 +533,9 @@ describe('API Integration Tests', () => { } } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(validMediator) .expect(201) const mediator = await MediatorModelAPI.findOne({ @@ -625,12 +569,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator) .expect(400) }) @@ -660,12 +601,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator) .expect(400) }) @@ -725,12 +663,9 @@ describe('API Integration Tests', () => { } } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator) .expect(201) }) @@ -759,12 +694,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator) .expect(400) }) @@ -794,12 +726,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator) .expect(400) }) @@ -829,12 +758,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(mediator) .expect(400) }) @@ -875,12 +801,9 @@ describe('API Integration Tests', () => { const mediator = await new MediatorModelAPI(mediatorDelete).save() const countBefore = await MediatorModelAPI.countDocuments() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/mediators/${mediator.urn}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const countAfter = await MediatorModelAPI.countDocuments() const notFoundDoc = await MediatorModelAPI.findOne({ @@ -891,12 +814,9 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user to remove a mediator', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/mediators/urn:uuid:EEA84E13-2M74-467C-UD7F-7C480462D1DF') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) @@ -905,14 +825,11 @@ describe('API Integration Tests', () => { it('should store uptime and lastHeartbeat then return a 200 status', async () => { await new MediatorModelAPI(mediator1).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/heartbeat' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ uptime: 50.25 }) @@ -940,14 +857,11 @@ describe('API Integration Tests', () => { await MediatorModelAPI.findOneAndUpdate({urn: mediator1.urn}, update) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/heartbeat' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ uptime: 50.25 }) @@ -972,14 +886,11 @@ describe('API Integration Tests', () => { await MediatorModelAPI.findOneAndUpdate({urn: mediator1.urn}, update) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/heartbeat' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ uptime: 50.25, config: true @@ -991,14 +902,11 @@ describe('API Integration Tests', () => { }) it('should deny access to a non admin user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/heartbeat' ) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ uptime: 50.25 }) @@ -1006,12 +914,9 @@ describe('API Integration Tests', () => { }) it('should return a 404 if the mediator specified by urn cannot be found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators/urn:uuid:this-doesnt-exist/heartbeat') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ uptime: 50.25 }) @@ -1020,14 +925,11 @@ describe('API Integration Tests', () => { it('should return a 400 if an invalid body is received', async () => { await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/heartbeat' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ downtime: 0.5 }) @@ -1037,14 +939,11 @@ describe('API Integration Tests', () => { describe('*setConfig()', () => { it('should deny access to a non admin user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/config' ) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ param1: 'val1', param2: 'val2' @@ -1053,12 +952,9 @@ describe('API Integration Tests', () => { }) it('should return a 404 if the mediator specified by urn cannot be found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/mediators/urn:uuid:this-doesnt-exist/config') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ param1: 'val1', param2: 'val2' @@ -1080,14 +976,11 @@ describe('API Integration Tests', () => { await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/config' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ param1: 'val1', param2: 'val2' @@ -1114,14 +1007,11 @@ describe('API Integration Tests', () => { ] await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .put( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/config' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ param1: 'val1', param2: 'val2', @@ -1133,28 +1023,22 @@ describe('API Integration Tests', () => { describe('*loadDefaultChannels()', () => { it('should deny access to non-admin users', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/channels' ) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send([]) .expect(403) }) it('should add all channels in the defaultChannelConfig property', async () => { await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/channels' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send([]) .expect(201) @@ -1169,14 +1053,11 @@ describe('API Integration Tests', () => { it('should add selected channels in the defaultChannelConfig property if the body is set (save one)', async () => { await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/channels' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(['Save Encounter 2']) .expect(201) @@ -1188,14 +1069,11 @@ describe('API Integration Tests', () => { it('should add selected channels in the defaultChannelConfig property if the body is set (save both)', async () => { await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/channels' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(['Save Encounter 1', 'Save Encounter 2']) .expect(201) @@ -1210,25 +1088,19 @@ describe('API Integration Tests', () => { it("should return a 400 when a channel from the request body isn't found", async () => { await new MediatorModelAPI(mediator1).save() - await request(constants.BASE_URL) + await request(BASE_URL) .post( '/mediators/urn:uuid:EEA84E13-1C92-467C-B0BD-7C480462D1ED/channels' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(['Something Wrong']) .expect(400) }) it("should return a 404 if the mediator isn't found", async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/mediators/urn:uuid:MISSING/channels') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send([]) .expect(404) }) diff --git a/test/integration/metadataAPITests.js b/test/integration/metadataAPITests.js index f54a9a67..e3d8fecf 100644 --- a/test/integration/metadataAPITests.js +++ b/test/integration/metadataAPITests.js @@ -104,19 +104,29 @@ const sampleMetadata = { ] } -let authDetails = {} - describe('API Integration Tests', () => { - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants describe('Metadata REST Api Testing', () => { + let rootCookie = '', + nonRootCookie = '' + before(async () => { await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) await testUtils.setupTestUsers() }) - beforeEach(() => { - authDetails = testUtils.getAuthDetails() + beforeEach(async () => { + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) after(async () => { @@ -136,12 +146,9 @@ describe('API Integration Tests', () => { }) it('should fetch channels and return status 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body[0].Channels.length.should.equal(1) @@ -162,12 +169,9 @@ describe('API Integration Tests', () => { }) it('should fetch clients and return status 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body[0].Clients.length.should.equal(1) @@ -188,12 +192,9 @@ describe('API Integration Tests', () => { }) it('should fetch mediators and return status 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body[0].Mediators.length.should.equal(1) @@ -206,12 +207,9 @@ describe('API Integration Tests', () => { describe('Users', () => { it('should fetch users and return status 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body[0].Users.length.should.equal(3) // Due to 3 auth test users @@ -228,12 +226,9 @@ describe('API Integration Tests', () => { }) it('should fetch contact groups and return status 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body[0].ContactGroups.length.should.equal(1) @@ -243,22 +238,16 @@ describe('API Integration Tests', () => { describe('Other Get Metadata', () => { it('should not allow a non admin user to get metadata', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/metadata') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('should return 404 if not found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/metadata/bleh') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(sampleMetadata) .expect(404) }) @@ -281,12 +270,9 @@ describe('API Integration Tests', () => { }) it('should insert a channel and return 201', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -300,23 +286,17 @@ describe('API Integration Tests', () => { }) it('should update a channel and return 201', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) testMetadata.Channels[0].urlPattern = 'sample/test' - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -332,12 +312,9 @@ describe('API Integration Tests', () => { it('should fail to insert a Channel and return 201', async () => { testMetadata.Channels = [{fakeChannel: 'fakeChannel'}] - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -402,12 +379,9 @@ describe('API Integration Tests', () => { const spy = sinon.spy(polling, 'registerPollingChannel') - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testPollingChannelImport) .expect(201) @@ -444,12 +418,9 @@ describe('API Integration Tests', () => { }) it('should insert a client and return 201', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -462,23 +433,17 @@ describe('API Integration Tests', () => { }) it('should update a client and return 201', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) testMetadata.Clients[0].name = 'Test Update' - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -493,12 +458,9 @@ describe('API Integration Tests', () => { it('should fail to insert a Client and return 201', async () => { testMetadata.Clients = [{fakeClient: 'fakeClient'}] - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -520,12 +482,9 @@ describe('API Integration Tests', () => { }) it('should insert a mediator and return 201', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -538,23 +497,17 @@ describe('API Integration Tests', () => { }) it('should update a mediator and return 201', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) testMetadata.Mediators[0].name = 'Updated Encounter Mediator' - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -569,12 +522,9 @@ describe('API Integration Tests', () => { it('should fail to insert a mediator and return 201', async () => { testMetadata.Mediators = [{fakeMediator: 'fakeMediator'}] - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -596,12 +546,9 @@ describe('API Integration Tests', () => { }) it('should insert a user and return 201', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -612,23 +559,17 @@ describe('API Integration Tests', () => { }) it('should update a user and return 201', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) testMetadata.Users[0].firstname = 'updatedNamey' - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -641,12 +582,9 @@ describe('API Integration Tests', () => { it('should fail to insert a user and return 201', async () => { testMetadata.Users = [{fakeUser: 'fakeUser'}] - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) res.body[0].should.have.property('status', 'Error') @@ -669,12 +607,9 @@ describe('API Integration Tests', () => { }) it('should insert a contactGroup and return 201', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -685,12 +620,9 @@ describe('API Integration Tests', () => { }) it('should update a contactGroup and return 201', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -700,12 +632,9 @@ describe('API Integration Tests', () => { maxAlerts: '1 per day' }) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -718,12 +647,9 @@ describe('API Integration Tests', () => { it('should fail to insert a ContactGroup and return 201', async () => { testMetadata.ContactGroups = [{fakeContactGroup: 'fakeContactGroup'}] - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -740,19 +666,15 @@ describe('API Integration Tests', () => { ContactGroupModelAPI.deleteMany({}) // User? ]) - authDetails = await testUtils.getAuthDetails() }) it('should ignore invalid metadata, insert valid metadata and return 201', async () => { let testMetadata = await JSON.parse(JSON.stringify(sampleMetadata)) testMetadata.Channels = [{InvalidChannel: 'InvalidChannel'}] - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -782,23 +704,17 @@ describe('API Integration Tests', () => { describe('Bad metadata import requests', () => { it('should not allow a non admin user to insert metadata', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(sampleMetadata) .expect(403) }) it('should return 404 if not found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata/bleh') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(sampleMetadata) .expect(404) }) @@ -813,12 +729,9 @@ describe('API Integration Tests', () => { }) it('should validate metadata and return status 201', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata/validate') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(sampleMetadata) .expect(201) @@ -837,12 +750,9 @@ describe('API Integration Tests', () => { let testMetadata = await JSON.parse(JSON.stringify(sampleMetadata)) testMetadata.Channels = [{'Invalid Channel': 'Invalid Channel'}] - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata/validate') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -865,12 +775,9 @@ describe('API Integration Tests', () => { await new UserModelAPI(sampleMetadata.Users[0]).save() await new ChannelModelAPI(sampleMetadata.Channels[0]) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/metadata/validate') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(testMetadata) .expect(201) @@ -887,23 +794,17 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user to validate metadata', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata/validate') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(sampleMetadata) .expect(403) }) it('should return 404 if not found', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/metadata/validate/bleh') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(sampleMetadata) .expect(404) }) diff --git a/test/integration/metricsAPITests.js b/test/integration/metricsAPITests.js index b73b183e..cb019744 100644 --- a/test/integration/metricsAPITests.js +++ b/test/integration/metricsAPITests.js @@ -12,11 +12,11 @@ import * as server from '../../src/server' import * as testUtils from '../utils' import {ChannelModel, MetricModel} from '../../src/model' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants describe('API Metrics Tests', () => describe('OpenHIM Metrics Api testing', () => { - let authDetails + let rootCookie = '' const channel1Doc = { _id: new ObjectId('111111111111111111111111'), name: 'Test Channel 11111', @@ -53,16 +53,17 @@ describe('API Metrics Tests', () => new ChannelModel(channel1Doc).save(), new ChannelModel(channel2Doc).save(), testUtils.setupMetricsTransactions(), - testUtils.setupTestUsers(), promisify(server.start)({ apiPort: SERVER_PORTS.apiPort, tcpHttpReceiverPort: SERVER_PORTS.tcpHttpReceiverPort - }) + }), + testUtils.setupTestUsers() ]) }) - beforeEach(() => { - authDetails = testUtils.getAuthDetails() + beforeEach(async () => { + const user = testUtils.rootUser + rootCookie = await testUtils.authenticate(request, BASE_URL, user) }) after(async () => { @@ -75,14 +76,11 @@ describe('API Metrics Tests', () => describe('*getMetrics()', () => { it('should fetch metrics and return a 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( '/metrics?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(1) @@ -90,14 +88,11 @@ describe('API Metrics Tests', () => }) it('should fetch metrics broken down by channels and return a 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( '/metrics/channels?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(2) @@ -106,14 +101,11 @@ describe('API Metrics Tests', () => }) it('should fetch metrics for a particular channel and return a 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( '/metrics/channels/222222222222222222222222?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(1) @@ -121,14 +113,11 @@ describe('API Metrics Tests', () => }) it('should fetch metrics in timeseries and return a 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( '/metrics/timeseries/day?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(4) @@ -138,14 +127,11 @@ describe('API Metrics Tests', () => }) it('should fetch metrics broken down by channels and timeseries and return a 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( '/metrics/timeseries/day/channels?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(8) @@ -156,14 +142,11 @@ describe('API Metrics Tests', () => }) it('should fetch metrics for a particular channel broken down by timeseries and return a 200', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get( '/metrics/timeseries/day/channels/222222222222222222222222?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(4) @@ -175,14 +158,14 @@ describe('API Metrics Tests', () => }) it('should fetch metrics for only the channels that a user can view', async () => { - const res = await request(constants.BASE_URL) + const user = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + const res = await request(BASE_URL) .get( '/metrics?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', cookie) .expect(200) res.body.length.should.be.exactly(1) @@ -190,34 +173,25 @@ describe('API Metrics Tests', () => }) it("should return a 401 when a channel isn't found", async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get( '/metrics/channels/333333333333333333333333?startDate=2014-07-15T00:00:00.000Z&endDate=2014-07-19T00:00:00.000Z' ) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(401) }) it('should return a 400 when startDate is not provided', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/metrics?endDate=2014-07-19T00:00:00.000Z') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(400) }) it('should return a 400 when endDate is not provided', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/metrics?startDate=2014-07-15T00:00:00.000Z') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(400) }) }) diff --git a/test/integration/restartAPITests.js b/test/integration/restartAPITests.js index 1eaefeb6..693e0501 100644 --- a/test/integration/restartAPITests.js +++ b/test/integration/restartAPITests.js @@ -14,11 +14,9 @@ import * as testUtils from '../utils' import {ChannelModelAPI} from '../../src/model/channels' describe('API Integration Tests', () => { - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants describe('Restart REST Api testing', () => { - let authDetails = {} - const channel = new ChannelModelAPI({ name: 'TestChannel1', urlPattern: 'test/sample', @@ -42,9 +40,9 @@ describe('API Integration Tests', () => { before(async () => { await testUtils.cleanupTestUsers() await Promise.all([ - testUtils.setupTestUsers(), channel.save(), - promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + promisify(server.start)({apiPort: SERVER_PORTS.apiPort}), + testUtils.setupTestUsers() ]) }) @@ -56,20 +54,16 @@ describe('API Integration Tests', () => { ]) }) - beforeEach(() => { - authDetails = testUtils.getAuthDetails() - }) - describe('*restart()', () => { it('should successfully send API request to restart the server', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + const stub = await sinon.stub(server, 'startRestartServerTimeout') - await request(constants.BASE_URL) + await request(BASE_URL) .post('/restart') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', cookie) .send() .expect(200) @@ -77,15 +71,19 @@ describe('API Integration Tests', () => { }) it('should not allow non admin user to restart the server', async () => { - await request(constants.BASE_URL) + const user = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL) .post('/restart') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', cookie) .send() .expect(403) }) + + it('should return 401 for unauthenticated restarting the server', async () => { + await request(BASE_URL).post('/restart').expect(401) + }) }) }) }) diff --git a/test/integration/rolesAPITests.js b/test/integration/rolesAPITests.js index 23bec117..390c7528 100644 --- a/test/integration/rolesAPITests.js +++ b/test/integration/rolesAPITests.js @@ -11,7 +11,7 @@ import * as server from '../../src/server' import * as testUtils from '../utils' import {ChannelModel, ClientModel} from '../../src/model' -const {SERVER_PORTS} = constants +const {SERVER_PORTS, BASE_URL} = constants describe('API Integration Tests', () => { describe('Roles REST Api testing', () => { @@ -99,18 +99,19 @@ describe('API Integration Tests', () => { roles: ['clientOnlyRole'] } - let authDetails let channel1 let channel2 let client1 let client2 let client3 let client4 + let rootCookie = '' + let nonRootCookie = '' before(async () => { await Promise.all([ - testUtils.setupTestUsers(), - promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) + promisify(server.start)({apiPort: SERVER_PORTS.apiPort}), + testUtils.setupTestUsers() ]) }) @@ -134,7 +135,16 @@ describe('API Integration Tests', () => { client3 = result.shift() client4 = result.shift() - authDetails = testUtils.getAuthDetails() + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) after(async () => { @@ -153,12 +163,9 @@ describe('API Integration Tests', () => { describe('*getRoles()', () => { it('should fetch all roles and list linked channels', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(6) @@ -186,12 +193,9 @@ describe('API Integration Tests', () => { }) it('should fetch all roles and list linked clients', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(6) @@ -223,12 +227,9 @@ describe('API Integration Tests', () => { it('should fetch all roles if there are only linked clients', async () => { await ChannelModel.deleteMany({}) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(5) @@ -259,12 +260,9 @@ describe('API Integration Tests', () => { }) it('should not misinterpret a client as a role', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.exactly(6) @@ -273,24 +271,15 @@ describe('API Integration Tests', () => { }) it('should reject a request from a non root user', async () => { - request(constants.BASE_URL) - .get('/roles') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) - .expect(403) + request(BASE_URL).get('/roles').set('Cookie', nonRootCookie).expect(403) }) }) describe('*getRole()', () => { it('should get a role', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/roles/role2') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('name', 'role2') @@ -304,12 +293,9 @@ describe('API Integration Tests', () => { }) it('should get a role that is just linked to a client', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/roles/other-role') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('name', 'other-role') @@ -320,34 +306,25 @@ describe('API Integration Tests', () => { }) it('should respond with 404 Not Found if role does not exist', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/roles/nonexistent') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(404) }) it('should reject a request from a non root user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/roles/role1') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) describe('*addRole()', () => { it('should respond with 400 Bad Request if role already exists', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role1', channels: [{_id: `${channel2._id}`}] @@ -356,12 +333,9 @@ describe('API Integration Tests', () => { }) it('should respond with 400 Bad Request if role does not have a channel or client', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'newRole' }) @@ -373,12 +347,9 @@ describe('API Integration Tests', () => { }) it('should add a role', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role4', channels: [{_id: `${channel1._id}`}, {_id: `${channel2._id}`}] @@ -394,12 +365,9 @@ describe('API Integration Tests', () => { }) it('should add a role and update clients', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role4', channels: [{_id: `${channel1._id}`}, {_id: `${channel2._id}`}], @@ -415,12 +383,9 @@ describe('API Integration Tests', () => { }) it('should add a role and update channels specified with either _id or name', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role4', channels: [{_id: `${channel1._id}`}, {name: channel2.name}] @@ -435,12 +400,9 @@ describe('API Integration Tests', () => { }) it('should add a role and update clients specified with either _id or clientID', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role4', channels: [{_id: `${channel1._id}`}, {_id: `${channel2._id}`}], @@ -460,12 +422,9 @@ describe('API Integration Tests', () => { }) it('should respond with 400 Bad Request if name is not specified', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [{_id: `${channel1._id}`}, {_id: `${channel2._id}`}] }) @@ -473,12 +432,9 @@ describe('API Integration Tests', () => { }) it('should respond with 400 Bad Request if channels is empty', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role2', channels: [] @@ -487,12 +443,9 @@ describe('API Integration Tests', () => { }) it('should respond with 400 Bad Request if channels and clients are not specified', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role2' }) @@ -500,12 +453,9 @@ describe('API Integration Tests', () => { }) it('should reject a request from a non root user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ name: 'role4', channels: [{_id: `${channel1._id}`}] @@ -514,12 +464,9 @@ describe('API Integration Tests', () => { }) it('should add a role for clients', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role4', clients: [{_id: `${client1._id}`}, {_id: `${client2._id}`}] @@ -535,12 +482,9 @@ describe('API Integration Tests', () => { }) it('should reject a role that conflicts with a clientID', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/roles') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'client1', channels: [{_id: `${channel1._id}`}] @@ -551,12 +495,9 @@ describe('API Integration Tests', () => { describe('*updateRole()', () => { it("should respond with 404 Not Found if role doesn't exist", async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role4') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [{_id: `${channel1._id}`}] }) @@ -564,12 +505,9 @@ describe('API Integration Tests', () => { }) it('should respond with 400 if channels and clients is empty', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [], clients: [] @@ -578,12 +516,9 @@ describe('API Integration Tests', () => { }) it('should respond with 400 if clearing the channels will remove the role', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/channelOnlyRole') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [] }) @@ -591,12 +526,9 @@ describe('API Integration Tests', () => { }) it('should respond with 400 if clearing the clients will remove the role', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/clientOnlyRole') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ clients: [] }) @@ -604,12 +536,9 @@ describe('API Integration Tests', () => { }) it('should update a role (enable role1 on channel2 and remove from channel1)', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [{_id: `${channel2._id}`}] }) @@ -621,12 +550,9 @@ describe('API Integration Tests', () => { }) it('should update a role (enable role1 for client2 and client3 and disable for client1)', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ clients: [{_id: `${client2._id}`}, {_id: `${client3._id}`}] }) @@ -640,12 +566,9 @@ describe('API Integration Tests', () => { }) it('should update a role (enable role1 on both channel1 and channel2)', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [{_id: `${channel1._id}`}, {_id: `${channel2._id}`}] }) @@ -659,12 +582,9 @@ describe('API Integration Tests', () => { }) it('should remove a role from all channels that is an update of an empty channel array', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role2') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [] }) @@ -675,12 +595,9 @@ describe('API Integration Tests', () => { }) it('should not remove a role from clients if update contains empty channel array', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role2') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [] }) @@ -691,12 +608,9 @@ describe('API Integration Tests', () => { }) it('should update a role using channel name', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [{name: channel2.name}] }) @@ -709,12 +623,9 @@ describe('API Integration Tests', () => { }) it('should reject a request from a non root user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ channels: [{_id: `${channel2._id}`}] }) @@ -722,12 +633,9 @@ describe('API Integration Tests', () => { }) it('should rename a role', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'the-new-role-name' }) @@ -750,12 +658,9 @@ describe('API Integration Tests', () => { }) it('should reject a request to rename a role into an existing role name', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'role2' }) @@ -763,12 +668,9 @@ describe('API Integration Tests', () => { }) it('should reject a role that conflicts with a clientID', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role1') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ name: 'client1' }) @@ -778,12 +680,9 @@ describe('API Integration Tests', () => { describe('*deleteRole()', () => { it("should respond with 404 Not Found if role doesn't exist", async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/roles/role4') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ channels: [{_id: `${channel1._id}`}] }) @@ -791,12 +690,9 @@ describe('API Integration Tests', () => { }) it('should delete a role', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .delete('/roles/role2') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const channels = await ChannelModel.find({allow: {$in: ['role2']}}) @@ -807,12 +703,9 @@ describe('API Integration Tests', () => { }) it("should delete a role that's only linked to a client", async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .delete('/roles/other-role') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const clients = await ClientModel.find({ @@ -822,12 +715,9 @@ describe('API Integration Tests', () => { }) it('should reject a request from a non root user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .delete('/roles/role2') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) diff --git a/test/integration/tasksAPITests.js b/test/integration/tasksAPITests.js index 0555a37a..91bcbf58 100644 --- a/test/integration/tasksAPITests.js +++ b/test/integration/tasksAPITests.js @@ -17,7 +17,7 @@ import {TransactionModelAPI} from '../../src/model/transactions' const {ObjectId} = Types describe('API Integration Tests', () => { - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants describe('Tasks REST Api testing', () => { const task1 = new TaskModelAPI({ @@ -282,7 +282,8 @@ describe('API Integration Tests', () => { } }) - let authDetails = {} + let rootCookie = '', + nonRootCookie = '' before(async () => { await TaskModelAPI.deleteMany({}) @@ -303,6 +304,19 @@ describe('API Integration Tests', () => { await promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) }) + beforeEach(async () => { + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) + }) + after(async () => { await promisify(server.stop)() await testUtils.cleanupTestUsers() @@ -318,10 +332,6 @@ describe('API Integration Tests', () => { } }) - beforeEach(() => { - authDetails = testUtils.getAuthDetails() - }) - describe('*getTasks()', () => { it('should fetch all tasks', async () => { const obj = { @@ -342,12 +352,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/tasks?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.eql(3) @@ -374,12 +381,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/tasks?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.be.eql(1) @@ -396,12 +400,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTask) .expect(201) @@ -434,12 +435,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(newTask) .expect(201) @@ -471,12 +469,9 @@ describe('API Integration Tests', () => { ] const newTask = {tids} - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTask) .expect(201) @@ -516,14 +511,13 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(newTask) .expect(403) + + await request(BASE_URL).post('/tasks').send(newTask).expect(401) }) it('should NOT add a new task if there are transactions linked to disabled channels', async () => { @@ -536,12 +530,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTask) .expect(400) }) @@ -556,12 +547,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTask) .expect(400) }) @@ -576,12 +564,9 @@ describe('API Integration Tests', () => { paused: true } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTask) .expect(201) @@ -635,12 +620,9 @@ describe('API Integration Tests', () => { await retry2.save() await retry3.save() - await request(constants.BASE_URL) + await request(BASE_URL) .post('/tasks') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTask) .expect(201) const results = await AutoRetryModelAPI.find() @@ -672,12 +654,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/tasks/aaa908908bbb98cc1d0809ee?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('_id', 'aaa908908bbb98cc1d0809ee') @@ -704,12 +683,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/tasks/bbb777777bbb66cc5d4444ee?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('_id', 'bbb777777bbb66cc5d4444ee') @@ -757,12 +733,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/tasks/bbb777777bbb66cc5d4444ee?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('_id', 'bbb777777bbb66cc5d4444ee') @@ -817,12 +790,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/tasks/bbb777777bbb66cc5d4444ee?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.have.property('_id', 'bbb777777bbb66cc5d4444ee') @@ -838,12 +808,9 @@ describe('API Integration Tests', () => { completed: '2014-06-18T13:30:00.929Z' } - await request(constants.BASE_URL) + await request(BASE_URL) .put('/tasks/aaa777777bbb66cc5d4444ee') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) const task = await TaskModelAPI.findOne({ @@ -856,25 +823,24 @@ describe('API Integration Tests', () => { it('should not allow a non admin user to update a task', async () => { const updates = {} - request(constants.BASE_URL) + request(BASE_URL) .put('/tasks/890aaS0b93ccccc30dddddd0') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(updates) .expect(403) + + request(BASE_URL) + .put('/tasks/890aaS0b93ccccc30dddddd0') + .send(updates) + .expect(401) }) }) describe('*removeTask(taskId)', () => { it('should remove a specific task by ID', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/tasks/aaa777777bbb66cc5d4444ee') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const task = await TaskModelAPI.find({ @@ -884,13 +850,14 @@ describe('API Integration Tests', () => { }) it('should not only allow a non admin user to remove a task', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/tasks/890aaS0b93ccccc30dddddd0') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) + + await request(BASE_URL) + .del('/tasks/890aaS0b93ccccc30dddddd0') + .expect(401) }) }) }) diff --git a/test/integration/transactionsAPITests.js b/test/integration/transactionsAPITests.js index b8b2acd7..146c5fb0 100644 --- a/test/integration/transactionsAPITests.js +++ b/test/integration/transactionsAPITests.js @@ -15,7 +15,10 @@ import * as testUtils from '../utils' import {AutoRetryModelAPI} from '../../src/model/autoRetry' import {ChannelModel} from '../../src/model/channels' import {EventModelAPI} from '../../src/model/events' -import {TransactionModel, TransactionModelAPI} from '../../src/model/transactions' +import { + TransactionModel, + TransactionModelAPI +} from '../../src/model/transactions' import {config} from '../../src/config' import {TaskModel} from '../../src/model' @@ -42,7 +45,7 @@ const MAX_BODY_MB = 1 const MAX_BODY_SIZE = MAX_BODY_MB * 1024 * 1024 describe('API Integration Tests', () => { - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants const LARGE_BODY = Buffer.alloc(MAX_BODY_SIZE, '1234567890').toString() const requestDoc = { @@ -102,10 +105,11 @@ describe('API Integration Tests', () => { Object.freeze(transactionData) - let authDetails = {} let channel let channel2 let channel3 + let rootCookie = '' + let nonRootCookie = '' const channelDoc = { name: 'TestChannel1', @@ -202,7 +206,16 @@ describe('API Integration Tests', () => { }) beforeEach(async () => { - authDetails = testUtils.getAuthDetails() + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) afterEach(async () => { @@ -219,12 +232,9 @@ describe('API Integration Tests', () => { td.channelID = channel._id td.request.body = '' td.response.body = LARGE_BODY - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(td) .expect(201) @@ -240,12 +250,9 @@ describe('API Integration Tests', () => { const newTransactionData = Object.assign({}, transactionData, { channelID: channel._id }) - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTransactionData) .expect(201) @@ -276,12 +283,9 @@ describe('API Integration Tests', () => { const td = testUtils.clone(transactionData) td.channelID = channel._id td.request.body = LARGE_BODY - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(td) .expect(201) @@ -298,12 +302,9 @@ describe('API Integration Tests', () => { td.channelID = channel._id td.request.body = LARGE_BODY td.response.body = LARGE_BODY - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(td) .expect(201) @@ -324,12 +325,9 @@ describe('API Integration Tests', () => { td.routes[0].request.body = LARGE_BODY // When - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(td) .expect(201) @@ -351,12 +349,9 @@ describe('API Integration Tests', () => { td.routes[0].response.body = LARGE_BODY // When - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(td) .expect(201) @@ -378,12 +373,9 @@ describe('API Integration Tests', () => { td.orchestrations[0].request.body = LARGE_BODY // When - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(td) .expect(201) @@ -405,12 +397,9 @@ describe('API Integration Tests', () => { td.orchestrations[0].response.body = LARGE_BODY // When - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(td) .expect(201) @@ -426,12 +415,9 @@ describe('API Integration Tests', () => { }) it('should only allow admin users to add transactions', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(transactionData) .expect(403) }) @@ -440,12 +426,9 @@ describe('API Integration Tests', () => { const newTransactionData = Object.assign({}, transactionData, { channelID: channel._id }) - await request(constants.BASE_URL) + await request(BASE_URL) .post('/transactions') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(newTransactionData) .expect(201) @@ -510,12 +493,9 @@ describe('API Integration Tests', () => { } } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -558,12 +538,9 @@ describe('API Integration Tests', () => { clientID: '777777777777777777777777' } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -593,12 +570,9 @@ describe('API Integration Tests', () => { clientID: '777777777777777777777777' } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -642,12 +616,9 @@ describe('API Integration Tests', () => { } } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -677,12 +648,9 @@ describe('API Integration Tests', () => { } } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -714,12 +682,9 @@ describe('API Integration Tests', () => { } } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -753,12 +718,9 @@ describe('API Integration Tests', () => { ] } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(updates) .expect(200) @@ -783,12 +745,9 @@ describe('API Integration Tests', () => { transactionId = result._id const updates = {} - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/transactions/${transactionId}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(updates) .expect(403) }) @@ -799,12 +758,9 @@ describe('API Integration Tests', () => { const countBefore = await TransactionModel.countDocuments({}) countBefore.should.equal(0) await new TransactionModel(transactionData).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/transactions?filterPage=0&filterLimit=10&filters={}') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(countBefore + 1) @@ -836,12 +792,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) await new TransactionModel(transactionData).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(1) @@ -875,12 +828,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) await new TransactionModel(transactionData).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(1) }) @@ -913,12 +863,9 @@ describe('API Integration Tests', () => { params = encodeURI(params) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions?${params}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(0) @@ -935,12 +882,9 @@ describe('API Integration Tests', () => { _id: '111111111111111111111112' }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/transactions') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body.should.have.length(1) @@ -959,12 +903,9 @@ describe('API Integration Tests', () => { }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions?filters={"channelID":"${channel._id}"}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body.should.have.length(1) @@ -990,12 +931,9 @@ describe('API Integration Tests', () => { }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions?filterRepresentation=full`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body.should.have.length(2) @@ -1014,24 +952,18 @@ describe('API Integration Tests', () => { _id: '111111111111111111111112' }) ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .get(`/transactions?filters={"channelID":"${tx2.channelID}"}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('should truncate transaction details if filterRepresentation is fulltruncate ', async () => { await new TransactionModel(transactionData).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/transactions?filterRepresentation=fulltruncate') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.length.should.equal(1) @@ -1080,12 +1012,9 @@ describe('API Integration Tests', () => { } await new TransactionModel(transactionData).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/transactions?filterRepresentation=bulkrerun') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body.count.should.equal(1) @@ -1093,13 +1022,10 @@ describe('API Integration Tests', () => { it('should fail to fetch transactions (intenal server error)', async () => { const stub = sinon.stub(TransactionModelAPI, 'find') - stub.callsFake((() => Promise.reject())) - await request(constants.BASE_URL) + stub.callsFake(() => Promise.reject()) + await request(BASE_URL) .get('/transactions') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(500) stub.restore() }) @@ -1109,12 +1035,9 @@ describe('API Integration Tests', () => { it('should fetch a transaction by ID - admin user', async () => { const tx = await new TransactionModel(transactionData).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions/${tx._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) ;(res !== null).should.be.true @@ -1135,12 +1058,9 @@ describe('API Integration Tests', () => { Object.assign({}, transactionData, {channelID: channel2._id}) ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .get(`/transactions/${tx._id}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) @@ -1149,12 +1069,9 @@ describe('API Integration Tests', () => { Object.assign({}, transactionData, {channelID: channel._id}) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions/${tx._id}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) ;(res !== null).should.be.true @@ -1177,12 +1094,9 @@ describe('API Integration Tests', () => { Object.assign({}, transactionData, {channelID: channel._id}) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions/${tx._id}?filterRepresentation=fulltruncate`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.request.body.should.equal(` { clientID: '555555555555555555555556' }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post(`/bulkrerun`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ batchSize: 1, filters: {} @@ -1218,12 +1129,9 @@ describe('API Integration Tests', () => { ).save() await TaskModel.deleteMany({}) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post(`/bulkrerun`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send({ batchSize: 1, filters: {} @@ -1239,12 +1147,9 @@ describe('API Integration Tests', () => { }) it('should do bulk rerun for non-admin user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/bulkrerun') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ batchSize: 1, filters: {} @@ -1253,12 +1158,9 @@ describe('API Integration Tests', () => { }) it('should do bulk rerun on specific channel', async () => { - const res = await request(constants.BASE_URL) + await request(BASE_URL) .post('/bulkrerun') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ batchSize: 1, filters: { @@ -1269,12 +1171,9 @@ describe('API Integration Tests', () => { }) it('should fail to do bulk rerun on rescrticted channel', async () => { - const res = await request(constants.BASE_URL) + await request(BASE_URL) .post('/bulkrerun') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ batchSize: 1, filters: { @@ -1286,13 +1185,10 @@ describe('API Integration Tests', () => { it('should fail to do bulk rerun (intenal server error)', async () => { const stub = sinon.stub(TransactionModelAPI, 'count') - stub.callsFake((() => Promise.reject())) - const res = await request(constants.BASE_URL) + stub.callsFake(() => Promise.reject()) + await request(BASE_URL) .post('/bulkrerun') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send({ batchSize: 1, filters: {} @@ -1309,12 +1205,9 @@ describe('API Integration Tests', () => { clientID: '555555555555555555555555' }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions/clients/${tx.clientID}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body[0].clientID.should.equal(tx.clientID.toString()) }) @@ -1327,12 +1220,9 @@ describe('API Integration Tests', () => { }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions/clients/${tx.clientID}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body.should.have.length(0) }) @@ -1345,12 +1235,9 @@ describe('API Integration Tests', () => { }) ).save() - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/transactions/clients/${tx.clientID}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(200) res.body[0].clientID.should.equal(tx.clientID.toString()) @@ -1365,12 +1252,9 @@ describe('API Integration Tests', () => { }) ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/transactions/${tx._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const txFound = await TransactionModel.findById(tx._id) @@ -1384,12 +1268,9 @@ describe('API Integration Tests', () => { }) ).save() - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/transactions/${transactionId}`) - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) }) diff --git a/test/integration/usersAPITests.js b/test/integration/usersAPITests.js index 471b85c4..5a59fde2 100644 --- a/test/integration/usersAPITests.js +++ b/test/integration/usersAPITests.js @@ -12,12 +12,624 @@ import * as constants from '../constants' import * as contact from '../../src/contact' import * as server from '../../src/server' import * as testUtils from '../utils' -import {UserModelAPI} from '../../src/model/users' +import {UserModelAPI, createUser, updateTokenUser} from '../../src/model/users' +import {PassportModelAPI} from '../../src/model' +import {config} from '../../src/config' describe('API Integration Tests', () => { - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants describe('Users REST Api testing', () => { + const user1 = { + firstname: 'Ryan', + surname: 'Chrichton', + email: 'r..@jembi.org', + password: 'password', + groups: ['admin', 'RHIE'] + } + + const user2 = { + firstname: 'Bill', + surname: 'Murray', + email: 'bfm@crazy.net', + password: 'password', + groups: ['HISP'] + } + + let newUser = { + firstname: 'Jane', + surname: 'Doe', + email: 'jane@doe.net', + token: 'l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM', + tokenType: 'newUser', + password: 'password', + locked: true, + expiry: moment().add(2, 'days').utc().format(), + groups: ['HISP'] + } + + const newUserExpired = { + firstname: 'John', + surname: 'Smith', + email: 'john@smith.net', + token: 'hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg', + tokenType: 'newUser', + password: 'password', + locked: true, + expiry: moment().subtract(2, 'days').utc().format(), + groups: ['HISP'] + } + + before(async () => { + config.api.maxAge = 1000 + + await Promise.all([ + promisify(server.start)({apiPort: SERVER_PORTS.apiPort}), + testUtils.setupTestUsers(), + createUser(user1), + createUser(user2), + createUser(newUser), + createUser(newUserExpired) + ]) + }) + + after(async () => { + await Promise.all([ + UserModelAPI.deleteMany({}), + testUtils.cleanupTestUsers(), + server.stop() + ]) + }) + + describe('*authenticate', () => { + it('should return cookies', async () => { + const _user1 = {email: user1.email, password: user1.password} + const cookie1 = await testUtils.authenticate(request, BASE_URL, _user1) + + cookie1.should.not.be.empty() + + const _user2 = {email: user2.email, password: user2.password} + const cookie2 = await testUtils.authenticate(request, BASE_URL, _user2) + + cookie2.should.not.be.empty() + }) + + it('should return user when authenticated with local auth and requesting me', async () => { + const user = {email: user1.email, password: user1.password} + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + const res = await request(BASE_URL) + .get('/me') + .set('Cookie', cookie) + .expect(200) + + res.body.should.have.property('user') + res.body.user.should.have.property('firstname', user1.firstname) + res.body.user.should.have.property('surname', user1.surname) + res.body.user.should.have.property('email', user1.email) + res.body.user.should.have.property('groups', user1.groups) + res.body.user.should.not.have.property('password') + }) + + it('should return 404 when unauthenticated and requesting me', async () => { + const res = await request(BASE_URL).get('/me').expect(404) + + res.text.should.be.equal('Not authenticated') + }) + + it('should return 404 when cookies are expired and requesting me', async () => { + const user = {email: user1.email, password: user1.password} + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await new Promise(resolve => setTimeout(resolve, 1000)) + + const res = await request(BASE_URL) + .get('/me') + .set('Cookie', cookie) + .expect(404) + + res.text.should.be.equal('Not authenticated') + }) + }) + + describe('*logout', () => { + it('should logout and remove the session', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL).get('/logout').set('Cookie', cookie).expect(200) + + await request(BASE_URL).get('/me').set('Cookie', cookie).expect(404) + + await request(BASE_URL) + .get('/transactions') + .set('Cookie', cookie) + .expect(401) + }) + }) + + describe('*userPasswordResetRequest(email)', () => { + it('should return 403 when requesting root@openhim.org password reset', async () => { + await request(BASE_URL) + .get('/password-reset-request/root@openhim.org') + .expect(403) + }) + + it('should update the user with a token and send reset email', async () => { + const stubContact = await sinon.stub(contact, 'sendEmail') + await stubContact.yields(null) + + await request(BASE_URL) + .get('/password-reset-request/r..@jembi.org') + .expect(201) + + const user = await UserModelAPI.findOne({email: 'r..@jembi.org'}) + user.should.have.property('firstname', 'Ryan') + user.should.have.property('surname', 'Chrichton') + user.should.have.property('token') + user.should.have.property('tokenType', 'existingUser') + user.should.have.property('expiry') + await stubContact.restore() + }) + + it('should find user regardless of case and send reset email', async () => { + const stubContact = await sinon.stub(contact, 'sendEmail') + await stubContact.yields(null) + + await request(BASE_URL) + .get('/password-reset-request/R..@jembi.org') + .expect(201) + + const user = await UserModelAPI.findOne({email: user1.email}) + user.should.have.property('firstname', 'Ryan') + user.email.should.eql('r..@jembi.org') + await stubContact.restore() + }) + + it('should update the user with a token get a 500 error when nodemailer fails', async () => { + const stubContact = await sinon.stub(contact, 'sendEmail') + + await stubContact.yields('An error occurred trying to send the email.') + + await request(BASE_URL) + .get('/password-reset-request/r..@jembi.org') + .expect(500) + + await stubContact.restore() + }) + + it('should return a not found error', async () => { + await request(BASE_URL) + .get('/password-reset-request/test@jembi.org') + .expect(404) + }) + }) + + describe('*getUserByToken(token)', () => { + it('should return a users details (basic details)', async () => { + const res = await request(BASE_URL) + .get('/token/l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM') + .expect(200) + + res.body.email.should.eql('jane@doe.net') + res.body.firstname.should.eql('Jane') + res.body.surname.should.eql('Doe') + res.body.token.should.eql('l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM') + res.body.tokenType.should.eql('newUser') + res.body.locked.should.eql(true) + + should.exist(res.body.expiry) + should.not.exist(res.body.password) + should.not.exist(res.body.groups) + }) + + it('should return a not found error', async () => { + const token = 'hSas987asdS7y9vqqKJHDSoARXtA098g' + + const res = await request(BASE_URL).get(`/token/${token}`).expect(404) + + res.text.should.be.equal(`User with token ${token} could not be found.`) + }) + + it('should return a expired token error', async () => { + await request(BASE_URL) + .get('/token/hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg') + .expect(410) + }) + }) + + describe('*updateUserByToken(token)', () => { + it('should update a user by the supplied token', async () => { + const updates = { + firstname: 'Jane Sally', + surname: 'Doe', + msisdn: '27123456789', + password: 'password-updated' + } + + await request(BASE_URL) + .put('/token/l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM') + .send(updates) + .expect(200) + + const user = await UserModelAPI.findOne({email: 'jane@doe.net'}) + + user.should.have.property('firstname', 'Jane Sally') + user.should.have.property('surname', 'Doe') + user.should.have.property('token', null) + user.should.have.property('tokenType', null) + user.should.have.property('locked', false) + user.should.have.property('expiry', null) + + const passport = await PassportModelAPI.findOne({user: user.id}) + + passport.should.have.property('password') + }) + + it('should prevent an update with an expired token (expired token)', async () => { + const updates = { + firstname: 'Peter', + surname: 'smith', + msisdn: '27123456789', + password: 'password-updated' + } + + await request(BASE_URL) + .put('/token/hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg') + .send(updates) + .expect(410) + }) + + it('should return a not found error', async () => { + const updates = {} + const token = 'hSas987asdS7y9vqqKJHDSoARXtA098g' + + const res = await request(BASE_URL) + .put(`/token/${token}`) + .send(updates) + .expect(404) + + res.text.should.be.equal(`User with token ${token} could not be found.`) + }) + }) + + describe('*getUsers()', () => { + it('should fetch all users', async () => { + const user = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + const res = await request(BASE_URL) + .get('/users') + .set('Cookie', cookie) + .expect(200) + + // user1, user2, newUser, newUserExpired, + the 2 API test users and the root user + res.body.length.should.be.eql(7) + }) + + it('should not allow non admin user to fetch all users', async () => { + const user = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, user) + + await request(BASE_URL).get('/users').set('Cookie', cookie).expect(403) + }) + }) + + describe('*addUser()', () => { + it('should add a new user', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + newUser = { + firstname: 'Bill', + surname: 'Newman', + email: 'bill@newman.com', + password: 'password', + groups: ['HISP'] + } + + await request(BASE_URL) + .post('/users') + .set('Cookie', cookie) + .send(newUser) + .expect(201) + + const user = await UserModelAPI.findOne({email: 'bill@newman.com'}) + + user.should.have.property('firstname', 'Bill') + user.should.have.property('surname', 'Newman') + user.groups.should.have.length(1) + user.should.have.property('token') + user.should.have.property('tokenType', 'newUser') + user.should.have.property('locked', true) + user.should.have.property('expiry') + }) + + it('should save new users username in lowercase only', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + newUser = { + firstname: 'Matome', + surname: 'Phoshoko', + email: 'MATOME.Phoshoko@jembi.org', + password: 'password', + groups: ['HISP'] + } + + await request(BASE_URL) + .post('/users') + .send(newUser) + .set('Cookie', cookie) + .expect(201) + + const user = await UserModelAPI.findOne({ + email: 'matome.phoshoko@jembi.org' + }) + user.email.should.eql('matome.phoshoko@jembi.org') + }) + + it('should not allow a non admin user to add a user', async () => { + const authUser = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + newUser = {} + + await request(BASE_URL) + .post('/users') + .set('Cookie', cookie) + .send(newUser) + .expect(403) + + await request(BASE_URL).post('/users').send(newUser).expect(401) + }) + }) + + describe('*findUserByUsername(email)', () => { + it('should find a user by their email address', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const res = await request(BASE_URL) + .get('/users/r..@jembi.org') + .set('Cookie', cookie) + .expect(200) + + res.body.should.have.property('surname', 'Chrichton') + res.body.should.have.property('email', 'r..@jembi.org') + res.body.groups.should.have.length(2) + }) + + it('should not allow a non admin user to find a user to email', async () => { + const authUser = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + await request(BASE_URL) + .get('/users/r..@jembi.org') + .set('Cookie', cookie) + .expect(403) + + await request(BASE_URL).get('/users/r..@jembi.org').expect(401) + }) + + it('should always allow a user to fetch their own details', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const res = await request(BASE_URL) + .get(`/users/${testUtils.nonRootUser.email}`) + .set('Cookie', cookie) + .expect(200) + + res.body.should.have.property('firstname', 'Non') + res.body.should.have.property('surname', 'Root') + res.body.should.have.property('email', 'nonroot@jembi.org') + res.body.groups.should.have.length(2) + }) + + it(`should find a user regardless of email case`, async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const res = await request(BASE_URL) + .get(`/users/${user1.email.toUpperCase()}`) + .set('Cookie', cookie) + .expect(200) + + res.body.should.have.property('email', user1.email) + }) + + it(`should return 404 when user is not found`, async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const res = await request(BASE_URL) + .get(`/users/unexistent@user.org`) + .set('Cookie', cookie) + .expect(404) + + res.text.should.be.equal( + 'User with email unexistent@user.org could not be found.' + ) + }) + }) + + describe('*updateUser(email)', () => { + it('should update a specific user by email', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const updates = { + _id: 'thisShouldBeIgnored', + surname: 'Crichton', + email: 'rg..@jembi.org', + groups: ['admin', 'RHIE', 'HISP'], + password: 'new-password' + } + + await request(BASE_URL) + .put('/users/r..@jembi.org') + .set('Cookie', cookie) + .send(updates) + .expect(200) + + const user = await UserModelAPI.findOne({email: 'rg..@jembi.org'}) + user.should.have.property('surname', 'Crichton') + user.should.have.property('email', 'rg..@jembi.org') + user.should.have.property('token', null) + user.should.have.property('tokenType', null) + user.should.have.property('locked', false) + user.should.have.property('expiry', null) + user.groups.should.have.length(3) + }) + + it('should update a specific user regardless of email case', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const updates = { + _id: 'thisShouldBeIgnored', + surname: 'Crichton', + email: 'r..@jembi.org', + groups: ['admin', 'RHIE', 'HISP'] + } + + await request(BASE_URL) + .put('/users/RG..@jembi.org') + .set('Cookie', cookie) + .send(updates) + .expect(200) + + const user = await UserModelAPI.findOne({email: 'r..@jembi.org'}) + user.should.have.property('email', updates.email) + }) + + it('should return a not found error', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const updates = {} + + await request(BASE_URL) + .put('/users/doesnt-exist@test.com') + .set('Cookie', cookie) + .send(updates) + .expect(404) + }) + + it('should not allow non admin users to update a user', async () => { + const authUser = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const updates = {} + + await request(BASE_URL) + .put('/users/r..@jembi.org') + .set('Cookie', cookie) + .send(updates) + .expect(403) + + await request(BASE_URL) + .put('/users/r..@jembi.org') + .send(updates) + .expect(401) + }) + + it('should always allow a user to update their own details', async () => { + const authUser = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const updates = { + _id: 'thisShouldBeIgnored', + surname: 'Root-updated' + } + + await request(BASE_URL) + .put(`/users/${testUtils.nonRootUser.email}`) + .set('Cookie', cookie) + .send(updates) + .expect(200) + + const user = await UserModelAPI.findOne({ + email: testUtils.nonRootUser.email + }) + user.should.have.property('surname', 'Root-updated') + }) + + it('should NOT allow a non-admin user to update their groups', async () => { + const authUser = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + const updates = { + _id: 'thisShouldBeIgnored', + groups: ['admin'] + } + await request(BASE_URL) + .put(`/users/${testUtils.nonRootUser.email}`) + .set('Cookie', cookie) + .send(updates) + .expect(200) + + const user = await UserModelAPI.findOne({ + email: testUtils.nonRootUser.email + }) + user.groups.should.be.length(2) + user.groups.should.not.containEql('admin') + }) + }) + + describe('*removeUser(email)', () => { + it('should remove a specific user by email', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + await request(BASE_URL) + .del('/users/bfm@crazy.net') + .set('Cookie', cookie) + .expect(200) + + const users = await UserModelAPI.find({name: 'bfm@crazy.net'}) + users.should.have.length(0) + }) + + it('should find and remove specific user by case insensitive email', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + await request(BASE_URL) + .del('/users/BMF@crazy.Net') + .set('Cookie', cookie) + .expect(200) + + const users = await UserModelAPI.find({name: user2.email}) + users.should.have.length(0) + }) + + it('should not allow a non admin user to remove a user', async () => { + const authUser = testUtils.nonRootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + await request(BASE_URL) + .del('/users/bfm@crazy.net') + .set('Cookie', cookie) + .expect(403) + + await request(BASE_URL).del('/users/bfm@crazy.net').expect(401) + }) + + it('should not be able to remove the root user', async () => { + const authUser = testUtils.rootUser + const cookie = await testUtils.authenticate(request, BASE_URL, authUser) + + await request(BASE_URL) + .del('/users/root@openhim.org') + .set('Cookie', cookie) + .expect(403) + }) + }) + }) + + describe('Users REST Api testing (token auth)', () => { const user1 = new UserModelAPI({ firstname: 'Ryan', surname: 'Chrichton', @@ -64,18 +676,24 @@ describe('API Integration Tests', () => { before(async () => { await Promise.all([ - user1.save(), - user2.save(), newUser.save(), newUserExpired.save(), - testUtils.setupTestUsers(), + testUtils.setupTestUsersWithToken(), promisify(server.start)({apiPort: SERVER_PORTS.apiPort}) ]) + + const user1Res = await user1.save() + const user2Res = await user2.save() + + // Create token passport for these users + await updateTokenUser({id: user1Res._id, ...user1._doc}) + await updateTokenUser({id: user2Res._id, ...user2._doc}) }) after(async () => { await Promise.all([ UserModelAPI.deleteMany({}), + PassportModelAPI.deleteMany({}), testUtils.cleanupTestUsers(), server.stop() ]) @@ -87,35 +705,47 @@ describe('API Integration Tests', () => { describe('*authenticate(email)', () => { it('should return the requested users salt', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/authenticate/bfm@crazy.net') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) .expect(200) res.body.salt.should.eql('22a61686-66f6-483c-a524-185aac251fb0') should.exist(res.body.ts) }) - }) - it('should return the requested case insensitive users salt', async () => { - const res = await request(constants.BASE_URL) - .get('/authenticate/R..@jembi.org') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) - .expect(200) - - res.body.salt.should.eql('bf93caba-6eec-4c0c-a1a3-d968a7533fd7') - should.exist(res.body.ts) + it('should return the requested case insensitive users salt', async () => { + const res = await request(BASE_URL) + .get('/authenticate/R..@jembi.org') + .expect(200) + + res.body.salt.should.eql('bf93caba-6eec-4c0c-a1a3-d968a7533fd7') + should.exist(res.body.ts) + }) + + it('should return 404 if user not found', async () => { + const res = await request(BASE_URL) + .get('/authenticate/unexisten-user@test.org') + .expect(404) + + res.text.should.eql( + `Could not find user by email unexisten-user@test.org` + ) + }) + + it('should return 404 if passport not found', async () => { + const res = await request(BASE_URL) + .get(`/authenticate/${newUser.email}`) + .expect(404) + + res.text.should.eql( + `Could not find token passport for user ${newUser.email}` + ) + }) }) describe('*userPasswordResetRequest(email)', () => { it('should return 403 when requesting root@openhim.org password reset', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/password-reset-request/root@openhim.org') .expect(403) }) @@ -124,7 +754,7 @@ describe('API Integration Tests', () => { const stubContact = await sinon.stub(contact, 'sendEmail') await stubContact.yields(null) - await request(constants.BASE_URL) + await request(BASE_URL) .get('/password-reset-request/r..@jembi.org') .expect(201) @@ -141,7 +771,7 @@ describe('API Integration Tests', () => { const stubContact = await sinon.stub(contact, 'sendEmail') await stubContact.yields(null) - await request(constants.BASE_URL) + await request(BASE_URL) .get('/password-reset-request/R..@jembi.org') .expect(201) @@ -156,7 +786,7 @@ describe('API Integration Tests', () => { await stubContact.yields('An error occurred trying to send the email.') - await request(constants.BASE_URL) + await request(BASE_URL) .get('/password-reset-request/r..@jembi.org') .expect(500) @@ -164,7 +794,7 @@ describe('API Integration Tests', () => { }) it('should return a not found error', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/password-reset-request/test@jembi.org') .expect(404) }) @@ -172,7 +802,7 @@ describe('API Integration Tests', () => { describe('*getUserByToken(token)', () => { it('should return a users details (basic details)', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/token/l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM') .expect(200) @@ -191,13 +821,13 @@ describe('API Integration Tests', () => { }) it('should return a not found error', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/token/hSas987asdS7y9vqqKJHDSoARXtA098g') .expect(404) }) it('should return a expired token error', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/token/hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg') .expect(410) }) @@ -214,27 +844,39 @@ describe('API Integration Tests', () => { passwordSalt: 'eca7205c-2129-4558-85da-45845d17bd5f' } - await request(constants.BASE_URL) + await request(BASE_URL) .put('/token/l9Q87x4b0OXHM9eaUBHIv59co5NZG1bM') .send(updates) .expect(200) - const user = await UserModelAPI.findOne({email: 'jane@doe.net'}) + const {_doc: user} = await UserModelAPI.findOne({email: 'jane@doe.net'}) user.should.have.property('firstname', 'Jane Sally') user.should.have.property('surname', 'Doe') - user.should.have.property( + ;(!user.passwordHash).should.be.true() + ;(!user.passwordSalt).should.be.true() + ;(!user.passwordAlgorithm).should.be.true() + user.should.have.property('provider', 'token') + user.should.have.property('token', null) + user.should.have.property('tokenType', null) + user.should.have.property('locked', false) + user.should.have.property('expiry', null) + + const passport = await PassportModelAPI.findOne({ + user: user._id, + protocol: 'token' + }) + + passport.should.have.property('protocol', 'token') + passport.should.have.property('passwordAlgorithm', 'sha256') + passport.should.have.property( 'passwordHash', 'af200ab5-4227-4840-97d1-92ba91206499' ) - user.should.have.property( + passport.should.have.property( 'passwordSalt', 'eca7205c-2129-4558-85da-45845d17bd5f' ) - user.should.have.property('token', null) - user.should.have.property('tokenType', null) - user.should.have.property('locked', false) - user.should.have.property('expiry', null) }) it('should prevent an update with an expired token (expired token)', async () => { @@ -247,7 +889,7 @@ describe('API Integration Tests', () => { passwordSalt: 'eca7205c-2129-4558-85da-45845d17bd5f' } - await request(constants.BASE_URL) + await request(BASE_URL) .put('/token/hS40KZItS7y9vqqEGhE6ARXtAA3wNhCg') .send(updates) .expect(410) @@ -256,7 +898,7 @@ describe('API Integration Tests', () => { describe('*getUsers()', () => { it('should fetch all users', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/users') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -269,7 +911,7 @@ describe('API Integration Tests', () => { }) it('should not allow non admin user to fetch all users', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/users') .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) @@ -291,7 +933,7 @@ describe('API Integration Tests', () => { groups: ['HISP'] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/users') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -322,7 +964,7 @@ describe('API Integration Tests', () => { groups: ['HISP'] } - await request(constants.BASE_URL) + await request(BASE_URL) .post('/users') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -340,7 +982,7 @@ describe('API Integration Tests', () => { it('should not allow a non admin user to add a user', async () => { newUser = {} - await request(constants.BASE_URL) + await request(BASE_URL) .post('/users') .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) @@ -353,7 +995,7 @@ describe('API Integration Tests', () => { describe('*findUserByUsername(email)', () => { it('should find a user by their email address', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/users/r..@jembi.org') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -367,7 +1009,7 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user to find a user to email', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/users/r..@jembi.org') .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) @@ -377,7 +1019,7 @@ describe('API Integration Tests', () => { }) it('should always allow a user to fetch their own details', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/users/${testUtils.nonRootUser.email}`) .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) @@ -392,7 +1034,7 @@ describe('API Integration Tests', () => { }) it(`should find a user regardless of email case`, async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/users/${user1.email.toUpperCase()}`) .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -402,6 +1044,20 @@ describe('API Integration Tests', () => { res.body.should.have.property('email', user1.email) }) + + it('should return 404 when no user is found', async () => { + const res = await request(BASE_URL) + .get('/users/unexistent@user.org') + .set('auth-username', testUtils.rootUser.email) + .set('auth-ts', authDetails.authTS) + .set('auth-salt', authDetails.authSalt) + .set('auth-token', authDetails.authToken) + .expect(404) + + res.text.should.be.equal( + 'User with email unexistent@user.org could not be found.' + ) + }) }) describe('*updateUser(email)', () => { @@ -410,10 +1066,13 @@ describe('API Integration Tests', () => { _id: 'thisShouldBeIgnored', surname: 'Crichton', email: 'rg..@jembi.org', - groups: ['admin', 'RHIE', 'HISP'] + groups: ['admin', 'RHIE', 'HISP'], + passwordAlgorithm: 'md5', + passwordHash: '3cc90918-7044-4e55-b61d-92ae73cb261e', + passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0' } - await request(constants.BASE_URL) + await request(BASE_URL) .put('/users/r..@jembi.org') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -426,18 +1085,30 @@ describe('API Integration Tests', () => { user.should.have.property('surname', 'Crichton') user.should.have.property('email', 'rg..@jembi.org') user.groups.should.have.length(3) + + const passport = await PassportModelAPI.findOne({ + user: user.id, + protocol: 'token' + }) + + passport.should.have.property( + 'passwordAlgorithm', + updates.passwordAlgorithm + ) + passport.should.have.property('passwordHash', updates.passwordHash) + passport.should.have.property('passwordSalt', updates.passwordSalt) }) it('should update a specific user regardless of email case', async () => { const updates = { _id: 'thisShouldBeIgnored', surname: 'Crichton', - email: 'rg..@jembi.org', + email: 'r..@jembi.org', groups: ['admin', 'RHIE', 'HISP'] } - await request(constants.BASE_URL) - .put('/users/R..@jembi.org') + await request(BASE_URL) + .put('/users/RG..@jembi.org') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) .set('auth-salt', authDetails.authSalt) @@ -445,14 +1116,14 @@ describe('API Integration Tests', () => { .send(updates) .expect(200) - const user = await UserModelAPI.findOne({email: 'rg..@jembi.org'}) + const user = await UserModelAPI.findOne({email: 'r..@jembi.org'}) user.should.have.property('email', updates.email) }) it('should not allow non admin users to update a user', async () => { const updates = {} - await request(constants.BASE_URL) + await request(BASE_URL) .put('/users/r..@jembi.org') .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) @@ -468,7 +1139,7 @@ describe('API Integration Tests', () => { surname: 'Root-updated' } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/users/${testUtils.nonRootUser.email}`) .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) @@ -488,7 +1159,7 @@ describe('API Integration Tests', () => { _id: 'thisShouldBeIgnored', groups: ['admin'] } - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/users/${testUtils.nonRootUser.email}`) .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) @@ -507,7 +1178,7 @@ describe('API Integration Tests', () => { describe('*removeUser(email)', () => { it('should remove a specific user by email', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/users/bfm@crazy.net') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -520,7 +1191,7 @@ describe('API Integration Tests', () => { }) it('should find and remove specific user by case insensitive email', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/users/BMF@crazy.Net') .set('auth-username', testUtils.rootUser.email) .set('auth-ts', authDetails.authTS) @@ -533,7 +1204,7 @@ describe('API Integration Tests', () => { }) it('should not allow a non admin user to remove a user', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .del('/users/bfm@crazy.net') .set('auth-username', testUtils.nonRootUser.email) .set('auth-ts', authDetails.authTS) diff --git a/test/integration/visualizersAPITests.js b/test/integration/visualizersAPITests.js index e71b38fd..30e2816a 100644 --- a/test/integration/visualizersAPITests.js +++ b/test/integration/visualizersAPITests.js @@ -11,7 +11,7 @@ import * as testUtils from '../utils' import {VisualizerModelAPI} from '../../src/model/visualizer' describe('API Integration Tests', () => { - const {SERVER_PORTS} = constants + const {SERVER_PORTS, BASE_URL} = constants describe('Visualizers REST API testing', () => { const visObj = { @@ -72,7 +72,8 @@ describe('API Integration Tests', () => { ] } - let authDetails = {} + let rootCookie = '', + nonRootCookie = '' before(async () => { await Promise.all([ @@ -89,8 +90,17 @@ describe('API Integration Tests', () => { ]) }) - beforeEach(() => { - authDetails = testUtils.getAuthDetails() + beforeEach(async () => { + rootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.rootUser + ) + nonRootCookie = await testUtils.authenticate( + request, + BASE_URL, + testUtils.nonRootUser + ) }) afterEach(() => VisualizerModelAPI.deleteMany({})) @@ -107,12 +117,9 @@ describe('API Integration Tests', () => { await Promise.all([vis1.save(), vis2.save()]) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/visualizers') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.be.an.Array() @@ -123,22 +130,16 @@ describe('API Integration Tests', () => { }) it('should return a 403 response if the user is not an admin', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/visualizers') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('should return an empty array if there are no visualizers', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/visualizers') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.be.an.Array() @@ -158,12 +159,9 @@ describe('API Integration Tests', () => { await Promise.all([vis1.save(), vis2.save()]) - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get(`/visualizers/${vis1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) res.body.should.be.an.Object() @@ -171,22 +169,16 @@ describe('API Integration Tests', () => { }) it('should return a 403 response if the user is not an admin', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .get('/visualizers/111111111111111111111111') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) it('should return 404 with message if no visualizers match the _id', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .get('/visualizers/111111111111111111111111') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(404) res.text.should.equal( @@ -197,12 +189,9 @@ describe('API Integration Tests', () => { describe('*addVisualizer()', () => { it('should add a visualizer and return a 201 response', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/visualizers') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(Object.assign({}, visObj)) .expect(201) @@ -210,23 +199,17 @@ describe('API Integration Tests', () => { }) it('should return a 403 response if the user is not an admin', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .post('/visualizers') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(Object.assign({}, visObj)) .expect(403) }) it('should return 404 if no request object is sent', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .post('/visualizers') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send() .expect(404) @@ -246,12 +229,9 @@ describe('API Integration Tests', () => { vis1.save() - await request(constants.BASE_URL) + await request(BASE_URL) .put(`/visualizers/${vis1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(visUpdate) .expect(200) @@ -262,23 +242,17 @@ describe('API Integration Tests', () => { }) it('should return a 403 response if the user is not an admin', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .put('/visualizers/111111111111111111111111') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .send(Object.assign({}, visObj)) .expect(403) }) it('should return 404 if no request object is sent', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .put('/visualizers/111111111111111111111111') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send() .expect(404) res.text.should.equal( @@ -287,12 +261,9 @@ describe('API Integration Tests', () => { }) it('should return 404 if no visualizers match the _id', async () => { - const res = await request(constants.BASE_URL) + const res = await request(BASE_URL) .put('/visualizers/111111111111111111111111') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .send(Object.assign({}, visObj)) .expect(404) res.text.should.equal( @@ -313,34 +284,25 @@ describe('API Integration Tests', () => { await Promise.all([vis1.save(), vis2.save()]) - await request(constants.BASE_URL) + await request(BASE_URL) .del(`/visualizers/${vis1._id}`) - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(200) const visualizers = await VisualizerModelAPI.find() visualizers.length.should.be.exactly(1) }) it('should return a 403 response if the user is not an admin', async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .delete('/visualizers/111111111111111111111111') - .set('auth-username', testUtils.nonRootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', nonRootCookie) .expect(403) }) return it("should return a 404 when the visualizer doesn't exist", async () => { - await request(constants.BASE_URL) + await request(BASE_URL) .delete('/visualizers/111111111111111111111111') - .set('auth-username', testUtils.rootUser.email) - .set('auth-ts', authDetails.authTS) - .set('auth-salt', authDetails.authSalt) - .set('auth-token', authDetails.authToken) + .set('Cookie', rootCookie) .expect(404) }) }) diff --git a/test/unit/basicAuthenticationTest.js b/test/unit/basicAuthenticationTest.js index 48d27ddc..d42a8f7c 100644 --- a/test/unit/basicAuthenticationTest.js +++ b/test/unit/basicAuthenticationTest.js @@ -50,7 +50,7 @@ describe('Basic Auth', () => { it('ctx.authenticated should not exist', done => { const ctx = buildEmptyCtx() basicAuthentication.authenticateUser(ctx, () => { - ;({}.should.not.equal(ctx.authenticated)) + ;({}).should.not.equal(ctx.authenticated) return done() }) })) @@ -59,7 +59,7 @@ describe('Basic Auth', () => { it('ctx.authenticated should not exist', done => { const ctx = buildCtx('incorrect_user', 'incorrect_password') basicAuthentication.authenticateUser(ctx, () => { - ;({}.should.not.equal(ctx.authenticated)) + ;({}).should.not.equal(ctx.authenticated) return done() }) })) diff --git a/test/unit/passportTest.js b/test/unit/passportTest.js new file mode 100644 index 00000000..ca20312e --- /dev/null +++ b/test/unit/passportTest.js @@ -0,0 +1,86 @@ +'use strict' + +/* eslint-env mocha */ +/* eslint no-unused-expressions:0 */ + +import should from 'should' + +import * as model from '../../src/model' + +describe('PassportModel tests', () => { + let userId + + const user = new model.UserModelAPI({ + firstname: 'Bill', + surname: 'Murray', + email: 'bfm@crazy.net', + groups: ['HISP', 'group2'] + }) + + before(async () => { + const res = await user.save() + userId = res.id + }) + + after(async () => { + await model.UserModelAPI.deleteMany({}) + }) + + describe('.createPassport()', () => { + it('should create a new password', async () => { + const {error, user} = await model.createPassport({id: userId}, 'password') + + should.equal(error, null) + user.should.have.property('id', userId) + + const passportResult = await model.PassportModelAPI.findOne({ + user: userId + }) + + passportResult.should.have.property('password') + }) + + it('should return error for non existent user', async () => { + const {error, user} = await model.createPassport( + {id: 'non_existent_id'}, + 'password' + ) + + should.equal(user, null) + error.should.have.property('message') + }) + }) + + describe('.updatePassport()', () => { + it('should update passport of a user', async () => { + const passportResult = await model.PassportModelAPI.findOne({ + user: userId + }) + + const {error, user} = await model.updatePassport( + {id: userId}, + {id: passportResult.id, password: 'new_password'} + ) + + should.equal(error, null) + user.should.have.property('id', userId) + + const newPassportResult = await model.PassportModelAPI.findOne({ + user: userId + }) + + newPassportResult.should.have.property('password') + newPassportResult.password.should.not.equal(passportResult.password) + }) + + it('should return error for non existent passport', async () => { + const {error, user} = await model.updatePassport( + {id: userId}, + {id: 'non_existent_id'} + ) + + should.equal(user, null) + error.should.have.property('message') + }) + }) +}) diff --git a/test/unit/upgradeDBTest.js b/test/unit/upgradeDBTest.js index dde7002f..ebdcc661 100644 --- a/test/unit/upgradeDBTest.js +++ b/test/unit/upgradeDBTest.js @@ -11,6 +11,7 @@ import { ClientModel, DbVersionModel, KeystoreModel, + PassportModel, UserModel, VisualizerModel } from '../../src/model' @@ -420,4 +421,133 @@ describe('Upgrade DB Tests', () => { visualizers.length.should.eql(2) }) }) + + describe(`updateFunction3 - Migrate password properties of token auth strategy from User collection to Passport collection`, () => { + const upgradeFunc = originalUpgradeFuncs[3].func + let userId1 = '', + userId2 = '' + + const userObj1 = { + // password: "password" + firstname: 'Test', + surname: 'User1', + email: 'test1@user.org', + passwordAlgorithm: 'sha256', + passwordHash: + '2e4aeb43a1adcfc8fb26699c44f2088ac694eee6bc18cd91211e317b099806b1', + passwordSalt: '25ahdud42' + } + const userObj2 = { + // password: "password" + firstname: 'Test', + surname: 'User2', + email: 'test2@user.org', + passwordAlgorithm: 'MD5', + passwordHash: '5f4dcc3b5aa765d61d8327deb882cf99', + passwordSalt: '1hj7g9eeF&rs' + } + const userObj3 = { + firstname: 'Test', + surname: 'User3', + email: 'test3@user.org', + passwordAlgorithm: 'SHA-1' + } + const userObj4 = { + email: 'test4@user.org', + firstname: 'Test', + surname: 'User4', + groups: ['admin'], + passwordHash: '5f4dcc3b5aa765d61d8327deb882cf99' + } + + afterEach(async () => { + await Promise.all([UserModel.deleteMany(), PassportModel.deleteMany()]) + await testUtils.setImmediatePromise() + }) + + before(async () => { + await Promise.all([UserModel.deleteMany(), PassportModel.deleteMany()]) + }) + + beforeEach(async () => { + const res1 = await new UserModel(userObj1).save() + userId1 = res1._id + const res2 = await new UserModel(userObj2).save() + userId2 = res2._id + }) + + it('should migrate password properties of token auth strategy from User to Passport collection', async () => { + await upgradeFunc() + + await testUtils.pollCondition(() => + PassportModel.countDocuments().then(c => c === 2) + ) + const passports = await PassportModel.find() + + passports.length.should.be.exactly(2) + const passwordAlgos = passports.map(p => p.passwordAlgorithm) + const idx1 = passwordAlgos.indexOf(userObj1.passwordAlgorithm) + const idx2 = passwordAlgos.indexOf(userObj2.passwordAlgorithm) + + idx1.should.be.above(-1) + passports[idx1].passwordHash.should.be.equal(userObj1.passwordHash) + passports[idx1].passwordSalt.should.be.equal(userObj1.passwordSalt) + passports[idx1].user.should.be.deepEqual(userId1) + passports[idx1].protocol.should.be.equal('token') + idx2.should.be.above(-1) + passports[idx2].passwordHash.should.be.equal(userObj2.passwordHash) + passports[idx2].passwordSalt.should.be.equal(userObj2.passwordSalt) + passports[idx2].user.should.be.deepEqual(userId2) + passports[idx2].protocol.should.be.equal('token') + }) + + it('should remove the users password fields from User collection', async () => { + await upgradeFunc() + const user1 = await UserModel.findOne({email: userObj1.email}) + const user2 = await UserModel.findOne({email: userObj2.email}) + + should.not.exist(user1.passwordHash) + should.not.exist(user2.passwordHash) + should.not.exist(user1.passwordSalt) + should.not.exist(user2.passwordSalt) + should.not.exist(user1.passwordAlgorithm) + should.not.exist(user2.passwordAlgorithm) + }) + + it('should add a new property provider "token" to both users', async () => { + await upgradeFunc() + const user1 = await UserModel.findOne({email: userObj1.email}) + const user2 = await UserModel.findOne({email: userObj2.email}) + + user1.provider.should.be.equal('token') + user2.provider.should.be.equal('token') + }) + + it("should ignore users that don't have a password fields set", async () => { + const users = await UserModel.find() + + users[0].set('passwordHash', undefined) + users[0].set('passwordSalt', undefined) + users[0].set('passwordAlgorithm', undefined) + + users[1].set('passwordHash', undefined) + users[1].set('passwordSalt', undefined) + users[1].set('passwordAlgorithm', undefined) + + await Promise.all(users.map(u => u.save())) + await upgradeFunc() + + const passports = await PassportModel.find() + passports.length.should.eql(0) + }) + + it(`should ignore users that does not have all the 3 password fields set`, async () => { + await new UserModel(userObj3).save() + await new UserModel(userObj4).save() + await upgradeFunc() + + const passports = await PassportModel.find() + passports.length.should.eql(2) + }) + }) }) diff --git a/test/unit/usersTest.js b/test/unit/usersTest.js new file mode 100644 index 00000000..4d7c3db5 --- /dev/null +++ b/test/unit/usersTest.js @@ -0,0 +1,367 @@ +'use strict' + +/* eslint-env mocha */ +/* eslint no-unused-expressions:0 */ + +import should from 'should' + +import * as model from '../../src/model' +import {config} from '../../src/config' + +describe('UserModel tests', () => { + describe('.createUser(user)', () => { + after(async () => { + await model.UserModelAPI.deleteMany({}) + await model.PassportModelAPI.deleteMany({}) + }) + + it('should create a new user with a passport', async () => { + const userToBeCreated = { + firstname: 'Bill', + surname: 'Murray', + email: 'bfm@crazy.net', + password: 'password', + groups: ['HISP', 'group2'] + } + + const {error, user} = await model.createUser(userToBeCreated) + + should.equal(error, null) + + user.should.have.property('id') + user.should.have.property('firstname', userToBeCreated.firstname) + user.should.have.property('surname', userToBeCreated.surname) + user.should.have.property('email', userToBeCreated.email) + user.should.not.have.property('password') + + const passportResult = await model.PassportModelAPI.findOne({ + user: user.id + }) + + passportResult.should.have.property('password') + }) + + it('should return error when no password is provided', async () => { + const userToBeCreated = { + firstname: 'Bill', + surname: 'Murray', + email: 'bfm@crazy.net', + groups: ['HISP', 'group2'] + } + + const {error, user} = await model.createUser(userToBeCreated) + + should.equal(user, null) + error.should.have.property('message') + }) + + it('should return error when firstname is not provided', async () => { + const userToBeCreated = { + surname: 'Murray', + email: 'bfm@crazy.net', + password: 'password', + groups: ['HISP', 'group2'] + } + + const {error, user} = await model.createUser(userToBeCreated) + + should.equal(user, null) + error.should.have.property('message') + }) + }) + + describe('.updateUser(user)', () => { + let userId = null + let userIdWithoutPassword = null + let oldPassword = null + + const userToBeCreated = { + firstname: 'Bill', + surname: 'Murray', + email: 'bfm@crazy.net', + password: 'password', + groups: ['HISP', 'group2'] + } + + const userWithoutPassword = new model.UserModelAPI({ + id: userId, + firstname: 'Elena', + surname: 'Smith', + email: 'bfm@cool.net', + groups: ['group1'] + }) + + before(async () => { + const {user, error} = await model.createUser(userToBeCreated) + + if (error) { + throw new Error(error) + } + userId = user.id + + const passportResult = await model.PassportModelAPI.findOne({ + user: userId + }) + oldPassword = passportResult.password + + const res = await userWithoutPassword.save() + userIdWithoutPassword = res.id + }) + + after(async () => { + await model.UserModelAPI.deleteMany({}) + await model.PassportModelAPI.deleteMany({}) + config.api.salt = 10 + }) + + it('should update user without password update', async () => { + const userToBeUpdated = { + id: userId, + firstname: 'Elena', + surname: 'Smith', + email: 'bfm@notcrazy.net', + groups: ['group1'] + } + + const {error, user} = await model.updateUser(userToBeUpdated) + + should.equal(error, null) + + user.should.have.property('id') + user.should.have.property('firstname', userToBeUpdated.firstname) + user.should.have.property('surname', userToBeUpdated.surname) + user.should.have.property('email', userToBeUpdated.email) + user.should.not.have.property('password') + }) + + it('should update user with password update', async () => { + const userToBeUpdated = { + id: userId, + firstname: 'Elena', + surname: 'Smith', + email: 'bfm@notcrazy.net', + password: 'new_password', + groups: ['group1'] + } + + const {error, user} = await model.updateUser(userToBeUpdated) + + should.equal(error, null) + + user.should.have.property('id') + user.should.have.property('firstname', userToBeUpdated.firstname) + user.should.have.property('surname', userToBeUpdated.surname) + user.should.have.property('email', userToBeUpdated.email) + user.should.not.have.property('password') + + const passportResult = await model.PassportModelAPI.find({ + user: user.id + }) + .limit(1) + .sort({$natural: -1}) + + passportResult.length.should.equal(1) + passportResult[0].should.have.property('password') + passportResult[0].password.should.not.equal(oldPassword) + }) + + it('should create a new passport of a user if he does not have one already', async () => { + const userToBeUpdated = { + id: userIdWithoutPassword, + password: 'password' + } + + const {error, user} = await model.updateUser(userToBeUpdated) + + should.equal(error, null) + + user.should.have.property('id') + user.should.have.property('firstname', userWithoutPassword.firstname) + user.should.have.property('surname', userWithoutPassword.surname) + user.should.have.property('email', userWithoutPassword.email) + user.should.not.have.property('password') + + const passportResult = await model.PassportModelAPI.findOne({ + user: user.id + }) + passportResult.should.have.property('password') + }) + + it('should return error for non existent user ID', async () => { + const userToBeUpdated = { + id: 'non_existent_id' + } + + const {error, user} = await model.updateUser(userToBeUpdated) + + should.equal(user, null) + error.should.have.property('message') + }) + + it('should return error when the config salt is not appropriate', async () => { + config.api.salt = '2xld' + const userToBeUpdated = { + id: userIdWithoutPassword, + password: 'password' + } + + const {error, user} = await model.updateUser(userToBeUpdated) + + should.equal(user, null) + error.should.have.property('message') + }) + }) + + describe('.updateTokenUser(user)', () => { + let userId = null + let userIdWithoutPassword = null + let oldPassport = null + + const userToBeCreated = { + firstname: 'Bill', + surname: 'Murray', + email: 'bfm@crazy.net', + passwordAlgorithm: 'sha512', + passwordHash: '796a5a8e-4e44-4d9f-9e04-c27ec6374ffa', + passwordSalt: 'bf93caba-6eec-4c0c-a1a3-d968a7533fd7', + groups: ['HISP', 'group2'] + } + + const userWithoutPassword = new model.UserModelAPI({ + id: userId, + firstname: 'Elena', + surname: 'Smith', + email: 'bfm@cool.net', + groups: ['group1'] + }) + + before(async () => { + const user = await model.UserModelAPI(userToBeCreated).save() + userId = user.id + + await model.updateTokenUser({id: userId, ...userToBeCreated}) + + oldPassport = await model.PassportModelAPI.findOne({ + user: userId + }) + + const res = await userWithoutPassword.save() + userIdWithoutPassword = res.id + }) + + after(async () => { + await model.UserModelAPI.deleteMany({}) + await model.PassportModelAPI.deleteMany({}) + }) + + it('should update user without password update', async () => { + const userToBeUpdated = { + id: userId, + firstname: 'Elena', + surname: 'Smith', + email: 'bfm@notcrazy.net', + groups: ['group1'] + } + + const {error, user} = await model.updateTokenUser(userToBeUpdated) + + should.equal(error, null) + + user.should.have.property('id') + user.should.have.property('firstname', userToBeUpdated.firstname) + user.should.have.property('surname', userToBeUpdated.surname) + user.should.have.property('email', userToBeUpdated.email) + ;(!user.passwordAlgorithm).should.be.true() + ;(!user.passwordHash).should.be.true() + ;(!user.passwordSalt).should.be.true() + }) + + it('should update user with password update', async () => { + const userToBeUpdated = { + id: userId, + firstname: 'Elena', + surname: 'Smith', + email: 'bfm@notcrazy.net', + passwordAlgorithm: 'sha1', + passwordHash: '3cc90918-7044-4e55-b61d-92ae73cb261e', + passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0', + groups: ['group1'] + } + + const {error, user} = await model.updateTokenUser(userToBeUpdated) + + should.equal(error, null) + + user.should.have.property('id') + user.should.have.property('firstname', userToBeUpdated.firstname) + user.should.have.property('surname', userToBeUpdated.surname) + user.should.have.property('email', userToBeUpdated.email) + + const res = await model.PassportModelAPI.find({ + user: user.id, + protocol: 'token' + }) + .limit(1) + .sort({$natural: -1}) + + res.length.should.equal(1) + let passportResult = res[0]._doc + passportResult.should.not.have.property('password') + passportResult.should.have.property('passwordAlgorithm') + passportResult.passwordAlgorithm.should.not.equal( + oldPassport.passwordAlgorithm + ) + passportResult.should.have.property('passwordHash') + passportResult.passwordHash.should.not.equal(oldPassport.passwordHash) + passportResult.should.have.property('passwordSalt') + passportResult.passwordSalt.should.not.equal(oldPassport.passwordSalt) + }) + + it('should create a new passport of a user if he does not have one already', async () => { + const userToBeUpdated = { + id: userIdWithoutPassword, + passwordAlgorithm: 'sha512', + passwordHash: '796a5a8e-4e44-4d9f-9e04-c27ec6374ffa', + passwordSalt: 'bf93caba-6eec-4c0c-a1a3-d968a7533fd7' + } + + const {error, user} = await model.updateTokenUser(userToBeUpdated) + + should.equal(error, null) + + user.should.have.property('id') + user.should.have.property('firstname', userWithoutPassword.firstname) + user.should.have.property('surname', userWithoutPassword.surname) + user.should.have.property('email', userWithoutPassword.email) + user.should.have.property('provider', 'token') + + const passportResult = await model.PassportModelAPI.findOne({ + user: user.id, + protocol: 'token' + }) + passportResult.should.have.property( + 'passwordAlgorithm', + userToBeUpdated.passwordAlgorithm + ) + passportResult.should.have.property( + 'passwordHash', + userToBeUpdated.passwordHash + ) + passportResult.should.have.property( + 'passwordSalt', + userToBeUpdated.passwordSalt + ) + }) + + it('should return error when non existent user ID', async () => { + const userToBeUpdated = { + id: 'non_existent_id' + } + + const {error, user} = await model.updateTokenUser(userToBeUpdated) + + should.equal(user, null) + error.should.have.property('message') + }) + }) +}) diff --git a/test/unit/utilsTest.js b/test/unit/utilsTest.js index bcaa55c4..b90e7acf 100644 --- a/test/unit/utilsTest.js +++ b/test/unit/utilsTest.js @@ -6,8 +6,9 @@ import should from 'should' import * as utils from '../../src/utils' +import {config} from '../../src/config' -describe('Utils', () => +describe('Utils', () => { describe('.statusCodePatternMatch()', () => { it('should return true when pattern value match status code (2xx)', () => { const result = utils.statusCodePatternMatch('2xx') @@ -28,4 +29,33 @@ describe('Utils', () => const result = utils.serverTimezone() should.exist(result) }) - })) + }) + + describe('.hashPassword()', () => { + after(() => { + config.api.salt = 10 + }) + + it('should return a non empty hashed password', async () => { + const result = await utils.hashPassword('password') + result.should.not.be.empty() + }) + + it('should return an error when password is not provided', async () => { + try { + await utils.hashPassword() + } catch (err) { + err.message.should.be.equal("Password wasn't provided") + } + }) + + it('should return an error if salt provided is invalid', async () => { + config.api.salt = '2xld' + try { + await utils.hashPassword('password') + } catch (err) { + err.message.should.match(/Invalid salt version/) + } + }) + }) +}) diff --git a/test/utils.js b/test/utils.js index d27bee1f..68b4847a 100644 --- a/test/utils.js +++ b/test/utils.js @@ -20,7 +20,9 @@ import { MetricModel, UserModel, METRIC_TYPE_HOUR, - METRIC_TYPE_DAY + METRIC_TYPE_DAY, + createUser, + updateTokenUser } from '../src/model' import {config, encodeMongoURI} from '../src/config' @@ -36,25 +38,29 @@ export const rootUser = { firstname: 'Admin', surname: 'User', email: 'root@jembi.org', + password: 'password', + groups: ['HISP', 'admin'], + + // @deprecated passwordAlgorithm: 'sha512', passwordHash: '669c981d4edccb5ed61f4d77f9fcc4bf594443e2740feb1a23f133bdaf80aae41804d10aa2ce254cfb6aca7c497d1a717f2dd9a794134217219d8755a84b6b4e', - passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0', - groups: ['HISP', 'admin'] + passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0' } -// password is 'password' export const nonRootUser = { firstname: 'Non', surname: 'Root', email: 'nonroot@jembi.org', + password: 'password', + groups: ['group1', 'group2'], + + // @deprecated passwordAlgorithm: 'sha512', passwordHash: '669c981d4edccb5ed61f4d77f9fcc4bf594443e2740feb1a23f133bdaf80aae41804d10aa2ce254cfb6aca7c497d1a717f2dd9a794134217219d8755a84b6b4e', - passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0', - groups: ['group1', 'group2'] + passwordSalt: '22a61686-66f6-483c-a524-185aac251fb0' } -// password is 'password' export function secureSocketTest(portOrOptions, data, waitForResponse = true) { const options = {} @@ -123,11 +129,68 @@ export async function pollCondition(pollPredicate, pollBreak = 20) { } } -export function setupTestUsers() { - return Promise.all([ - new UserModel(rootUser).save(), - new UserModel(nonRootUser).save() - ]) +export async function setupTestUsers() { + const res = await Promise.all([createUser(rootUser), createUser(nonRootUser)]) + + const errors = res + .filter(r => r.error) + .map(r => (r.error.message ? r.error.message : r.error)) + + if (errors.length > 0) { + throw new Error('Error creating test users:\n' + errors.join('\n')) + } + + return res +} + +export async function setupTestUsersWithToken() { + try { + const root = await new UserModel(rootUser).save() + const nonRoot = await new UserModel(nonRootUser).save() + + // Add token passports @deprecated + const res = await Promise.all([ + updateTokenUser({...rootUser, id: root.id}), + updateTokenUser({...nonRootUser, id: nonRoot.id}) + ]) + + const errors = res + .filter(r => r.error) + .map(r => (r.error.message ? r.error.message : r.error)) + + if (errors.length > 0) { + throw new Error('Error creating test users:\n' + errors.join('\n')) + } + + return res + } catch (err) { + throw new Error('Error creating test users:\n' + err) + } +} + +export function getCookie(encodedCookies) { + let decodedCookies = '' + + if (Array.isArray(encodedCookies) && encodedCookies.length > 0) { + for (let cookie of encodedCookies) { + let ca = cookie.split(';') + if (ca.length > 0) { + decodedCookies += ca[0] + ';' + } + } + } + return decodedCookies +} + +export const authenticate = async (request, BASE_URL, user) => { + const {email, password} = user + + const authResult = await request(BASE_URL) + .post('/authenticate/local') + .send({username: email, password: password}) + .expect(200) + + return getCookie(authResult.headers['set-cookie']) } export function getAuthDetails() {