diff --git a/.eslintrc.json b/.eslintrc.json
index 5995321633..c04e2d3109 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -25,5 +25,8 @@
"space-infix-ops": "error",
"no-useless-escape": "off",
"require-atomic-updates": "off"
+ },
+ "globals": {
+ "Parse": true
}
}
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 756e4e2419..17ca3a56ac 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,7 +1,7 @@
name: ci
on:
push:
- branches: [ release, alpha, beta, next-major, 'release-[0-9]+.x.x' ]
+ branches: [release, alpha, beta, next-major, 'release-[0-9]+.x.x']
pull_request:
branches:
- '**'
@@ -21,17 +21,17 @@ jobs:
strategy:
fail-fast: false
matrix:
- language: [ 'javascript' ]
+ language: ['javascript']
steps:
- - name: Checkout repository
- uses: actions/checkout@v3
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v2
- with:
- languages: ${{ matrix.language }}
- source-root: src
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ source-root: src
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
check-ci:
name: Node Engine Check
timeout-minutes: 15
@@ -54,30 +54,30 @@ jobs:
- name: CI Node Engine Check
run: npm run ci:checkNodeEngine
check-lint:
- name: Lint
- timeout-minutes: 15
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Use Node.js ${{ matrix.NODE_VERSION }}
- uses: actions/setup-node@v2
- with:
- node-version: ${{ matrix.node-version }}
- - name: Cache Node.js modules
- uses: actions/cache@v2
- with:
- path: ~/.npm
- key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
- - name: Install dependencies
- run: npm ci
- - run: npm run lint
+ name: Lint
+ timeout-minutes: 15
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Use Node.js ${{ matrix.NODE_VERSION }}
+ uses: actions/setup-node@v2
+ with:
+ node-version: ${{ matrix.node-version }}
+ - name: Cache Node.js modules
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
+ - name: Install dependencies
+ run: npm ci
+ - run: npm run lint
check-definitions:
- name: Check Definitions
- timeout-minutes: 5
- runs-on: ubuntu-latest
- steps:
+ name: Check Definitions
+ timeout-minutes: 5
+ runs-on: ubuntu-latest
+ steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.NODE_VERSION }}
uses: actions/setup-node@v2
@@ -95,25 +95,25 @@ jobs:
- name: CI Definitions Check
run: npm run ci:definitionsCheck
check-circular:
- name: Circular Dependencies
- timeout-minutes: 5
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - name: Use Node.js ${{ matrix.NODE_VERSION }}
- uses: actions/setup-node@v2
- with:
- node-version: ${{ matrix.node-version }}
- - name: Cache Node.js modules
- uses: actions/cache@v2
- with:
- path: ~/.npm
- key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
- - name: Install dependencies
- run: npm ci
- - run: npm run madge:circular
+ name: Circular Dependencies
+ timeout-minutes: 5
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Use Node.js ${{ matrix.NODE_VERSION }}
+ uses: actions/setup-node@v2
+ with:
+ node-version: ${{ matrix.node-version }}
+ - name: Cache Node.js modules
+ uses: actions/cache@v2
+ with:
+ path: ~/.npm
+ key: ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-${{ matrix.NODE_VERSION }}-
+ - name: Install dependencies
+ run: npm ci
+ - run: npm run madge:circular
check-docker:
name: Docker Build
timeout-minutes: 15
@@ -147,19 +147,23 @@ jobs:
include:
- name: MongoDB 4.2, ReplicaSet
MONGODB_VERSION: 4.2.19
- MONGODB_TOPOLOGY: replicaset
+ MONGODB_TOPOLOGY: replset
NODE_VERSION: 19.3.0
- name: MongoDB 4.4, ReplicaSet
MONGODB_VERSION: 4.4.13
- MONGODB_TOPOLOGY: replicaset
+ MONGODB_TOPOLOGY: replset
NODE_VERSION: 19.3.0
- name: MongoDB 5, ReplicaSet
MONGODB_VERSION: 5.3.2
- MONGODB_TOPOLOGY: replicaset
+ MONGODB_TOPOLOGY: replset
NODE_VERSION: 19.3.0
- name: MongoDB 6, ReplicaSet
MONGODB_VERSION: 6.0.2
- MONGODB_TOPOLOGY: replicaset
+ MONGODB_TOPOLOGY: replset
+ NODE_VERSION: 19.3.0
+ - name: MongoDB 7, ReplicaSet
+ MONGODB_VERSION: 7.0.1
+ MONGODB_TOPOLOGY: replset
NODE_VERSION: 19.3.0
- name: Redis Cache
PARSE_SERVER_TEST_CACHE: redis
@@ -186,7 +190,7 @@ jobs:
redis:
image: redis
ports:
- - 6379:6379
+ - 6379:6379
env:
MONGODB_VERSION: ${{ matrix.MONGODB_VERSION }}
MONGODB_TOPOLOGY: ${{ matrix.MONGODB_TOPOLOGY }}
diff --git a/DEPRECATIONS.md b/DEPRECATIONS.md
index 56359c937e..b825e50b2f 100644
--- a/DEPRECATIONS.md
+++ b/DEPRECATIONS.md
@@ -13,6 +13,7 @@ The following is a list of deprecations, according to the [Deprecation Policy](h
| DEPPS7 | Remove file trigger syntax `Parse.Cloud.beforeSaveFile((request) => {})` | [#7966](https://github.com/parse-community/parse-server/pull/7966) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS8 | Login with expired 3rd party authentication token defaults to `false` | [#7079](https://github.com/parse-community/parse-server/pull/7079) | 5.3.0 (2022) | 7.0.0 (2024) | deprecated | - |
| DEPPS9 | Rename LiveQuery `fields` option to `keys` | [#8389](https://github.com/parse-community/parse-server/issues/8389) | 6.0.0 (2023) | 7.0.0 (2024) | deprecated | - |
+| DEPPS10 | Config option `encodeParseObjectInCloudFunction` defaults to `true` | [#8634](https://github.com/parse-community/parse-server/issues/8634) | 6.2.0 (2023) | 8.0.0 (2025) | deprecated | - |
[i_deprecation]: ## "The version and date of the deprecation."
[i_removal]: ## "The version and date of the planned removal."
diff --git a/README.md b/README.md
index 0288d5f4ba..9d969fff97 100644
--- a/README.md
+++ b/README.md
@@ -139,12 +139,13 @@ Parse Server is continuously tested with the most recent releases of Node.js to
Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and [MongoDB lifecycle schedule](https://www.mongodb.com/support-policy/lifecycles) and only test against versions that are officially supported and have not reached their end-of-life date. We consider the end-of-life date of a MongoDB "rapid release" to be the same as its major version release.
| Version | Latest Version | End-of-Life | Compatible |
-|-------------|----------------|---------------|------------|
-| MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes |
-| MongoDB 4.2 | 4.2.19 | April 2023 | ✅ Yes |
-| MongoDB 4.4 | 4.4.13 | February 2024 | ✅ Yes |
-| MongoDB 5 | 5.3.2 | October 2024 | ✅ Yes |
-| MongoDB 6 | 6.0.2 | July 2025 | ✅ Yes |
+| ----------- | -------------- | ------------- | ---------- |
+| MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes |
+| MongoDB 4.2 | 4.2.19 | April 2023 | ✅ Yes |
+| MongoDB 4.4 | 4.4.13 | February 2024 | ✅ Yes |
+| MongoDB 5 | 5.3.2 | October 2024 | ✅ Yes |
+| MongoDB 6 | 6.0.2 | July 2025 | ✅ Yes |
+| MongoDB 7 | 7.0.1 | TDB | ✅ Yes |
#### PostgreSQL
@@ -358,12 +359,14 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
## Access Scopes
-| Scope | Internal data | Custom data | Restricted by CLP, ACL | Key |
-|----------------|---------------|-------------|------------------------|---------------------|
-| Internal | r/w | r/w | no | `maintenanceKey` |
-| Master | -/- | r/w | no | `masterKey` |
-| ReadOnlyMaster | -/- | r/- | no | `readOnlyMasterKey` |
-| Session | -/- | r/w | yes | `sessionToken` |
+| Scope | Internal data | Read-only data (1) | Custom data | Restricted by CLP, ACL | Key |
+|----------------|---------------|-------------------------------|-------------|------------------------|---------------------|
+| Internal | r/w | r/w | r/w | no | `maintenanceKey` |
+| Master | -/- | r/- | r/w | no | `masterKey` |
+| ReadOnlyMaster | -/- | r/- | r/- | no | `readOnlyMasterKey` |
+| Session | -/- | r/- | r/w | yes | `sessionToken` |
+
+(1) `Parse.Object.createdAt`, `Parse.Object.updatedAt`.
## Email Verification and Password Reset
diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md
index b9b1925b78..427189b692 100644
--- a/changelogs/CHANGELOG_alpha.md
+++ b/changelogs/CHANGELOG_alpha.md
@@ -1,3 +1,246 @@
+# [7.0.0-alpha.9](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.8...7.0.0-alpha.9) (2024-01-15)
+
+
+### Bug Fixes
+
+* Server crashes when receiving an array of `Parse.Pointer` in the request body ([#8784](https://github.com/parse-community/parse-server/issues/8784)) ([66e3603](https://github.com/parse-community/parse-server/commit/66e36039d8af654cfa0284666c0ddd94975dcb52))
+
+# [7.0.0-alpha.8](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.7...7.0.0-alpha.8) (2024-01-15)
+
+
+### Bug Fixes
+
+* Incomplete user object in `verifyEmail` function if both username and email are changed ([#8889](https://github.com/parse-community/parse-server/issues/8889)) ([1eb95ae](https://github.com/parse-community/parse-server/commit/1eb95aeb41a96250e582d79a703f6adcb403c08b))
+
+# [7.0.0-alpha.7](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.6...7.0.0-alpha.7) (2024-01-14)
+
+
+### Bug Fixes
+
+* Username is `undefined` in email verification link on email change ([#8887](https://github.com/parse-community/parse-server/issues/8887)) ([e315c13](https://github.com/parse-community/parse-server/commit/e315c137bf41bedfa8f0df537f2c3f6ab45b7e60))
+
+# [7.0.0-alpha.6](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.5...7.0.0-alpha.6) (2024-01-14)
+
+
+### Bug Fixes
+
+* Parse Server option `emailVerifyTokenReuseIfValid: true` generates new token on every email verification request ([#8885](https://github.com/parse-community/parse-server/issues/8885)) ([0023ce4](https://github.com/parse-community/parse-server/commit/0023ce448a5e9423337d0e1a25648bde1156bc95))
+
+# [7.0.0-alpha.5](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.4...7.0.0-alpha.5) (2024-01-06)
+
+
+### Features
+
+* Add `installationId`, `ip`, `resendRequest` to arguments passed to `verifyUserEmails` on verification email request ([#8873](https://github.com/parse-community/parse-server/issues/8873)) ([8adcbee](https://github.com/parse-community/parse-server/commit/8adcbee11283d3e95179ca2047e2615f52c18806))
+
+
+### BREAKING CHANGES
+
+* The `Parse.User` passed as argument if `verifyUserEmails` is set to a function is renamed from `user` to `object` for consistency with invocations of `verifyUserEmails` on signup or login; the user object is not a plain JavaScript object anymore but an instance of `Parse.User` ([8adcbee](8adcbee))
+
+# [7.0.0-alpha.4](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.3...7.0.0-alpha.4) (2023-12-27)
+
+
+### Features
+
+* Add `Parse.User` as function parameter to Parse Server options `verifyUserEmails`, `preventLoginWithUnverifiedEmail` on login ([#8850](https://github.com/parse-community/parse-server/issues/8850)) ([972f630](https://github.com/parse-community/parse-server/commit/972f6300163b3cd7d95eeb95986e8322c95f821c))
+
+# [7.0.0-alpha.3](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.2...7.0.0-alpha.3) (2023-12-26)
+
+
+### Bug Fixes
+
+* Conditional email verification not working in some cases if `verifyUserEmails`, `preventLoginWithUnverifiedEmail` set to functions ([#8838](https://github.com/parse-community/parse-server/issues/8838)) ([8e7a6b1](https://github.com/parse-community/parse-server/commit/8e7a6b1480c0117e6c73e7adc5a6619115a04e85))
+
+### Features
+
+* Allow `Parse.Session.current` on expired session token instead of throwing error ([#8722](https://github.com/parse-community/parse-server/issues/8722)) ([f9dde4a](https://github.com/parse-community/parse-server/commit/f9dde4a9f8a90c63f71172c9bc515b0f6c6d2e4a))
+
+
+### BREAKING CHANGES
+
+* `Parse.Session.current()` no longer throws an error if the session token is expired, but instead returns the session token with its expiration date to allow checking its validity ([f9dde4a](f9dde4a))
+
+# [7.0.0-alpha.2](https://github.com/parse-community/parse-server/compare/7.0.0-alpha.1...7.0.0-alpha.2) (2023-12-17)
+
+
+### Features
+
+* Add `installationId` to arguments for `verifyUserEmails`, `preventLoginWithUnverifiedEmail` ([#8836](https://github.com/parse-community/parse-server/issues/8836)) ([a22dbe1](https://github.com/parse-community/parse-server/commit/a22dbe16d5ac0090608f6caaf0ebd134925b7fd4))
+
+# [7.0.0-alpha.1](https://github.com/parse-community/parse-server/compare/6.5.0-alpha.2...7.0.0-alpha.1) (2023-12-10)
+
+
+### Features
+
+* Add support for MongoDB 7 ([#8761](https://github.com/parse-community/parse-server/issues/8761)) ([3de8494](https://github.com/parse-community/parse-server/commit/3de8494a221991dfd10a74e0a2dc89576265c9b7))
+
+
+### BREAKING CHANGES
+
+* `Parse.Query` no longer supports the BSON type `code`; although this feature was never officially documented, its removal is announced as a breaking change to protect deployments where it might be in use. ([3de8494](3de8494))
+
+# [6.5.0-alpha.2](https://github.com/parse-community/parse-server/compare/6.5.0-alpha.1...6.5.0-alpha.2) (2023-11-19)
+
+
+### Performance Improvements
+
+* Improved IP validation performance for `masterKeyIPs`, `maintenanceKeyIPs` ([#8510](https://github.com/parse-community/parse-server/issues/8510)) ([b87daba](https://github.com/parse-community/parse-server/commit/b87daba0671a1b0b7b8d63bc671d665c91a04522))
+
+# [6.5.0-alpha.1](https://github.com/parse-community/parse-server/compare/6.4.0...6.5.0-alpha.1) (2023-11-18)
+
+
+### Bug Fixes
+
+* Context not passed to Cloud Code Trigger `beforeFind` when using `Parse.Query.include` ([#8765](https://github.com/parse-community/parse-server/issues/8765)) ([7d32d89](https://github.com/parse-community/parse-server/commit/7d32d8934f3ae7af7a7d8b9cc6a829c7d73973d3))
+* Parse Server option `fileUpload.fileExtensions` fails to determine file extension if filename contains multiple dots ([#8754](https://github.com/parse-community/parse-server/issues/8754)) ([3d6d50e](https://github.com/parse-community/parse-server/commit/3d6d50e0afff18b95fb906914e2cebd3839b517a))
+* Security bump @babel/traverse from 7.20.5 to 7.23.2 ([#8777](https://github.com/parse-community/parse-server/issues/8777)) ([2d6b3d1](https://github.com/parse-community/parse-server/commit/2d6b3d18499179e99be116f25c0850d3f449509c))
+* Security upgrade graphql from 16.6.0 to 16.8.1 ([#8758](https://github.com/parse-community/parse-server/issues/8758)) ([71dfd8a](https://github.com/parse-community/parse-server/commit/71dfd8a7ece8c0dd1a66d03bb9420cfd39f4f9b1))
+
+### Features
+
+* Add `$setOnInsert` operator to `Parse.Server.database.update` ([#8791](https://github.com/parse-community/parse-server/issues/8791)) ([f630a45](https://github.com/parse-community/parse-server/commit/f630a45aa5e87bc73a81fded061400c199b71a29))
+* Add compatibility for MongoDB Atlas Serverless and AWS Amazon DocumentDB with collation options `enableCollationCaseComparison`, `transformEmailToLowercase`, `transformUsernameToLowercase` ([#8805](https://github.com/parse-community/parse-server/issues/8805)) ([09fbeeb](https://github.com/parse-community/parse-server/commit/09fbeebba8870e7cf371fb84371a254c7b368620))
+* Add context to Cloud Code Triggers `beforeLogin` and `afterLogin` ([#8724](https://github.com/parse-community/parse-server/issues/8724)) ([a9c34ef](https://github.com/parse-community/parse-server/commit/a9c34ef1e2c78a42fb8b5fa8d569b7677c74919d))
+* Allow setting `createdAt` and `updatedAt` during `Parse.Object` creation with maintenance key ([#8696](https://github.com/parse-community/parse-server/issues/8696)) ([77bbfb3](https://github.com/parse-community/parse-server/commit/77bbfb3f186f5651c33ba152f04cff95128eaf2d))
+* Upgrade Parse Server Push Adapter to 5.0.2 ([#8813](https://github.com/parse-community/parse-server/issues/8813)) ([6ef1986](https://github.com/parse-community/parse-server/commit/6ef1986c03a1d84b7e11c05851e5bf9688d88740))
+
+# [6.4.0-alpha.8](https://github.com/parse-community/parse-server/compare/6.4.0-alpha.7...6.4.0-alpha.8) (2023-11-13)
+
+
+### Features
+
+* Add compatibility for MongoDB Atlas Serverless and AWS Amazon DocumentDB with collation options `enableCollationCaseComparison`, `transformEmailToLowercase`, `transformUsernameToLowercase` ([#8805](https://github.com/parse-community/parse-server/issues/8805)) ([09fbeeb](https://github.com/parse-community/parse-server/commit/09fbeebba8870e7cf371fb84371a254c7b368620))
+
+# [6.4.0-alpha.7](https://github.com/parse-community/parse-server/compare/6.4.0-alpha.6...6.4.0-alpha.7) (2023-10-25)
+
+
+### Features
+
+* Add `$setOnInsert` operator to `Parse.Server.database.update` ([#8791](https://github.com/parse-community/parse-server/issues/8791)) ([f630a45](https://github.com/parse-community/parse-server/commit/f630a45aa5e87bc73a81fded061400c199b71a29))
+
+# [6.4.0-alpha.6](https://github.com/parse-community/parse-server/compare/6.4.0-alpha.5...6.4.0-alpha.6) (2023-10-18)
+
+
+### Bug Fixes
+
+* Security bump @babel/traverse from 7.20.5 to 7.23.2 ([#8777](https://github.com/parse-community/parse-server/issues/8777)) ([2d6b3d1](https://github.com/parse-community/parse-server/commit/2d6b3d18499179e99be116f25c0850d3f449509c))
+
+# [6.4.0-alpha.5](https://github.com/parse-community/parse-server/compare/6.4.0-alpha.4...6.4.0-alpha.5) (2023-10-14)
+
+
+### Bug Fixes
+
+* Context not passed to Cloud Code Trigger `beforeFind` when using `Parse.Query.include` ([#8765](https://github.com/parse-community/parse-server/issues/8765)) ([7d32d89](https://github.com/parse-community/parse-server/commit/7d32d8934f3ae7af7a7d8b9cc6a829c7d73973d3))
+
+# [6.4.0-alpha.4](https://github.com/parse-community/parse-server/compare/6.4.0-alpha.3...6.4.0-alpha.4) (2023-09-29)
+
+
+### Features
+
+* Allow setting `createdAt` and `updatedAt` during `Parse.Object` creation with maintenance key ([#8696](https://github.com/parse-community/parse-server/issues/8696)) ([77bbfb3](https://github.com/parse-community/parse-server/commit/77bbfb3f186f5651c33ba152f04cff95128eaf2d))
+
+# [6.4.0-alpha.3](https://github.com/parse-community/parse-server/compare/6.4.0-alpha.2...6.4.0-alpha.3) (2023-09-23)
+
+
+### Bug Fixes
+
+* Parse Server option `fileUpload.fileExtensions` fails to determine file extension if filename contains multiple dots ([#8754](https://github.com/parse-community/parse-server/issues/8754)) ([3d6d50e](https://github.com/parse-community/parse-server/commit/3d6d50e0afff18b95fb906914e2cebd3839b517a))
+
+# [6.4.0-alpha.2](https://github.com/parse-community/parse-server/compare/6.4.0-alpha.1...6.4.0-alpha.2) (2023-09-22)
+
+
+### Bug Fixes
+
+* Security upgrade graphql from 16.6.0 to 16.8.1 ([#8758](https://github.com/parse-community/parse-server/issues/8758)) ([71dfd8a](https://github.com/parse-community/parse-server/commit/71dfd8a7ece8c0dd1a66d03bb9420cfd39f4f9b1))
+
+# [6.4.0-alpha.1](https://github.com/parse-community/parse-server/compare/6.3.0...6.4.0-alpha.1) (2023-09-20)
+
+### Features
+
+* Add context to Cloud Code Triggers `beforeLogin` and `afterLogin` ([#8724](https://github.com/parse-community/parse-server/issues/8724)) ([a9c34ef](https://github.com/parse-community/parse-server/commit/a9c34ef1e2c78a42fb8b5fa8d569b7677c74919d))
+
+# [6.3.0-alpha.9](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.8...6.3.0-alpha.9) (2023-09-13)
+
+
+### Performance Improvements
+
+* Improve performance of recursive pointer iterations ([#8741](https://github.com/parse-community/parse-server/issues/8741)) ([45a3ed0](https://github.com/parse-community/parse-server/commit/45a3ed0fcf2c0170607505a1550fb15896e705fd))
+
+# [6.3.0-alpha.8](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.7...6.3.0-alpha.8) (2023-08-30)
+
+
+### Bug Fixes
+
+* Redis 4 does not reconnect after unhandled error ([#8706](https://github.com/parse-community/parse-server/issues/8706)) ([2b3d4e5](https://github.com/parse-community/parse-server/commit/2b3d4e5d3c85cd142f85af68dec51a8523548d49))
+
+# [6.3.0-alpha.7](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.6...6.3.0-alpha.7) (2023-08-18)
+
+
+### Bug Fixes
+
+* Remove config logging when launching Parse Server via CLI ([#8710](https://github.com/parse-community/parse-server/issues/8710)) ([ae68f0c](https://github.com/parse-community/parse-server/commit/ae68f0c31b741eeb83379c905c7ddfaa124436ec))
+
+# [6.3.0-alpha.6](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.5...6.3.0-alpha.6) (2023-07-17)
+
+
+### Bug Fixes
+
+* Parse Server option `fileUpload.fileExtensions` does not work with an array of extensions ([#8688](https://github.com/parse-community/parse-server/issues/8688)) ([6a4a00c](https://github.com/parse-community/parse-server/commit/6a4a00ca7af1163ea74b047b85cd6817366b824b))
+
+# [6.3.0-alpha.5](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.4...6.3.0-alpha.5) (2023-07-05)
+
+
+### Features
+
+* Add property `Parse.Server.version` to determine current version of Parse Server in Cloud Code ([#8670](https://github.com/parse-community/parse-server/issues/8670)) ([a9d376b](https://github.com/parse-community/parse-server/commit/a9d376b61f5b07806eafbda91c4e36c322f09298))
+
+# [6.3.0-alpha.4](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.3...6.3.0-alpha.4) (2023-07-04)
+
+
+### Bug Fixes
+
+* Server does not start via CLI when `auth` option is set ([#8666](https://github.com/parse-community/parse-server/issues/8666)) ([4e2000b](https://github.com/parse-community/parse-server/commit/4e2000bc563324389584ace3c090a5c1a7796a64))
+
+# [6.3.0-alpha.3](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.2...6.3.0-alpha.3) (2023-06-23)
+
+
+### Features
+
+* Add TOTP authentication adapter ([#8457](https://github.com/parse-community/parse-server/issues/8457)) ([cc079a4](https://github.com/parse-community/parse-server/commit/cc079a40f6849a0e9bc6fdc811e8649ecb67b589))
+
+# [6.3.0-alpha.2](https://github.com/parse-community/parse-server/compare/6.3.0-alpha.1...6.3.0-alpha.2) (2023-06-20)
+
+
+### Features
+
+* Add conditional email verification via dynamic Parse Server options `verifyUserEmails`, `sendUserEmailVerification` that now accept functions ([#8425](https://github.com/parse-community/parse-server/issues/8425)) ([44acd6d](https://github.com/parse-community/parse-server/commit/44acd6d9ed157ad4842200c9d01f9c77a05fec3a))
+
+# [6.3.0-alpha.1](https://github.com/parse-community/parse-server/compare/6.2.0...6.3.0-alpha.1) (2023-06-18)
+
+
+### Bug Fixes
+
+* Cloud Code Trigger `afterSave` executes even if not set ([#8520](https://github.com/parse-community/parse-server/issues/8520)) ([afd0515](https://github.com/parse-community/parse-server/commit/afd0515e207bd947840579d3f245980dffa6f804))
+* GridFS file storage doesn't work with certain `enableSchemaHooks` settings ([#8467](https://github.com/parse-community/parse-server/issues/8467)) ([d4cda4b](https://github.com/parse-community/parse-server/commit/d4cda4b26c9bde8c812549b8780bea1cfabdb394))
+* Inaccurate table total row count for PostgreSQL ([#8511](https://github.com/parse-community/parse-server/issues/8511)) ([0823a02](https://github.com/parse-community/parse-server/commit/0823a02fbf80bc88dc403bc47e9f5c6597ea78b4))
+* LiveQuery server is not shut down properly when `handleShutdown` is called ([#8491](https://github.com/parse-community/parse-server/issues/8491)) ([967700b](https://github.com/parse-community/parse-server/commit/967700bdbc94c74f75ba84d2b3f4b9f3fd2dca0b))
+* Rate limit feature is incompatible with Node 14 ([#8578](https://github.com/parse-community/parse-server/issues/8578)) ([f911f2c](https://github.com/parse-community/parse-server/commit/f911f2cd3a8c45cd326272dcd681532764a3761e))
+* Unnecessary log entries by `extendSessionOnUse` ([#8562](https://github.com/parse-community/parse-server/issues/8562)) ([fd6a007](https://github.com/parse-community/parse-server/commit/fd6a0077f2e5cf83d65e52172ae5a950ab0f1eae))
+
+### Features
+
+* `extendSessionOnUse` to automatically renew Parse Sessions ([#8505](https://github.com/parse-community/parse-server/issues/8505)) ([6f885d3](https://github.com/parse-community/parse-server/commit/6f885d36b94902fdfea873fc554dee83589e6029))
+* Add new Parse Server option `preventSignupWithUnverifiedEmail` to prevent returning a user without session token on sign-up with unverified email address ([#8451](https://github.com/parse-community/parse-server/issues/8451)) ([82da308](https://github.com/parse-community/parse-server/commit/82da30842a55980aa90cb7680fbf6db37ee16dab))
+* Add option to change the log level of logs emitted by Cloud Functions ([#8530](https://github.com/parse-community/parse-server/issues/8530)) ([2caea31](https://github.com/parse-community/parse-server/commit/2caea310be412d82b04a85716bc769ccc410316d))
+* Add support for `$eq` query constraint in LiveQuery ([#8614](https://github.com/parse-community/parse-server/issues/8614)) ([656d673](https://github.com/parse-community/parse-server/commit/656d673cf5dea354e4f2b3d4dc2b29a41d311b3e))
+* Add zones for rate limiting by `ip`, `user`, `session`, `global` ([#8508](https://github.com/parse-community/parse-server/issues/8508)) ([03fba97](https://github.com/parse-community/parse-server/commit/03fba97e0549bfcaeee9f2fa4c9905dbcc91840e))
+* Allow `Parse.Object` pointers in Cloud Code arguments ([#8490](https://github.com/parse-community/parse-server/issues/8490)) ([28aeda3](https://github.com/parse-community/parse-server/commit/28aeda3f160efcbbcf85a85484a8d26567fa9761))
+
+### Reverts
+
+* fix: Inaccurate table total row count for PostgreSQL ([6722110](https://github.com/parse-community/parse-server/commit/6722110f203bc5fdcaa68cdf091cf9e7b48d1cff))
+
# [6.1.0-alpha.20](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.19...6.1.0-alpha.20) (2023-06-09)
diff --git a/changelogs/CHANGELOG_beta.md b/changelogs/CHANGELOG_beta.md
index 289b86d780..dd80a35e3e 100644
--- a/changelogs/CHANGELOG_beta.md
+++ b/changelogs/CHANGELOG_beta.md
@@ -1,3 +1,40 @@
+# [6.5.0-beta.1](https://github.com/parse-community/parse-server/compare/6.4.0...6.5.0-beta.1) (2023-11-16)
+
+
+### Bug Fixes
+
+* Context not passed to Cloud Code Trigger `beforeFind` when using `Parse.Query.include` ([#8765](https://github.com/parse-community/parse-server/issues/8765)) ([7d32d89](https://github.com/parse-community/parse-server/commit/7d32d8934f3ae7af7a7d8b9cc6a829c7d73973d3))
+* Parse Server option `fileUpload.fileExtensions` fails to determine file extension if filename contains multiple dots ([#8754](https://github.com/parse-community/parse-server/issues/8754)) ([3d6d50e](https://github.com/parse-community/parse-server/commit/3d6d50e0afff18b95fb906914e2cebd3839b517a))
+* Security bump @babel/traverse from 7.20.5 to 7.23.2 ([#8777](https://github.com/parse-community/parse-server/issues/8777)) ([2d6b3d1](https://github.com/parse-community/parse-server/commit/2d6b3d18499179e99be116f25c0850d3f449509c))
+* Security upgrade graphql from 16.6.0 to 16.8.1 ([#8758](https://github.com/parse-community/parse-server/issues/8758)) ([71dfd8a](https://github.com/parse-community/parse-server/commit/71dfd8a7ece8c0dd1a66d03bb9420cfd39f4f9b1))
+
+### Features
+
+* Add `$setOnInsert` operator to `Parse.Server.database.update` ([#8791](https://github.com/parse-community/parse-server/issues/8791)) ([f630a45](https://github.com/parse-community/parse-server/commit/f630a45aa5e87bc73a81fded061400c199b71a29))
+* Add compatibility for MongoDB Atlas Serverless and AWS Amazon DocumentDB with collation options `enableCollationCaseComparison`, `transformEmailToLowercase`, `transformUsernameToLowercase` ([#8805](https://github.com/parse-community/parse-server/issues/8805)) ([09fbeeb](https://github.com/parse-community/parse-server/commit/09fbeebba8870e7cf371fb84371a254c7b368620))
+* Add context to Cloud Code Triggers `beforeLogin` and `afterLogin` ([#8724](https://github.com/parse-community/parse-server/issues/8724)) ([a9c34ef](https://github.com/parse-community/parse-server/commit/a9c34ef1e2c78a42fb8b5fa8d569b7677c74919d))
+* Allow setting `createdAt` and `updatedAt` during `Parse.Object` creation with maintenance key ([#8696](https://github.com/parse-community/parse-server/issues/8696)) ([77bbfb3](https://github.com/parse-community/parse-server/commit/77bbfb3f186f5651c33ba152f04cff95128eaf2d))
+
+# [6.4.0-beta.1](https://github.com/parse-community/parse-server/compare/6.3.0...6.4.0-beta.1) (2023-09-16)
+
+
+### Bug Fixes
+
+* Parse Server option `fileUpload.fileExtensions` does not work with an array of extensions ([#8688](https://github.com/parse-community/parse-server/issues/8688)) ([6a4a00c](https://github.com/parse-community/parse-server/commit/6a4a00ca7af1163ea74b047b85cd6817366b824b))
+* Redis 4 does not reconnect after unhandled error ([#8706](https://github.com/parse-community/parse-server/issues/8706)) ([2b3d4e5](https://github.com/parse-community/parse-server/commit/2b3d4e5d3c85cd142f85af68dec51a8523548d49))
+* Remove config logging when launching Parse Server via CLI ([#8710](https://github.com/parse-community/parse-server/issues/8710)) ([ae68f0c](https://github.com/parse-community/parse-server/commit/ae68f0c31b741eeb83379c905c7ddfaa124436ec))
+* Server does not start via CLI when `auth` option is set ([#8666](https://github.com/parse-community/parse-server/issues/8666)) ([4e2000b](https://github.com/parse-community/parse-server/commit/4e2000bc563324389584ace3c090a5c1a7796a64))
+
+### Features
+
+* Add conditional email verification via dynamic Parse Server options `verifyUserEmails`, `sendUserEmailVerification` that now accept functions ([#8425](https://github.com/parse-community/parse-server/issues/8425)) ([44acd6d](https://github.com/parse-community/parse-server/commit/44acd6d9ed157ad4842200c9d01f9c77a05fec3a))
+* Add property `Parse.Server.version` to determine current version of Parse Server in Cloud Code ([#8670](https://github.com/parse-community/parse-server/issues/8670)) ([a9d376b](https://github.com/parse-community/parse-server/commit/a9d376b61f5b07806eafbda91c4e36c322f09298))
+* Add TOTP authentication adapter ([#8457](https://github.com/parse-community/parse-server/issues/8457)) ([cc079a4](https://github.com/parse-community/parse-server/commit/cc079a40f6849a0e9bc6fdc811e8649ecb67b589))
+
+### Performance Improvements
+
+* Improve performance of recursive pointer iterations ([#8741](https://github.com/parse-community/parse-server/issues/8741)) ([45a3ed0](https://github.com/parse-community/parse-server/commit/45a3ed0fcf2c0170607505a1550fb15896e705fd))
+
# [6.3.0-beta.1](https://github.com/parse-community/parse-server/compare/6.2.0...6.3.0-beta.1) (2023-06-10)
diff --git a/changelogs/CHANGELOG_release.md b/changelogs/CHANGELOG_release.md
index 4cd0131cdb..eaf5301ccc 100644
--- a/changelogs/CHANGELOG_release.md
+++ b/changelogs/CHANGELOG_release.md
@@ -1,3 +1,69 @@
+# [6.4.0](https://github.com/parse-community/parse-server/compare/6.3.1...6.4.0) (2023-11-16)
+
+
+### Bug Fixes
+
+* Parse Server option `fileUpload.fileExtensions` does not work with an array of extensions ([#8688](https://github.com/parse-community/parse-server/issues/8688)) ([6a4a00c](https://github.com/parse-community/parse-server/commit/6a4a00ca7af1163ea74b047b85cd6817366b824b))
+* Redis 4 does not reconnect after unhandled error ([#8706](https://github.com/parse-community/parse-server/issues/8706)) ([2b3d4e5](https://github.com/parse-community/parse-server/commit/2b3d4e5d3c85cd142f85af68dec51a8523548d49))
+* Remove config logging when launching Parse Server via CLI ([#8710](https://github.com/parse-community/parse-server/issues/8710)) ([ae68f0c](https://github.com/parse-community/parse-server/commit/ae68f0c31b741eeb83379c905c7ddfaa124436ec))
+* Server does not start via CLI when `auth` option is set ([#8666](https://github.com/parse-community/parse-server/issues/8666)) ([4e2000b](https://github.com/parse-community/parse-server/commit/4e2000bc563324389584ace3c090a5c1a7796a64))
+
+### Features
+
+* Add conditional email verification via dynamic Parse Server options `verifyUserEmails`, `sendUserEmailVerification` that now accept functions ([#8425](https://github.com/parse-community/parse-server/issues/8425)) ([44acd6d](https://github.com/parse-community/parse-server/commit/44acd6d9ed157ad4842200c9d01f9c77a05fec3a))
+* Add property `Parse.Server.version` to determine current version of Parse Server in Cloud Code ([#8670](https://github.com/parse-community/parse-server/issues/8670)) ([a9d376b](https://github.com/parse-community/parse-server/commit/a9d376b61f5b07806eafbda91c4e36c322f09298))
+* Add TOTP authentication adapter ([#8457](https://github.com/parse-community/parse-server/issues/8457)) ([cc079a4](https://github.com/parse-community/parse-server/commit/cc079a40f6849a0e9bc6fdc811e8649ecb67b589))
+
+### Performance Improvements
+
+* Improve performance of recursive pointer iterations ([#8741](https://github.com/parse-community/parse-server/issues/8741)) ([45a3ed0](https://github.com/parse-community/parse-server/commit/45a3ed0fcf2c0170607505a1550fb15896e705fd))
+
+## [6.3.1](https://github.com/parse-community/parse-server/compare/6.3.0...6.3.1) (2023-10-20)
+
+
+### Bug Fixes
+
+* Server crash when uploading file without extension; fixes security vulnerability [GHSA-792q-q67h-w579](https://github.com/parse-community/parse-server/security/advisories/GHSA-792q-q67h-w579) ([#8781](https://github.com/parse-community/parse-server/issues/8781)) ([fd86278](https://github.com/parse-community/parse-server/commit/fd86278919556d3682e7e2c856dfccd5beffbfc0))
+
+# [6.3.0](https://github.com/parse-community/parse-server/compare/6.2.2...6.3.0) (2023-09-16)
+
+
+### Bug Fixes
+
+* Cloud Code Trigger `afterSave` executes even if not set ([#8520](https://github.com/parse-community/parse-server/issues/8520)) ([afd0515](https://github.com/parse-community/parse-server/commit/afd0515e207bd947840579d3f245980dffa6f804))
+* GridFS file storage doesn't work with certain `enableSchemaHooks` settings ([#8467](https://github.com/parse-community/parse-server/issues/8467)) ([d4cda4b](https://github.com/parse-community/parse-server/commit/d4cda4b26c9bde8c812549b8780bea1cfabdb394))
+* Inaccurate table total row count for PostgreSQL ([#8511](https://github.com/parse-community/parse-server/issues/8511)) ([0823a02](https://github.com/parse-community/parse-server/commit/0823a02fbf80bc88dc403bc47e9f5c6597ea78b4))
+* LiveQuery server is not shut down properly when `handleShutdown` is called ([#8491](https://github.com/parse-community/parse-server/issues/8491)) ([967700b](https://github.com/parse-community/parse-server/commit/967700bdbc94c74f75ba84d2b3f4b9f3fd2dca0b))
+* Rate limit feature is incompatible with Node 14 ([#8578](https://github.com/parse-community/parse-server/issues/8578)) ([f911f2c](https://github.com/parse-community/parse-server/commit/f911f2cd3a8c45cd326272dcd681532764a3761e))
+* Unnecessary log entries by `extendSessionOnUse` ([#8562](https://github.com/parse-community/parse-server/issues/8562)) ([fd6a007](https://github.com/parse-community/parse-server/commit/fd6a0077f2e5cf83d65e52172ae5a950ab0f1eae))
+
+### Features
+
+* `extendSessionOnUse` to automatically renew Parse Sessions ([#8505](https://github.com/parse-community/parse-server/issues/8505)) ([6f885d3](https://github.com/parse-community/parse-server/commit/6f885d36b94902fdfea873fc554dee83589e6029))
+* Add new Parse Server option `preventSignupWithUnverifiedEmail` to prevent returning a user without session token on sign-up with unverified email address ([#8451](https://github.com/parse-community/parse-server/issues/8451)) ([82da308](https://github.com/parse-community/parse-server/commit/82da30842a55980aa90cb7680fbf6db37ee16dab))
+* Add option to change the log level of logs emitted by Cloud Functions ([#8530](https://github.com/parse-community/parse-server/issues/8530)) ([2caea31](https://github.com/parse-community/parse-server/commit/2caea310be412d82b04a85716bc769ccc410316d))
+* Add support for `$eq` query constraint in LiveQuery ([#8614](https://github.com/parse-community/parse-server/issues/8614)) ([656d673](https://github.com/parse-community/parse-server/commit/656d673cf5dea354e4f2b3d4dc2b29a41d311b3e))
+* Add zones for rate limiting by `ip`, `user`, `session`, `global` ([#8508](https://github.com/parse-community/parse-server/issues/8508)) ([03fba97](https://github.com/parse-community/parse-server/commit/03fba97e0549bfcaeee9f2fa4c9905dbcc91840e))
+* Allow `Parse.Object` pointers in Cloud Code arguments ([#8490](https://github.com/parse-community/parse-server/issues/8490)) ([28aeda3](https://github.com/parse-community/parse-server/commit/28aeda3f160efcbbcf85a85484a8d26567fa9761))
+
+### Reverts
+
+* fix: Inaccurate table total row count for PostgreSQL ([6722110](https://github.com/parse-community/parse-server/commit/6722110f203bc5fdcaa68cdf091cf9e7b48d1cff))
+
+## [6.2.2](https://github.com/parse-community/parse-server/compare/6.2.1...6.2.2) (2023-09-04)
+
+
+### Bug Fixes
+
+* Parse Pointer allows to access internal Parse Server classes and circumvent `beforeFind` query trigger; fixes security vulnerability [GHSA-fcv6-fg5r-jm9q](https://github.com/parse-community/parse-server/security/advisories/GHSA-fcv6-fg5r-jm9q) ([be4c7e2](https://github.com/parse-community/parse-server/commit/be4c7e23c63a2fb690685665cebed0de26be05c5))
+
+## [6.2.1](https://github.com/parse-community/parse-server/compare/6.2.0...6.2.1) (2023-06-28)
+
+
+### Bug Fixes
+
+* Remote code execution via MongoDB BSON parser through prototype pollution; fixes security vulnerability [GHSA-462x-c3jw-7vr6](https://github.com/parse-community/parse-server/security/advisories/GHSA-462x-c3jw-7vr6) ([#8674](https://github.com/parse-community/parse-server/issues/8674)) ([3dd99dd](https://github.com/parse-community/parse-server/commit/3dd99dd80e27e5e1d99b42844180546d90c7aa90))
+
# [6.2.0](https://github.com/parse-community/parse-server/compare/6.1.0...6.2.0) (2023-05-20)
diff --git a/jsdoc-conf.json b/jsdoc-conf.json
index 4a1e5de846..efbaa0a37c 100644
--- a/jsdoc-conf.json
+++ b/jsdoc-conf.json
@@ -29,7 +29,7 @@
"template": "./node_modules/clean-jsdoc-theme",
"theme_opts": {
"default_theme": "dark",
- "title": "Parse Server",
+ "title": "
",
"create_style": "header, .sidebar-section-title, .sidebar-title { color: #139cee !important } .logo { margin-left : 40px; margin-right: 40px }"
}
},
diff --git a/package-lock.json b/package-lock.json
index a617dd7c3e..f52f11c463 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "parse-server",
- "version": "6.3.0-beta.1",
+ "version": "7.0.0-alpha.9",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "parse-server",
- "version": "6.3.0-beta.1",
+ "version": "7.0.0-alpha.9",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -16,7 +16,7 @@
"@graphql-tools/utils": "8.12.0",
"@graphql-yoga/node": "2.6.0",
"@parse/fs-files-adapter": "1.2.2",
- "@parse/push-adapter": "4.1.3",
+ "@parse/push-adapter": "5.0.2",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"commander": "10.0.1",
@@ -24,21 +24,21 @@
"deepcopy": "2.1.0",
"express": "4.18.2",
"express-rate-limit": "6.7.0",
- "follow-redirects": "1.15.2",
- "graphql": "16.6.0",
+ "follow-redirects": "^1.15.4",
+ "graphql": "16.8.1",
"graphql-list-fields": "2.0.2",
"graphql-relay": "0.10.0",
"graphql-tag": "2.12.6",
"intersect": "1.0.1",
- "ip-range-check": "0.2.0",
"jsonwebtoken": "9.0.0",
"jwks-rsa": "2.1.5",
"ldapjs": "3.0.2",
"lodash": "4.17.21",
"lru-cache": "9.1.1",
"mime": "3.0.0",
- "mongodb": "4.10.0",
+ "mongodb": "5.9.0",
"mustache": "4.2.0",
+ "otpauth": "9.1.2",
"parse": "4.1.0",
"path-to-regexp": "6.2.1",
"pg-monitor": "2.0.0",
@@ -46,7 +46,7 @@
"pluralize": "8.0.0",
"rate-limit-redis": "3.0.2",
"redis": "4.6.6",
- "semver": "7.5.1",
+ "semver": "7.5.2",
"subscriptions-transport-ws": "0.11.0",
"tv4": "1.3.0",
"uuid": "9.0.0",
@@ -92,7 +92,7 @@
"madge": "5.0.1",
"mock-files-adapter": "file:spec/dependencies/mock-files-adapter",
"mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter",
- "mongodb-runner": "4.8.1",
+ "mongodb-runner": "5.4.4",
"mongodb-version-list": "1.0.0",
"node-abort-controller": "3.0.1",
"node-fetch": "3.2.10",
@@ -226,11 +226,12 @@
}
},
"node_modules/@babel/code-frame": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
- "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dependencies": {
- "@babel/highlight": "^7.18.6"
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
},
"engines": {
"node": ">=6.9.0"
@@ -324,12 +325,13 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
- "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+ "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dependencies": {
- "@babel/types": "^7.20.5",
+ "@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"engines": {
@@ -375,9 +377,9 @@
}
},
"node_modules/@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==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"engines": {
"node": ">=6.9.0"
}
@@ -395,23 +397,23 @@
}
},
"node_modules/@babel/helper-function-name": {
- "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==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dependencies": {
- "@babel/template": "^7.18.10",
- "@babel/types": "^7.19.0"
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-hoist-variables": {
- "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==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dependencies": {
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
@@ -519,28 +521,28 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
- "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==",
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dependencies": {
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@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==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "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==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"engines": {
"node": ">=6.9.0"
}
@@ -582,12 +584,12 @@
}
},
"node_modules/@babel/highlight": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
- "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.18.6",
- "chalk": "^2.0.0",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
"js-tokens": "^4.0.0"
},
"engines": {
@@ -595,9 +597,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.21.4",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
- "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+ "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -1796,31 +1798,31 @@
}
},
"node_modules/@babel/template": {
- "version": "7.18.10",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
- "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dependencies": {
- "@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.18.10",
- "@babel/types": "^7.18.10"
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
- "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
- "dependencies": {
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.5",
- "@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.5",
- "@babel/types": "^7.20.5",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+ "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
+ "dependencies": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/generator": "^7.23.0",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.0",
+ "@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -1829,12 +1831,12 @@
}
},
"node_modules/@babel/types": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
- "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+ "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dependencies": {
- "@babel/helper-string-parser": "^7.19.4",
- "@babel/helper-validator-identifier": "^7.19.1",
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -2402,6 +2404,70 @@
"resolved": "https://registry.npmjs.org/@ldapjs/protocol/-/protocol-1.2.1.tgz",
"integrity": "sha512-O89xFDLW2gBoZWNXuXpBSM32/KealKCTb3JGtJdtUQc7RjAk8XzrRgyz02cPAwGKwKPxy0ivuC7UP9bmN87egQ=="
},
+ "node_modules/@mongodb-js/mongodb-downloader": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.2.8.tgz",
+ "integrity": "sha512-y+mgw9QspvgTLRNHZJRS+DUTPk45RWpvYD1MaGDWhZ4ajffvxGqanY+Z4R6z01n+tIRmQvpShzF6zk+2Pr9d6w==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "decompress": "^4.2.1",
+ "mongodb-download-url": "^1.3.0",
+ "node-fetch": "^2.6.11",
+ "tar": "^6.1.15"
+ }
+ },
+ "node_modules/@mongodb-js/mongodb-downloader/node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@mongodb-js/mongodb-downloader/node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "node_modules/@mongodb-js/mongodb-downloader/node_modules/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
+ },
+ "node_modules/@mongodb-js/mongodb-downloader/node_modules/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,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/@mongodb-js/saslprep": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz",
+ "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==",
+ "optional": true,
+ "dependencies": {
+ "sparse-bitfield": "^3.0.3"
+ }
+ },
"node_modules/@napi-rs/triples": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.1.0.tgz",
@@ -2807,17 +2873,17 @@
"integrity": "sha512-VUsVZXgt53FULqUd9xqGDW6RXes62qHXTNOeRSlS1MOemiCdtQOUGgLHgjdYQXnZ1hPLkxZKph96AluZUb953g=="
},
"node_modules/@parse/node-apn": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.3.tgz",
- "integrity": "sha512-Bwhmbm895lEIF2772PJ8dSvBjrtOG9/q/TDMxmX40IgZxQFoXS73+JUIKTq3CA7SUB/Szu5roJINQ0L2U/1MJw==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-6.0.1.tgz",
+ "integrity": "sha512-QQxqEN/zbtEkSgj41oX/tQUavML+G+JHeQi2YVlgZlponnwIxA3fb5tEbXPm+fdR6rL1pi2/z2PcOwINOyx2eA==",
"dependencies": {
"debug": "4.3.3",
- "jsonwebtoken": "8.5.1",
- "node-forge": "1.3.0",
+ "jsonwebtoken": "9.0.0",
+ "node-forge": "1.3.1",
"verror": "1.10.1"
},
"engines": {
- "node": ">= 12"
+ "node": ">= 14"
}
},
"node_modules/@parse/node-apn/node_modules/debug": {
@@ -2836,35 +2902,6 @@
}
}
},
- "node_modules/@parse/node-apn/node_modules/jsonwebtoken": {
- "version": "8.5.1",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
- "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
- "dependencies": {
- "jws": "^3.2.2",
- "lodash.includes": "^4.3.0",
- "lodash.isboolean": "^3.0.3",
- "lodash.isinteger": "^4.0.4",
- "lodash.isnumber": "^3.0.3",
- "lodash.isplainobject": "^4.0.6",
- "lodash.isstring": "^4.0.1",
- "lodash.once": "^4.0.0",
- "ms": "^2.1.1",
- "semver": "^5.6.0"
- },
- "engines": {
- "node": ">=4",
- "npm": ">=1.4.28"
- }
- },
- "node_modules/@parse/node-apn/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "bin": {
- "semver": "bin/semver"
- }
- },
"node_modules/@parse/node-gcm": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@parse/node-gcm/-/node-gcm-1.0.2.tgz",
@@ -2887,91 +2924,36 @@
}
},
"node_modules/@parse/push-adapter": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.3.tgz",
- "integrity": "sha512-Oy53ag7DpUva5dUWwP6tNEsrxv2xU9QIk+rb84q1DIm1qVgo2yl4oXcZ3FPG2Ks/NYURbv4w+z9oaSgVfyBRfQ==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-5.0.2.tgz",
+ "integrity": "sha512-0nVBGj8p8cYGjoMdkVAlsa/UlB1Z4W6Ch7MEVcEfnyCmJBw6bvHwB1VVWoclcRqi3phsu3SizR5zVvB/Cx8I/g==",
"dependencies": {
- "@parse/node-apn": "5.1.3",
+ "@parse/node-apn": "6.0.1",
"@parse/node-gcm": "1.0.2",
"npmlog": "4.1.2",
- "parse": "3.4.0"
- },
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/@parse/push-adapter/node_modules/@babel/runtime": {
- "version": "7.15.4",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz",
- "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==",
- "dependencies": {
- "regenerator-runtime": "^0.13.4"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@parse/push-adapter/node_modules/@babel/runtime-corejs3": {
- "version": "7.14.7",
- "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz",
- "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==",
- "dependencies": {
- "core-js-pure": "^3.15.0",
- "regenerator-runtime": "^0.13.4"
+ "parse": "4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">= 14"
}
},
- "node_modules/@parse/push-adapter/node_modules/idb-keyval": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-5.0.6.tgz",
- "integrity": "sha512-6lJuVbwyo82mKSH6Wq2eHkt9LcbwHAelMIcMe0tP4p20Pod7tTxq9zf0ge2n/YDfMOpDryerfmmYyuQiaFaKOg=="
- },
"node_modules/@parse/push-adapter/node_modules/parse": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.0.tgz",
- "integrity": "sha512-FMZLxPW6PvrBgxkXc9AmnYsFKvPwiS4G2n9OI4mdfiSoNzIVLc+bXzlUdJ+I7hiqHsBTP0BrdQczw2/cnVkJ6w==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/parse/-/parse-4.2.0.tgz",
+ "integrity": "sha512-K8bWs0wM2qRhkSr6N16j8OvsF6Uallrynqng9e+tzR3RdKuB09vaJh48qrf9MbiJ1Ya4JZI7AfEHYF+ywEKs7Q==",
"dependencies": {
- "@babel/runtime": "7.15.4",
- "@babel/runtime-corejs3": "7.14.7",
- "idb-keyval": "5.0.6",
+ "@babel/runtime-corejs3": "7.21.0",
+ "idb-keyval": "6.2.0",
"react-native-crypto-js": "1.0.0",
- "uuid": "3.4.0",
- "ws": "7.5.1",
+ "uuid": "9.0.0",
+ "ws": "8.13.0",
"xmlhttprequest": "1.8.0"
},
- "optionalDependencies": {
- "crypto-js": "4.1.1"
- }
- },
- "node_modules/@parse/push-adapter/node_modules/uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
- "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
- "bin": {
- "uuid": "bin/uuid"
- }
- },
- "node_modules/@parse/push-adapter/node_modules/ws": {
- "version": "7.5.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
- "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
"engines": {
- "node": ">=8.3.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "node": ">=14.21.0 <17 || >=18 <20"
},
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
+ "optionalDependencies": {
+ "crypto-js": "4.1.1"
}
},
"node_modules/@redis/bloom": {
@@ -3719,73 +3701,6 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
- "node_modules/ampersand-events": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/ampersand-events/-/ampersand-events-2.0.2.tgz",
- "integrity": "sha512-pPnVEJviRxXi9YhZA9j3GwGGBTlDLi+YIoBvrpKXgce+CO1nMlZU2aOV8OJogNuR2YPbptAUHNz7SKX+MvLj8A==",
- "dev": true,
- "dependencies": {
- "ampersand-version": "^1.0.2",
- "lodash": "^4.6.1"
- }
- },
- "node_modules/ampersand-state": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/ampersand-state/-/ampersand-state-5.0.3.tgz",
- "integrity": "sha512-sr904K5zvw6mkGjFHhTcfBIdpoJ6mn/HrFg7OleRmBpw3apLb3Z0gVrgRTb7kK1wOLI34vs4S+IXqNHUeqWCzw==",
- "dev": true,
- "dependencies": {
- "ampersand-events": "^2.0.1",
- "ampersand-version": "^1.0.0",
- "array-next": "~0.0.1",
- "key-tree-store": "^1.3.0",
- "lodash": "^4.12.0"
- }
- },
- "node_modules/ampersand-version": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/ampersand-version/-/ampersand-version-1.0.2.tgz",
- "integrity": "sha512-FVVLY7Pghtgc8pQl0rF3A3+OS/CZ+/ILLMIYIaO1cA9v5SRkainqUMfSot3fu32svuThIsYK3q9iCsH9W5+mWQ==",
- "dev": true,
- "dependencies": {
- "find-root": "^0.1.1",
- "through2": "^0.6.3"
- }
- },
- "node_modules/ampersand-version/node_modules/isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
- "dev": true
- },
- "node_modules/ampersand-version/node_modules/readable-stream": {
- "version": "1.0.34",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
- "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
- "dev": true,
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.1",
- "isarray": "0.0.1",
- "string_decoder": "~0.10.x"
- }
- },
- "node_modules/ampersand-version/node_modules/string_decoder": {
- "version": "0.10.31",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
- "dev": true
- },
- "node_modules/ampersand-version/node_modules/through2": {
- "version": "0.6.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
- "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==",
- "dev": true,
- "dependencies": {
- "readable-stream": ">=1.0.33-1 <1.1.0-0",
- "xtend": ">=4.0.0 <4.1.0-0"
- }
- },
"node_modules/ansi": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz",
@@ -4125,12 +4040,6 @@
"integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
"dev": true
},
- "node_modules/array-next": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/array-next/-/array-next-0.0.1.tgz",
- "integrity": "sha512-sBOC/Iaz2hCcYi2XlyRfyZCRUxamlE5NJXEFjE9BTx23HALnWAFsPjGtfrAclt9o3G/38Het2yyeyOd3CEY7lg==",
- "dev": true
- },
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -4371,6 +4280,7 @@
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -4570,20 +4480,18 @@
}
},
"node_modules/bson": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz",
- "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==",
- "dependencies": {
- "buffer": "^5.6.0"
- },
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz",
+ "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g==",
"engines": {
- "node": ">=6.9.0"
+ "node": ">=14.20.1"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -4875,21 +4783,6 @@
"node": ">= 8"
}
},
- "node_modules/caw": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
- "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
- "dev": true,
- "dependencies": {
- "get-proxy": "^2.0.0",
- "isurl": "^1.0.0-alpha5",
- "tunnel-agent": "^0.6.0",
- "url-to-options": "^1.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -4954,6 +4847,15 @@
"fsevents": "^1.2.7"
}
},
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
@@ -5038,18 +4940,6 @@
"node": ">=6"
}
},
- "node_modules/cli-color": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz",
- "integrity": "sha512-Ys/nDhHNRcxrS4EUI2RS/QCUE+61AMuEOj3sWDX+EIHkJWj+4XkRbOdwdxJteAJKjXYBbeFJMtfaEPd1MBF9pQ==",
- "dev": true,
- "dependencies": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.2",
- "memoizee": "0.3.x",
- "timers-ext": "0.1.x"
- }
- },
"node_modules/cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -5137,15 +5027,6 @@
"node": ">=0.8"
}
},
- "node_modules/clui": {
- "version": "0.3.6",
- "resolved": "https://registry.npmjs.org/clui/-/clui-0.3.6.tgz",
- "integrity": "sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==",
- "dev": true,
- "dependencies": {
- "cli-color": "0.3.2"
- }
- },
"node_modules/cluster-key-slot": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
@@ -5315,22 +5196,6 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
- "node_modules/config-chain": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
- "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
- "dev": true,
- "dependencies": {
- "ini": "^1.3.4",
- "proto-list": "~1.2.1"
- }
- },
- "node_modules/connected-domain": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz",
- "integrity": "sha512-lHlohUiJxlpunvDag2Y0pO20bnvarMjnrdciZeuJUqRwrf/5JHNhdpiPIr5GQ8IkqrFj5TDMQwcCjblGo1oeuA==",
- "dev": true
- },
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -5637,15 +5502,6 @@
"node": "*"
}
},
- "node_modules/d": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz",
- "integrity": "sha512-0SdM9V9pd/OXJHoWmTfNPTAeD+lw6ZqHg+isPyBFuJsZLSE0Ygg1cYZ/0l6DrKQXMOqGOu1oWupMoOfoRfMZrQ==",
- "dev": true,
- "dependencies": {
- "es5-ext": "~0.10.2"
- }
- },
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -6064,14 +5920,6 @@
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
},
- "node_modules/denque": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
- "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -6256,15 +6104,6 @@
"node": ">=8"
}
},
- "node_modules/docopt": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
- "integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -6374,155 +6213,6 @@
"rimraf": "bin.js"
}
},
- "node_modules/download": {
- "version": "6.2.5",
- "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz",
- "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==",
- "dev": true,
- "dependencies": {
- "caw": "^2.0.0",
- "content-disposition": "^0.5.2",
- "decompress": "^4.0.0",
- "ext-name": "^5.0.0",
- "file-type": "5.2.0",
- "filenamify": "^2.0.0",
- "get-stream": "^3.0.0",
- "got": "^7.0.0",
- "make-dir": "^1.0.0",
- "p-event": "^1.0.0",
- "pify": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/decompress-response": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
- "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
- "dev": true,
- "dependencies": {
- "mimic-response": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/get-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
- "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/got": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz",
- "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==",
- "dev": true,
- "dependencies": {
- "decompress-response": "^3.2.0",
- "duplexer3": "^0.1.4",
- "get-stream": "^3.0.0",
- "is-plain-obj": "^1.1.0",
- "is-retry-allowed": "^1.0.0",
- "is-stream": "^1.0.0",
- "isurl": "^1.0.0-alpha5",
- "lowercase-keys": "^1.0.0",
- "p-cancelable": "^0.3.0",
- "p-timeout": "^1.1.1",
- "safe-buffer": "^5.0.1",
- "timed-out": "^4.0.0",
- "url-parse-lax": "^1.0.0",
- "url-to-options": "^1.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/is-stream": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/download/node_modules/lowercase-keys": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
- "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/download/node_modules/make-dir": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
- "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
- "dev": true,
- "dependencies": {
- "pify": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/mimic-response": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
- "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/p-cancelable": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz",
- "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/p-event": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz",
- "integrity": "sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA==",
- "dev": true,
- "dependencies": {
- "p-timeout": "^1.1.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/p-timeout": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
- "integrity": "sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==",
- "dev": true,
- "dependencies": {
- "p-finally": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/download/node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/dset": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz",
@@ -6540,12 +6230,6 @@
"readable-stream": "^2.0.2"
}
},
- "node_modules/duplexer3": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
- "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==",
- "dev": true
- },
"node_modules/ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -6730,39 +6414,6 @@
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
- "node_modules/es6-weak-map": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz",
- "integrity": "sha512-P+N5Cd2TXeb7G59euFiM7snORspgbInS29Nbf3KNO2JQp/DyhvMCDWd58nsVAXwYJ6W3Bx7qDdy6QQ3PCJ7jKQ==",
- "dev": true,
- "dependencies": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.6",
- "es6-iterator": "~0.1.3",
- "es6-symbol": "~2.0.1"
- }
- },
- "node_modules/es6-weak-map/node_modules/es6-iterator": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz",
- "integrity": "sha512-6TOmbFM6OPWkTe+bQ3ZuUkvqcWUjAnYjKUCLdbvRsAUz2Pr+fYIibwNXNkLNtIK9PPFbNMZZddaRNkyJhlGJhA==",
- "dev": true,
- "dependencies": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.5",
- "es6-symbol": "~2.0.1"
- }
- },
- "node_modules/es6-weak-map/node_modules/es6-symbol": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz",
- "integrity": "sha512-wjobO4zO8726HVU7mI2OA/B6QszqwHJuKab7gKHVx+uRfVVYGcWJkCIFxV2Madqb9/RUSrhJ/r6hPfG7FsWtow==",
- "dev": true,
- "dependencies": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.5"
- }
- },
"node_modules/escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -7442,31 +7093,6 @@
"type": "^2.7.2"
}
},
- "node_modules/ext-list": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
- "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
- "dev": true,
- "dependencies": {
- "mime-db": "^1.28.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ext-name": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
- "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
- "dev": true,
- "dependencies": {
- "ext-list": "^2.0.0",
- "sort-keys-length": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -7795,29 +7421,6 @@
"dev": true,
"optional": true
},
- "node_modules/filename-reserved-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
- "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/filenamify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz",
- "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==",
- "dev": true,
- "dependencies": {
- "filename-reserved-regex": "^2.0.0",
- "strip-outer": "^1.0.0",
- "trim-repeated": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/filing-cabinet": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-3.3.0.tgz",
@@ -8014,12 +7617,6 @@
"semver": "bin/semver.js"
}
},
- "node_modules/find-root": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/find-root/-/find-root-0.1.2.tgz",
- "integrity": "sha512-GyDxVgA61TZcrgDJPqOqGBpi80Uf2yIstubgizi7AjC9yPdRrqBR+Y0MvK4kXnYlaoz3d+SGxDHMYVkwI/yd2w==",
- "dev": true
- },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -8092,9 +7689,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"node_modules/follow-redirects": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
- "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "version": "1.15.4",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
+ "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"funding": [
{
"type": "individual",
@@ -8272,6 +7869,30 @@
"node": ">=10"
}
},
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
@@ -8416,35 +8037,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-mongodb-version": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/get-mongodb-version/-/get-mongodb-version-2.0.1.tgz",
- "integrity": "sha512-yTN0UY7VJSSt01QH/aCiqiBjfxcDrEdKeM3uXY6QR3sRARoftx36QT0YNsCQm7FDTgrmDje7bK2C9ClM7SGKDA==",
- "dev": true,
- "dependencies": {
- "lodash.startswith": "^4.2.1",
- "minimist": "^1.1.1",
- "which": "^1.1.1"
- },
- "bin": {
- "get-mongodb-version": "bin/get-mongodb-version.js"
- },
- "optionalDependencies": {
- "mongodb": "*"
- }
- },
- "node_modules/get-mongodb-version/node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
- },
"node_modules/get-own-enumerable-property-symbols": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
@@ -8460,18 +8052,6 @@
"node": ">=8.0.0"
}
},
- "node_modules/get-proxy": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
- "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==",
- "dev": true,
- "dependencies": {
- "npm-conf": "^1.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -8698,9 +8278,9 @@
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ=="
},
"node_modules/graphql": {
- "version": "16.6.0",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz",
- "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==",
+ "version": "16.8.1",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz",
+ "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==",
"engines": {
"node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
}
@@ -8827,15 +8407,6 @@
"node": ">=4"
}
},
- "node_modules/has-symbol-support-x": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
- "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
@@ -8847,18 +8418,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-to-string-tag-x": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
- "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
- "dev": true,
- "dependencies": {
- "has-symbol-support-x": "^1.4.1"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -9271,6 +8830,7 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -9408,14 +8968,6 @@
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
},
- "node_modules/ip-range-check": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/ip-range-check/-/ip-range-check-0.2.0.tgz",
- "integrity": "sha512-oaM3l/3gHbLlt/tCWLvt0mj1qUaI+STuRFnUvARGCujK9vvU61+2JsDpmkMzR4VsJhuFXWWgeKKVnwwoFfzCqw==",
- "dependencies": {
- "ipaddr.js": "^1.0.1"
- }
- },
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -9559,37 +9111,6 @@
"node": ">=8"
}
},
- "node_modules/is-mongodb-running": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-mongodb-running/-/is-mongodb-running-1.0.2.tgz",
- "integrity": "sha512-EslN8MErcBPExb+iK4RnG1n28JGjByA2Rm3YPmdHDGCRd7Hc2uvqshyVMAJXxbDSxRMy8vhxims2oRqQUeGJeA==",
- "dev": true,
- "dependencies": {
- "chalk": "^2.4.1",
- "debug": ">= 2.6.9",
- "figures": "^2.0.0",
- "lodash": "^4.17.10",
- "lsof": "^0.1.0",
- "minimist": "^1.2.0",
- "node-netstat": "^1.4.2",
- "ps-node": "^0.1.6"
- },
- "bin": {
- "is-mongodb-running": "bin/is-mongodb-running.js"
- }
- },
- "node_modules/is-mongodb-running/node_modules/figures": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
- "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
- "dev": true,
- "dependencies": {
- "escape-string-regexp": "^1.0.5"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/is-natural-number": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
@@ -9618,15 +9139,6 @@
"node": ">=8"
}
},
- "node_modules/is-object": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
- "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-path-cwd": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
@@ -9682,15 +9194,6 @@
"integrity": "sha512-i1h+y50g+0hRbBD+dbnInl3JlJ702aar58snAeX+MxBAPvzXGej7sYoPMhlnykabt0ZzCJNBEyzMlekuQZN7fA==",
"dev": true
},
- "node_modules/is-retry-allowed": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
- "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -9758,15 +9261,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -9986,19 +9480,6 @@
"node": ">=8"
}
},
- "node_modules/isurl": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
- "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
- "dev": true,
- "dependencies": {
- "has-to-string-tag-x": "^1.2.0",
- "is-object": "^1.0.1"
- },
- "engines": {
- "node": ">= 4"
- }
- },
"node_modules/iterall": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz",
@@ -10297,6 +9778,14 @@
"extsprintf": "^1.2.0"
}
},
+ "node_modules/jssha": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.3.0.tgz",
+ "integrity": "sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
@@ -10332,12 +9821,6 @@
"safe-buffer": "^5.0.1"
}
},
- "node_modules/key-tree-store": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/key-tree-store/-/key-tree-store-1.3.0.tgz",
- "integrity": "sha512-qXk+lR+LXvGos3wqMxIMWweKDgCx8ZKWM6BEPm7iZkOKug5ggi66vUt+3vbtKJLBrAyOxQ4S8JRwK++Q4XZRmw==",
- "dev": true
- },
"node_modules/keyv": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
@@ -10824,12 +10307,6 @@
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
"dev": true
},
- "node_modules/lodash.difference": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
- "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
- "dev": true
- },
"node_modules/lodash.escaperegexp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
@@ -10860,41 +10337,23 @@
"integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==",
"dev": true
},
- "node_modules/lodash.includes": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
- "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
- },
- "node_modules/lodash.isboolean": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
- "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="
- },
- "node_modules/lodash.isinteger": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
- "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
- },
"node_modules/lodash.ismatch": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz",
"integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==",
"dev": true
},
- "node_modules/lodash.isnumber": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
- "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw=="
- },
"node_modules/lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "dev": true
},
"node_modules/lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
- "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "dev": true
},
"node_modules/lodash.map": {
"version": "4.6.0",
@@ -10907,11 +10366,6 @@
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
- "node_modules/lodash.once": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
- },
"node_modules/lodash.pad": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz",
@@ -10954,12 +10408,6 @@
"integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==",
"dev": true
},
- "node_modules/lodash.startswith": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz",
- "integrity": "sha512-XClYR1h4/fJ7H+mmCKppbiBmljN/nGs73iq2SjCT9SF4CBPoUHzLvWmH1GtZMhMBZSiRkHXfeA2RY1eIlJ75ww==",
- "dev": true
- },
"node_modules/lodash.uniqby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz",
@@ -11201,16 +10649,6 @@
"es5-ext": "~0.10.2"
}
},
- "node_modules/lsof": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/lsof/-/lsof-0.1.0.tgz",
- "integrity": "sha512-RlNW3s4gQ0CIlDM3jwfx/Ogdwpa8PHySyd5FnKKXfi2NPXEjqgwONyA0y9ax33ur1G+K+f192zzKNQljupSgNA==",
- "deprecated": "No longer maintained",
- "dev": true,
- "engines": {
- "node": ">= 0.2.0"
- }
- },
"node_modules/madge": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/madge/-/madge-5.0.1.tgz",
@@ -11447,27 +10885,6 @@
"node": ">= 0.6"
}
},
- "node_modules/memoizee": {
- "version": "0.3.10",
- "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz",
- "integrity": "sha512-LLzVUuWwGBKK188spgOK/ukrp5zvd9JGsiLDH41pH9vt5jvhZfsu5pxDuAnYAMG8YEGce72KO07sSBy9KkvOfw==",
- "dev": true,
- "dependencies": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.11",
- "es6-weak-map": "~0.1.4",
- "event-emitter": "~0.3.4",
- "lru-queue": "0.1",
- "next-tick": "~0.2.2",
- "timers-ext": "0.1"
- }
- },
- "node_modules/memoizee/node_modules/next-tick": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz",
- "integrity": "sha512-f7h4svPtl+QidoBv4taKXUjJ70G2asaZ8G28nS0OkqaalX8dwwrtWtyxEDPK62AC00ur/+/E0pUwBwY5EPn15Q==",
- "dev": true
- },
"node_modules/memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
@@ -11700,6 +11117,40 @@
"node": ">=0.10.0"
}
},
+ "node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/mixin-deep": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -11819,20 +11270,43 @@
}
},
"node_modules/mongodb": {
- "version": "4.10.0",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.10.0.tgz",
- "integrity": "sha512-My2QxLTw0Cc1O9gih0mz4mqo145Jq4rLAQx0Glk/Ha9iYBzYpt4I2QFNRIh35uNFNfe8KFQcdwY1/HKxXBkinw==",
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz",
+ "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==",
"dependencies": {
- "bson": "^4.7.0",
- "denque": "^2.1.0",
- "mongodb-connection-string-url": "^2.5.3",
- "socks": "^2.7.0"
+ "bson": "^5.5.0",
+ "mongodb-connection-string-url": "^2.6.0",
+ "socks": "^2.7.1"
},
"engines": {
- "node": ">=12.9.0"
+ "node": ">=14.20.1"
},
"optionalDependencies": {
- "saslprep": "^1.0.3"
+ "@mongodb-js/saslprep": "^1.1.0"
+ },
+ "peerDependencies": {
+ "@aws-sdk/credential-providers": "^3.188.0",
+ "@mongodb-js/zstd": "^1.0.0",
+ "kerberos": "^1.0.0 || ^2.0.0",
+ "mongodb-client-encryption": ">=2.3.0 <3",
+ "snappy": "^7.2.2"
+ },
+ "peerDependenciesMeta": {
+ "@aws-sdk/credential-providers": {
+ "optional": true
+ },
+ "@mongodb-js/zstd": {
+ "optional": true
+ },
+ "kerberos": {
+ "optional": true
+ },
+ "mongodb-client-encryption": {
+ "optional": true
+ },
+ "snappy": {
+ "optional": true
+ }
}
},
"node_modules/mongodb-connection-string-url": {
@@ -11844,82 +11318,10 @@
"whatwg-url": "^11.0.0"
}
},
- "node_modules/mongodb-core": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.7.tgz",
- "integrity": "sha512-WypKdLxFNPOH/Jy6i9z47IjG2wIldA54iDZBmHMINcgKOUcWJh8og+Wix76oGd7EyYkHJKssQ2FAOw5Su/n4XQ==",
- "dev": true,
- "dependencies": {
- "bson": "^1.1.1",
- "require_optional": "^1.0.1",
- "safe-buffer": "^5.1.2"
- },
- "optionalDependencies": {
- "saslprep": "^1.0.0"
- }
- },
- "node_modules/mongodb-core/node_modules/bson": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
- "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
- "dev": true,
- "engines": {
- "node": ">=0.6.19"
- }
- },
- "node_modules/mongodb-dbpath": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/mongodb-dbpath/-/mongodb-dbpath-0.0.1.tgz",
- "integrity": "sha512-JljM2Gci3LQgECY4Wnp8tRx6eDNSoTnqiz4TIaOfqLuPr3SAbSdZEAQomHniH8DQJpn97gxdYkW/XomxYPZM2w==",
- "dev": true,
- "dependencies": {
- "async": "^1.4.0",
- "debug": "^2.1.1",
- "minimist": "^1.1.1",
- "mkdirp": "^0.5.1",
- "untildify": "^1.0.0"
- },
- "bin": {
- "mongodb-dbpath": "bin/mongodb-dbpath.js"
- }
- },
- "node_modules/mongodb-dbpath/node_modules/async": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
- "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
- "dev": true
- },
- "node_modules/mongodb-dbpath/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/mongodb-dbpath/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/mongodb-dbpath/node_modules/untildify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/untildify/-/untildify-1.0.0.tgz",
- "integrity": "sha512-LSU5BVpAncfzB2UBQaqfNww36wRSehWHs2grMM0ueYctZYxAhntiMvqDBhezYCYvbLeejeZ1nUWSl3mmkdPp+g==",
- "dev": true,
- "dependencies": {
- "user-home": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/mongodb-download-url": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.2.2.tgz",
- "integrity": "sha512-RD3jsswLVMkVp6QVudrKPLNMmiC1FHElTkTzU845K1Pr8ZL7M9HSBvVThXKrLT/WgChUHohEeCsmCmgeHW3ajQ==",
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.4.1.tgz",
+ "integrity": "sha512-OC0EGXiYTwZNcLq2U7Hbt1MDSPQR57/Kput4+W0F2kwVOa0HwWW4oY6DS1gOLlIeVOsihRKKH9EPNnc/BxF7UA==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
@@ -11932,9 +11334,9 @@
}
},
"node_modules/mongodb-download-url/node_modules/node-fetch": {
- "version": "2.6.7",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
- "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dev": true,
"dependencies": {
"whatwg-url": "^5.0.0"
@@ -11974,184 +11376,119 @@
}
},
"node_modules/mongodb-runner": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-4.8.1.tgz",
- "integrity": "sha512-1jv7EEyh+ajvGmLwDMXY5BjT/Xqdxgf+AwPK99JHhgeoAISffS3l9Z1c/IIOsSCulMlL7KlR10TyUdzSHZqMhg==",
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.4.4.tgz",
+ "integrity": "sha512-bODXH7sOMRXbpVceIR8zLnEgg9kv1eXW60pxW5dfNShkjWd+7wmalJY/Dm9LG1tcL7+O5H7lTZH+s32IWg+FVA==",
"dev": true,
"dependencies": {
- "async": "^3.1.0",
- "clui": "^0.3.6",
- "debug": "^4.1.1",
- "fs-extra": "^8.1.0",
- "is-mongodb-running": "^1.0.1",
- "lodash.defaults": "^4.2.0",
- "minimist": "^1.2.0",
- "mkdirp": "^0.5.1",
- "mongodb": "^3.4.0",
- "mongodb-dbpath": "^0.0.1",
- "mongodb-tools": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0",
- "mongodb-version-manager": "^1.4.3",
- "untildify": "^4.0.0",
- "which": "^2.0.1"
+ "@mongodb-js/mongodb-downloader": "^0.2.8",
+ "debug": "^4.3.4",
+ "mongodb": "^5.6.0",
+ "mongodb-connection-string-url": "^2.6.0",
+ "yargs": "^17.7.2"
},
"bin": {
- "mongodb-runner": "bin/mongodb-runner.js"
+ "mongodb-runner": "bin/runner.js"
}
},
- "node_modules/mongodb-runner/node_modules/bl": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
- "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
+ "node_modules/mongodb-runner/node_modules/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,
"dependencies": {
- "readable-stream": "^2.3.5",
- "safe-buffer": "^5.1.1"
- }
- },
- "node_modules/mongodb-runner/node_modules/bson": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
- "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
- "dev": true,
+ "color-convert": "^2.0.1"
+ },
"engines": {
- "node": ">=0.6.19"
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/mongodb-runner/node_modules/denque": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
- "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==",
+ "node_modules/mongodb-runner/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
"engines": {
- "node": ">=0.10"
+ "node": ">=12"
}
},
- "node_modules/mongodb-runner/node_modules/fs-extra": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
- "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "node_modules/mongodb-runner/node_modules/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,
"dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
+ "color-name": "~1.1.4"
},
"engines": {
- "node": ">=6 <7 || >=8"
+ "node": ">=7.0.0"
}
},
- "node_modules/mongodb-runner/node_modules/jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "dev": true,
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
+ "node_modules/mongodb-runner/node_modules/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
},
- "node_modules/mongodb-runner/node_modules/mongodb": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
- "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==",
+ "node_modules/mongodb-runner/node_modules/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,
"dependencies": {
- "bl": "^2.2.1",
- "bson": "^1.1.4",
- "denque": "^1.4.1",
- "optional-require": "^1.1.8",
- "safe-buffer": "^5.1.2"
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
},
"engines": {
- "node": ">=4"
- },
- "optionalDependencies": {
- "saslprep": "^1.0.0"
+ "node": ">=10"
},
- "peerDependenciesMeta": {
- "aws4": {
- "optional": true
- },
- "bson-ext": {
- "optional": true
- },
- "kerberos": {
- "optional": true
- },
- "mongodb-client-encryption": {
- "optional": true
- },
- "mongodb-extjson": {
- "optional": true
- },
- "snappy": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/mongodb-runner/node_modules/universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "node_modules/mongodb-runner/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
"engines": {
- "node": ">= 4.0.0"
- }
- },
- "node_modules/mongodb-tools": {
- "version": "1.2.0",
- "resolved": "git+ssh://git@github.com/mongodb-js/mongodb-tools.git#0d1a90f49796c41f6d47c7c7999fe384014a16a0",
- "integrity": "sha512-DNJJQYg1/VcE4gNP7zpKeWGIezwcpkI8XzG4YFL3WybY6cuKWMz3d1CIp3uKKEpva1qOHk2LI8mKWJX1Vpw4Sg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "debug": "^2.2.0",
- "lodash": "^4.17.12",
- "mkdirp": "0.5.0",
- "mongodb-core": "*",
- "rimraf": "2.2.6"
- }
- },
- "node_modules/mongodb-tools/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "dependencies": {
- "ms": "2.0.0"
+ "node": ">=10"
}
},
- "node_modules/mongodb-tools/node_modules/minimist": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
- "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==",
- "dev": true
- },
- "node_modules/mongodb-tools/node_modules/mkdirp": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
- "integrity": "sha512-xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==",
- "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
+ "node_modules/mongodb-runner/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dev": true,
"dependencies": {
- "minimist": "0.0.8"
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
},
- "bin": {
- "mkdirp": "bin/cmd.js"
+ "engines": {
+ "node": ">=12"
}
},
- "node_modules/mongodb-tools/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/mongodb-tools/node_modules/rimraf": {
- "version": "2.2.6",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz",
- "integrity": "sha512-33Fa/MIw/3F9KcDE/uJ2OuYUyxY+fkmw1c20DFnyhP7dfo2+BexeE1thjluPiJaG8sW6CcaqnTffwpRd4NAiTg==",
+ "node_modules/mongodb-runner/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
- "bin": {
- "rimraf": "bin.js"
+ "engines": {
+ "node": ">=12"
}
},
"node_modules/mongodb-version-list": {
@@ -12224,84 +11561,6 @@
"semver": "bin/semver"
}
},
- "node_modules/mongodb-version-manager": {
- "version": "1.4.6",
- "resolved": "https://registry.npmjs.org/mongodb-version-manager/-/mongodb-version-manager-1.4.6.tgz",
- "integrity": "sha512-UxXZy7iqHUa039Bp8e1Y2tSLh/X/JtHRqnlcVkqNEWpX/5ETPaKwrT7QIVZc1Tk5tEkQXjRHd6nQtUjcemOHmA==",
- "dev": true,
- "dependencies": {
- "ampersand-state": "^5.0.3",
- "async": "^3.1.0",
- "chalk": "^2.1.0",
- "debug": ">= 2.6.9 < 3.0.0 || >= ^3.1.0",
- "docopt": "^0.6.2",
- "download": "^6.2.5",
- "figures": "^3.2.0",
- "fs-extra": "^8.1.0",
- "get-mongodb-version": "^2.0.1",
- "lodash.defaults": "^4.2.0",
- "lodash.difference": "^4.1.1",
- "mongodb-download-url": "^1.0.0",
- "mongodb-version-list": "^1.0.0",
- "semver": "^5.3.0",
- "tildify": "^2.0.0",
- "untildify": "^4.0.0"
- },
- "bin": {
- "m": "bin/m.js",
- "mongodb-version-manager": "bin/mongodb-version-manager.js"
- }
- },
- "node_modules/mongodb-version-manager/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/mongodb-version-manager/node_modules/fs-extra": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
- "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- },
- "engines": {
- "node": ">=6 <7 || >=8"
- }
- },
- "node_modules/mongodb-version-manager/node_modules/jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "dev": true,
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/mongodb-version-manager/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/mongodb-version-manager/node_modules/universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
- "dev": true,
- "engines": {
- "node": ">= 4.0.0"
- }
- },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -12323,10 +11582,16 @@
"optional": true
},
"node_modules/nanoid": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
- "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -12553,22 +11818,13 @@
}
},
"node_modules/node-forge": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz",
- "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"engines": {
"node": ">= 6.13.0"
}
},
- "node_modules/node-netstat": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/node-netstat/-/node-netstat-1.8.0.tgz",
- "integrity": "sha512-P1a5Sh9FfjTXxI6hC9q/Nqre8kT63FQxBCr1qz5ffk76EkQBH62+XEhIhlzfz6Bz+FRwOFqidW2FDGXnOXvyJQ==",
- "dev": true,
- "dependencies": {
- "is-wsl": "^1.1.0"
- }
- },
"node_modules/node-preload": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
@@ -12791,28 +12047,6 @@
"node": ">=10"
}
},
- "node_modules/npm-conf": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
- "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
- "dev": true,
- "dependencies": {
- "config-chain": "^1.1.11",
- "pify": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-conf/node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -15888,18 +15122,6 @@
"node": ">=8"
}
},
- "node_modules/optional-require": {
- "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==",
- "dev": true,
- "dependencies": {
- "require-at": "^1.0.6"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -16009,6 +15231,17 @@
"node": ">=8"
}
},
+ "node_modules/otpauth": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/otpauth/-/otpauth-9.1.2.tgz",
+ "integrity": "sha512-iI5nlVvMFP3aTPdjG/fnC4mhVJ/KZOSnBrvo/VnYHUwlTp9jVLjAe2B3i3pyCH+3/E5jYQRSvuHk/8oas3870g==",
+ "dependencies": {
+ "jssha": "~3.3.0"
+ },
+ "funding": {
+ "url": "https://github.com/hectorm/otpauth?sponsor=1"
+ }
+ },
"node_modules/p-cancelable": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
@@ -16051,15 +15284,6 @@
"node": ">=6"
}
},
- "node_modules/p-finally": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
- "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/p-is-promise": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz",
@@ -16687,9 +15911,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.20",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
- "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"funding": [
{
@@ -16699,10 +15923,14 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
- "nanoid": "^3.3.4",
+ "nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
},
@@ -16846,15 +16074,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/prepend-http": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
- "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/prettier": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
@@ -16915,12 +16134,6 @@
"react-is": "^16.13.1"
}
},
- "node_modules/proto-list": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
- "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
- "dev": true
- },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -16933,15 +16146,6 @@
"node": ">= 0.10"
}
},
- "node_modules/ps-node": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz",
- "integrity": "sha512-w7QJhUTbu70hpDso0YXDRNKCPNuchV8UTUZsAv0m7Qj5g85oHOJfr9drA1EjvK4nQK/bG8P97W4L6PJ3IQLoOA==",
- "dev": true,
- "dependencies": {
- "table-parser": "^0.1.3"
- }
- },
"node_modules/pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -17696,43 +16900,6 @@
"uuid": "bin/uuid"
}
},
- "node_modules/require_optional": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
- "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
- "dev": true,
- "dependencies": {
- "resolve-from": "^2.0.0",
- "semver": "^5.1.0"
- }
- },
- "node_modules/require_optional/node_modules/resolve-from": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
- "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/require_optional/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/require-at": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz",
- "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -17988,18 +17155,6 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
- "node_modules/saslprep": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
- "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
- "optional": true,
- "dependencies": {
- "sparse-bitfield": "^3.0.3"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/sass-lookup": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-3.0.0.tgz",
@@ -18252,9 +17407,9 @@
}
},
"node_modules/semver": {
- "version": "7.5.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
- "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
+ "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -18728,30 +17883,6 @@
"npm": ">= 3.0.0"
}
},
- "node_modules/sort-keys": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
- "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==",
- "dev": true,
- "dependencies": {
- "is-plain-obj": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/sort-keys-length": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
- "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==",
- "dev": true,
- "dependencies": {
- "sort-keys": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -19180,18 +18311,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/strip-outer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
- "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
- "dev": true,
- "dependencies": {
- "escape-string-regexp": "^1.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/stylus-lookup": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-3.0.2.tgz",
@@ -19324,15 +18443,6 @@
"node": ">=0.10"
}
},
- "node_modules/table-parser": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz",
- "integrity": "sha512-LCYeuvqqoPII3lzzYaXKbC3Forb+d2u4bNwhk/9FlivuGRxPE28YEWAYcujeSlLLDlMfvy29+WPybFJZFiKMYg==",
- "dev": true,
- "dependencies": {
- "connected-domain": "^1.0.0"
- }
- },
"node_modules/taffydb": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
@@ -19348,6 +18458,23 @@
"node": ">=6"
}
},
+ "node_modules/tar": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
+ "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
+ "dev": true,
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/tar-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
@@ -19376,6 +18503,18 @@
"safe-buffer": "^5.1.1"
}
},
+ "node_modules/tar/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/temp": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/temp/-/temp-0.4.0.tgz",
@@ -19487,24 +18626,6 @@
"node": ">= 6"
}
},
- "node_modules/tildify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz",
- "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/timed-out": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
- "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/timers-ext": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
@@ -19733,18 +18854,6 @@
"node": ">=8"
}
},
- "node_modules/trim-repeated": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
- "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
- "dev": true,
- "dependencies": {
- "escape-string-regexp": "^1.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/triple-beam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
@@ -20103,15 +19212,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/untildify": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
- "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/upath": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
@@ -20184,27 +19284,6 @@
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
"dev": true
},
- "node_modules/url-parse-lax": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
- "integrity": "sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==",
- "dev": true,
- "dependencies": {
- "prepend-http": "^1.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/url-to-options": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
- "integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
"node_modules/use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@@ -20224,18 +19303,6 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
- "node_modules/user-home": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz",
- "integrity": "sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==",
- "dev": true,
- "bin": {
- "user-home": "cli.js"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -20491,9 +19558,9 @@
}
},
"node_modules/word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"engines": {
"node": ">=0.10.0"
}
@@ -20855,11 +19922,12 @@
}
},
"@babel/code-frame": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
- "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "version": "7.22.13",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+ "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"requires": {
- "@babel/highlight": "^7.18.6"
+ "@babel/highlight": "^7.22.13",
+ "chalk": "^2.4.2"
}
},
"@babel/compat-data": {
@@ -20925,12 +19993,13 @@
}
},
"@babel/generator": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
- "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
+ "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"requires": {
- "@babel/types": "^7.20.5",
+ "@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"dependencies": {
@@ -20966,9 +20035,9 @@
}
},
"@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=="
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA=="
},
"@babel/helper-explode-assignable-expression": {
"version": "7.18.6",
@@ -20980,20 +20049,20 @@
}
},
"@babel/helper-function-name": {
- "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==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"requires": {
- "@babel/template": "^7.18.10",
- "@babel/types": "^7.19.0"
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
}
},
"@babel/helper-hoist-variables": {
- "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==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"requires": {
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.22.5"
}
},
"@babel/helper-member-expression-to-functions": {
@@ -21074,22 +20143,22 @@
}
},
"@babel/helper-split-export-declaration": {
- "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==",
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"requires": {
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.22.5"
}
},
"@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=="
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
},
"@babel/helper-validator-identifier": {
- "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=="
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
},
"@babel/helper-validator-option": {
"version": "7.18.6",
@@ -21119,19 +20188,19 @@
}
},
"@babel/highlight": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
- "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
+ "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"requires": {
- "@babel/helper-validator-identifier": "^7.18.6",
- "chalk": "^2.0.0",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
"js-tokens": "^4.0.0"
}
},
"@babel/parser": {
- "version": "7.21.4",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz",
- "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw=="
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
+ "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
},
"@babel/plugin-proposal-object-rest-spread": {
"version": "7.10.0",
@@ -21958,39 +21027,39 @@
}
},
"@babel/template": {
- "version": "7.18.10",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
- "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"requires": {
- "@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.18.10",
- "@babel/types": "^7.18.10"
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
}
},
"@babel/traverse": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
- "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
- "requires": {
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.5",
- "@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.5",
- "@babel/types": "^7.20.5",
+ "version": "7.23.2",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
+ "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
+ "requires": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/generator": "^7.23.0",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.0",
+ "@babel/types": "^7.23.0",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
- "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
+ "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"requires": {
- "@babel/helper-string-parser": "^7.19.4",
- "@babel/helper-validator-identifier": "^7.19.1",
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
}
},
@@ -22451,6 +21520,61 @@
"resolved": "https://registry.npmjs.org/@ldapjs/protocol/-/protocol-1.2.1.tgz",
"integrity": "sha512-O89xFDLW2gBoZWNXuXpBSM32/KealKCTb3JGtJdtUQc7RjAk8XzrRgyz02cPAwGKwKPxy0ivuC7UP9bmN87egQ=="
},
+ "@mongodb-js/mongodb-downloader": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/@mongodb-js/mongodb-downloader/-/mongodb-downloader-0.2.8.tgz",
+ "integrity": "sha512-y+mgw9QspvgTLRNHZJRS+DUTPk45RWpvYD1MaGDWhZ4ajffvxGqanY+Z4R6z01n+tIRmQvpShzF6zk+2Pr9d6w==",
+ "dev": true,
+ "requires": {
+ "debug": "^4.3.4",
+ "decompress": "^4.2.1",
+ "mongodb-download-url": "^1.3.0",
+ "node-fetch": "^2.6.11",
+ "tar": "^6.1.15"
+ },
+ "dependencies": {
+ "node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dev": true,
+ "requires": {
+ "whatwg-url": "^5.0.0"
+ }
+ },
+ "tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "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"
+ }
+ }
+ }
+ },
+ "@mongodb-js/saslprep": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz",
+ "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==",
+ "optional": true,
+ "requires": {
+ "sparse-bitfield": "^3.0.3"
+ }
+ },
"@napi-rs/triples": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@napi-rs/triples/-/triples-1.1.0.tgz",
@@ -22737,13 +21861,13 @@
"integrity": "sha512-VUsVZXgt53FULqUd9xqGDW6RXes62qHXTNOeRSlS1MOemiCdtQOUGgLHgjdYQXnZ1hPLkxZKph96AluZUb953g=="
},
"@parse/node-apn": {
- "version": "5.1.3",
- "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.3.tgz",
- "integrity": "sha512-Bwhmbm895lEIF2772PJ8dSvBjrtOG9/q/TDMxmX40IgZxQFoXS73+JUIKTq3CA7SUB/Szu5roJINQ0L2U/1MJw==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-6.0.1.tgz",
+ "integrity": "sha512-QQxqEN/zbtEkSgj41oX/tQUavML+G+JHeQi2YVlgZlponnwIxA3fb5tEbXPm+fdR6rL1pi2/z2PcOwINOyx2eA==",
"requires": {
"debug": "4.3.3",
- "jsonwebtoken": "8.5.1",
- "node-forge": "1.3.0",
+ "jsonwebtoken": "9.0.0",
+ "node-forge": "1.3.1",
"verror": "1.10.1"
},
"dependencies": {
@@ -22754,28 +21878,6 @@
"requires": {
"ms": "2.1.2"
}
- },
- "jsonwebtoken": {
- "version": "8.5.1",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
- "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
- "requires": {
- "jws": "^3.2.2",
- "lodash.includes": "^4.3.0",
- "lodash.isboolean": "^3.0.3",
- "lodash.isinteger": "^4.0.4",
- "lodash.isnumber": "^3.0.3",
- "lodash.isplainobject": "^4.0.6",
- "lodash.isstring": "^4.0.1",
- "lodash.once": "^4.0.0",
- "ms": "^2.1.1",
- "semver": "^5.6.0"
- }
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
@@ -22800,63 +21902,29 @@
}
},
"@parse/push-adapter": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.3.tgz",
- "integrity": "sha512-Oy53ag7DpUva5dUWwP6tNEsrxv2xU9QIk+rb84q1DIm1qVgo2yl4oXcZ3FPG2Ks/NYURbv4w+z9oaSgVfyBRfQ==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-5.0.2.tgz",
+ "integrity": "sha512-0nVBGj8p8cYGjoMdkVAlsa/UlB1Z4W6Ch7MEVcEfnyCmJBw6bvHwB1VVWoclcRqi3phsu3SizR5zVvB/Cx8I/g==",
"requires": {
- "@parse/node-apn": "5.1.3",
+ "@parse/node-apn": "6.0.1",
"@parse/node-gcm": "1.0.2",
"npmlog": "4.1.2",
- "parse": "3.4.0"
+ "parse": "4.2.0"
},
"dependencies": {
- "@babel/runtime": {
- "version": "7.15.4",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz",
- "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==",
- "requires": {
- "regenerator-runtime": "^0.13.4"
- }
- },
- "@babel/runtime-corejs3": {
- "version": "7.14.7",
- "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz",
- "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==",
- "requires": {
- "core-js-pure": "^3.15.0",
- "regenerator-runtime": "^0.13.4"
- }
- },
- "idb-keyval": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-5.0.6.tgz",
- "integrity": "sha512-6lJuVbwyo82mKSH6Wq2eHkt9LcbwHAelMIcMe0tP4p20Pod7tTxq9zf0ge2n/YDfMOpDryerfmmYyuQiaFaKOg=="
- },
"parse": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.0.tgz",
- "integrity": "sha512-FMZLxPW6PvrBgxkXc9AmnYsFKvPwiS4G2n9OI4mdfiSoNzIVLc+bXzlUdJ+I7hiqHsBTP0BrdQczw2/cnVkJ6w==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/parse/-/parse-4.2.0.tgz",
+ "integrity": "sha512-K8bWs0wM2qRhkSr6N16j8OvsF6Uallrynqng9e+tzR3RdKuB09vaJh48qrf9MbiJ1Ya4JZI7AfEHYF+ywEKs7Q==",
"requires": {
- "@babel/runtime": "7.15.4",
- "@babel/runtime-corejs3": "7.14.7",
+ "@babel/runtime-corejs3": "7.21.0",
"crypto-js": "4.1.1",
- "idb-keyval": "5.0.6",
+ "idb-keyval": "6.2.0",
"react-native-crypto-js": "1.0.0",
- "uuid": "3.4.0",
- "ws": "7.5.1",
+ "uuid": "9.0.0",
+ "ws": "8.13.0",
"xmlhttprequest": "1.8.0"
}
- },
- "uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
- },
- "ws": {
- "version": "7.5.1",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz",
- "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==",
- "requires": {}
}
}
},
@@ -23439,75 +22507,6 @@
}
}
},
- "ampersand-events": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/ampersand-events/-/ampersand-events-2.0.2.tgz",
- "integrity": "sha512-pPnVEJviRxXi9YhZA9j3GwGGBTlDLi+YIoBvrpKXgce+CO1nMlZU2aOV8OJogNuR2YPbptAUHNz7SKX+MvLj8A==",
- "dev": true,
- "requires": {
- "ampersand-version": "^1.0.2",
- "lodash": "^4.6.1"
- }
- },
- "ampersand-state": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/ampersand-state/-/ampersand-state-5.0.3.tgz",
- "integrity": "sha512-sr904K5zvw6mkGjFHhTcfBIdpoJ6mn/HrFg7OleRmBpw3apLb3Z0gVrgRTb7kK1wOLI34vs4S+IXqNHUeqWCzw==",
- "dev": true,
- "requires": {
- "ampersand-events": "^2.0.1",
- "ampersand-version": "^1.0.0",
- "array-next": "~0.0.1",
- "key-tree-store": "^1.3.0",
- "lodash": "^4.12.0"
- }
- },
- "ampersand-version": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/ampersand-version/-/ampersand-version-1.0.2.tgz",
- "integrity": "sha512-FVVLY7Pghtgc8pQl0rF3A3+OS/CZ+/ILLMIYIaO1cA9v5SRkainqUMfSot3fu32svuThIsYK3q9iCsH9W5+mWQ==",
- "dev": true,
- "requires": {
- "find-root": "^0.1.1",
- "through2": "^0.6.3"
- },
- "dependencies": {
- "isarray": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
- "dev": true
- },
- "readable-stream": {
- "version": "1.0.34",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
- "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
- "dev": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.1",
- "isarray": "0.0.1",
- "string_decoder": "~0.10.x"
- }
- },
- "string_decoder": {
- "version": "0.10.31",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
- "dev": true
- },
- "through2": {
- "version": "0.6.5",
- "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
- "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==",
- "dev": true,
- "requires": {
- "readable-stream": ">=1.0.33-1 <1.1.0-0",
- "xtend": ">=4.0.0 <4.1.0-0"
- }
- }
- }
- },
"ansi": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz",
@@ -23775,12 +22774,6 @@
"integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
"dev": true
},
- "array-next": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/array-next/-/array-next-0.0.1.tgz",
- "integrity": "sha512-sBOC/Iaz2hCcYi2XlyRfyZCRUxamlE5NJXEFjE9BTx23HALnWAFsPjGtfrAclt9o3G/38Het2yyeyOd3CEY7lg==",
- "dev": true
- },
"array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -23965,7 +22958,8 @@
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true
},
"bcrypt-nodejs": {
"version": "0.0.3",
@@ -24125,17 +23119,15 @@
}
},
"bson": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz",
- "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==",
- "requires": {
- "buffer": "^5.6.0"
- }
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-5.5.1.tgz",
+ "integrity": "sha512-ix0EwukN2EpC0SRWIj/7B5+A6uQMQy6KMREI9qQqvgpkV2frH63T0UDVd1SYedL6dNCmDBYB3QtXi4ISk9YT+g=="
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
@@ -24344,18 +23336,6 @@
"lodash": "^4.17.14"
}
},
- "caw": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz",
- "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==",
- "dev": true,
- "requires": {
- "get-proxy": "^2.0.0",
- "isurl": "^1.0.0-alpha5",
- "tunnel-agent": "^0.6.0",
- "url-to-options": "^1.0.1"
- }
- },
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
@@ -24411,6 +23391,12 @@
"upath": "^1.1.1"
}
},
+ "chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "dev": true
+ },
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
@@ -24481,18 +23467,6 @@
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
"dev": true
},
- "cli-color": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-0.3.2.tgz",
- "integrity": "sha512-Ys/nDhHNRcxrS4EUI2RS/QCUE+61AMuEOj3sWDX+EIHkJWj+4XkRbOdwdxJteAJKjXYBbeFJMtfaEPd1MBF9pQ==",
- "dev": true,
- "requires": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.2",
- "memoizee": "0.3.x",
- "timers-ext": "0.1.x"
- }
- },
"cli-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
@@ -24554,15 +23528,6 @@
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"dev": true
},
- "clui": {
- "version": "0.3.6",
- "resolved": "https://registry.npmjs.org/clui/-/clui-0.3.6.tgz",
- "integrity": "sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==",
- "dev": true,
- "requires": {
- "cli-color": "0.3.2"
- }
- },
"cluster-key-slot": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
@@ -24701,22 +23666,6 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
- "config-chain": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
- "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
- "dev": true,
- "requires": {
- "ini": "^1.3.4",
- "proto-list": "~1.2.1"
- }
- },
- "connected-domain": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/connected-domain/-/connected-domain-1.0.0.tgz",
- "integrity": "sha512-lHlohUiJxlpunvDag2Y0pO20bnvarMjnrdciZeuJUqRwrf/5JHNhdpiPIr5GQ8IkqrFj5TDMQwcCjblGo1oeuA==",
- "dev": true
- },
"console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -24950,15 +23899,6 @@
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
"dev": true
},
- "d": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz",
- "integrity": "sha512-0SdM9V9pd/OXJHoWmTfNPTAeD+lw6ZqHg+isPyBFuJsZLSE0Ygg1cYZ/0l6DrKQXMOqGOu1oWupMoOfoRfMZrQ==",
- "dev": true,
- "requires": {
- "es5-ext": "~0.10.2"
- }
- },
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -25276,11 +24216,6 @@
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
},
- "denque": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
- "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
- },
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@@ -25426,12 +24361,6 @@
"path-type": "^4.0.0"
}
},
- "docopt": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
- "integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==",
- "dev": true
- },
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
@@ -25534,121 +24463,6 @@
}
}
},
- "download": {
- "version": "6.2.5",
- "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz",
- "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==",
- "dev": true,
- "requires": {
- "caw": "^2.0.0",
- "content-disposition": "^0.5.2",
- "decompress": "^4.0.0",
- "ext-name": "^5.0.0",
- "file-type": "5.2.0",
- "filenamify": "^2.0.0",
- "get-stream": "^3.0.0",
- "got": "^7.0.0",
- "make-dir": "^1.0.0",
- "p-event": "^1.0.0",
- "pify": "^3.0.0"
- },
- "dependencies": {
- "decompress-response": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
- "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
- "dev": true,
- "requires": {
- "mimic-response": "^1.0.0"
- }
- },
- "get-stream": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
- "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
- "dev": true
- },
- "got": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz",
- "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==",
- "dev": true,
- "requires": {
- "decompress-response": "^3.2.0",
- "duplexer3": "^0.1.4",
- "get-stream": "^3.0.0",
- "is-plain-obj": "^1.1.0",
- "is-retry-allowed": "^1.0.0",
- "is-stream": "^1.0.0",
- "isurl": "^1.0.0-alpha5",
- "lowercase-keys": "^1.0.0",
- "p-cancelable": "^0.3.0",
- "p-timeout": "^1.1.1",
- "safe-buffer": "^5.0.1",
- "timed-out": "^4.0.0",
- "url-parse-lax": "^1.0.0",
- "url-to-options": "^1.0.1"
- }
- },
- "is-stream": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
- "dev": true
- },
- "lowercase-keys": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
- "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
- "dev": true
- },
- "make-dir": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
- "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
- "dev": true,
- "requires": {
- "pify": "^3.0.0"
- }
- },
- "mimic-response": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
- "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
- "dev": true
- },
- "p-cancelable": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz",
- "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==",
- "dev": true
- },
- "p-event": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz",
- "integrity": "sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA==",
- "dev": true,
- "requires": {
- "p-timeout": "^1.1.1"
- }
- },
- "p-timeout": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz",
- "integrity": "sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==",
- "dev": true,
- "requires": {
- "p-finally": "^1.0.0"
- }
- },
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true
- }
- }
- },
"dset": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz",
@@ -25663,12 +24477,6 @@
"readable-stream": "^2.0.2"
}
},
- "duplexer3": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
- "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==",
- "dev": true
- },
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -25838,41 +24646,6 @@
}
}
},
- "es6-weak-map": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz",
- "integrity": "sha512-P+N5Cd2TXeb7G59euFiM7snORspgbInS29Nbf3KNO2JQp/DyhvMCDWd58nsVAXwYJ6W3Bx7qDdy6QQ3PCJ7jKQ==",
- "dev": true,
- "requires": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.6",
- "es6-iterator": "~0.1.3",
- "es6-symbol": "~2.0.1"
- },
- "dependencies": {
- "es6-iterator": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz",
- "integrity": "sha512-6TOmbFM6OPWkTe+bQ3ZuUkvqcWUjAnYjKUCLdbvRsAUz2Pr+fYIibwNXNkLNtIK9PPFbNMZZddaRNkyJhlGJhA==",
- "dev": true,
- "requires": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.5",
- "es6-symbol": "~2.0.1"
- }
- },
- "es6-symbol": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz",
- "integrity": "sha512-wjobO4zO8726HVU7mI2OA/B6QszqwHJuKab7gKHVx+uRfVVYGcWJkCIFxV2Madqb9/RUSrhJ/r6hPfG7FsWtow==",
- "dev": true,
- "requires": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.5"
- }
- }
- }
- },
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -26387,25 +25160,6 @@
"type": "^2.7.2"
}
},
- "ext-list": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
- "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
- "dev": true,
- "requires": {
- "mime-db": "^1.28.0"
- }
- },
- "ext-name": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
- "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
- "dev": true,
- "requires": {
- "ext-list": "^2.0.0",
- "sort-keys-length": "^1.0.0"
- }
- },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -26652,23 +25406,6 @@
"dev": true,
"optional": true
},
- "filename-reserved-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
- "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
- "dev": true
- },
- "filenamify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz",
- "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==",
- "dev": true,
- "requires": {
- "filename-reserved-regex": "^2.0.0",
- "strip-outer": "^1.0.0",
- "trim-repeated": "^1.0.0"
- }
- },
"filing-cabinet": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-3.3.0.tgz",
@@ -26820,12 +25557,6 @@
}
}
},
- "find-root": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/find-root/-/find-root-0.1.2.tgz",
- "integrity": "sha512-GyDxVgA61TZcrgDJPqOqGBpi80Uf2yIstubgizi7AjC9yPdRrqBR+Y0MvK4kXnYlaoz3d+SGxDHMYVkwI/yd2w==",
- "dev": true
- },
"find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -26876,9 +25607,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"follow-redirects": {
- "version": "1.15.2",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
- "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+ "version": "1.15.4",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
+ "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw=="
},
"for-in": {
"version": "1.0.2",
@@ -26997,6 +25728,26 @@
"universalify": "^2.0.0"
}
},
+ "fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
"fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
@@ -27108,29 +25859,6 @@
"has-symbols": "^1.0.3"
}
},
- "get-mongodb-version": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/get-mongodb-version/-/get-mongodb-version-2.0.1.tgz",
- "integrity": "sha512-yTN0UY7VJSSt01QH/aCiqiBjfxcDrEdKeM3uXY6QR3sRARoftx36QT0YNsCQm7FDTgrmDje7bK2C9ClM7SGKDA==",
- "dev": true,
- "requires": {
- "lodash.startswith": "^4.2.1",
- "minimist": "^1.1.1",
- "mongodb": "*",
- "which": "^1.1.1"
- },
- "dependencies": {
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- }
- }
- },
"get-own-enumerable-property-symbols": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
@@ -27143,15 +25871,6 @@
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true
},
- "get-proxy": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz",
- "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==",
- "dev": true,
- "requires": {
- "npm-conf": "^1.1.0"
- }
- },
"get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -27337,9 +26056,9 @@
"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ=="
},
"graphql": {
- "version": "16.6.0",
- "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz",
- "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw=="
+ "version": "16.8.1",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz",
+ "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw=="
},
"graphql-list-fields": {
"version": "2.0.2",
@@ -27424,26 +26143,11 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="
},
- "has-symbol-support-x": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
- "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
- "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-to-string-tag-x": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
- "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
- "dev": true,
- "requires": {
- "has-symbol-support-x": "^1.4.1"
- }
- },
"has-unicode": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -27766,7 +26470,8 @@
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true
},
"ignore": {
"version": "5.2.4",
@@ -27865,14 +26570,6 @@
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
},
- "ip-range-check": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/ip-range-check/-/ip-range-check-0.2.0.tgz",
- "integrity": "sha512-oaM3l/3gHbLlt/tCWLvt0mj1qUaI+STuRFnUvARGCujK9vvU61+2JsDpmkMzR4VsJhuFXWWgeKKVnwwoFfzCqw==",
- "requires": {
- "ipaddr.js": "^1.0.1"
- }
- },
"ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
@@ -27982,33 +26679,6 @@
"integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
"dev": true
},
- "is-mongodb-running": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-mongodb-running/-/is-mongodb-running-1.0.2.tgz",
- "integrity": "sha512-EslN8MErcBPExb+iK4RnG1n28JGjByA2Rm3YPmdHDGCRd7Hc2uvqshyVMAJXxbDSxRMy8vhxims2oRqQUeGJeA==",
- "dev": true,
- "requires": {
- "chalk": "^2.4.1",
- "debug": ">= 2.6.9",
- "figures": "^2.0.0",
- "lodash": "^4.17.10",
- "lsof": "^0.1.0",
- "minimist": "^1.2.0",
- "node-netstat": "^1.4.2",
- "ps-node": "^0.1.6"
- },
- "dependencies": {
- "figures": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
- "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
- "dev": true,
- "requires": {
- "escape-string-regexp": "^1.0.5"
- }
- }
- }
- },
"is-natural-number": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
@@ -28031,12 +26701,6 @@
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
"dev": true
},
- "is-object": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
- "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==",
- "dev": true
- },
"is-path-cwd": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
@@ -28077,12 +26741,6 @@
"integrity": "sha512-i1h+y50g+0hRbBD+dbnInl3JlJ702aar58snAeX+MxBAPvzXGej7sYoPMhlnykabt0ZzCJNBEyzMlekuQZN7fA==",
"dev": true
},
- "is-retry-allowed": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
- "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
- "dev": true
- },
"is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -28126,12 +26784,6 @@
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
},
- "is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
- "dev": true
- },
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -28305,16 +26957,6 @@
"istanbul-lib-report": "^3.0.0"
}
},
- "isurl": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
- "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
- "dev": true,
- "requires": {
- "has-to-string-tag-x": "^1.2.0",
- "is-object": "^1.0.1"
- }
- },
"iterall": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz",
@@ -28550,6 +27192,11 @@
}
}
},
+ "jssha": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/jssha/-/jssha-3.3.0.tgz",
+ "integrity": "sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w=="
+ },
"jwa": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
@@ -28582,12 +27229,6 @@
"safe-buffer": "^5.0.1"
}
},
- "key-tree-store": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/key-tree-store/-/key-tree-store-1.3.0.tgz",
- "integrity": "sha512-qXk+lR+LXvGos3wqMxIMWweKDgCx8ZKWM6BEPm7iZkOKug5ggi66vUt+3vbtKJLBrAyOxQ4S8JRwK++Q4XZRmw==",
- "dev": true
- },
"keyv": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
@@ -28975,12 +27616,6 @@
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
"dev": true
},
- "lodash.difference": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
- "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
- "dev": true
- },
"lodash.escaperegexp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz",
@@ -29011,41 +27646,23 @@
"integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==",
"dev": true
},
- "lodash.includes": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
- "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="
- },
- "lodash.isboolean": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
- "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": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="
- },
"lodash.ismatch": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz",
"integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==",
"dev": true
},
- "lodash.isnumber": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
- "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": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "dev": true
},
"lodash.isstring": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
- "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw=="
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "dev": true
},
"lodash.map": {
"version": "4.6.0",
@@ -29058,11 +27675,6 @@
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
- "lodash.once": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="
- },
"lodash.pad": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz",
@@ -29105,12 +27717,6 @@
"integrity": "sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==",
"dev": true
},
- "lodash.startswith": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/lodash.startswith/-/lodash.startswith-4.2.1.tgz",
- "integrity": "sha512-XClYR1h4/fJ7H+mmCKppbiBmljN/nGs73iq2SjCT9SF4CBPoUHzLvWmH1GtZMhMBZSiRkHXfeA2RY1eIlJ75ww==",
- "dev": true
- },
"lodash.uniqby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz",
@@ -29298,12 +27904,6 @@
"es5-ext": "~0.10.2"
}
},
- "lsof": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/lsof/-/lsof-0.1.0.tgz",
- "integrity": "sha512-RlNW3s4gQ0CIlDM3jwfx/Ogdwpa8PHySyd5FnKKXfi2NPXEjqgwONyA0y9ax33ur1G+K+f192zzKNQljupSgNA==",
- "dev": true
- },
"madge": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/madge/-/madge-5.0.1.tgz",
@@ -29480,29 +28080,6 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
},
- "memoizee": {
- "version": "0.3.10",
- "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz",
- "integrity": "sha512-LLzVUuWwGBKK188spgOK/ukrp5zvd9JGsiLDH41pH9vt5jvhZfsu5pxDuAnYAMG8YEGce72KO07sSBy9KkvOfw==",
- "dev": true,
- "requires": {
- "d": "~0.1.1",
- "es5-ext": "~0.10.11",
- "es6-weak-map": "~0.1.4",
- "event-emitter": "~0.3.4",
- "lru-queue": "0.1",
- "next-tick": "~0.2.2",
- "timers-ext": "0.1"
- },
- "dependencies": {
- "next-tick": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz",
- "integrity": "sha512-f7h4svPtl+QidoBv4taKXUjJ70G2asaZ8G28nS0OkqaalX8dwwrtWtyxEDPK62AC00ur/+/E0pUwBwY5EPn15Q==",
- "dev": true
- }
- }
- },
"memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
@@ -29672,6 +28249,33 @@
}
}
},
+ "minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true
+ },
+ "minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "requires": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "dependencies": {
+ "minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ }
+ }
+ },
"mixin-deep": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -29763,15 +28367,14 @@
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"mongodb": {
- "version": "4.10.0",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.10.0.tgz",
- "integrity": "sha512-My2QxLTw0Cc1O9gih0mz4mqo145Jq4rLAQx0Glk/Ha9iYBzYpt4I2QFNRIh35uNFNfe8KFQcdwY1/HKxXBkinw==",
+ "version": "5.9.0",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz",
+ "integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==",
"requires": {
- "bson": "^4.7.0",
- "denque": "^2.1.0",
- "mongodb-connection-string-url": "^2.5.3",
- "saslprep": "^1.0.3",
- "socks": "^2.7.0"
+ "@mongodb-js/saslprep": "^1.1.0",
+ "bson": "^5.5.0",
+ "mongodb-connection-string-url": "^2.6.0",
+ "socks": "^2.7.1"
}
},
"mongodb-connection-string-url": {
@@ -29783,75 +28386,10 @@
"whatwg-url": "^11.0.0"
}
},
- "mongodb-core": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.7.tgz",
- "integrity": "sha512-WypKdLxFNPOH/Jy6i9z47IjG2wIldA54iDZBmHMINcgKOUcWJh8og+Wix76oGd7EyYkHJKssQ2FAOw5Su/n4XQ==",
- "dev": true,
- "requires": {
- "bson": "^1.1.1",
- "require_optional": "^1.0.1",
- "safe-buffer": "^5.1.2",
- "saslprep": "^1.0.0"
- },
- "dependencies": {
- "bson": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
- "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
- "dev": true
- }
- }
- },
- "mongodb-dbpath": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/mongodb-dbpath/-/mongodb-dbpath-0.0.1.tgz",
- "integrity": "sha512-JljM2Gci3LQgECY4Wnp8tRx6eDNSoTnqiz4TIaOfqLuPr3SAbSdZEAQomHniH8DQJpn97gxdYkW/XomxYPZM2w==",
- "dev": true,
- "requires": {
- "async": "^1.4.0",
- "debug": "^2.1.1",
- "minimist": "^1.1.1",
- "mkdirp": "^0.5.1",
- "untildify": "^1.0.0"
- },
- "dependencies": {
- "async": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
- "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
- "dev": true
- },
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "untildify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/untildify/-/untildify-1.0.0.tgz",
- "integrity": "sha512-LSU5BVpAncfzB2UBQaqfNww36wRSehWHs2grMM0ueYctZYxAhntiMvqDBhezYCYvbLeejeZ1nUWSl3mmkdPp+g==",
- "dev": true,
- "requires": {
- "user-home": "^1.0.0"
- }
- }
- }
- },
"mongodb-download-url": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.2.2.tgz",
- "integrity": "sha512-RD3jsswLVMkVp6QVudrKPLNMmiC1FHElTkTzU845K1Pr8ZL7M9HSBvVThXKrLT/WgChUHohEeCsmCmgeHW3ajQ==",
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/mongodb-download-url/-/mongodb-download-url-1.4.1.tgz",
+ "integrity": "sha512-OC0EGXiYTwZNcLq2U7Hbt1MDSPQR57/Kput4+W0F2kwVOa0HwWW4oY6DS1gOLlIeVOsihRKKH9EPNnc/BxF7UA==",
"dev": true,
"requires": {
"debug": "^4.1.1",
@@ -29861,9 +28399,9 @@
},
"dependencies": {
"node-fetch": {
- "version": "2.6.7",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
- "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"dev": true,
"requires": {
"whatwg-url": "^5.0.0"
@@ -29894,138 +28432,89 @@
}
},
"mongodb-runner": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-4.8.1.tgz",
- "integrity": "sha512-1jv7EEyh+ajvGmLwDMXY5BjT/Xqdxgf+AwPK99JHhgeoAISffS3l9Z1c/IIOsSCulMlL7KlR10TyUdzSHZqMhg==",
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/mongodb-runner/-/mongodb-runner-5.4.4.tgz",
+ "integrity": "sha512-bODXH7sOMRXbpVceIR8zLnEgg9kv1eXW60pxW5dfNShkjWd+7wmalJY/Dm9LG1tcL7+O5H7lTZH+s32IWg+FVA==",
"dev": true,
"requires": {
- "async": "^3.1.0",
- "clui": "^0.3.6",
- "debug": "^4.1.1",
- "fs-extra": "^8.1.0",
- "is-mongodb-running": "^1.0.1",
- "lodash.defaults": "^4.2.0",
- "minimist": "^1.2.0",
- "mkdirp": "^0.5.1",
- "mongodb": "^3.4.0",
- "mongodb-dbpath": "^0.0.1",
- "mongodb-tools": "github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0",
- "mongodb-version-manager": "^1.4.3",
- "untildify": "^4.0.0",
- "which": "^2.0.1"
+ "@mongodb-js/mongodb-downloader": "^0.2.8",
+ "debug": "^4.3.4",
+ "mongodb": "^5.6.0",
+ "mongodb-connection-string-url": "^2.6.0",
+ "yargs": "^17.7.2"
},
"dependencies": {
- "bl": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
- "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
- "dev": true,
- "requires": {
- "readable-stream": "^2.3.5",
- "safe-buffer": "^5.1.1"
- }
- },
- "bson": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
- "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
- "dev": true
- },
- "denque": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
- "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==",
- "dev": true
- },
- "fs-extra": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
- "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "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": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
+ "color-convert": "^2.0.1"
}
},
- "jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dev": true,
"requires": {
- "graceful-fs": "^4.1.6"
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
}
},
- "mongodb": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
- "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==",
+ "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": {
- "bl": "^2.2.1",
- "bson": "^1.1.4",
- "denque": "^1.4.1",
- "optional-require": "^1.1.8",
- "safe-buffer": "^5.1.2",
- "saslprep": "^1.0.0"
+ "color-name": "~1.1.4"
}
},
- "universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "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
- }
- }
- },
- "mongodb-tools": {
- "version": "git+ssh://git@github.com/mongodb-js/mongodb-tools.git#0d1a90f49796c41f6d47c7c7999fe384014a16a0",
- "integrity": "sha512-DNJJQYg1/VcE4gNP7zpKeWGIezwcpkI8XzG4YFL3WybY6cuKWMz3d1CIp3uKKEpva1qOHk2LI8mKWJX1Vpw4Sg==",
- "dev": true,
- "from": "mongodb-tools@github:mongodb-js/mongodb-tools#0d1a90f49796c41f6d47c7c7999fe384014a16a0",
- "requires": {
- "debug": "^2.2.0",
- "lodash": "^4.17.12",
- "mkdirp": "0.5.0",
- "mongodb-core": "*",
- "rimraf": "2.2.6"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ },
+ "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": {
- "ms": "2.0.0"
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
}
},
- "minimist": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
- "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==",
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true
},
- "mkdirp": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
- "integrity": "sha512-xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==",
+ "yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dev": true,
"requires": {
- "minimist": "0.0.8"
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
}
},
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "rimraf": {
- "version": "2.2.6",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz",
- "integrity": "sha512-33Fa/MIw/3F9KcDE/uJ2OuYUyxY+fkmw1c20DFnyhP7dfo2+BexeE1thjluPiJaG8sW6CcaqnTffwpRd4NAiTg==",
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true
}
}
@@ -30096,73 +28585,6 @@
}
}
},
- "mongodb-version-manager": {
- "version": "1.4.6",
- "resolved": "https://registry.npmjs.org/mongodb-version-manager/-/mongodb-version-manager-1.4.6.tgz",
- "integrity": "sha512-UxXZy7iqHUa039Bp8e1Y2tSLh/X/JtHRqnlcVkqNEWpX/5ETPaKwrT7QIVZc1Tk5tEkQXjRHd6nQtUjcemOHmA==",
- "dev": true,
- "requires": {
- "ampersand-state": "^5.0.3",
- "async": "^3.1.0",
- "chalk": "^2.1.0",
- "debug": ">= 2.6.9 < 3.0.0 || >= ^3.1.0",
- "docopt": "^0.6.2",
- "download": "^6.2.5",
- "figures": "^3.2.0",
- "fs-extra": "^8.1.0",
- "get-mongodb-version": "^2.0.1",
- "lodash.defaults": "^4.2.0",
- "lodash.difference": "^4.1.1",
- "mongodb-download-url": "^1.0.0",
- "mongodb-version-list": "^1.0.0",
- "semver": "^5.3.0",
- "tildify": "^2.0.0",
- "untildify": "^4.0.0"
- },
- "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"
- }
- },
- "fs-extra": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
- "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- }
- },
- "jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.6"
- }
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- },
- "universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
- "dev": true
- }
- }
- },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -30181,9 +28603,9 @@
"optional": true
},
"nanoid": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
- "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
"dev": true
},
"nanomatch": {
@@ -30357,18 +28779,9 @@
}
},
"node-forge": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz",
- "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA=="
- },
- "node-netstat": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/node-netstat/-/node-netstat-1.8.0.tgz",
- "integrity": "sha512-P1a5Sh9FfjTXxI6hC9q/Nqre8kT63FQxBCr1qz5ffk76EkQBH62+XEhIhlzfz6Bz+FRwOFqidW2FDGXnOXvyJQ==",
- "dev": true,
- "requires": {
- "is-wsl": "^1.1.0"
- }
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA=="
},
"node-preload": {
"version": "0.2.1",
@@ -32505,24 +30918,6 @@
}
}
},
- "npm-conf": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz",
- "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==",
- "dev": true,
- "requires": {
- "config-chain": "^1.1.11",
- "pify": "^3.0.0"
- },
- "dependencies": {
- "pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true
- }
- }
- },
"npm-run-path": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
@@ -32773,15 +31168,6 @@
}
}
},
- "optional-require": {
- "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==",
- "dev": true,
- "requires": {
- "require-at": "^1.0.6"
- }
- },
"optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -32863,6 +31249,14 @@
}
}
},
+ "otpauth": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/otpauth/-/otpauth-9.1.2.tgz",
+ "integrity": "sha512-iI5nlVvMFP3aTPdjG/fnC4mhVJ/KZOSnBrvo/VnYHUwlTp9jVLjAe2B3i3pyCH+3/E5jYQRSvuHk/8oas3870g==",
+ "requires": {
+ "jssha": "~3.3.0"
+ }
+ },
"p-cancelable": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
@@ -32892,12 +31286,6 @@
}
}
},
- "p-finally": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
- "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
- "dev": true
- },
"p-is-promise": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz",
@@ -33367,12 +31755,12 @@
"optional": true
},
"postcss": {
- "version": "8.4.20",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
- "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
"dev": true,
"requires": {
- "nanoid": "^3.3.4",
+ "nanoid": "^3.3.6",
"picocolors": "^1.0.0",
"source-map-js": "^1.0.2"
}
@@ -33481,12 +31869,6 @@
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
},
- "prepend-http": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
- "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==",
- "dev": true
- },
"prettier": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
@@ -33532,12 +31914,6 @@
"react-is": "^16.13.1"
}
},
- "proto-list": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
- "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
- "dev": true
- },
"proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -33547,15 +31923,6 @@
"ipaddr.js": "1.9.1"
}
},
- "ps-node": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz",
- "integrity": "sha512-w7QJhUTbu70hpDso0YXDRNKCPNuchV8UTUZsAv0m7Qj5g85oHOJfr9drA1EjvK4nQK/bG8P97W4L6PJ3IQLoOA==",
- "dev": true,
- "requires": {
- "table-parser": "^0.1.3"
- }
- },
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -34154,36 +32521,6 @@
}
}
},
- "require_optional": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
- "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
- "dev": true,
- "requires": {
- "resolve-from": "^2.0.0",
- "semver": "^5.1.0"
- },
- "dependencies": {
- "resolve-from": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
- "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==",
- "dev": true
- },
- "semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
- }
- }
- },
- "require-at": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz",
- "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==",
- "dev": true
- },
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -34356,15 +32693,6 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
- "saslprep": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
- "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
- "optional": true,
- "requires": {
- "sparse-bitfield": "^3.0.3"
- }
- },
"sass-lookup": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-3.0.0.tgz",
@@ -34562,9 +32890,9 @@
}
},
"semver": {
- "version": "7.5.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
- "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
+ "version": "7.5.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz",
+ "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==",
"requires": {
"lru-cache": "^6.0.0"
},
@@ -34949,24 +33277,6 @@
"smart-buffer": "^4.2.0"
}
},
- "sort-keys": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
- "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==",
- "dev": true,
- "requires": {
- "is-plain-obj": "^1.0.0"
- }
- },
- "sort-keys-length": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
- "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==",
- "dev": true,
- "requires": {
- "sort-keys": "^1.0.0"
- }
- },
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@@ -35314,15 +33624,6 @@
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
},
- "strip-outer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
- "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
- "dev": true,
- "requires": {
- "escape-string-regexp": "^1.0.2"
- }
- },
"stylus-lookup": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-3.0.2.tgz",
@@ -35413,15 +33714,6 @@
"integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==",
"dev": true
},
- "table-parser": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/table-parser/-/table-parser-0.1.3.tgz",
- "integrity": "sha512-LCYeuvqqoPII3lzzYaXKbC3Forb+d2u4bNwhk/9FlivuGRxPE28YEWAYcujeSlLLDlMfvy29+WPybFJZFiKMYg==",
- "dev": true,
- "requires": {
- "connected-domain": "^1.0.0"
- }
- },
"taffydb": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz",
@@ -35434,6 +33726,28 @@
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"dev": true
},
+ "tar": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz",
+ "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==",
+ "dev": true,
+ "requires": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "dependencies": {
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ }
+ }
+ },
"tar-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
@@ -35549,18 +33863,6 @@
}
}
},
- "tildify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz",
- "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==",
- "dev": true
- },
- "timed-out": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
- "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==",
- "dev": true
- },
"timers-ext": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
@@ -35739,15 +34041,6 @@
"integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
"dev": true
},
- "trim-repeated": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
- "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
- "dev": true,
- "requires": {
- "escape-string-regexp": "^1.0.2"
- }
- },
"triple-beam": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
@@ -36029,12 +34322,6 @@
}
}
},
- "untildify": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
- "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
- "dev": true
- },
"upath": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
@@ -36085,21 +34372,6 @@
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
"dev": true
},
- "url-parse-lax": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
- "integrity": "sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==",
- "dev": true,
- "requires": {
- "prepend-http": "^1.0.1"
- }
- },
- "url-to-options": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
- "integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==",
- "dev": true
- },
"use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@@ -36114,12 +34386,6 @@
"dev": true,
"requires": {}
},
- "user-home": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz",
- "integrity": "sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==",
- "dev": true
- },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -36323,9 +34589,9 @@
}
},
"word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="
},
"wordwrap": {
"version": "1.0.0",
diff --git a/package.json b/package.json
index 2d6914cb99..e425251b57 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "parse-server",
- "version": "6.3.0-beta.1",
+ "version": "7.0.0-alpha.9",
"description": "An express module providing a Parse-compatible API server",
"main": "lib/index.js",
"repository": {
@@ -25,7 +25,7 @@
"@graphql-tools/utils": "8.12.0",
"@graphql-yoga/node": "2.6.0",
"@parse/fs-files-adapter": "1.2.2",
- "@parse/push-adapter": "4.1.3",
+ "@parse/push-adapter": "5.0.2",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"commander": "10.0.1",
@@ -33,21 +33,21 @@
"deepcopy": "2.1.0",
"express": "4.18.2",
"express-rate-limit": "6.7.0",
- "follow-redirects": "1.15.2",
- "graphql": "16.6.0",
+ "follow-redirects": "1.15.4",
+ "graphql": "16.8.1",
"graphql-list-fields": "2.0.2",
"graphql-relay": "0.10.0",
"graphql-tag": "2.12.6",
"intersect": "1.0.1",
- "ip-range-check": "0.2.0",
"jsonwebtoken": "9.0.0",
"jwks-rsa": "2.1.5",
"ldapjs": "3.0.2",
"lodash": "4.17.21",
"lru-cache": "9.1.1",
"mime": "3.0.0",
- "mongodb": "4.10.0",
+ "mongodb": "5.9.0",
"mustache": "4.2.0",
+ "otpauth": "9.1.2",
"parse": "4.1.0",
"path-to-regexp": "6.2.1",
"pg-monitor": "2.0.0",
@@ -55,7 +55,7 @@
"pluralize": "8.0.0",
"rate-limit-redis": "3.0.2",
"redis": "4.6.6",
- "semver": "7.5.1",
+ "semver": "7.5.2",
"subscriptions-transport-ws": "0.11.0",
"tv4": "1.3.0",
"uuid": "9.0.0",
@@ -98,7 +98,7 @@
"madge": "5.0.1",
"mock-files-adapter": "file:spec/dependencies/mock-files-adapter",
"mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter",
- "mongodb-runner": "4.8.1",
+ "mongodb-runner": "5.4.4",
"mongodb-version-list": "1.0.0",
"node-abort-controller": "3.0.1",
"node-fetch": "3.2.10",
@@ -117,18 +117,18 @@
"lint-fix": "eslint --fix --cache ./",
"build": "babel src/ -d lib/ --copy-files",
"watch": "babel --watch src/ -d lib/ --copy-files",
- "test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start",
+ "test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
"test:mongodb:testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
"test:mongodb": "npm run test:mongodb:runnerstart --dbversion=$npm_config_dbversion && npm run test:mongodb:testonly --dbversion=$npm_config_dbversion",
"test:mongodb:4.2.19": "npm run test:mongodb --dbversion=4.2.19",
"test:mongodb:4.4.13": "npm run test:mongodb --dbversion=4.4.13",
"test:mongodb:5.3.2": "npm run test:mongodb --dbversion=5.3.2",
"test:mongodb:6.0.2": "npm run test:mongodb --dbversion=6.0.2",
- "posttest:mongodb": "mongodb-runner stop",
- "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start",
+ "test:mongodb:7.0.1": "npm run test:mongodb --dbversion=7.0.1",
+ "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner start -t ${MONGODB_TOPOLOGY} --version ${MONGODB_VERSION} -- --port 27017",
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 jasmine",
"test": "npm run testonly",
- "posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} mongodb-runner stop",
+ "posttest": "cross-env mongodb-runner stop --all",
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.3.2} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} TESTING=1 nyc jasmine",
"start": "node ./bin/parse-server",
"prettier": "prettier --write {src,spec}/{**/*,*}.js",
diff --git a/postinstall.js b/postinstall.js
index fef1fb31ff..fe1fc96bae 100644
--- a/postinstall.js
+++ b/postinstall.js
@@ -1,6 +1,6 @@
const pkg = require('./package.json');
-const version = parseFloat(process.version.substr(1));
+const version = parseFloat(process.version.substring(1));
const minimum = parseFloat(pkg.engines.node.match(/\d+/g).join('.'));
module.exports = function () {
diff --git a/release.config.js b/release.config.js
index b3776e2320..67d62c56c6 100644
--- a/release.config.js
+++ b/release.config.js
@@ -40,8 +40,8 @@ async function config() {
{ name: 'alpha', prerelease: true },
{ name: 'beta', prerelease: true },
'next-major',
- // Long-Term-Support branches; defined as GLOB pattern
- 'release-+([0-9]).x.x',
+ // Long-Term-Support branch of previous major version
+ 'release-6.x.x',
],
dryRun: false,
debug: true,
diff --git a/release_docs.sh b/release_docs.sh
index a7bb26324c..a9cc5bf3bc 100755
--- a/release_docs.sh
+++ b/release_docs.sh
@@ -27,3 +27,8 @@ npm run docs
mkdir -p "docs/api/${DEST}"
cp -R out/* "docs/api/${DEST}"
+
+# Copy other resources
+RESOURCE_DIR=".github"
+mkdir -p "docs/${RESOURCE_DIR}"
+cp "./.github/parse-server-logo.png" "docs/${RESOURCE_DIR}/"
diff --git a/resources/buildConfigDefinitions.js b/resources/buildConfigDefinitions.js
index e0d33daa4b..0be6e0085d 100644
--- a/resources/buildConfigDefinitions.js
+++ b/resources/buildConfigDefinitions.js
@@ -255,7 +255,16 @@ function inject(t, list) {
props.push(t.objectProperty(t.stringLiteral('action'), action));
}
if (elt.defaultValue) {
- const parsedValue = parseDefaultValue(elt, elt.defaultValue, t);
+ let parsedValue = parseDefaultValue(elt, elt.defaultValue, t);
+ if (!parsedValue) {
+ for (const type of elt.typeAnnotation.types) {
+ elt.type = type.type;
+ parsedValue = parseDefaultValue(elt, elt.defaultValue, t);
+ if (parsedValue) {
+ break;
+ }
+ }
+ }
if (parsedValue) {
props.push(t.objectProperty(t.stringLiteral('default'), parsedValue));
} else {
diff --git a/spec/.eslintrc.json b/spec/.eslintrc.json
index 8f8bcfeddc..cb61d2fd6c 100644
--- a/spec/.eslintrc.json
+++ b/spec/.eslintrc.json
@@ -15,6 +15,7 @@
"equal": true,
"expectAsync": true,
"notEqual": true,
+ "it_id": true,
"it_only_db": true,
"it_only_mongodb_version": true,
"it_only_postgres_version": true,
@@ -27,6 +28,7 @@
"fit_exclude_node_version": true,
"it_exclude_dbs": true,
"describe_only_db": true,
+ "fdescribe_only_db": true,
"describe_only": true,
"on_db": true,
"defaultConfiguration": true,
diff --git a/spec/AudienceRouter.spec.js b/spec/AudienceRouter.spec.js
index 9f0f77896a..f2302d32f7 100644
--- a/spec/AudienceRouter.spec.js
+++ b/spec/AudienceRouter.spec.js
@@ -339,11 +339,12 @@ describe('AudiencesRouter', () => {
)
.then(result => {
expect(result).toBeTruthy();
+
database
.collection('test__Audience')
.find({ _id: audience.objectId })
- .toArray((error, rows) => {
- expect(error).toEqual(undefined);
+ .toArray()
+ .then(rows => {
expect(rows[0]['times_used']).toEqual(1);
expect(rows[0]['_last_used']).toEqual(now);
Parse._request(
@@ -362,6 +363,9 @@ describe('AudiencesRouter', () => {
.catch(error => {
done.fail(error);
});
+ })
+ .catch(error => {
+ done.fail(error);
});
});
});
diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js
index bb89596cef..dee82fdc58 100644
--- a/spec/AuthenticationAdapters.spec.js
+++ b/spec/AuthenticationAdapters.spec.js
@@ -1454,7 +1454,6 @@ describe('oauth2 auth adapter', () => {
describe('apple signin auth adapter', () => {
const apple = require('../lib/Adapters/Auth/apple');
const jwt = require('jsonwebtoken');
- const util = require('util');
const authUtils = require('../lib/Adapters/Auth/utils');
it('(using client id as string) should throw error with missing id_token', async () => {
@@ -1512,12 +1511,10 @@ describe('apple signin auth adapter', () => {
sub: 'the_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
const result = await apple.validateAuthData(
{ id: 'the_user_id', token: 'the_token' },
@@ -1529,11 +1526,9 @@ describe('apple signin auth adapter', () => {
it('should not verify invalid id_token', async () => {
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
try {
await apple.validateAuthData(
@@ -1566,11 +1561,9 @@ describe('apple signin auth adapter', () => {
sub: 'the_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
const result = await apple.validateAuthData(
@@ -1588,11 +1581,9 @@ describe('apple signin auth adapter', () => {
sub: 'the_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
const result = await apple.validateAuthData(
@@ -1610,11 +1601,9 @@ describe('apple signin auth adapter', () => {
sub: 'the_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
const result = await apple.validateAuthData(
@@ -1630,11 +1619,9 @@ describe('apple signin auth adapter', () => {
sub: 'the_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -1658,11 +1645,9 @@ describe('apple signin auth adapter', () => {
sub: 'the_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -1687,11 +1672,9 @@ describe('apple signin auth adapter', () => {
sub: 'the_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -1759,11 +1742,9 @@ describe('apple signin auth adapter', () => {
sub: 'a_different_user_id',
};
const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -2025,7 +2006,6 @@ describe('microsoft graph auth adapter', () => {
describe('facebook limited auth adapter', () => {
const facebook = require('../lib/Adapters/Auth/facebook');
const jwt = require('jsonwebtoken');
- const util = require('util');
const authUtils = require('../lib/Adapters/Auth/utils');
// TODO: figure out a way to run this test alongside facebook classic tests
@@ -2086,18 +2066,11 @@ describe('facebook limited auth adapter', () => {
exp: Date.now(),
sub: 'the_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken.header);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
const result = await facebook.validateAuthData(
{ id: 'the_user_id', token: 'the_token' },
@@ -2108,17 +2081,10 @@ describe('facebook limited auth adapter', () => {
});
it('should not verify invalid id_token', async () => {
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
try {
await facebook.validateAuthData(
@@ -2150,17 +2116,10 @@ describe('facebook limited auth adapter', () => {
exp: Date.now(),
sub: 'the_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
const result = await facebook.validateAuthData(
@@ -2177,17 +2136,10 @@ describe('facebook limited auth adapter', () => {
exp: Date.now(),
sub: 'the_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
const result = await facebook.validateAuthData(
@@ -2204,17 +2156,10 @@ describe('facebook limited auth adapter', () => {
exp: Date.now(),
sub: 'the_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
const result = await facebook.validateAuthData(
@@ -2229,17 +2174,10 @@ describe('facebook limited auth adapter', () => {
iss: 'https://not.facebook.com',
sub: 'the_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -2262,17 +2200,10 @@ describe('facebook limited auth adapter', () => {
iss: 'https://not.facebook.com',
sub: 'the_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -2296,17 +2227,10 @@ describe('facebook limited auth adapter', () => {
iss: 'https://not.facebook.com',
sub: 'the_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -2382,17 +2306,10 @@ describe('facebook limited auth adapter', () => {
aud: 'invalid_client_id',
sub: 'a_different_user_id',
};
- const fakeDecodedToken = {
- header: { kid: '123', alg: 'RS256' },
- };
+ const fakeDecodedToken = { header: { kid: '123', alg: 'RS256' } };
+ const fakeSigningKey = { kid: '123', rsaPublicKey: 'the_rsa_public_key' };
spyOn(authUtils, 'getHeaderFromToken').and.callFake(() => fakeDecodedToken);
- const fakeGetSigningKeyAsyncFunction = () => {
- return {
- kid: '123',
- rsaPublicKey: 'the_rsa_public_key',
- };
- };
- spyOn(util, 'promisify').and.callFake(() => fakeGetSigningKeyAsyncFunction);
+ spyOn(authUtils, 'getSigningKey').and.resolveTo(fakeSigningKey);
spyOn(jwt, 'verify').and.callFake(() => fakeClaim);
try {
@@ -2406,3 +2323,342 @@ describe('facebook limited auth adapter', () => {
}
});
});
+
+describe('OTP TOTP auth adatper', () => {
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ };
+ beforeEach(async () => {
+ await reconfigureServer({
+ auth: {
+ mfa: {
+ enabled: true,
+ options: ['TOTP'],
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ },
+ },
+ });
+ });
+
+ it('can enroll', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const OTPAuth = require('otpauth');
+ const secret = new OTPAuth.Secret();
+ const totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret,
+ });
+ const token = totp.generate();
+ await user.save(
+ { authData: { mfa: { secret: secret.base32, token } } },
+ { sessionToken: user.getSessionToken() }
+ );
+ const response = user.get('authDataResponse');
+ expect(response.mfa).toBeDefined();
+ expect(response.mfa.recovery).toBeDefined();
+ expect(response.mfa.recovery.split(',').length).toEqual(2);
+ await user.fetch();
+ expect(user.get('authData').mfa).toEqual({ status: 'enabled' });
+ });
+
+ it('can login with valid token', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const OTPAuth = require('otpauth');
+ const secret = new OTPAuth.Secret();
+ const totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret,
+ });
+ const token = totp.generate();
+ await user.save(
+ { authData: { mfa: { secret: secret.base32, token } } },
+ { sessionToken: user.getSessionToken() }
+ );
+ const response = await request({
+ headers,
+ method: 'POST',
+ url: 'http://localhost:8378/1/login',
+ body: JSON.stringify({
+ username: 'username',
+ password: 'password',
+ authData: {
+ mfa: {
+ token: totp.generate(),
+ },
+ },
+ }),
+ }).then(res => res.data);
+ expect(response.objectId).toEqual(user.id);
+ expect(response.sessionToken).toBeDefined();
+ expect(response.authData).toEqual({ mfa: { status: 'enabled' } });
+ expect(Object.keys(response).sort()).toEqual(
+ [
+ 'objectId',
+ 'username',
+ 'createdAt',
+ 'updatedAt',
+ 'authData',
+ 'ACL',
+ 'sessionToken',
+ 'authDataResponse',
+ ].sort()
+ );
+ });
+
+ it('can change OTP with valid token', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const OTPAuth = require('otpauth');
+ const secret = new OTPAuth.Secret();
+ const totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret,
+ });
+ const token = totp.generate();
+ await user.save(
+ { authData: { mfa: { secret: secret.base32, token } } },
+ { sessionToken: user.getSessionToken() }
+ );
+
+ const new_secret = new OTPAuth.Secret();
+ const new_totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret: new_secret,
+ });
+ const new_token = new_totp.generate();
+ await user.save(
+ {
+ authData: { mfa: { secret: new_secret.base32, token: new_token, old: totp.generate() } },
+ },
+ { sessionToken: user.getSessionToken() }
+ );
+ await user.fetch({ useMasterKey: true });
+ expect(user.get('authData').mfa.secret).toEqual(new_secret.base32);
+ });
+
+ it('cannot change OTP with invalid token', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const OTPAuth = require('otpauth');
+ const secret = new OTPAuth.Secret();
+ const totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret,
+ });
+ const token = totp.generate();
+ await user.save(
+ { authData: { mfa: { secret: secret.base32, token } } },
+ { sessionToken: user.getSessionToken() }
+ );
+
+ const new_secret = new OTPAuth.Secret();
+ const new_totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret: new_secret,
+ });
+ const new_token = new_totp.generate();
+ await expectAsync(
+ user.save(
+ {
+ authData: { mfa: { secret: new_secret.base32, token: new_token, old: '123' } },
+ },
+ { sessionToken: user.getSessionToken() }
+ )
+ ).toBeRejectedWith(new Parse.Error(Parse.Error.OTHER_CAUSE, 'Invalid MFA token'));
+ await user.fetch({ useMasterKey: true });
+ expect(user.get('authData').mfa.secret).toEqual(secret.base32);
+ });
+
+ it('future logins require TOTP token', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const OTPAuth = require('otpauth');
+ const secret = new OTPAuth.Secret();
+ const totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret,
+ });
+ const token = totp.generate();
+ await user.save(
+ { authData: { mfa: { secret: secret.base32, token } } },
+ { sessionToken: user.getSessionToken() }
+ );
+ await expectAsync(Parse.User.logIn('username', 'password')).toBeRejectedWith(
+ new Parse.Error(Parse.Error.OTHER_CAUSE, 'Missing additional authData mfa')
+ );
+ });
+
+ it('future logins reject incorrect TOTP token', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const OTPAuth = require('otpauth');
+ const secret = new OTPAuth.Secret();
+ const totp = new OTPAuth.TOTP({
+ algorithm: 'SHA1',
+ digits: 6,
+ period: 30,
+ secret,
+ });
+ const token = totp.generate();
+ await user.save(
+ { authData: { mfa: { secret: secret.base32, token } } },
+ { sessionToken: user.getSessionToken() }
+ );
+ await expectAsync(
+ request({
+ headers,
+ method: 'POST',
+ url: 'http://localhost:8378/1/login',
+ body: JSON.stringify({
+ username: 'username',
+ password: 'password',
+ authData: {
+ mfa: {
+ token: 'abcd',
+ },
+ },
+ }),
+ }).catch(e => {
+ throw e.data;
+ })
+ ).toBeRejectedWith({ code: Parse.Error.SCRIPT_FAILED, error: 'Invalid MFA token' });
+ });
+});
+
+describe('OTP SMS auth adatper', () => {
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ };
+ let code;
+ let mobile;
+ const mfa = {
+ enabled: true,
+ options: ['SMS'],
+ sendSMS(smsCode, number) {
+ expect(smsCode).toBeDefined();
+ expect(number).toBeDefined();
+ expect(smsCode.length).toEqual(6);
+ code = smsCode;
+ mobile = number;
+ },
+ digits: 6,
+ period: 30,
+ };
+ beforeEach(async () => {
+ code = '';
+ mobile = '';
+ await reconfigureServer({
+ auth: {
+ mfa,
+ },
+ });
+ });
+
+ it('can enroll', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const sessionToken = user.getSessionToken();
+ const spy = spyOn(mfa, 'sendSMS').and.callThrough();
+ await user.save({ authData: { mfa: { mobile: '+11111111111' } } }, { sessionToken });
+ await user.fetch({ sessionToken });
+ expect(user.get('authData')).toEqual({ mfa: { status: 'disabled' } });
+ expect(spy).toHaveBeenCalledWith(code, '+11111111111');
+ await user.fetch({ useMasterKey: true });
+ const authData = user.get('authData').mfa?.pending;
+ expect(authData).toBeDefined();
+ expect(authData['+11111111111']).toBeDefined();
+ expect(Object.keys(authData['+11111111111'])).toEqual(['token', 'expiry']);
+
+ await user.save({ authData: { mfa: { mobile, token: code } } }, { sessionToken });
+ await user.fetch({ sessionToken });
+ expect(user.get('authData')).toEqual({ mfa: { status: 'enabled' } });
+ });
+
+ it('future logins require SMS code', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ const spy = spyOn(mfa, 'sendSMS').and.callThrough();
+ await user.save(
+ { authData: { mfa: { mobile: '+11111111111' } } },
+ { sessionToken: user.getSessionToken() }
+ );
+
+ await user.save(
+ { authData: { mfa: { mobile, token: code } } },
+ { sessionToken: user.getSessionToken() }
+ );
+
+ spy.calls.reset();
+
+ await expectAsync(Parse.User.logIn('username', 'password')).toBeRejectedWith(
+ new Parse.Error(Parse.Error.OTHER_CAUSE, 'Missing additional authData mfa')
+ );
+ const res = await request({
+ headers,
+ method: 'POST',
+ url: 'http://localhost:8378/1/login',
+ body: JSON.stringify({
+ username: 'username',
+ password: 'password',
+ authData: {
+ mfa: {
+ token: 'request',
+ },
+ },
+ }),
+ }).catch(e => e.data);
+ expect(res).toEqual({ code: Parse.Error.SCRIPT_FAILED, error: 'Please enter the token' });
+ expect(spy).toHaveBeenCalledWith(code, '+11111111111');
+ const response = await request({
+ headers,
+ method: 'POST',
+ url: 'http://localhost:8378/1/login',
+ body: JSON.stringify({
+ username: 'username',
+ password: 'password',
+ authData: {
+ mfa: {
+ token: code,
+ },
+ },
+ }),
+ }).then(res => res.data);
+ expect(response.objectId).toEqual(user.id);
+ expect(response.sessionToken).toBeDefined();
+ expect(response.authData).toEqual({ mfa: { status: 'enabled' } });
+ expect(Object.keys(response).sort()).toEqual(
+ [
+ 'objectId',
+ 'username',
+ 'createdAt',
+ 'updatedAt',
+ 'authData',
+ 'ACL',
+ 'sessionToken',
+ 'authDataResponse',
+ ].sort()
+ );
+ });
+
+ it('partially enrolled users can still login', async () => {
+ const user = await Parse.User.signUp('username', 'password');
+ await user.save({ authData: { mfa: { mobile: '+11111111111' } } });
+ const spy = spyOn(mfa, 'sendSMS').and.callThrough();
+ await Parse.User.logIn('username', 'password');
+ expect(spy).not.toHaveBeenCalled();
+ });
+});
diff --git a/spec/CLI.spec.js b/spec/CLI.spec.js
index 20667fd349..d73b854a9b 100644
--- a/spec/CLI.spec.js
+++ b/spec/CLI.spec.js
@@ -302,4 +302,25 @@ describe('execution', () => {
done.fail(data.toString());
});
});
+
+ it('can start Parse Server with auth via CLI', done => {
+ const env = { ...process.env };
+ env.NODE_OPTIONS = '--dns-result-order=ipv4first';
+ childProcess = spawn(
+ binPath,
+ ['--databaseURI', databaseURI, './spec/configs/CLIConfigAuth.json'],
+ { env }
+ );
+ childProcess.stdout.on('data', data => {
+ data = data.toString();
+ console.log(data);
+ if (data.includes('parse-server running on')) {
+ done();
+ }
+ });
+ childProcess.stderr.on('data', data => {
+ data = data.toString();
+ done.fail(data.toString());
+ });
+ });
});
diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js
index a8795a4e84..a1c8b48bfd 100644
--- a/spec/CloudCode.spec.js
+++ b/spec/CloudCode.spec.js
@@ -103,6 +103,14 @@ describe('Cloud Code', () => {
expect(currentConfig.silent).toBeFalse();
});
+ it('can get curent version', () => {
+ const version = require('../package.json').version;
+ const currentConfig = Config.get('test');
+ expect(Parse.Server.version).toBeDefined();
+ expect(currentConfig.version).toBeDefined();
+ expect(Parse.Server.version).toEqual(version);
+ });
+
it('show warning on duplicate cloud functions', done => {
const logger = require('../lib/logger').logger;
spyOn(logger, 'warn').and.callFake(() => {});
@@ -1353,7 +1361,27 @@ describe('Cloud Code', () => {
});
});
+ it('should not encode Parse Objects', async () => {
+ const user = new Parse.User();
+ user.setUsername('username');
+ user.setPassword('password');
+ user.set('deleted', false);
+ await user.signUp();
+ Parse.Cloud.define(
+ 'deleteAccount',
+ async req => {
+ expect(req.params.object instanceof Parse.Object).not.toBeTrue();
+ return 'Object deleted';
+ },
+ {
+ requireMaster: true,
+ }
+ );
+ await Parse.Cloud.run('deleteAccount', { object: user.toPointer() }, { useMasterKey: true });
+ });
+
it('allow cloud to encode Parse Objects', async () => {
+ await reconfigureServer({ encodeParseObjectInCloudFunction: true });
const user = new Parse.User();
user.setUsername('username');
user.setPassword('password');
@@ -2370,6 +2398,56 @@ describe('beforeFind hooks', () => {
});
});
+ it('sets correct beforeFind trigger isGet parameter for Parse.Object.fetch request', async () => {
+ const hook = {
+ method: req => {
+ expect(req.isGet).toEqual(true);
+ return Promise.resolve();
+ },
+ };
+ spyOn(hook, 'method').and.callThrough();
+ Parse.Cloud.beforeFind('MyObject', hook.method);
+ const obj = new Parse.Object('MyObject');
+ await obj.save();
+ const getObj = await obj.fetch();
+ expect(getObj).toBeInstanceOf(Parse.Object);
+ expect(hook.method).toHaveBeenCalledTimes(1);
+ });
+
+ it('sets correct beforeFind trigger isGet parameter for Parse.Query.get request', async () => {
+ const hook = {
+ method: req => {
+ expect(req.isGet).toEqual(false);
+ return Promise.resolve();
+ },
+ };
+ spyOn(hook, 'method').and.callThrough();
+ Parse.Cloud.beforeFind('MyObject', hook.method);
+ const obj = new Parse.Object('MyObject');
+ await obj.save();
+ const query = new Parse.Query('MyObject');
+ const getObj = await query.get(obj.id);
+ expect(getObj).toBeInstanceOf(Parse.Object);
+ expect(hook.method).toHaveBeenCalledTimes(1);
+ });
+
+ it('sets correct beforeFind trigger isGet parameter for Parse.Query.find request', async () => {
+ const hook = {
+ method: req => {
+ expect(req.isGet).toEqual(false);
+ return Promise.resolve();
+ },
+ };
+ spyOn(hook, 'method').and.callThrough();
+ Parse.Cloud.beforeFind('MyObject', hook.method);
+ const obj = new Parse.Object('MyObject');
+ await obj.save();
+ const query = new Parse.Query('MyObject');
+ const findObjs = await query.find();
+ expect(findObjs?.[0]).toBeInstanceOf(Parse.Object);
+ expect(hook.method).toHaveBeenCalledTimes(1);
+ });
+
it('should have request headers', done => {
Parse.Cloud.beforeFind('MyObject', req => {
expect(req.headers).toBeDefined();
@@ -2403,6 +2481,60 @@ describe('beforeFind hooks', () => {
})
.then(() => done());
});
+
+ it('should run beforeFind on pointers and array of pointers from an object', async () => {
+ const obj1 = new Parse.Object('TestObject');
+ const obj2 = new Parse.Object('TestObject2');
+ const obj3 = new Parse.Object('TestObject');
+ obj2.set('aField', 'aFieldValue');
+ await obj2.save();
+ obj1.set('pointerField', obj2);
+ obj3.set('pointerFieldArray', [obj2]);
+ await obj1.save();
+ await obj3.save();
+ const spy = jasmine.createSpy('beforeFindSpy');
+ Parse.Cloud.beforeFind('TestObject2', spy);
+ const query = new Parse.Query('TestObject');
+ await query.get(obj1.id);
+ // Pointer not included in query so we don't expect beforeFind to be called
+ expect(spy).not.toHaveBeenCalled();
+ const query2 = new Parse.Query('TestObject');
+ query2.include('pointerField');
+ const res = await query2.get(obj1.id);
+ expect(res.get('pointerField').get('aField')).toBe('aFieldValue');
+ // Pointer included in query so we expect beforeFind to be called
+ expect(spy).toHaveBeenCalledTimes(1);
+ const query3 = new Parse.Query('TestObject');
+ query3.include('pointerFieldArray');
+ const res2 = await query3.get(obj3.id);
+ expect(res2.get('pointerFieldArray')[0].get('aField')).toBe('aFieldValue');
+ expect(spy).toHaveBeenCalledTimes(2);
+ });
+
+ it('should have access to context in include query in beforeFind hook', async () => {
+ let beforeFindTestObjectCalled = false;
+ let beforeFindTestObject2Called = false;
+ const obj1 = new Parse.Object('TestObject');
+ const obj2 = new Parse.Object('TestObject2');
+ obj2.set('aField', 'aFieldValue');
+ await obj2.save();
+ obj1.set('pointerField', obj2);
+ await obj1.save();
+ Parse.Cloud.beforeFind('TestObject', req => {
+ expect(req.context).toBeDefined();
+ expect(req.context.a).toEqual('a');
+ beforeFindTestObjectCalled = true;
+ });
+ Parse.Cloud.beforeFind('TestObject2', req => {
+ expect(req.context).toBeDefined();
+ expect(req.context.a).toEqual('a');
+ beforeFindTestObject2Called = true;
+ });
+ const query = new Parse.Query('TestObject');
+ await query.include('pointerField').find({ context: { a: 'a' } });
+ expect(beforeFindTestObjectCalled).toBeTrue();
+ expect(beforeFindTestObject2Called).toBeTrue();
+ });
});
describe('afterFind hooks', () => {
@@ -3220,7 +3352,7 @@ describe('beforeLogin hook', () => {
expect(req.headers).toBeDefined();
expect(req.ip).toBeDefined();
expect(req.installationId).toBeDefined();
- expect(req.context).toBeUndefined();
+ expect(req.context).toBeDefined();
});
await Parse.User.signUp('tupac', 'shakur');
@@ -3337,7 +3469,7 @@ describe('afterLogin hook', () => {
expect(req.headers).toBeDefined();
expect(req.ip).toBeDefined();
expect(req.installationId).toBeDefined();
- expect(req.context).toBeUndefined();
+ expect(req.context).toBeDefined();
});
await Parse.User.signUp('testuser', 'p@ssword');
diff --git a/spec/DatabaseController.spec.js b/spec/DatabaseController.spec.js
index 98103ce6e4..e1b50a5a52 100644
--- a/spec/DatabaseController.spec.js
+++ b/spec/DatabaseController.spec.js
@@ -1,3 +1,4 @@
+const Config = require('../lib/Config');
const DatabaseController = require('../lib/Controllers/DatabaseController.js');
const validateQuery = DatabaseController._validateQuery;
@@ -361,6 +362,259 @@ describe('DatabaseController', function () {
done();
});
});
+
+ describe('enableCollationCaseComparison', () => {
+ const dummyStorageAdapter = {
+ find: () => Promise.resolve([]),
+ watch: () => Promise.resolve(),
+ getAllClasses: () => Promise.resolve([]),
+ };
+
+ beforeEach(() => {
+ Config.get(Parse.applicationId).schemaCache.clear();
+ });
+
+ it('should force caseInsensitive to false with enableCollationCaseComparison option', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {
+ enableCollationCaseComparison: true,
+ });
+ const spy = spyOn(dummyStorageAdapter, 'find');
+ spy.and.callThrough();
+ await databaseController.find('SomeClass', {}, { caseInsensitive: true });
+ expect(spy.calls.all()[0].args[3].caseInsensitive).toEqual(false);
+ });
+
+ it('should support caseInsensitive without enableCollationCaseComparison option', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {});
+ const spy = spyOn(dummyStorageAdapter, 'find');
+ spy.and.callThrough();
+ await databaseController.find('_User', {}, { caseInsensitive: true });
+ expect(spy.calls.all()[0].args[3].caseInsensitive).toEqual(true);
+ });
+
+ it_only_db('mongo')(
+ 'should create insensitive indexes without enableCollationCaseComparison',
+ async () => {
+ await reconfigureServer({
+ databaseURI: 'mongodb://localhost:27017/enableCollationCaseComparisonFalse',
+ databaseAdapter: undefined,
+ });
+ const user = new Parse.User();
+ await user.save({
+ username: 'example',
+ password: 'password',
+ email: 'example@example.com',
+ });
+ const schemas = await Parse.Schema.all();
+ const UserSchema = schemas.find(({ className }) => className === '_User');
+ expect(UserSchema.indexes).toEqual({
+ _id_: { _id: 1 },
+ username_1: { username: 1 },
+ case_insensitive_username: { username: 1 },
+ case_insensitive_email: { email: 1 },
+ email_1: { email: 1 },
+ });
+ }
+ );
+
+ it_only_db('mongo')(
+ 'should not create insensitive indexes with enableCollationCaseComparison',
+ async () => {
+ await reconfigureServer({
+ enableCollationCaseComparison: true,
+ databaseURI: 'mongodb://localhost:27017/enableCollationCaseComparisonTrue',
+ databaseAdapter: undefined,
+ });
+ const user = new Parse.User();
+ await user.save({
+ username: 'example',
+ password: 'password',
+ email: 'example@example.com',
+ });
+ const schemas = await Parse.Schema.all();
+ const UserSchema = schemas.find(({ className }) => className === '_User');
+ expect(UserSchema.indexes).toEqual({
+ _id_: { _id: 1 },
+ username_1: { username: 1 },
+ email_1: { email: 1 },
+ });
+ }
+ );
+ });
+
+ describe('convertEmailToLowercase', () => {
+ const dummyStorageAdapter = {
+ createObject: () => Promise.resolve({ ops: [{}] }),
+ findOneAndUpdate: () => Promise.resolve({}),
+ watch: () => Promise.resolve(),
+ getAllClasses: () =>
+ Promise.resolve([
+ {
+ className: '_User',
+ fields: { email: 'String' },
+ indexes: {},
+ classLevelPermissions: { protectedFields: {} },
+ },
+ ]),
+ };
+ const dates = {
+ createdAt: { iso: undefined, __type: 'Date' },
+ updatedAt: { iso: undefined, __type: 'Date' },
+ };
+
+ it('should not transform email to lower case without convertEmailToLowercase option on create', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {});
+ const spy = spyOn(dummyStorageAdapter, 'createObject');
+ spy.and.callThrough();
+ await databaseController.create('_User', {
+ email: 'EXAMPLE@EXAMPLE.COM',
+ });
+ expect(spy.calls.all()[0].args[2]).toEqual({
+ email: 'EXAMPLE@EXAMPLE.COM',
+ ...dates,
+ });
+ });
+
+ it('should transform email to lower case with convertEmailToLowercase option on create', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {
+ convertEmailToLowercase: true,
+ });
+ const spy = spyOn(dummyStorageAdapter, 'createObject');
+ spy.and.callThrough();
+ await databaseController.create('_User', {
+ email: 'EXAMPLE@EXAMPLE.COM',
+ });
+ expect(spy.calls.all()[0].args[2]).toEqual({
+ email: 'example@example.com',
+ ...dates,
+ });
+ });
+
+ it('should not transform email to lower case without convertEmailToLowercase option on update', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {});
+ const spy = spyOn(dummyStorageAdapter, 'findOneAndUpdate');
+ spy.and.callThrough();
+ await databaseController.update('_User', { id: 'example' }, { email: 'EXAMPLE@EXAMPLE.COM' });
+ expect(spy.calls.all()[0].args[3]).toEqual({
+ email: 'EXAMPLE@EXAMPLE.COM',
+ });
+ });
+
+ it('should transform email to lower case with convertEmailToLowercase option on update', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {
+ convertEmailToLowercase: true,
+ });
+ const spy = spyOn(dummyStorageAdapter, 'findOneAndUpdate');
+ spy.and.callThrough();
+ await databaseController.update('_User', { id: 'example' }, { email: 'EXAMPLE@EXAMPLE.COM' });
+ expect(spy.calls.all()[0].args[3]).toEqual({
+ email: 'example@example.com',
+ });
+ });
+
+ it('should not find a case insensitive user by email with convertEmailToLowercase', async () => {
+ await reconfigureServer({ convertEmailToLowercase: true });
+ const user = new Parse.User();
+ await user.save({ username: 'EXAMPLE', email: 'EXAMPLE@EXAMPLE.COM', password: 'password' });
+
+ const query = new Parse.Query(Parse.User);
+ query.equalTo('email', 'EXAMPLE@EXAMPLE.COM');
+ const result = await query.find({ useMasterKey: true });
+ expect(result.length).toEqual(0);
+
+ const query2 = new Parse.Query(Parse.User);
+ query2.equalTo('email', 'example@example.com');
+ const result2 = await query2.find({ useMasterKey: true });
+ expect(result2.length).toEqual(1);
+ });
+ });
+
+ describe('convertUsernameToLowercase', () => {
+ const dummyStorageAdapter = {
+ createObject: () => Promise.resolve({ ops: [{}] }),
+ findOneAndUpdate: () => Promise.resolve({}),
+ watch: () => Promise.resolve(),
+ getAllClasses: () =>
+ Promise.resolve([
+ {
+ className: '_User',
+ fields: { username: 'String' },
+ indexes: {},
+ classLevelPermissions: { protectedFields: {} },
+ },
+ ]),
+ };
+ const dates = {
+ createdAt: { iso: undefined, __type: 'Date' },
+ updatedAt: { iso: undefined, __type: 'Date' },
+ };
+
+ it('should not transform username to lower case without convertUsernameToLowercase option on create', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {});
+ const spy = spyOn(dummyStorageAdapter, 'createObject');
+ spy.and.callThrough();
+ await databaseController.create('_User', {
+ username: 'EXAMPLE',
+ });
+ expect(spy.calls.all()[0].args[2]).toEqual({
+ username: 'EXAMPLE',
+ ...dates,
+ });
+ });
+
+ it('should transform username to lower case with convertUsernameToLowercase option on create', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {
+ convertUsernameToLowercase: true,
+ });
+ const spy = spyOn(dummyStorageAdapter, 'createObject');
+ spy.and.callThrough();
+ await databaseController.create('_User', {
+ username: 'EXAMPLE',
+ });
+ expect(spy.calls.all()[0].args[2]).toEqual({
+ username: 'example',
+ ...dates,
+ });
+ });
+
+ it('should not transform username to lower case without convertUsernameToLowercase option on update', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {});
+ const spy = spyOn(dummyStorageAdapter, 'findOneAndUpdate');
+ spy.and.callThrough();
+ await databaseController.update('_User', { id: 'example' }, { username: 'EXAMPLE' });
+ expect(spy.calls.all()[0].args[3]).toEqual({
+ username: 'EXAMPLE',
+ });
+ });
+
+ it('should transform username to lower case with convertUsernameToLowercase option on update', async () => {
+ const databaseController = new DatabaseController(dummyStorageAdapter, {
+ convertUsernameToLowercase: true,
+ });
+ const spy = spyOn(dummyStorageAdapter, 'findOneAndUpdate');
+ spy.and.callThrough();
+ await databaseController.update('_User', { id: 'example' }, { username: 'EXAMPLE' });
+ expect(spy.calls.all()[0].args[3]).toEqual({
+ username: 'example',
+ });
+ });
+
+ it('should not find a case insensitive user by username with convertUsernameToLowercase', async () => {
+ await reconfigureServer({ convertUsernameToLowercase: true });
+ const user = new Parse.User();
+ await user.save({ username: 'EXAMPLE', password: 'password' });
+
+ const query = new Parse.Query(Parse.User);
+ query.equalTo('username', 'EXAMPLE');
+ const result = await query.find({ useMasterKey: true });
+ expect(result.length).toEqual(0);
+
+ const query2 = new Parse.Query(Parse.User);
+ query2.equalTo('username', 'example');
+ const result2 = await query2.find({ useMasterKey: true });
+ expect(result2.length).toEqual(1);
+ });
+ });
});
function buildCLP(pointerNames) {
diff --git a/spec/DefinedSchemas.spec.js b/spec/DefinedSchemas.spec.js
index 8d8853766e..a1c7e3dca5 100644
--- a/spec/DefinedSchemas.spec.js
+++ b/spec/DefinedSchemas.spec.js
@@ -554,7 +554,7 @@ describe('DefinedSchemas', () => {
});
});
- it('should not delete automatically classes', async () => {
+ it('should not delete classes automatically', async () => {
await reconfigureServer({
schema: { definitions: [{ className: '_User' }, { className: 'Test' }] },
});
diff --git a/spec/EmailVerificationToken.spec.js b/spec/EmailVerificationToken.spec.js
index e21a049719..e4e36eaa94 100644
--- a/spec/EmailVerificationToken.spec.js
+++ b/spec/EmailVerificationToken.spec.js
@@ -3,6 +3,7 @@
const Auth = require('../lib/Auth');
const Config = require('../lib/Config');
const request = require('../lib/request');
+const MockEmailAdapterWithOptions = require('./support/MockEmailAdapterWithOptions');
describe('Email Verification Token Expiration: ', () => {
it('show the invalid verification link page, if the user clicks on the verify email link after the email verify token expires', done => {
@@ -126,6 +127,7 @@ describe('Email Verification Token Expiration: ', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
request({
url: sendEmailOptions.link,
@@ -167,6 +169,7 @@ describe('Email Verification Token Expiration: ', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
request({
url: sendEmailOptions.link,
@@ -214,6 +217,7 @@ describe('Email Verification Token Expiration: ', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
request({
url: sendEmailOptions.link,
@@ -288,6 +292,223 @@ describe('Email Verification Token Expiration: ', () => {
});
});
+ it('can conditionally send emails', async () => {
+ let sendEmailOptions;
+ const emailAdapter = {
+ sendVerificationEmail: options => {
+ sendEmailOptions = options;
+ },
+ sendPasswordResetEmail: () => Promise.resolve(),
+ sendMail: () => {},
+ };
+ const verifyUserEmails = {
+ method(req) {
+ expect(Object.keys(req)).toEqual(['original', 'object', 'master', 'ip', 'installationId']);
+ return false;
+ },
+ };
+ const verifySpy = spyOn(verifyUserEmails, 'method').and.callThrough();
+ await reconfigureServer({
+ appName: 'emailVerifyToken',
+ verifyUserEmails: verifyUserEmails.method,
+ emailAdapter: emailAdapter,
+ emailVerifyTokenValidityDuration: 5, // 5 seconds
+ publicServerURL: 'http://localhost:8378/1',
+ });
+ const beforeSave = {
+ method(req) {
+ req.object.set('emailVerified', true);
+ },
+ };
+ const saveSpy = spyOn(beforeSave, 'method').and.callThrough();
+ const emailSpy = spyOn(emailAdapter, 'sendVerificationEmail').and.callThrough();
+ Parse.Cloud.beforeSave(Parse.User, beforeSave.method);
+ const user = new Parse.User();
+ user.setUsername('sets_email_verify_token_expires_at');
+ user.setPassword('expiringToken');
+ user.set('email', 'user@example.com');
+ await user.signUp();
+
+ const config = Config.get('test');
+ const results = await config.database.find(
+ '_User',
+ {
+ username: 'sets_email_verify_token_expires_at',
+ },
+ {},
+ Auth.maintenance(config)
+ );
+
+ expect(results.length).toBe(1);
+ const user_data = results[0];
+ expect(typeof user_data).toBe('object');
+ expect(user_data.emailVerified).toEqual(true);
+ expect(user_data._email_verify_token).toBeUndefined();
+ expect(user_data._email_verify_token_expires_at).toBeUndefined();
+ expect(emailSpy).not.toHaveBeenCalled();
+ expect(saveSpy).toHaveBeenCalled();
+ expect(sendEmailOptions).toBeUndefined();
+ expect(verifySpy).toHaveBeenCalled();
+ });
+
+ it('can conditionally send emails and allow conditional login', async () => {
+ let sendEmailOptions;
+ const emailAdapter = {
+ sendVerificationEmail: options => {
+ sendEmailOptions = options;
+ },
+ sendPasswordResetEmail: () => Promise.resolve(),
+ sendMail: () => {},
+ };
+ const verifyUserEmails = {
+ method(req) {
+ expect(Object.keys(req)).toEqual(['original', 'object', 'master', 'ip', 'installationId']);
+ if (req.object.get('username') === 'no_email') {
+ return false;
+ }
+ return true;
+ },
+ };
+ const verifySpy = spyOn(verifyUserEmails, 'method').and.callThrough();
+ await reconfigureServer({
+ appName: 'emailVerifyToken',
+ verifyUserEmails: verifyUserEmails.method,
+ preventLoginWithUnverifiedEmail: verifyUserEmails.method,
+ emailAdapter: emailAdapter,
+ emailVerifyTokenValidityDuration: 5, // 5 seconds
+ publicServerURL: 'http://localhost:8378/1',
+ });
+ const user = new Parse.User();
+ user.setUsername('no_email');
+ user.setPassword('expiringToken');
+ user.set('email', 'user@example.com');
+ await user.signUp();
+ expect(sendEmailOptions).toBeUndefined();
+ expect(user.getSessionToken()).toBeDefined();
+ expect(verifySpy).toHaveBeenCalledTimes(2);
+ const user2 = new Parse.User();
+ user2.setUsername('email');
+ user2.setPassword('expiringToken');
+ user2.set('email', 'user2@example.com');
+ await user2.signUp();
+ await jasmine.timeout();
+ expect(user2.getSessionToken()).toBeUndefined();
+ expect(sendEmailOptions).toBeDefined();
+ expect(verifySpy).toHaveBeenCalledTimes(5);
+ });
+
+ it('can conditionally send user email verification', async () => {
+ const emailAdapter = {
+ sendVerificationEmail: () => {},
+ sendPasswordResetEmail: () => Promise.resolve(),
+ sendMail: () => {},
+ };
+ const sendVerificationEmail = {
+ method(req) {
+ expect(req.user).toBeDefined();
+ expect(req.master).toBeDefined();
+ return false;
+ },
+ };
+ const sendSpy = spyOn(sendVerificationEmail, 'method').and.callThrough();
+ await reconfigureServer({
+ appName: 'emailVerifyToken',
+ verifyUserEmails: true,
+ emailAdapter: emailAdapter,
+ emailVerifyTokenValidityDuration: 5, // 5 seconds
+ publicServerURL: 'http://localhost:8378/1',
+ sendUserEmailVerification: sendVerificationEmail.method,
+ });
+ const emailSpy = spyOn(emailAdapter, 'sendVerificationEmail').and.callThrough();
+ const newUser = new Parse.User();
+ newUser.setUsername('unsets_email_verify_token_expires_at');
+ newUser.setPassword('expiringToken');
+ newUser.set('email', 'user@example.com');
+ await newUser.signUp();
+ await Parse.User.requestEmailVerification('user@example.com');
+ await jasmine.timeout();
+ expect(sendSpy).toHaveBeenCalledTimes(2);
+ expect(emailSpy).toHaveBeenCalledTimes(0);
+ });
+
+ it('provides full user object in email verification function on email and username change', async () => {
+ const emailAdapter = {
+ sendVerificationEmail: () => {},
+ sendPasswordResetEmail: () => Promise.resolve(),
+ sendMail: () => {},
+ };
+ const sendVerificationEmail = {
+ method(req) {
+ expect(req.user).toBeDefined();
+ expect(req.user.id).toBeDefined();
+ expect(req.user.get('createdAt')).toBeDefined();
+ expect(req.user.get('updatedAt')).toBeDefined();
+ expect(req.master).toBeDefined();
+ return false;
+ },
+ };
+ await reconfigureServer({
+ appName: 'emailVerifyToken',
+ verifyUserEmails: true,
+ emailAdapter: emailAdapter,
+ emailVerifyTokenValidityDuration: 5,
+ publicServerURL: 'http://localhost:8378/1',
+ sendUserEmailVerification: sendVerificationEmail.method,
+ });
+ const user = new Parse.User();
+ user.setPassword('password');
+ user.setUsername('new@example.com');
+ user.setEmail('user@example.com');
+ await user.save(null, { useMasterKey: true });
+
+ // Update email and username
+ user.setUsername('new@example.com');
+ user.setEmail('new@example.com');
+ await user.save(null, { useMasterKey: true });
+ });
+
+ it('beforeSave options do not change existing behaviour', async () => {
+ let sendEmailOptions;
+ const emailAdapter = {
+ sendVerificationEmail: options => {
+ sendEmailOptions = options;
+ },
+ sendPasswordResetEmail: () => Promise.resolve(),
+ sendMail: () => {},
+ };
+ await reconfigureServer({
+ appName: 'emailVerifyToken',
+ verifyUserEmails: true,
+ emailAdapter: emailAdapter,
+ emailVerifyTokenValidityDuration: 5, // 5 seconds
+ publicServerURL: 'http://localhost:8378/1',
+ });
+ const emailSpy = spyOn(emailAdapter, 'sendVerificationEmail').and.callThrough();
+ const newUser = new Parse.User();
+ newUser.setUsername('unsets_email_verify_token_expires_at');
+ newUser.setPassword('expiringToken');
+ newUser.set('email', 'user@parse.com');
+ await newUser.signUp();
+ await jasmine.timeout();
+ const response = await request({
+ url: sendEmailOptions.link,
+ followRedirects: false,
+ });
+ expect(response.status).toEqual(302);
+ const config = Config.get('test');
+ const results = await config.database.find('_User', {
+ username: 'unsets_email_verify_token_expires_at',
+ });
+
+ expect(results.length).toBe(1);
+ const user = results[0];
+ expect(typeof user).toBe('object');
+ expect(user.emailVerified).toEqual(true);
+ expect(typeof user._email_verify_token).toBe('undefined');
+ expect(typeof user._email_verify_token_expires_at).toBe('undefined');
+ expect(emailSpy).toHaveBeenCalled();
+ });
+
it('unsets the _email_verify_token_expires_at and _email_verify_token fields in the User class if email verification is successful', done => {
const user = new Parse.User();
let sendEmailOptions;
@@ -311,6 +532,7 @@ describe('Email Verification Token Expiration: ', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
request({
url: sendEmailOptions.link,
@@ -370,6 +592,7 @@ describe('Email Verification Token Expiration: ', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
return request({
url: sendEmailOptions.link,
@@ -587,6 +810,9 @@ describe('Email Verification Token Expiration: ', () => {
})
.then(response => {
expect(response.status).toBe(200);
+ })
+ .then(() => jasmine.timeout())
+ .then(() => {
expect(sendVerificationEmailCallCount).toBe(2);
expect(sendEmailOptions).toBeDefined();
@@ -616,6 +842,41 @@ describe('Email Verification Token Expiration: ', () => {
});
});
+ it('provides function arguments in verifyUserEmails on verificationEmailRequest', async () => {
+ const user = new Parse.User();
+ user.setUsername('user');
+ user.setPassword('pass');
+ user.set('email', 'test@example.com');
+ await user.signUp();
+
+ const verifyUserEmails = {
+ method: async params => {
+ expect(params.object).toBeInstanceOf(Parse.User);
+ expect(params.ip).toBeDefined();
+ expect(params.master).toBeDefined();
+ expect(params.installationId).toBeDefined();
+ expect(params.resendRequest).toBeTrue();
+ return true;
+ },
+ };
+ const verifyUserEmailsSpy = spyOn(verifyUserEmails, 'method').and.callThrough();
+ await reconfigureServer({
+ appName: 'test',
+ publicServerURL: 'http://localhost:1337/1',
+ verifyUserEmails: verifyUserEmails.method,
+ preventLoginWithUnverifiedEmail: verifyUserEmails.method,
+ preventSignupWithUnverifiedEmail: true,
+ emailAdapter: MockEmailAdapterWithOptions({
+ fromAddress: 'parse@example.com',
+ apiKey: 'k',
+ domain: 'd',
+ }),
+ });
+
+ await expectAsync(Parse.User.requestEmailVerification('test@example.com')).toBeResolved();
+ expect(verifyUserEmailsSpy).toHaveBeenCalledTimes(1);
+ });
+
it('should throw with invalid emailVerifyTokenReuseIfValid', async done => {
const sendEmailOptions = [];
const emailAdapter = {
@@ -681,9 +942,14 @@ describe('Email Verification Token Expiration: ', () => {
await user.signUp();
const config = Config.get('test');
- const [userBeforeRequest] = await config.database.find('_User', {
- username: 'resends_verification_token',
- });
+ const [userBeforeRequest] = await config.database.find(
+ '_User',
+ {
+ username: 'resends_verification_token',
+ },
+ {},
+ Auth.maintenance(config)
+ );
// store this user before we make our email request
expect(sendVerificationEmailCallCount).toBe(1);
await new Promise(resolve => {
@@ -703,17 +969,25 @@ describe('Email Verification Token Expiration: ', () => {
'Content-Type': 'application/json',
},
});
+ await jasmine.timeout();
expect(response.status).toBe(200);
expect(sendVerificationEmailCallCount).toBe(2);
expect(sendEmailOptions).toBeDefined();
- const [userAfterRequest] = await config.database.find('_User', {
- username: 'resends_verification_token',
- });
+ const [userAfterRequest] = await config.database.find(
+ '_User',
+ {
+ username: 'resends_verification_token',
+ },
+ {},
+ Auth.maintenance(config)
+ );
- // verify that our token & expiration has been changed for this new request
+ // Verify that token & expiration haven't been changed for this new request
expect(typeof userAfterRequest).toBe('object');
+ expect(userBeforeRequest._email_verify_token).toBeDefined();
expect(userBeforeRequest._email_verify_token).toEqual(userAfterRequest._email_verify_token);
+ expect(userBeforeRequest._email_verify_token_expires_at).toBeDefined();
expect(userBeforeRequest._email_verify_token_expires_at).toEqual(
userAfterRequest._email_verify_token_expires_at
);
@@ -745,6 +1019,7 @@ describe('Email Verification Token Expiration: ', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
return request({
url: sendEmailOptions.link,
@@ -983,6 +1258,7 @@ describe('Email Verification Token Expiration: ', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
request({
url: sendEmailOptions.link,
diff --git a/spec/Middlewares.spec.js b/spec/Middlewares.spec.js
index 636e7809f9..7ec50bd434 100644
--- a/spec/Middlewares.spec.js
+++ b/spec/Middlewares.spec.js
@@ -1,10 +1,19 @@
const middlewares = require('../lib/middlewares');
const AppCache = require('../lib/cache').AppCache;
+const { BlockList } = require('net');
+
+const AppCachePut = (appId, config) =>
+ AppCache.put(appId, {
+ ...config,
+ maintenanceKeyIpsStore: new Map(),
+ masterKeyIpsStore: new Map(),
+ });
describe('middlewares', () => {
let fakeReq, fakeRes;
beforeEach(() => {
fakeReq = {
+ ip: '127.0.0.1',
originalUrl: 'http://example.com/parse/',
url: 'http://example.com/',
body: {
@@ -16,7 +25,7 @@ describe('middlewares', () => {
},
};
fakeRes = jasmine.createSpyObj('fakeRes', ['end', 'status']);
- AppCache.put(fakeReq.body._ApplicationId, {});
+ AppCachePut(fakeReq.body._ApplicationId, {});
});
afterEach(() => {
@@ -35,7 +44,7 @@ describe('middlewares', () => {
});
it('should give invalid response when keys are configured but no key supplied', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey',
});
@@ -44,7 +53,7 @@ describe('middlewares', () => {
});
it('should give invalid response when keys are configured but supplied key is incorrect', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey',
});
@@ -54,7 +63,7 @@ describe('middlewares', () => {
});
it('should give invalid response when keys are configured but different key is supplied', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
restAPIKey: 'restAPIKey',
});
@@ -64,7 +73,7 @@ describe('middlewares', () => {
});
it('should succeed when any one of the configured keys supplied', done => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
clientKey: 'clientKey',
masterKey: 'masterKey',
restAPIKey: 'restAPIKey',
@@ -77,7 +86,7 @@ describe('middlewares', () => {
});
it('should succeed when client key supplied but empty', done => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
clientKey: '',
masterKey: 'masterKey',
restAPIKey: 'restAPIKey',
@@ -90,7 +99,7 @@ describe('middlewares', () => {
});
it('should succeed when no keys are configured and none supplied', done => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
});
middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
@@ -117,7 +126,7 @@ describe('middlewares', () => {
otherKey => otherKey !== infoKey && otherKey !== 'javascriptKey'
);
it(`it should pull ${bodyKey} into req.info`, done => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKeyIps: ['0.0.0.0/0'],
});
fakeReq.ip = '127.0.0.1';
@@ -138,7 +147,7 @@ describe('middlewares', () => {
it('should not succeed and log if the ip does not belong to masterKeyIps list', async () => {
const logger = require('../lib/logger').logger;
spyOn(logger, 'error').and.callFake(() => {});
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
masterKeyIps: ['10.0.0.1'],
});
@@ -152,7 +161,7 @@ describe('middlewares', () => {
});
it('should not succeed if the ip does not belong to masterKeyIps list', async () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
masterKeyIps: ['10.0.0.1'],
});
@@ -165,7 +174,7 @@ describe('middlewares', () => {
it('should not succeed if the ip does not belong to maintenanceKeyIps list', async () => {
const logger = require('../lib/logger').logger;
spyOn(logger, 'error').and.callFake(() => {});
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
maintenanceKey: 'masterKey',
maintenanceKeyIps: ['10.0.0.0', '10.0.0.1'],
});
@@ -179,7 +188,7 @@ describe('middlewares', () => {
});
it('should succeed if the ip does belong to masterKeyIps list', async () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
masterKeyIps: ['10.0.0.1'],
});
@@ -190,7 +199,7 @@ describe('middlewares', () => {
});
it('should allow any ip to use masterKey if masterKeyIps is empty', async () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
masterKeyIps: ['0.0.0.0/0'],
});
@@ -221,7 +230,7 @@ describe('middlewares', () => {
});
it('should set default Access-Control-Allow-Headers if allowHeaders are empty', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
allowHeaders: undefined,
});
const headers = {};
@@ -234,7 +243,7 @@ describe('middlewares', () => {
allowCrossDomain(fakeReq, res, () => {});
expect(headers['Access-Control-Allow-Headers']).toContain(middlewares.DEFAULT_ALLOWED_HEADERS);
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
allowHeaders: [],
});
allowCrossDomain(fakeReq, res, () => {});
@@ -242,7 +251,7 @@ describe('middlewares', () => {
});
it('should append custom headers to Access-Control-Allow-Headers if allowHeaders provided', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
allowHeaders: ['Header-1', 'Header-2'],
});
const headers = {};
@@ -258,7 +267,7 @@ describe('middlewares', () => {
});
it('should set default Access-Control-Allow-Origin if allowOrigin is empty', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
allowOrigin: undefined,
});
const headers = {};
@@ -273,7 +282,7 @@ describe('middlewares', () => {
});
it('should set custom origin to Access-Control-Allow-Origin if allowOrigin is provided', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
allowOrigin: 'https://parseplatform.org/',
});
const headers = {};
@@ -317,7 +326,7 @@ describe('middlewares', () => {
});
it('should use user provided on field userFromJWT', done => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
});
fakeReq.userFromJWT = 'fake-user';
@@ -328,11 +337,87 @@ describe('middlewares', () => {
});
it('should give invalid response when upload file without x-parse-application-id in header', () => {
- AppCache.put(fakeReq.body._ApplicationId, {
+ AppCachePut(fakeReq.body._ApplicationId, {
masterKey: 'masterKey',
});
fakeReq.body = Buffer.from('fake-file');
middlewares.handleParseHeaders(fakeReq, fakeRes);
expect(fakeRes.status).toHaveBeenCalledWith(403);
});
+
+ it('should match address', () => {
+ const ipv6 = '2001:0db8:85a3:0000:0000:8a2e:0370:7334';
+ const anotherIpv6 = '::ffff:101.10.0.1';
+ const ipv4 = '192.168.0.101';
+ const localhostV6 = '::1';
+ const localhostV62 = '::ffff:127.0.0.1';
+ const localhostV4 = '127.0.0.1';
+
+ const v6 = [ipv6, anotherIpv6];
+ v6.forEach(ip => {
+ expect(middlewares.checkIp(ip, ['::/0'], new Map())).toBe(true);
+ expect(middlewares.checkIp(ip, ['::'], new Map())).toBe(true);
+ expect(middlewares.checkIp(ip, ['0.0.0.0'], new Map())).toBe(false);
+ expect(middlewares.checkIp(ip, ['0.0.0.0/0'], new Map())).toBe(false);
+ expect(middlewares.checkIp(ip, ['123.123.123.123'], new Map())).toBe(false);
+ });
+
+ expect(middlewares.checkIp(ipv6, [anotherIpv6], new Map())).toBe(false);
+ expect(middlewares.checkIp(ipv6, [ipv6], new Map())).toBe(true);
+ expect(middlewares.checkIp(ipv6, ['2001:db8:85a3:0:0:8a2e:0:0/100'], new Map())).toBe(true);
+
+ expect(middlewares.checkIp(ipv4, ['::'], new Map())).toBe(false);
+ expect(middlewares.checkIp(ipv4, ['::/0'], new Map())).toBe(false);
+ expect(middlewares.checkIp(ipv4, ['0.0.0.0'], new Map())).toBe(true);
+ expect(middlewares.checkIp(ipv4, ['0.0.0.0/0'], new Map())).toBe(true);
+ expect(middlewares.checkIp(ipv4, ['123.123.123.123'], new Map())).toBe(false);
+ expect(middlewares.checkIp(ipv4, [ipv4], new Map())).toBe(true);
+ expect(middlewares.checkIp(ipv4, ['192.168.0.0/24'], new Map())).toBe(true);
+
+ expect(middlewares.checkIp(localhostV4, ['::1'], new Map())).toBe(false);
+ expect(middlewares.checkIp(localhostV6, ['::1'], new Map())).toBe(true);
+ // ::ffff:127.0.0.1 is a padded ipv4 address but not ::1
+ expect(middlewares.checkIp(localhostV62, ['::1'], new Map())).toBe(false);
+ // ::ffff:127.0.0.1 is a padded ipv4 address and is a match for 127.0.0.1
+ expect(middlewares.checkIp(localhostV62, ['127.0.0.1'], new Map())).toBe(true);
+ });
+
+ it('should match address with cache', () => {
+ const ipv6 = '2001:0db8:85a3:0000:0000:8a2e:0370:7334';
+ const cache1 = new Map();
+ const spyBlockListCheck = spyOn(BlockList.prototype, 'check').and.callThrough();
+ expect(middlewares.checkIp(ipv6, ['::'], cache1)).toBe(true);
+ expect(cache1.get('2001:0db8:85a3:0000:0000:8a2e:0370:7334')).toBe(undefined);
+ expect(cache1.get('allowAllIpv6')).toBe(true);
+ expect(spyBlockListCheck).toHaveBeenCalledTimes(0);
+
+ const cache2 = new Map();
+ expect(middlewares.checkIp('::1', ['::1'], cache2)).toBe(true);
+ expect(cache2.get('::1')).toBe(true);
+ expect(spyBlockListCheck).toHaveBeenCalledTimes(1);
+ expect(middlewares.checkIp('::1', ['::1'], cache2)).toBe(true);
+ expect(spyBlockListCheck).toHaveBeenCalledTimes(1);
+ spyBlockListCheck.calls.reset();
+
+ const cache3 = new Map();
+ expect(middlewares.checkIp('127.0.0.1', ['127.0.0.1'], cache3)).toBe(true);
+ expect(cache3.get('127.0.0.1')).toBe(true);
+ expect(spyBlockListCheck).toHaveBeenCalledTimes(1);
+ expect(middlewares.checkIp('127.0.0.1', ['127.0.0.1'], cache3)).toBe(true);
+ expect(spyBlockListCheck).toHaveBeenCalledTimes(1);
+ spyBlockListCheck.calls.reset();
+
+ const cache4 = new Map();
+ const ranges = ['127.0.0.1', '192.168.0.0/24'];
+ // should not cache negative match
+ expect(middlewares.checkIp('123.123.123.123', ranges, cache4)).toBe(false);
+ expect(cache4.get('123.123.123.123')).toBe(undefined);
+ expect(spyBlockListCheck).toHaveBeenCalledTimes(1);
+ spyBlockListCheck.calls.reset();
+
+ // should not cache cidr
+ expect(middlewares.checkIp('192.168.0.101', ranges, cache4)).toBe(true);
+ expect(cache4.get('192.168.0.101')).toBe(undefined);
+ expect(spyBlockListCheck).toHaveBeenCalledTimes(1);
+ });
});
diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js
index 1b5cc0c5e9..e7bbfe0cd8 100644
--- a/spec/MongoStorageAdapter.spec.js
+++ b/spec/MongoStorageAdapter.spec.js
@@ -254,6 +254,47 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
expect(obj.get('foo').test.date[0] instanceof Date).toBeTrue();
});
+ it('upserts with $setOnInsert', async () => {
+ const uuid = require('uuid');
+ const uuid1 = uuid.v4();
+ const uuid2 = uuid.v4();
+ const schema = {
+ className: 'MyClass',
+ fields: {
+ x: { type: 'Number' },
+ count: { type: 'Number' },
+ },
+ classLevelPermissions: {},
+ };
+
+ const myClassSchema = new Parse.Schema(schema.className);
+ myClassSchema.setCLP(schema.classLevelPermissions);
+ await myClassSchema.save();
+
+ const query = {
+ x: 1,
+ };
+ const update = {
+ objectId: {
+ __op: 'SetOnInsert',
+ amount: uuid1,
+ },
+ count: {
+ __op: 'Increment',
+ amount: 1,
+ },
+ };
+ await Parse.Server.database.update('MyClass', query, update, { upsert: true });
+ update.objectId.amount = uuid2;
+ await Parse.Server.database.update('MyClass', query, update, { upsert: true });
+
+ const res = await Parse.Server.database.find(schema.className, {}, {});
+ expect(res.length).toBe(1);
+ expect(res[0].objectId).toBe(uuid1);
+ expect(res[0].count).toBe(2);
+ expect(res[0].x).toBe(1);
+ });
+
it('handles updating a single object with array, object date', done => {
const adapter = new MongoStorageAdapter({ uri: databaseURI });
diff --git a/spec/PagesRouter.spec.js b/spec/PagesRouter.spec.js
index e50144f1fe..5f86922b08 100644
--- a/spec/PagesRouter.spec.js
+++ b/spec/PagesRouter.spec.js
@@ -749,6 +749,7 @@ describe('Pages Router', () => {
user.setPassword('examplePassword');
user.set('email', 'mail@example.com');
await user.signUp();
+ await jasmine.timeout();
const link = sendVerificationEmail.calls.all()[0].args[0].link;
const linkWithLocale = new URL(link);
@@ -777,6 +778,7 @@ describe('Pages Router', () => {
user.setPassword('examplePassword');
user.set('email', 'mail@example.com');
await user.signUp();
+ await jasmine.timeout();
const link = sendVerificationEmail.calls.all()[0].args[0].link;
const linkWithLocale = new URL(link);
@@ -830,6 +832,7 @@ describe('Pages Router', () => {
user.setPassword('examplePassword');
user.set('email', 'mail@example.com');
await user.signUp();
+ await jasmine.timeout();
const link = sendVerificationEmail.calls.all()[0].args[0].link;
const linkWithLocale = new URL(link);
@@ -846,6 +849,8 @@ describe('Pages Router', () => {
const locale = linkResponse.headers['x-parse-page-param-locale'];
const username = linkResponse.headers['x-parse-page-param-username'];
const publicServerUrl = linkResponse.headers['x-parse-page-param-publicserverurl'];
+ await jasmine.timeout();
+
const invalidVerificationPagePath = pageResponse.calls.all()[0].args[0];
expect(appId).toBeDefined();
expect(locale).toBe(exampleLocale);
@@ -1190,6 +1195,7 @@ describe('Pages Router', () => {
user.setPassword('examplePassword');
user.set('email', 'mail@example.com');
await user.signUp();
+ await jasmine.timeout();
const link = sendVerificationEmail.calls.all()[0].args[0].link;
const linkResponse = await request({
@@ -1197,7 +1203,6 @@ describe('Pages Router', () => {
followRedirects: false,
});
expect(linkResponse.status).toBe(200);
-
const pagePath = pageResponse.calls.all()[0].args[0];
expect(pagePath).toMatch(new RegExp(`\/${pages.emailVerificationSuccess.defaultFile}`));
});
diff --git a/spec/Parse.Push.spec.js b/spec/Parse.Push.spec.js
index 1732e426e3..143922852d 100644
--- a/spec/Parse.Push.spec.js
+++ b/spec/Parse.Push.spec.js
@@ -2,14 +2,12 @@
const request = require('../lib/request');
-const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
-
const pushCompleted = async pushId => {
const query = new Parse.Query('_PushStatus');
query.equalTo('objectId', pushId);
let result = await query.first({ useMasterKey: true });
while (!(result && result.get('status') === 'succeeded')) {
- await sleep(100);
+ await jasmine.timeout();
result = await query.first({ useMasterKey: true });
}
};
diff --git a/spec/ParseAPI.spec.js b/spec/ParseAPI.spec.js
index 9b1a97af87..4f8190a4a6 100644
--- a/spec/ParseAPI.spec.js
+++ b/spec/ParseAPI.spec.js
@@ -1267,6 +1267,25 @@ describe('miscellaneous', function () {
});
});
+ it('test cloud function query parameters with array of pointers', async () => {
+ Parse.Cloud.define('echoParams', req => {
+ return req.params;
+ });
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-Javascript-Key': 'test',
+ };
+ const response = await request({
+ method: 'POST',
+ headers: headers,
+ url: 'http://localhost:8378/1/functions/echoParams',
+ body: '{"arr": [{ "__type": "Pointer", "className": "PointerTest" }]}',
+ });
+ const res = response.data.result;
+ expect(res.arr.length).toEqual(1);
+ });
+
it('can handle null params in cloud functions (regression test for #1742)', done => {
Parse.Cloud.define('func', request => {
expect(request.params.nullParam).toEqual(null);
diff --git a/spec/ParseFile.spec.js b/spec/ParseFile.spec.js
index eeab537008..e36929636b 100644
--- a/spec/ParseFile.spec.js
+++ b/spec/ParseFile.spec.js
@@ -1364,11 +1364,107 @@ describe('Parse.File testing', () => {
);
});
+ it('works with a period in the file name', async () => {
+ await reconfigureServer({
+ fileUpload: {
+ enableForPublic: true,
+ fileExtensions: ['^[^hH][^tT][^mM][^lL]?$'],
+ },
+ });
+ const headers = {
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ };
+
+ const values = ['file.png.html', 'file.txt.png.html', 'file.png.txt.html'];
+
+ for (const value of values) {
+ await expectAsync(
+ request({
+ method: 'POST',
+ headers: headers,
+ url: `http://localhost:8378/1/files/${value}`,
+ body: '\n',
+ }).catch(e => {
+ throw new Error(e.data.error);
+ })
+ ).toBeRejectedWith(
+ new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`)
+ );
+ }
+ });
+
+ it('works to stop invalid filenames', async () => {
+ await reconfigureServer({
+ fileUpload: {
+ enableForPublic: true,
+ fileExtensions: ['^[^hH][^tT][^mM][^lL]?$'],
+ },
+ });
+ const headers = {
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ };
+
+ const values = [
+ '!invalid.png',
+ '.png',
+ '.html',
+ ' .html',
+ '.png.html',
+ '~invalid.png',
+ '-invalid.png',
+ ];
+
+ for (const value of values) {
+ await expectAsync(
+ request({
+ method: 'POST',
+ headers: headers,
+ url: `http://localhost:8378/1/files/${value}`,
+ body: '\n',
+ }).catch(e => {
+ throw new Error(e.data.error);
+ })
+ ).toBeRejectedWith(
+ new Parse.Error(Parse.Error.INVALID_FILE_NAME, `Filename contains invalid characters.`)
+ );
+ }
+ });
+
+ it('allows file without extension', async () => {
+ await reconfigureServer({
+ fileUpload: {
+ enableForPublic: true,
+ fileExtensions: ['^[^hH][^tT][^mM][^lL]?$'],
+ },
+ });
+ const headers = {
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ };
+
+ const values = ['filenamewithoutextension'];
+
+ for (const value of values) {
+ await expectAsync(
+ request({
+ method: 'POST',
+ headers: headers,
+ url: `http://localhost:8378/1/files/${value}`,
+ body: '\n',
+ }).catch(e => {
+ throw new Error(e.data.error);
+ })
+ ).toBeResolved();
+ }
+ });
+
it('works with array', async () => {
await reconfigureServer({
fileUpload: {
enableForPublic: true,
- fileExtensions: ['jpg'],
+ fileExtensions: ['jpg', 'wav'],
},
});
await expectAsync(
@@ -1387,6 +1483,30 @@ describe('Parse.File testing', () => {
).toBeRejectedWith(
new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`)
);
+ await expectAsync(
+ request({
+ method: 'POST',
+ url: 'http://localhost:8378/1/files/file',
+ body: JSON.stringify({
+ _ApplicationId: 'test',
+ _JavaScriptKey: 'test',
+ _ContentType: 'image/jpg',
+ base64: 'PGh0bWw+PC9odG1sPgo=',
+ }),
+ })
+ ).toBeResolved();
+ await expectAsync(
+ request({
+ method: 'POST',
+ url: 'http://localhost:8378/1/files/file',
+ body: JSON.stringify({
+ _ApplicationId: 'test',
+ _JavaScriptKey: 'test',
+ _ContentType: 'audio/wav',
+ base64: 'UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA',
+ }),
+ })
+ ).toBeResolved();
});
it('works with array without Content-Type', async () => {
diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js
index 87718da13a..022fb99fd2 100644
--- a/spec/ParseGraphQLServer.spec.js
+++ b/spec/ParseGraphQLServer.spec.js
@@ -5275,7 +5275,6 @@ describe('ParseGraphQLServer', () => {
it('should only count', async () => {
await prepareData();
-
await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear();
const where = {
diff --git a/spec/ParseHooks.spec.js b/spec/ParseHooks.spec.js
index f4bcc2e440..16a2e17be3 100644
--- a/spec/ParseHooks.spec.js
+++ b/spec/ParseHooks.spec.js
@@ -190,7 +190,7 @@ describe('Hooks', () => {
it('should fail trying to create two times the same function', done => {
Parse.Hooks.createFunction('my_new_function', 'http://url.com')
- .then(() => new Promise(resolve => setTimeout(resolve, 100)))
+ .then(() => jasmine.timeout())
.then(
() => {
return Parse.Hooks.createFunction('my_new_function', 'http://url.com');
diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js
index c398aa0989..7ebffa4d34 100644
--- a/spec/ParseQuery.hint.spec.js
+++ b/spec/ParseQuery.hint.spec.js
@@ -86,6 +86,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
let result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
explain: true,
});
+
let { queryPlanner } = result[0].stages[0].$cursor;
expect(queryPlanner.winningPlan.stage).toBe('COLLSCAN');
@@ -93,6 +94,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
hint: '_id_',
explain: true,
});
+
queryPlanner = result[0].stages[0].$cursor.queryPlanner;
expect(queryPlanner.winningPlan.stage).toBe('FETCH');
expect(queryPlanner.winningPlan.inputStage.indexName).toBe('_id_');
diff --git a/spec/ParseRole.spec.js b/spec/ParseRole.spec.js
index 47fed865fb..31de5b661e 100644
--- a/spec/ParseRole.spec.js
+++ b/spec/ParseRole.spec.js
@@ -142,7 +142,7 @@ describe('Parse Role testing', () => {
return Promise.all(promises);
};
- const restExecute = spyOn(RestQuery.prototype, 'execute').and.callThrough();
+ const restExecute = spyOn(RestQuery._UnsafeRestQuery.prototype, 'execute').and.callThrough();
let user, auth, getAllRolesSpy;
createTestUser()
diff --git a/spec/ParseUser.spec.js b/spec/ParseUser.spec.js
index 4d3beaf349..5a4a81d0a7 100644
--- a/spec/ParseUser.spec.js
+++ b/spec/ParseUser.spec.js
@@ -107,6 +107,36 @@ describe('Parse.User testing', () => {
}
});
+ it('user login with context', async () => {
+ let hit = 0;
+ const context = { foo: 'bar' };
+ Parse.Cloud.beforeLogin(req => {
+ expect(req.context).toEqual(context);
+ hit++;
+ });
+ Parse.Cloud.afterLogin(req => {
+ expect(req.context).toEqual(context);
+ hit++;
+ });
+ await Parse.User.signUp('asdf', 'zxcv');
+ await request({
+ method: 'POST',
+ url: 'http://localhost:8378/1/login',
+ headers: {
+ 'X-Parse-Application-Id': Parse.applicationId,
+ 'X-Parse-REST-API-Key': 'rest',
+ 'X-Parse-Cloud-Context': JSON.stringify(context),
+ 'Content-Type': 'application/json',
+ },
+ body: {
+ _method: 'GET',
+ username: 'asdf',
+ password: 'zxcv',
+ },
+ });
+ expect(hit).toBe(2);
+ });
+
it('user login with non-string username with REST API', async done => {
await Parse.User.signUp('asdf', 'zxcv');
request({
@@ -3037,6 +3067,7 @@ describe('Parse.User testing', () => {
},
});
})
+ .then(() => jasmine.timeout())
.then(() => {
expect(emailCalled).toBe(true);
expect(emailOptions).not.toBeUndefined();
@@ -3194,6 +3225,35 @@ describe('Parse.User testing', () => {
.catch(done.fail);
});
+ it('should return current session with expired expiration date', async () => {
+ await Parse.User.signUp('buser', 'somepass', null);
+ const response = await request({
+ method: 'GET',
+ url: 'http://localhost:8378/1/classes/_Session',
+ headers: {
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-Master-Key': 'test',
+ },
+ });
+ const body = response.data;
+ const id = body.results[0].objectId;
+ const expiresAt = new Date(new Date().setYear(2015));
+ await request({
+ method: 'PUT',
+ url: 'http://localhost:8378/1/classes/_Session/' + id,
+ headers: {
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-Master-Key': 'test',
+ 'Content-Type': 'application/json',
+ },
+ body: {
+ expiresAt: { __type: 'Date', iso: expiresAt.toISOString() },
+ },
+ });
+ const session = await Parse.Session.current();
+ expect(session.get('expiresAt')).toEqual(expiresAt);
+ });
+
it('should not create extraneous session tokens', done => {
const config = Config.get(Parse.applicationId);
config.database
diff --git a/spec/PushController.spec.js b/spec/PushController.spec.js
index 49613214f5..572fc9bcf9 100644
--- a/spec/PushController.spec.js
+++ b/spec/PushController.spec.js
@@ -26,14 +26,12 @@ const successfulIOS = function (body, installations) {
return Promise.all(promises);
};
-const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
-
const pushCompleted = async pushId => {
const query = new Parse.Query('_PushStatus');
query.equalTo('objectId', pushId);
let result = await query.first({ useMasterKey: true });
while (!(result && result.get('status') === 'succeeded')) {
- await sleep(100);
+ await jasmine.timeout();
result = await query.first({ useMasterKey: true });
}
};
@@ -562,7 +560,7 @@ describe('PushController', () => {
});
const pushStatusId = await sendPush(payload, {}, config, auth);
// it is enqueued so it can take time
- await sleep(1000);
+ await jasmine.timeout(1000);
Parse.serverURL = 'http://localhost:8378/1'; // GOOD url
const result = await Parse.Push.getPushStatus(pushStatusId);
expect(result).toBeDefined();
@@ -801,7 +799,7 @@ describe('PushController', () => {
});
await Parse.Object.saveAll(installations);
await pushController.sendPush(payload, {}, config, auth);
- await sleep(1000);
+ await jasmine.timeout(1000);
const query = new Parse.Query('_PushStatus');
const results = await query.find({ useMasterKey: true });
expect(results.length).toBe(1);
@@ -856,7 +854,7 @@ describe('PushController', () => {
const config = Config.get(Parse.applicationId);
await Parse.Object.saveAll(installations);
await pushController.sendPush(payload, {}, config, auth);
- await sleep(1000);
+ await jasmine.timeout(1000);
const query = new Parse.Query('_PushStatus');
const results = await query.find({ useMasterKey: true });
expect(results.length).toBe(1);
diff --git a/spec/RestQuery.spec.js b/spec/RestQuery.spec.js
index 24e22ac4f5..023d3b4790 100644
--- a/spec/RestQuery.spec.js
+++ b/spec/RestQuery.spec.js
@@ -399,15 +399,16 @@ describe('RestQuery.each', () => {
}
const config = Config.get('test');
await Parse.Object.saveAll(objects);
- const query = new RestQuery(
+ const query = await RestQuery({
+ method: RestQuery.Method.find,
config,
- auth.master(config),
- 'Object',
- { value: { $gt: 2 } },
- { limit: 2 }
- );
+ auth: auth.master(config),
+ className: 'Object',
+ restWhere: { value: { $gt: 2 } },
+ restOptions: { limit: 2 },
+ });
const spy = spyOn(query, 'execute').and.callThrough();
- const classSpy = spyOn(RestQuery.prototype, 'execute').and.callThrough();
+ const classSpy = spyOn(RestQuery._UnsafeRestQuery.prototype, 'execute').and.callThrough();
const results = [];
await query.each(result => {
expect(result.value).toBeGreaterThan(2);
@@ -438,34 +439,37 @@ describe('RestQuery.each', () => {
* Two queries needed since objectId are sorted and we can't know which one
* going to be the first and then skip by the $gt added by each
*/
- const queryOne = new RestQuery(
+ const queryOne = await RestQuery({
+ method: RestQuery.Method.get,
config,
- auth.master(config),
- 'Letter',
- {
+ auth: auth.master(config),
+ className: 'Letter',
+ restWhere: {
numbers: {
__type: 'Pointer',
className: 'Number',
objectId: object1.id,
},
},
- { limit: 1 }
- );
- const queryTwo = new RestQuery(
+ restOptions: { limit: 1 },
+ });
+
+ const queryTwo = await RestQuery({
+ method: RestQuery.Method.get,
config,
- auth.master(config),
- 'Letter',
- {
+ auth: auth.master(config),
+ className: 'Letter',
+ restWhere: {
numbers: {
__type: 'Pointer',
className: 'Number',
objectId: object2.id,
},
},
- { limit: 1 }
- );
+ restOptions: { limit: 1 },
+ });
- const classSpy = spyOn(RestQuery.prototype, 'execute').and.callThrough();
+ const classSpy = spyOn(RestQuery._UnsafeRestQuery.prototype, 'execute').and.callThrough();
const resultsOne = [];
const resultsTwo = [];
await queryOne.each(result => {
diff --git a/spec/UserController.spec.js b/spec/UserController.spec.js
index 6bcc454baf..49542ec43b 100644
--- a/spec/UserController.spec.js
+++ b/spec/UserController.spec.js
@@ -1,55 +1,90 @@
-const UserController = require('../lib/Controllers/UserController').UserController;
const emailAdapter = require('./support/MockEmailAdapter');
+const Config = require('../lib/Config');
+const Auth = require('../lib/Auth');
describe('UserController', () => {
- const user = {
- _email_verify_token: 'testToken',
- username: 'testUser',
- email: 'test@example.com',
- };
-
describe('sendVerificationEmail', () => {
describe('parseFrameURL not provided', () => {
- it('uses publicServerURL', async done => {
+ it('uses publicServerURL', async () => {
await reconfigureServer({
publicServerURL: 'http://www.example.com',
customPages: {
parseFrameURL: undefined,
},
+ verifyUserEmails: true,
+ emailAdapter,
+ appName: 'test',
});
+
+ let emailOptions;
emailAdapter.sendVerificationEmail = options => {
- expect(options.link).toEqual(
- 'http://www.example.com/apps/test/verify_email?token=testToken&username=testUser'
- );
- emailAdapter.sendVerificationEmail = () => Promise.resolve();
- done();
+ emailOptions = options;
+ return Promise.resolve();
};
- const userController = new UserController(emailAdapter, 'test', {
- verifyUserEmails: true,
- });
- userController.sendVerificationEmail(user);
+
+ const username = 'verificationUser';
+ const user = new Parse.User();
+ user.setUsername(username);
+ user.setPassword('pass');
+ user.setEmail('verification@example.com');
+ await user.signUp();
+
+ const config = Config.get('test');
+ const rawUser = await config.database.find(
+ '_User',
+ { username },
+ {},
+ Auth.maintenance(config)
+ );
+ const rawUsername = rawUser[0].username;
+ const rawToken = rawUser[0]._email_verify_token;
+ expect(rawToken).toBeDefined();
+ expect(rawUsername).toBe(username);
+ expect(emailOptions.link).toEqual(
+ `http://www.example.com/apps/test/verify_email?token=${rawToken}&username=${username}`
+ );
});
});
describe('parseFrameURL provided', () => {
- it('uses parseFrameURL and includes the destination in the link parameter', async done => {
+ it('uses parseFrameURL and includes the destination in the link parameter', async () => {
await reconfigureServer({
publicServerURL: 'http://www.example.com',
customPages: {
parseFrameURL: 'http://someother.example.com/handle-parse-iframe',
},
+ verifyUserEmails: true,
+ emailAdapter,
+ appName: 'test',
});
+
+ let emailOptions;
emailAdapter.sendVerificationEmail = options => {
- expect(options.link).toEqual(
- 'http://someother.example.com/handle-parse-iframe?link=%2Fapps%2Ftest%2Fverify_email&token=testToken&username=testUser'
- );
- emailAdapter.sendVerificationEmail = () => Promise.resolve();
- done();
+ emailOptions = options;
+ return Promise.resolve();
};
- const userController = new UserController(emailAdapter, 'test', {
- verifyUserEmails: true,
- });
- userController.sendVerificationEmail(user);
+
+ const username = 'verificationUser';
+ const user = new Parse.User();
+ user.setUsername(username);
+ user.setPassword('pass');
+ user.setEmail('verification@example.com');
+ await user.signUp();
+
+ const config = Config.get('test');
+ const rawUser = await config.database.find(
+ '_User',
+ { username },
+ {},
+ Auth.maintenance(config)
+ );
+ const rawUsername = rawUser[0].username;
+ const rawToken = rawUser[0]._email_verify_token;
+ expect(rawToken).toBeDefined();
+ expect(rawUsername).toBe(username);
+ expect(emailOptions.link).toEqual(
+ `http://someother.example.com/handle-parse-iframe?link=%2Fapps%2Ftest%2Fverify_email&token=${rawToken}&username=${username}`
+ );
});
});
});
diff --git a/spec/ValidationAndPasswordsReset.spec.js b/spec/ValidationAndPasswordsReset.spec.js
index ab944e14c1..544af343d6 100644
--- a/spec/ValidationAndPasswordsReset.spec.js
+++ b/spec/ValidationAndPasswordsReset.spec.js
@@ -51,6 +51,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
user.setUsername('zxcv');
user.setEmail('testIfEnabled@parse.com');
await user.signUp();
+ await jasmine.timeout();
expect(emailAdapter.sendVerificationEmail).toHaveBeenCalled();
user.fetch().then(() => {
expect(user.get('emailVerified')).toEqual(false);
@@ -137,6 +138,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
spyOn(emailAdapter, 'sendVerificationEmail').and.callFake(options => {
expect(options.link).not.toBeNull();
expect(options.link).not.toMatch(/token=undefined/);
+ expect(options.link).not.toMatch(/username=undefined/);
Promise.resolve();
});
const user = new Parse.User();
@@ -183,6 +185,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
user.setUsername('zxcv');
user.set('email', 'testSendSimpleAdapter@parse.com');
await user.signUp();
+ await jasmine.timeout();
expect(calls).toBe(1);
user
.fetch()
@@ -242,6 +245,66 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
});
});
+ it('prevents user from signup and login if email is not verified and preventLoginWithUnverifiedEmail is set to function returning true', async () => {
+ await reconfigureServer({
+ appName: 'test',
+ publicServerURL: 'http://localhost:1337/1',
+ verifyUserEmails: async () => true,
+ preventLoginWithUnverifiedEmail: async () => true,
+ preventSignupWithUnverifiedEmail: true,
+ emailAdapter: MockEmailAdapterWithOptions({
+ fromAddress: 'parse@example.com',
+ apiKey: 'k',
+ domain: 'd',
+ }),
+ });
+
+ const user = new Parse.User();
+ user.setPassword('asdf');
+ user.setUsername('zxcv');
+ user.set('email', 'testInvalidConfig@parse.com');
+ const signupRes = await user.signUp(null).catch(e => e);
+ expect(signupRes.message).toEqual('User email is not verified.');
+
+ const loginRes = await Parse.User.logIn('zxcv', 'asdf').catch(e => e);
+ expect(loginRes.message).toEqual('User email is not verified.');
+ });
+
+ it('provides function arguments in verifyUserEmails on login', async () => {
+ const user = new Parse.User();
+ user.setUsername('user');
+ user.setPassword('pass');
+ user.set('email', 'test@example.com');
+ await user.signUp();
+
+ const verifyUserEmails = {
+ method: async params => {
+ expect(params.object).toBeInstanceOf(Parse.User);
+ expect(params.ip).toBeDefined();
+ expect(params.master).toBeDefined();
+ expect(params.installationId).toBeDefined();
+ return true;
+ },
+ };
+ const verifyUserEmailsSpy = spyOn(verifyUserEmails, 'method').and.callThrough();
+ await reconfigureServer({
+ appName: 'test',
+ publicServerURL: 'http://localhost:1337/1',
+ verifyUserEmails: verifyUserEmails.method,
+ preventLoginWithUnverifiedEmail: verifyUserEmails.method,
+ preventSignupWithUnverifiedEmail: true,
+ emailAdapter: MockEmailAdapterWithOptions({
+ fromAddress: 'parse@example.com',
+ apiKey: 'k',
+ domain: 'd',
+ }),
+ });
+
+ const res = await Parse.User.logIn('user', 'pass').catch(e => e);
+ expect(res.code).toBe(205);
+ expect(verifyUserEmailsSpy).toHaveBeenCalledTimes(2);
+ });
+
it('allows user to login only after user clicks on the link to confirm email address if preventLoginWithUnverifiedEmail is set to true', async () => {
let sendEmailOptions;
const emailAdapter = {
@@ -263,6 +326,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
user.setUsername('user');
user.set('email', 'user@example.com');
await user.signUp();
+ await jasmine.timeout();
expect(sendEmailOptions).not.toBeUndefined();
const response = await request({
url: sendEmailOptions.link,
@@ -574,6 +638,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
user.setUsername('zxcv');
user.set('email', 'user@parse.com');
await user.signUp();
+ await jasmine.timeout();
expect(emailSent).toBe(true);
done();
});
@@ -601,6 +666,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
user.set('email', 'user@parse.com');
return user.signUp();
})
+ .then(() => jasmine.timeout())
.then(() => {
expect(sendEmailOptions).not.toBeUndefined();
request({
diff --git a/spec/configs/CLIConfigAuth.json b/spec/configs/CLIConfigAuth.json
new file mode 100644
index 0000000000..37a2a5f373
--- /dev/null
+++ b/spec/configs/CLIConfigAuth.json
@@ -0,0 +1,11 @@
+{
+ "appName": "test",
+ "appId": "test",
+ "masterKey": "test",
+ "logLevel": "error",
+ "auth": {
+ "facebook": {
+ "appIds": "test"
+ }
+ }
+}
diff --git a/spec/helper.js b/spec/helper.js
index 445de26509..fa6194b700 100644
--- a/spec/helper.js
+++ b/spec/helper.js
@@ -103,6 +103,7 @@ const defaultConfiguration = {
restAPIKey: 'rest',
webhookKey: 'hook',
masterKey: 'test',
+ maintenanceKey: 'testing',
readOnlyMasterKey: 'read-only-test',
fileKey: 'test',
directAccess: true,
@@ -427,6 +428,27 @@ global.it_exclude_dbs = excluded => {
}
};
+let testExclusionList = [];
+try {
+ // Fetch test exclusion list
+ testExclusionList = require('./testExclusionList.json');
+ console.log(`Using test exclusion list with ${testExclusionList.length} entries`);
+} catch (error) {
+ if (error.code !== 'MODULE_NOT_FOUND') {
+ throw error;
+ }
+}
+
+// Disable test if its UUID is found in testExclusionList
+global.it_id = (id, func) => {
+ if (testExclusionList.includes(id)) {
+ return xit;
+ } else {
+ if (func === undefined) return it;
+ else return func;
+ }
+};
+
global.it_only_db = db => {
if (
process.env.PARSE_SERVER_TEST_DB === db ||
@@ -546,6 +568,16 @@ global.describe_only_db = db => {
}
};
+global.fdescribe_only_db = db => {
+ if (process.env.PARSE_SERVER_TEST_DB == db) {
+ return fdescribe;
+ } else if (!process.env.PARSE_SERVER_TEST_DB && db == 'mongo') {
+ return fdescribe;
+ } else {
+ return xdescribe;
+ }
+};
+
global.describe_only = validator => {
if (validator()) {
return describe;
@@ -571,4 +603,4 @@ jasmine.restoreLibrary = function (library, name) {
require(library)[name] = libraryCache[library][name];
};
-jasmine.timeout = t => new Promise(resolve => setTimeout(resolve, t));
+jasmine.timeout = (t = 100) => new Promise(resolve => setTimeout(resolve, t));
diff --git a/spec/rest.spec.js b/spec/rest.spec.js
index 02d2f5960b..dc4e78ad0a 100644
--- a/spec/rest.spec.js
+++ b/spec/rest.spec.js
@@ -136,6 +136,117 @@ describe('rest create', () => {
});
});
+ describe('with maintenance key', () => {
+ let req;
+
+ async function getObject(id) {
+ const res = await request({
+ headers: {
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ },
+ method: 'GET',
+ url: `http://localhost:8378/1/classes/TestObject/${id}`,
+ });
+
+ return res.data;
+ }
+
+ beforeEach(() => {
+ req = {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ 'X-Parse-Maintenance-Key': 'testing',
+ },
+ method: 'POST',
+ url: 'http://localhost:8378/1/classes/TestObject',
+ };
+ });
+
+ it('allows createdAt', async () => {
+ const createdAt = { __type: 'Date', iso: '2019-01-01T00:00:00.000Z' };
+ req.body = { createdAt };
+
+ const res = await request(req);
+ expect(res.data.createdAt).toEqual(createdAt.iso);
+ });
+
+ it('allows createdAt and updatedAt', async () => {
+ const createdAt = { __type: 'Date', iso: '2019-01-01T00:00:00.000Z' };
+ const updatedAt = { __type: 'Date', iso: '2019-02-01T00:00:00.000Z' };
+ req.body = { createdAt, updatedAt };
+
+ const res = await request(req);
+
+ const obj = await getObject(res.data.objectId);
+ expect(obj.createdAt).toEqual(createdAt.iso);
+ expect(obj.updatedAt).toEqual(updatedAt.iso);
+ });
+
+ it('allows createdAt, updatedAt, and additional field', async () => {
+ const createdAt = { __type: 'Date', iso: '2019-01-01T00:00:00.000Z' };
+ const updatedAt = { __type: 'Date', iso: '2019-02-01T00:00:00.000Z' };
+ req.body = { createdAt, updatedAt, testing: 123 };
+
+ const res = await request(req);
+
+ const obj = await getObject(res.data.objectId);
+ expect(obj.createdAt).toEqual(createdAt.iso);
+ expect(obj.updatedAt).toEqual(updatedAt.iso);
+ expect(obj.testing).toEqual(123);
+ });
+
+ it('cannot set updatedAt dated before createdAt', async () => {
+ const createdAt = { __type: 'Date', iso: '2019-01-01T00:00:00.000Z' };
+ const updatedAt = { __type: 'Date', iso: '2018-12-01T00:00:00.000Z' };
+ req.body = { createdAt, updatedAt };
+
+ try {
+ await request(req);
+ fail();
+ } catch (err) {
+ expect(err.data.code).toEqual(Parse.Error.VALIDATION_ERROR);
+ }
+ });
+
+ it('cannot set updatedAt without createdAt', async () => {
+ const updatedAt = { __type: 'Date', iso: '2018-12-01T00:00:00.000Z' };
+ req.body = { updatedAt };
+
+ const res = await request(req);
+
+ const obj = await getObject(res.data.objectId);
+ expect(obj.updatedAt).not.toEqual(updatedAt.iso);
+ });
+
+ it('handles bad types for createdAt and updatedAt', async () => {
+ const createdAt = 12345;
+ const updatedAt = true;
+ req.body = { createdAt, updatedAt };
+
+ try {
+ await request(req);
+ fail();
+ } catch (err) {
+ expect(err.data.code).toEqual(Parse.Error.INCORRECT_TYPE);
+ }
+ });
+
+ it('cannot set createdAt or updatedAt without maintenance key', async () => {
+ const createdAt = { __type: 'Date', iso: '2019-01-01T00:00:00.000Z' };
+ const updatedAt = { __type: 'Date', iso: '2019-02-01T00:00:00.000Z' };
+ req.body = { createdAt, updatedAt };
+ delete req.headers['X-Parse-Maintenance-Key'];
+
+ const res = await request(req);
+
+ expect(res.data.createdAt).not.toEqual(createdAt.iso);
+ expect(res.data.updatedAt).not.toEqual(updatedAt.iso);
+ });
+ });
+
it('handles array, object, date', done => {
const now = new Date();
const obj = {
@@ -660,6 +771,38 @@ describe('rest create', () => {
});
});
+ it('cannot get object in volatileClasses if not masterKey through pointer', async () => {
+ const masterKeyOnlyClassObject = new Parse.Object('_PushStatus');
+ await masterKeyOnlyClassObject.save(null, { useMasterKey: true });
+ const obj2 = new Parse.Object('TestObject');
+ // Anyone is can basically create a pointer to any object
+ // or some developers can use master key in some hook to link
+ // private objects to standard objects
+ obj2.set('pointer', masterKeyOnlyClassObject);
+ await obj2.save();
+ const query = new Parse.Query('TestObject');
+ query.include('pointer');
+ await expectAsync(query.get(obj2.id)).toBeRejectedWithError(
+ "Clients aren't allowed to perform the get operation on the _PushStatus collection."
+ );
+ });
+
+ it('cannot get object in _GlobalConfig if not masterKey through pointer', async () => {
+ await Parse.Config.save({ privateData: 'secret' }, { privateData: true });
+ const obj2 = new Parse.Object('TestObject');
+ obj2.set('globalConfigPointer', {
+ __type: 'Pointer',
+ className: '_GlobalConfig',
+ objectId: 1,
+ });
+ await obj2.save();
+ const query = new Parse.Query('TestObject');
+ query.include('globalConfigPointer');
+ await expectAsync(query.get(obj2.id)).toBeRejectedWithError(
+ "Clients aren't allowed to perform the get operation on the _GlobalConfig collection."
+ );
+ });
+
it('locks down session', done => {
let currentUser;
Parse.User.signUp('foo', 'bar')
diff --git a/spec/vulnerabilities.spec.js b/spec/vulnerabilities.spec.js
index 5c83493c94..9bfafcffcb 100644
--- a/spec/vulnerabilities.spec.js
+++ b/spec/vulnerabilities.spec.js
@@ -138,6 +138,71 @@ describe('Vulnerabilities', () => {
);
});
+ it('denies creating global config with polluted data', async () => {
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-Master-Key': 'test',
+ };
+ const params = {
+ method: 'PUT',
+ url: 'http://localhost:8378/1/config',
+ json: true,
+ body: {
+ params: {
+ welcomeMesssage: 'Welcome to Parse',
+ foo: { _bsontype: 'Code', code: 'shell' },
+ },
+ },
+ headers,
+ };
+ const response = await request(params).catch(e => e);
+ expect(response.status).toBe(400);
+ const text = JSON.parse(response.text);
+ expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME);
+ expect(text.error).toBe(
+ 'Prohibited keyword in request data: {"key":"_bsontype","value":"Code"}.'
+ );
+ });
+
+ it('denies direct database write wih prohibited keys', async () => {
+ const Config = require('../lib/Config');
+ const config = Config.get(Parse.applicationId);
+ const user = {
+ objectId: '1234567890',
+ username: 'hello',
+ password: 'pass',
+ _session_token: 'abc',
+ foo: { _bsontype: 'Code', code: 'shell' },
+ };
+ await expectAsync(config.database.create('_User', user)).toBeRejectedWith(
+ new Parse.Error(
+ Parse.Error.INVALID_KEY_NAME,
+ 'Prohibited keyword in request data: {"key":"_bsontype","value":"Code"}.'
+ )
+ );
+ });
+
+ it('denies direct database update wih prohibited keys', async () => {
+ const Config = require('../lib/Config');
+ const config = Config.get(Parse.applicationId);
+ const user = {
+ objectId: '1234567890',
+ username: 'hello',
+ password: 'pass',
+ _session_token: 'abc',
+ foo: { _bsontype: 'Code', code: 'shell' },
+ };
+ await expectAsync(
+ config.database.update('_User', { _id: user.objectId }, user)
+ ).toBeRejectedWith(
+ new Parse.Error(
+ Parse.Error.INVALID_KEY_NAME,
+ 'Prohibited keyword in request data: {"key":"_bsontype","value":"Code"}.'
+ )
+ );
+ });
+
it('denies creating a hook with polluted data', async () => {
const express = require('express');
const bodyParser = require('body-parser');
@@ -170,32 +235,6 @@ describe('Vulnerabilities', () => {
await new Promise(resolve => server.close(resolve));
});
- it('allows BSON type code data in write request with custom denylist', async () => {
- await reconfigureServer({
- requestKeywordDenylist: [],
- });
- const headers = {
- 'Content-Type': 'application/json',
- 'X-Parse-Application-Id': 'test',
- 'X-Parse-REST-API-Key': 'rest',
- };
- const params = {
- headers: headers,
- method: 'POST',
- url: 'http://localhost:8378/1/classes/RCE',
- body: JSON.stringify({
- obj: {
- _bsontype: 'Code',
- code: 'delete Object.prototype.evalFunctions',
- },
- }),
- };
- const response = await request(params).catch(e => e);
- expect(response.status).toBe(201);
- const text = JSON.parse(response.text);
- expect(text.objectId).toBeDefined();
- });
-
it('denies write request with custom denylist of key/value', async () => {
await reconfigureServer({
requestKeywordDenylist: [{ key: 'a[K]ey', value: 'aValue[123]*' }],
diff --git a/src/Adapters/Auth/AuthAdapter.js b/src/Adapters/Auth/AuthAdapter.js
index 5b18c75170..e739df3f54 100644
--- a/src/Adapters/Auth/AuthAdapter.js
+++ b/src/Adapters/Auth/AuthAdapter.js
@@ -21,7 +21,9 @@ export class AuthAdapter {
* Usage policy
* @type {AuthPolicy}
*/
- this.policy = 'default';
+ if (!this.policy) {
+ this.policy = 'default';
+ }
}
/**
* @param appIds The specified app IDs in the configuration
diff --git a/src/Adapters/Auth/apple.js b/src/Adapters/Auth/apple.js
index 15b28ed203..4fd1153b75 100644
--- a/src/Adapters/Auth/apple.js
+++ b/src/Adapters/Auth/apple.js
@@ -3,7 +3,6 @@
const Parse = require('parse/node').Parse;
const jwksClient = require('jwks-rsa');
-const util = require('util');
const jwt = require('jsonwebtoken');
const authUtils = require('./utils');
@@ -17,11 +16,9 @@ const getAppleKeyByKeyId = async (keyId, cacheMaxEntries, cacheMaxAge) => {
cacheMaxAge,
});
- const asyncGetSigningKeyFunction = util.promisify(client.getSigningKey);
-
let key;
try {
- key = await asyncGetSigningKeyFunction(keyId);
+ key = await authUtils.getSigningKey(client, keyId);
} catch (error) {
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
diff --git a/src/Adapters/Auth/facebook.js b/src/Adapters/Auth/facebook.js
index 737657c8bd..896fad0ff4 100644
--- a/src/Adapters/Auth/facebook.js
+++ b/src/Adapters/Auth/facebook.js
@@ -2,7 +2,6 @@
const Parse = require('parse/node').Parse;
const crypto = require('crypto');
const jwksClient = require('jwks-rsa');
-const util = require('util');
const jwt = require('jsonwebtoken');
const httpsRequest = require('./httpsRequest');
const authUtils = require('./utils');
@@ -60,11 +59,9 @@ const getFacebookKeyByKeyId = async (keyId, cacheMaxEntries, cacheMaxAge) => {
cacheMaxAge,
});
- const asyncGetSigningKeyFunction = util.promisify(client.getSigningKey);
-
let key;
try {
- key = await asyncGetSigningKeyFunction(keyId);
+ key = await authUtils.getSigningKey(client, keyId);
} catch (error) {
throw new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
diff --git a/src/Adapters/Auth/index.js b/src/Adapters/Auth/index.js
index 2defcb0dc0..da65b24ba5 100755
--- a/src/Adapters/Auth/index.js
+++ b/src/Adapters/Auth/index.js
@@ -9,6 +9,7 @@ const facebook = require('./facebook');
const instagram = require('./instagram');
const linkedin = require('./linkedin');
const meetup = require('./meetup');
+import mfa from './mfa';
const google = require('./google');
const github = require('./github');
const twitter = require('./twitter');
@@ -44,6 +45,7 @@ const providers = {
instagram,
linkedin,
meetup,
+ mfa,
google,
github,
twitter,
@@ -75,7 +77,11 @@ function authDataValidator(provider, adapter, appIds, options) {
if (appIds && typeof adapter.validateAppId === 'function') {
await Promise.resolve(adapter.validateAppId(appIds, authData, options, requestObject));
}
- if (adapter.policy && !authAdapterPolicies[adapter.policy]) {
+ if (
+ adapter.policy &&
+ !authAdapterPolicies[adapter.policy] &&
+ typeof adapter.policy !== 'function'
+ ) {
throw new Parse.Error(
Parse.Error.OTHER_CAUSE,
'AuthAdapter policy is not configured correctly. The value must be either "solo", "additional", "default" or undefined (will be handled as "default")'
@@ -225,17 +231,20 @@ module.exports = function (authOptions = {}, enableAnonymousUsers = true) {
if (!authAdapter) {
return;
}
- const {
- adapter: { afterFind },
- providerOptions,
- } = authAdapter;
+ const { adapter, providerOptions } = authAdapter;
+ const afterFind = adapter.afterFind;
if (afterFind && typeof afterFind === 'function') {
const requestObject = {
ip: req.config.ip,
user: req.auth.user,
master: req.auth.isMaster,
};
- const result = afterFind(requestObject, authData[provider], providerOptions);
+ const result = afterFind.call(
+ adapter,
+ requestObject,
+ authData[provider],
+ providerOptions
+ );
if (result) {
authData[provider] = result;
}
diff --git a/src/Adapters/Auth/mfa.js b/src/Adapters/Auth/mfa.js
new file mode 100644
index 0000000000..a88eda99e7
--- /dev/null
+++ b/src/Adapters/Auth/mfa.js
@@ -0,0 +1,213 @@
+import { TOTP, Secret } from 'otpauth';
+import { randomString } from '../../cryptoUtils';
+import AuthAdapter from './AuthAdapter';
+class MFAAdapter extends AuthAdapter {
+ validateOptions(opts) {
+ const validOptions = opts.options;
+ if (!Array.isArray(validOptions)) {
+ throw 'mfa.options must be an array';
+ }
+ this.sms = validOptions.includes('SMS');
+ this.totp = validOptions.includes('TOTP');
+ if (!this.sms && !this.totp) {
+ throw 'mfa.options must include SMS or TOTP';
+ }
+ const digits = opts.digits || 6;
+ const period = opts.period || 30;
+ if (typeof digits !== 'number') {
+ throw 'mfa.digits must be a number';
+ }
+ if (typeof period !== 'number') {
+ throw 'mfa.period must be a number';
+ }
+ if (digits < 4 || digits > 10) {
+ throw 'mfa.digits must be between 4 and 10';
+ }
+ if (period < 10) {
+ throw 'mfa.period must be greater than 10';
+ }
+ const sendSMS = opts.sendSMS;
+ if (this.sms && typeof sendSMS !== 'function') {
+ throw 'mfa.sendSMS callback must be defined when using SMS OTPs';
+ }
+ this.smsCallback = sendSMS;
+ this.digits = digits;
+ this.period = period;
+ this.algorithm = opts.algorithm || 'SHA1';
+ }
+ validateSetUp(mfaData) {
+ if (mfaData.mobile && this.sms) {
+ return this.setupMobileOTP(mfaData.mobile);
+ }
+ if (this.totp) {
+ return this.setupTOTP(mfaData);
+ }
+ throw 'Invalid MFA data';
+ }
+ async validateLogin(loginData, _, req) {
+ const saveResponse = {
+ doNotSave: true,
+ };
+ const token = loginData.token;
+ const auth = req.original.get('authData') || {};
+ const { secret, recovery, mobile, token: saved, expiry } = auth.mfa || {};
+ if (this.sms && mobile) {
+ if (token === 'request') {
+ const { token: sendToken, expiry } = await this.sendSMS(mobile);
+ auth.mfa.token = sendToken;
+ auth.mfa.expiry = expiry;
+ req.object.set('authData', auth);
+ await req.object.save(null, { useMasterKey: true });
+ throw 'Please enter the token';
+ }
+ if (!saved || token !== saved) {
+ throw 'Invalid MFA token 1';
+ }
+ if (new Date() > expiry) {
+ throw 'Invalid MFA token 2';
+ }
+ delete auth.mfa.token;
+ delete auth.mfa.expiry;
+ return {
+ save: auth.mfa,
+ };
+ }
+ if (this.totp) {
+ if (typeof token !== 'string') {
+ throw 'Invalid MFA token';
+ }
+ if (!secret) {
+ return saveResponse;
+ }
+ if (recovery[0] === token || recovery[1] === token) {
+ return saveResponse;
+ }
+ const totp = new TOTP({
+ algorithm: this.algorithm,
+ digits: this.digits,
+ period: this.period,
+ secret: Secret.fromBase32(secret),
+ });
+ const valid = totp.validate({
+ token,
+ });
+ if (valid === null) {
+ throw 'Invalid MFA token';
+ }
+ }
+ return saveResponse;
+ }
+ async validateUpdate(authData, _, req) {
+ if (req.master) {
+ return;
+ }
+ if (authData.mobile && this.sms) {
+ if (!authData.token) {
+ throw 'MFA is already set up on this account';
+ }
+ return this.confirmSMSOTP(authData, req.original.get('authData')?.mfa || {});
+ }
+ if (this.totp) {
+ await this.validateLogin({ token: authData.old }, null, req);
+ return this.validateSetUp(authData);
+ }
+ throw 'Invalid MFA data';
+ }
+ afterFind(req, authData) {
+ if (req.master) {
+ return;
+ }
+ if (this.totp && authData.secret) {
+ return {
+ status: 'enabled',
+ };
+ }
+ if (this.sms && authData.mobile) {
+ return {
+ status: 'enabled',
+ };
+ }
+ return {
+ status: 'disabled',
+ };
+ }
+
+ policy(req, auth) {
+ if (this.sms && auth?.pending && Object.keys(auth).length === 1) {
+ return 'default';
+ }
+ return 'additional';
+ }
+
+ async setupMobileOTP(mobile) {
+ const { token, expiry } = await this.sendSMS(mobile);
+ return {
+ save: {
+ pending: {
+ [mobile]: {
+ token,
+ expiry,
+ },
+ },
+ },
+ };
+ }
+
+ async sendSMS(mobile) {
+ if (!/^[+]*[(]{0,1}[0-9]{1,3}[)]{0,1}[-\s\./0-9]*$/g.test(mobile)) {
+ throw 'Invalid mobile number.';
+ }
+ let token = '';
+ while (token.length < this.digits) {
+ token += randomString(10).replace(/\D/g, '');
+ }
+ token = token.substring(0, this.digits);
+ await Promise.resolve(this.smsCallback(token, mobile));
+ const expiry = new Date(new Date().getTime() + this.period * 1000);
+ return { token, expiry };
+ }
+
+ async confirmSMSOTP(inputData, authData) {
+ const { mobile, token } = inputData;
+ if (!authData.pending?.[mobile]) {
+ throw 'This number is not pending';
+ }
+ const pendingData = authData.pending[mobile];
+ if (token !== pendingData.token) {
+ throw 'Invalid MFA token';
+ }
+ if (new Date() > pendingData.expiry) {
+ throw 'Invalid MFA token';
+ }
+ delete authData.pending[mobile];
+ authData.mobile = mobile;
+ return {
+ save: authData,
+ };
+ }
+
+ setupTOTP(mfaData) {
+ const { secret, token } = mfaData;
+ if (!secret || !token || secret.length < 20) {
+ throw 'Invalid MFA data';
+ }
+ const totp = new TOTP({
+ algorithm: this.algorithm,
+ digits: this.digits,
+ period: this.period,
+ secret: Secret.fromBase32(secret),
+ });
+ const valid = totp.validate({
+ token,
+ });
+ if (valid === null) {
+ throw 'Invalid MFA token';
+ }
+ const recovery = [randomString(30), randomString(30)];
+ return {
+ response: { recovery: recovery.join(', ') },
+ save: { secret, recovery },
+ };
+ }
+}
+export default new MFAAdapter();
diff --git a/src/Adapters/Auth/utils.js b/src/Adapters/Auth/utils.js
index c50adaba79..0d4d7cd8a2 100644
--- a/src/Adapters/Auth/utils.js
+++ b/src/Adapters/Auth/utils.js
@@ -1,4 +1,5 @@
const jwt = require('jsonwebtoken');
+const util = require('util');
const Parse = require('parse/node').Parse;
const getHeaderFromToken = token => {
const decodedToken = jwt.decode(token, { complete: true });
@@ -8,6 +9,16 @@ const getHeaderFromToken = token => {
return decodedToken.header;
};
+
+/**
+ * Returns the signing key from a JWKS client.
+ * @param {Object} client The JWKS client.
+ * @param {String} key The kid.
+ */
+async function getSigningKey(client, key) {
+ return util.promisify(client.getSigningKey)(key);
+}
module.exports = {
getHeaderFromToken,
+ getSigningKey,
};
diff --git a/src/Adapters/Cache/RedisCacheAdapter.js b/src/Adapters/Cache/RedisCacheAdapter.js
index eba16694e3..25125a037c 100644
--- a/src/Adapters/Cache/RedisCacheAdapter.js
+++ b/src/Adapters/Cache/RedisCacheAdapter.js
@@ -17,6 +17,12 @@ export class RedisCacheAdapter {
this.ttl = isValidTTL(ttl) ? ttl : DEFAULT_REDIS_TTL;
this.client = createClient(redisCtx);
this.queue = new KeyPromiseQueue();
+ this.client.on('error', err => {
+ logger.error('RedisCacheAdapter client error', { error: err });
+ });
+ this.client.on('connect', () => {});
+ this.client.on('reconnecting', () => {});
+ this.client.on('ready', () => {});
}
async connect() {
diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js
index 451165789d..76a8f25d1b 100644
--- a/src/Adapters/Files/GridFSBucketAdapter.js
+++ b/src/Adapters/Files/GridFSBucketAdapter.js
@@ -28,7 +28,11 @@ export class GridFSBucketAdapter extends FilesAdapter {
this._algorithm = 'aes-256-gcm';
this._encryptionKey =
encryptionKey !== undefined
- ? crypto.createHash('sha256').update(String(encryptionKey)).digest('base64').substr(0, 32)
+ ? crypto
+ .createHash('sha256')
+ .update(String(encryptionKey))
+ .digest('base64')
+ .substring(0, 32)
: null;
const defaultMongoOptions = {
useNewUrlParser: true,
@@ -138,8 +142,8 @@ export class GridFSBucketAdapter extends FilesAdapter {
}
async rotateEncryptionKey(options = {}) {
- var fileNames = [];
- var oldKeyFileAdapter = {};
+ let fileNames = [];
+ let oldKeyFileAdapter = {};
const bucket = await this._getBucket();
if (options.oldKey !== undefined) {
oldKeyFileAdapter = new GridFSBucketAdapter(
@@ -158,51 +162,22 @@ export class GridFSBucketAdapter extends FilesAdapter {
fileNames.push(file.filename);
});
}
- return new Promise(resolve => {
- var fileNamesNotRotated = fileNames;
- var fileNamesRotated = [];
- var fileNameTotal = fileNames.length;
- var fileNameIndex = 0;
- fileNames.forEach(fileName => {
- oldKeyFileAdapter
- .getFileData(fileName)
- .then(plainTextData => {
- //Overwrite file with data encrypted with new key
- this.createFile(fileName, plainTextData)
- .then(() => {
- fileNamesRotated.push(fileName);
- fileNamesNotRotated = fileNamesNotRotated.filter(function (value) {
- return value !== fileName;
- });
- fileNameIndex += 1;
- if (fileNameIndex == fileNameTotal) {
- resolve({
- rotated: fileNamesRotated,
- notRotated: fileNamesNotRotated,
- });
- }
- })
- .catch(() => {
- fileNameIndex += 1;
- if (fileNameIndex == fileNameTotal) {
- resolve({
- rotated: fileNamesRotated,
- notRotated: fileNamesNotRotated,
- });
- }
- });
- })
- .catch(() => {
- fileNameIndex += 1;
- if (fileNameIndex == fileNameTotal) {
- resolve({
- rotated: fileNamesRotated,
- notRotated: fileNamesNotRotated,
- });
- }
- });
- });
- });
+ let fileNamesNotRotated = fileNames;
+ const fileNamesRotated = [];
+ for (const fileName of fileNames) {
+ try {
+ const plainTextData = await oldKeyFileAdapter.getFileData(fileName);
+ // Overwrite file with data encrypted with new key
+ await this.createFile(fileName, plainTextData);
+ fileNamesRotated.push(fileName);
+ fileNamesNotRotated = fileNamesNotRotated.filter(function (value) {
+ return value !== fileName;
+ });
+ } catch (err) {
+ continue;
+ }
+ }
+ return { rotated: fileNamesRotated, notRotated: fileNamesNotRotated };
}
getFileLocation(config, filename) {
diff --git a/src/Adapters/Storage/Mongo/MongoCollection.js b/src/Adapters/Storage/Mongo/MongoCollection.js
index f3f089f0f1..48de677c2e 100644
--- a/src/Adapters/Storage/Mongo/MongoCollection.js
+++ b/src/Adapters/Storage/Mongo/MongoCollection.js
@@ -160,18 +160,10 @@ export default class MongoCollection {
}
_ensureSparseUniqueIndexInBackground(indexRequest) {
- return new Promise((resolve, reject) => {
- this._mongoCollection.createIndex(
- indexRequest,
- { unique: true, background: true, sparse: true },
- error => {
- if (error) {
- reject(error);
- } else {
- resolve();
- }
- }
- );
+ return this._mongoCollection.createIndex(indexRequest, {
+ unique: true,
+ background: true,
+ sparse: true,
});
}
diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
index 2f59819895..53d1bc4959 100644
--- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
+++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
@@ -172,7 +172,6 @@ export class MongoStorageAdapter implements StorageAdapter {
// parsing and re-formatting causes the auth value (if there) to get URI
// encoded
const encodedUri = formatUrl(parseUrl(this._uri));
-
this.connectionPromise = MongoClient.connect(encodedUri, this._mongoOptions)
.then(client => {
// Starting mongoDB 3.0, the MongoClient.connect don't return a DB anymore but a client
@@ -687,13 +686,8 @@ export class MongoStorageAdapter implements StorageAdapter {
};
return this._adaptiveCollection(className)
- .then(
- collection =>
- new Promise((resolve, reject) =>
- collection._mongoCollection.createIndex(indexCreationRequest, indexOptions, error =>
- error ? reject(error) : resolve()
- )
- )
+ .then(collection =>
+ collection._mongoCollection.createIndex(indexCreationRequest, indexOptions)
)
.catch(err => this.handleError(err));
}
diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js
index 6f6811cec3..336d9affc9 100644
--- a/src/Adapters/Storage/Mongo/MongoTransform.js
+++ b/src/Adapters/Storage/Mongo/MongoTransform.js
@@ -457,6 +457,7 @@ const parseObjectKeyValueToMongoObjectKeyValue = (restKey, restValue, schema) =>
);
}
value = mapValues(restValue, transformInteriorValue);
+
return { key: restKey, value };
};
@@ -986,6 +987,13 @@ function transformUpdateOperator({ __op, amount, objects }, flatten) {
return { __op: '$inc', arg: amount };
}
+ case 'SetOnInsert':
+ if (flatten) {
+ return amount;
+ } else {
+ return { __op: '$setOnInsert', arg: amount };
+ }
+
case 'Add':
case 'AddUnique':
if (!(objects instanceof Array)) {
diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
index 3e8e867799..3ad59ec77f 100644
--- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
+++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
@@ -231,7 +231,7 @@ const transformAggregateField = fieldName => {
if (fieldName === '$_updated_at') {
return 'updatedAt';
}
- return fieldName.substr(1);
+ return fieldName.substring(1);
};
const validateKeys = object => {
@@ -1921,14 +1921,14 @@ export class PostgresStorageAdapter implements StorageAdapter {
};
}
if (object[fieldName] && schema.fields[fieldName].type === 'Polygon') {
- let coords = object[fieldName];
- coords = coords.substr(2, coords.length - 4).split('),(');
- coords = coords.map(point => {
+ let coords = new String(object[fieldName]);
+ coords = coords.substring(2, coords.length - 2).split('),(');
+ const updatedCoords = coords.map(point => {
return [parseFloat(point.split(',')[1]), parseFloat(point.split(',')[0])];
});
object[fieldName] = {
__type: 'Polygon',
- coordinates: coords,
+ coordinates: updatedCoords,
};
}
if (object[fieldName] && schema.fields[fieldName].type === 'File') {
@@ -2634,7 +2634,7 @@ function literalizeRegexPart(s: string) {
const result1: any = s.match(matcher1);
if (result1 && result1.length > 1 && result1.index > -1) {
// process regex that has a beginning and an end specified for the literal text
- const prefix = s.substr(0, result1.index);
+ const prefix = s.substring(0, result1.index);
const remaining = result1[1];
return literalizeRegexPart(prefix) + createLiteralRegex(remaining);
@@ -2644,7 +2644,7 @@ function literalizeRegexPart(s: string) {
const matcher2 = /\\Q((?!\\E).*)$/;
const result2: any = s.match(matcher2);
if (result2 && result2.length > 1 && result2.index > -1) {
- const prefix = s.substr(0, result2.index);
+ const prefix = s.substring(0, result2.index);
const remaining = result2[1];
return literalizeRegexPart(prefix) + createLiteralRegex(remaining);
diff --git a/src/Auth.js b/src/Auth.js
index 96c99cbb1d..6488b8427e 100644
--- a/src/Auth.js
+++ b/src/Auth.js
@@ -77,13 +77,16 @@ const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
throttle[sessionToken] = setTimeout(async () => {
try {
if (!session) {
- const { results } = await new RestQuery(
+ const query = await RestQuery({
+ method: RestQuery.Method.get,
config,
- master(config),
- '_Session',
- { sessionToken },
- { limit: 1 }
- ).execute();
+ auth: master(config),
+ runBeforeFind: false,
+ className: '_Session',
+ restWhere: { sessionToken },
+ restOptions: { limit: 1 },
+ });
+ const { results } = await query.execute();
session = results[0];
}
const lastUpdated = new Date(session?.updatedAt);
@@ -140,7 +143,15 @@ const getAuthForSessionToken = async function ({
include: 'user',
};
const RestQuery = require('./RestQuery');
- const query = new RestQuery(config, master(config), '_Session', { sessionToken }, restOptions);
+ const query = await RestQuery({
+ method: RestQuery.Method.get,
+ config,
+ runBeforeFind: false,
+ auth: master(config),
+ className: '_Session',
+ restWhere: { sessionToken },
+ restOptions,
+ });
results = (await query.execute()).results;
} else {
results = (
@@ -179,12 +190,20 @@ const getAuthForSessionToken = async function ({
});
};
-var getAuthForLegacySessionToken = function ({ config, sessionToken, installationId }) {
+var getAuthForLegacySessionToken = async function ({ config, sessionToken, installationId }) {
var restOptions = {
limit: 1,
};
const RestQuery = require('./RestQuery');
- var query = new RestQuery(config, master(config), '_User', { sessionToken }, restOptions);
+ var query = await RestQuery({
+ method: RestQuery.Method.get,
+ config,
+ runBeforeFind: false,
+ auth: master(config),
+ className: '_User',
+ restWhere: { _session_token: sessionToken },
+ restOptions,
+ });
return query.execute().then(response => {
var results = response.results;
if (results.length !== 1) {
@@ -229,9 +248,15 @@ Auth.prototype.getRolesForUser = async function () {
},
};
const RestQuery = require('./RestQuery');
- await new RestQuery(this.config, master(this.config), '_Role', restWhere, {}).each(result =>
- results.push(result)
- );
+ const query = await RestQuery({
+ method: RestQuery.Method.find,
+ runBeforeFind: false,
+ config: this.config,
+ auth: master(this.config),
+ className: '_Role',
+ restWhere,
+ });
+ await query.each(result => results.push(result));
} else {
await new Parse.Query(Parse.Role)
.equalTo('users', this.user)
@@ -323,9 +348,15 @@ Auth.prototype.getRolesByIds = async function (ins) {
});
const restWhere = { roles: { $in: roles } };
const RestQuery = require('./RestQuery');
- await new RestQuery(this.config, master(this.config), '_Role', restWhere, {}).each(result =>
- results.push(result)
- );
+ const query = await RestQuery({
+ method: RestQuery.Method.find,
+ config: this.config,
+ runBeforeFind: false,
+ auth: master(this.config),
+ className: '_Role',
+ restWhere,
+ });
+ await query.each(result => results.push(result));
}
return results;
};
@@ -407,6 +438,7 @@ const hasMutatedAuthData = (authData, userAuthData) => {
};
const checkIfUserHasProvidedConfiguredProvidersForLogin = (
+ req = {},
authData = {},
userAuthData = {},
config
@@ -430,7 +462,16 @@ const checkIfUserHasProvidedConfiguredProvidersForLogin = (
const additionProvidersNotFound = [];
const hasProvidedAtLeastOneAdditionalProvider = savedUserProviders.some(provider => {
- if (provider && provider.adapter && provider.adapter.policy === 'additional') {
+ let policy = provider.adapter.policy;
+ if (typeof policy === 'function') {
+ const requestObject = {
+ ip: req.config.ip,
+ user: req.auth.user,
+ master: req.auth.isMaster,
+ };
+ policy = policy.call(provider.adapter, requestObject, userAuthData[provider.name]);
+ }
+ if (policy === 'additional') {
if (authData[provider.name]) {
return true;
} else {
@@ -467,14 +508,8 @@ const handleAuthDataValidation = async (authData, req, foundUser) => {
await user.fetch({ useMasterKey: true });
}
- const { originalObject, updatedObject } = req.buildParseObjects();
- const requestObject = getRequestObject(
- undefined,
- req.auth,
- updatedObject,
- originalObject || user,
- req.config
- );
+ const { updatedObject } = req.buildParseObjects();
+ const requestObject = getRequestObject(undefined, req.auth, updatedObject, user, req.config);
// Perform validation as step-by-step pipeline for better error consistency
// and also to avoid to trigger a provider (like OTP SMS) if another one fails
const acc = { authData: {}, authDataResponse: {} };
diff --git a/src/Config.js b/src/Config.js
index 5e3a49bb35..0e8cdda246 100644
--- a/src/Config.js
+++ b/src/Config.js
@@ -7,6 +7,7 @@ import net from 'net';
import AppCache from './cache';
import DatabaseController from './Controllers/DatabaseController';
import { logLevels as validLogLevels } from './Controllers/LoggerController';
+import { version } from '../package.json';
import {
AccountLockoutOptions,
DatabaseOptions,
@@ -25,7 +26,7 @@ function removeTrailingSlash(str) {
return str;
}
if (str.endsWith('/')) {
- str = str.substr(0, str.length - 1);
+ str = str.substring(0, str.length - 1);
}
return str;
}
@@ -50,6 +51,7 @@ export class Config {
config.generateEmailVerifyTokenExpiresAt = config.generateEmailVerifyTokenExpiresAt.bind(
config
);
+ config.version = version;
return config;
}
diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js
index e3ac5723ab..5975e94053 100644
--- a/src/Controllers/DatabaseController.js
+++ b/src/Controllers/DatabaseController.js
@@ -279,6 +279,9 @@ const flattenUpdateOperatorsForCreate = object => {
}
object[key] = object[key].amount;
break;
+ case 'SetOnInsert':
+ object[key] = object[key].amount;
+ break;
case 'Add':
if (!(object[key].objects instanceof Array)) {
throw new Parse.Error(Parse.Error.INVALID_JSON, 'objects to add must be an array');
@@ -365,6 +368,22 @@ const relationSchema = {
fields: { relatedId: { type: 'String' }, owningId: { type: 'String' } },
};
+const convertEmailToLowercase = (object, className, options) => {
+ if (className === '_User' && options.convertEmailToLowercase) {
+ if (typeof object['email'] === 'string') {
+ object['email'] = object['email'].toLowerCase();
+ }
+ }
+};
+
+const convertUsernameToLowercase = (object, className, options) => {
+ if (className === '_User' && options.convertUsernameToLowercase) {
+ if (typeof object['username'] === 'string') {
+ object['username'] = object['username'].toLowerCase();
+ }
+ }
+};
+
class DatabaseController {
adapter: StorageAdapter;
schemaCache: any;
@@ -475,6 +494,11 @@ class DatabaseController {
validateOnly: boolean = false,
validSchemaController: SchemaController.SchemaController
): Promise {
+ try {
+ Utils.checkProhibitedKeywords(this.options, update);
+ } catch (error) {
+ return Promise.reject(new Parse.Error(Parse.Error.INVALID_KEY_NAME, error));
+ }
const originalQuery = query;
const originalUpdate = update;
// Make a copy of the object, so we don't mutate the incoming data.
@@ -565,6 +589,8 @@ class DatabaseController {
}
}
update = transformObjectACL(update);
+ convertEmailToLowercase(update, className, this.options);
+ convertUsernameToLowercase(update, className, this.options);
transformAuthData(className, update, schema);
if (validateOnly) {
return this.adapter.find(className, schema, query, {}).then(result => {
@@ -805,10 +831,17 @@ class DatabaseController {
validateOnly: boolean = false,
validSchemaController: SchemaController.SchemaController
): Promise {
+ try {
+ Utils.checkProhibitedKeywords(this.options, object);
+ } catch (error) {
+ return Promise.reject(new Parse.Error(Parse.Error.INVALID_KEY_NAME, error));
+ }
// Make a copy of the object, so we don't mutate the incoming data.
const originalObject = object;
object = transformObjectACL(object);
+ convertEmailToLowercase(object, className, this.options);
+ convertUsernameToLowercase(object, className, this.options);
object.createdAt = { iso: object.createdAt, __type: 'Date' };
object.updatedAt = { iso: object.updatedAt, __type: 'Date' };
@@ -1202,7 +1235,7 @@ class DatabaseController {
keys,
readPreference,
hint,
- caseInsensitive,
+ caseInsensitive: this.options.enableCollationCaseComparison ? false : caseInsensitive,
explain,
};
Object.keys(sort).forEach(fieldName => {
@@ -1706,31 +1739,27 @@ class DatabaseController {
throw error;
});
- await this.adapter
- .ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)
- .catch(error => {
- logger.warn('Unable to create case insensitive username index: ', error);
- throw error;
- });
- await this.adapter
- .ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)
- .catch(error => {
- logger.warn('Unable to create case insensitive username index: ', error);
- throw error;
- });
+ if (!this.options.enableCollationCaseComparison) {
+ await this.adapter
+ .ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)
+ .catch(error => {
+ logger.warn('Unable to create case insensitive username index: ', error);
+ throw error;
+ });
+
+ await this.adapter
+ .ensureIndex('_User', requiredUserFields, ['email'], 'case_insensitive_email', true)
+ .catch(error => {
+ logger.warn('Unable to create case insensitive email index: ', error);
+ throw error;
+ });
+ }
await this.adapter.ensureUniqueness('_User', requiredUserFields, ['email']).catch(error => {
logger.warn('Unable to ensure uniqueness for user email addresses: ', error);
throw error;
});
- await this.adapter
- .ensureIndex('_User', requiredUserFields, ['email'], 'case_insensitive_email', true)
- .catch(error => {
- logger.warn('Unable to create case insensitive email index: ', error);
- throw error;
- });
-
await this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name']).catch(error => {
logger.warn('Unable to ensure uniqueness for role name: ', error);
throw error;
@@ -1813,7 +1842,7 @@ class DatabaseController {
keyUpdate &&
typeof keyUpdate === 'object' &&
keyUpdate.__op &&
- ['Add', 'AddUnique', 'Remove', 'Increment'].indexOf(keyUpdate.__op) > -1
+ ['Add', 'AddUnique', 'Remove', 'Increment', 'SetOnInsert'].indexOf(keyUpdate.__op) > -1
) {
// only valid ops that produce an actionable result
// the op may have happened on a keypath
diff --git a/src/Controllers/PushController.js b/src/Controllers/PushController.js
index 1a5b9bf491..04fb5c4fd0 100644
--- a/src/Controllers/PushController.js
+++ b/src/Controllers/PushController.js
@@ -58,9 +58,16 @@ export class PushController {
// Force filtering on only valid device tokens
const updateWhere = applyDeviceTokenExists(where);
- badgeUpdate = () => {
+ badgeUpdate = async () => {
// Build a real RestQuery so we can use it in RestWrite
- const restQuery = new RestQuery(config, master(config), '_Installation', updateWhere);
+ const restQuery = await RestQuery({
+ method: RestQuery.Method.find,
+ config,
+ runBeforeFind: false,
+ auth: master(config),
+ className: '_Installation',
+ restWhere: updateWhere,
+ });
return restQuery.buildRestWhere().then(() => {
const write = new RestWrite(
config,
diff --git a/src/Controllers/UserController.js b/src/Controllers/UserController.js
index 6871add987..497348ea35 100644
--- a/src/Controllers/UserController.js
+++ b/src/Controllers/UserController.js
@@ -32,23 +32,35 @@ export class UserController extends AdaptableController {
}
get shouldVerifyEmails() {
- return this.options.verifyUserEmails;
+ return (this.config || this.options).verifyUserEmails;
}
- setEmailVerifyToken(user) {
- if (this.shouldVerifyEmails) {
- user._email_verify_token = randomString(25);
+ async setEmailVerifyToken(user, req, storage = {}) {
+ const shouldSendEmail =
+ this.shouldVerifyEmails === true ||
+ (typeof this.shouldVerifyEmails === 'function' &&
+ (await Promise.resolve(this.shouldVerifyEmails(req))) === true);
+ if (!shouldSendEmail) {
+ return false;
+ }
+ storage.sendVerificationEmail = true;
+ user._email_verify_token = randomString(25);
+ if (
+ !storage.fieldsChangedByTrigger ||
+ !storage.fieldsChangedByTrigger.includes('emailVerified')
+ ) {
user.emailVerified = false;
+ }
- if (this.config.emailVerifyTokenValidityDuration) {
- user._email_verify_token_expires_at = Parse._encode(
- this.config.generateEmailVerifyTokenExpiresAt()
- );
- }
+ if (this.config.emailVerifyTokenValidityDuration) {
+ user._email_verify_token_expires_at = Parse._encode(
+ this.config.generateEmailVerifyTokenExpiresAt()
+ );
}
+ return true;
}
- verifyEmail(username, token) {
+ async verifyEmail(username, token) {
if (!this.shouldVerifyEmails) {
// Trying to verify email when not enabled
// TODO: Better error here.
@@ -70,8 +82,14 @@ export class UserController extends AdaptableController {
updateFields._email_verify_token_expires_at = { __op: 'Delete' };
}
const maintenanceAuth = Auth.maintenance(this.config);
- var findUserForEmailVerification = new RestQuery(this.config, maintenanceAuth, '_User', {
- username,
+ var findUserForEmailVerification = await RestQuery({
+ method: RestQuery.Method.get,
+ config: this.config,
+ auth: maintenanceAuth,
+ className: '_User',
+ restWhere: {
+ username,
+ },
});
return findUserForEmailVerification.execute().then(result => {
if (result.results.length && result.results[0].emailVerified) {
@@ -110,10 +128,7 @@ export class UserController extends AdaptableController {
});
}
- getUserIfNeeded(user) {
- if (user.username && user.email) {
- return Promise.resolve(user);
- }
+ async getUserIfNeeded(user) {
var where = {};
if (user.username) {
where.username = user.username;
@@ -122,36 +137,55 @@ export class UserController extends AdaptableController {
where.email = user.email;
}
- var query = new RestQuery(this.config, Auth.master(this.config), '_User', where);
- return query.execute().then(function (result) {
- if (result.results.length != 1) {
- throw undefined;
- }
- return result.results[0];
+ var query = await RestQuery({
+ method: RestQuery.Method.get,
+ config: this.config,
+ runBeforeFind: false,
+ auth: Auth.master(this.config),
+ className: '_User',
+ restWhere: where,
});
+ const result = await query.execute();
+ if (result.results.length != 1) {
+ throw undefined;
+ }
+ return result.results[0];
}
- sendVerificationEmail(user) {
+ async sendVerificationEmail(user, req) {
if (!this.shouldVerifyEmails) {
return;
}
const token = encodeURIComponent(user._email_verify_token);
- // We may need to fetch the user in case of update email
- this.getUserIfNeeded(user).then(user => {
- const username = encodeURIComponent(user.username);
-
- const link = buildEmailLink(this.config.verifyEmailURL, username, token, this.config);
- const options = {
- appName: this.config.appName,
- link: link,
- user: inflate('_User', user),
- };
- if (this.adapter.sendVerificationEmail) {
- this.adapter.sendVerificationEmail(options);
- } else {
- this.adapter.sendMail(this.defaultVerificationEmail(options));
- }
- });
+ // We may need to fetch the user in case of update email; only use the `fetchedUser`
+ // from this point onwards; do not use the `user` as it may not contain all fields.
+ const fetchedUser = await this.getUserIfNeeded(user);
+ let shouldSendEmail = this.config.sendUserEmailVerification;
+ if (typeof shouldSendEmail === 'function') {
+ const response = await Promise.resolve(
+ this.config.sendUserEmailVerification({
+ user: Parse.Object.fromJSON({ className: '_User', ...fetchedUser }),
+ master: req.auth?.isMaster,
+ })
+ );
+ shouldSendEmail = !!response;
+ }
+ if (!shouldSendEmail) {
+ return;
+ }
+ const username = encodeURIComponent(fetchedUser.username);
+
+ const link = buildEmailLink(this.config.verifyEmailURL, username, token, this.config);
+ const options = {
+ appName: this.config.appName,
+ link: link,
+ user: inflate('_User', fetchedUser),
+ };
+ if (this.adapter.sendVerificationEmail) {
+ this.adapter.sendVerificationEmail(options);
+ } else {
+ this.adapter.sendMail(this.defaultVerificationEmail(options));
+ }
}
/**
@@ -160,7 +194,7 @@ export class UserController extends AdaptableController {
* @param user
* @returns {*}
*/
- regenerateEmailVerifyToken(user) {
+ async regenerateEmailVerifyToken(user, master, installationId, ip) {
const { _email_verify_token } = user;
let { _email_verify_token_expires_at } = user;
if (_email_verify_token_expires_at && _email_verify_token_expires_at.__type === 'Date') {
@@ -172,21 +206,35 @@ export class UserController extends AdaptableController {
_email_verify_token &&
new Date() < new Date(_email_verify_token_expires_at)
) {
- return Promise.resolve();
+ return Promise.resolve(true);
+ }
+ const shouldSend = await this.setEmailVerifyToken(user, {
+ object: Parse.User.fromJSON(Object.assign({ className: '_User' }, user)),
+ master,
+ installationId,
+ ip,
+ resendRequest: true,
+ });
+ if (!shouldSend) {
+ return;
}
- this.setEmailVerifyToken(user);
return this.config.database.update('_User', { username: user.username }, user);
}
- resendVerificationEmail(username) {
- return this.getUserIfNeeded({ username: username }).then(aUser => {
- if (!aUser || aUser.emailVerified) {
- throw undefined;
- }
- return this.regenerateEmailVerifyToken(aUser).then(() => {
- this.sendVerificationEmail(aUser);
- });
- });
+ async resendVerificationEmail(username, req) {
+ const aUser = await this.getUserIfNeeded({ username: username });
+ if (!aUser || aUser.emailVerified) {
+ throw undefined;
+ }
+ const generate = await this.regenerateEmailVerifyToken(
+ aUser,
+ req.auth?.isMaster,
+ req.auth?.installationId,
+ req.ip
+ );
+ if (generate) {
+ this.sendVerificationEmail(aUser, req);
+ }
}
setPasswordResetToken(email) {
diff --git a/src/Deprecator/Deprecations.js b/src/Deprecator/Deprecations.js
index 0afd98ff0c..2f698ad33e 100644
--- a/src/Deprecator/Deprecations.js
+++ b/src/Deprecator/Deprecations.js
@@ -18,4 +18,5 @@
module.exports = [
{ optionKey: 'allowClientClassCreation', changeNewDefault: 'false' },
{ optionKey: 'allowExpiredAuthDataToken', changeNewDefault: 'false' },
+ { optionKey: 'encodeParseObjectInCloudFunction', changeNewDefault: 'true' },
];
diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js
index 3815902c51..35da35bb5f 100644
--- a/src/Options/Definitions.js
+++ b/src/Options/Definitions.js
@@ -103,7 +103,6 @@ module.exports.ParseServerOptions = {
env: 'PARSE_SERVER_AUTH_PROVIDERS',
help:
'Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication',
- action: parsers.arrayParser,
},
cacheAdapter: {
env: 'PARSE_SERVER_CACHE_ADAPTER',
@@ -140,6 +139,20 @@ module.exports.ParseServerOptions = {
help: 'A collection prefix for the classes',
default: '',
},
+ convertEmailToLowercase: {
+ env: 'PARSE_SERVER_CONVERT_EMAIL_TO_LOWERCASE',
+ help:
+ 'Optional. If set to `true`, the `email` property of a user is automatically converted to lowercase before being stored in the database. Consequently, queries must match the case as stored in the database, which would be lowercase in this scenario. If `false`, the `email` property is stored as set, without any case modifications. Default is `false`.',
+ action: parsers.booleanParser,
+ default: false,
+ },
+ convertUsernameToLowercase: {
+ env: 'PARSE_SERVER_CONVERT_USERNAME_TO_LOWERCASE',
+ help:
+ 'Optional. If set to `true`, the `username` property of a user is automatically converted to lowercase before being stored in the database. Consequently, queries must match the case as stored in the database, which would be lowercase in this scenario. If `false`, the `username` property is stored as set, without any case modifications. Default is `false`.',
+ action: parsers.booleanParser,
+ default: false,
+ },
customPages: {
env: 'PARSE_SERVER_CUSTOM_PAGES',
help: 'custom pages for password validation and reset',
@@ -204,12 +217,26 @@ module.exports.ParseServerOptions = {
action: parsers.booleanParser,
default: true,
},
+ enableCollationCaseComparison: {
+ env: 'PARSE_SERVER_ENABLE_COLLATION_CASE_COMPARISON',
+ help:
+ 'Optional. If set to `true`, the collation rule of case comparison for queries and indexes is enabled. Enable this option to run Parse Server with MongoDB Atlas Serverless or AWS Amazon DocumentDB. If `false`, the collation rule of case comparison is disabled. Default is `false`.',
+ action: parsers.booleanParser,
+ default: false,
+ },
enableExpressErrorHandler: {
env: 'PARSE_SERVER_ENABLE_EXPRESS_ERROR_HANDLER',
help: 'Enables the default express error handler for all errors',
action: parsers.booleanParser,
default: false,
},
+ encodeParseObjectInCloudFunction: {
+ env: 'PARSE_SERVER_ENCODE_PARSE_OBJECT_IN_CLOUD_FUNCTION',
+ help:
+ 'If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.
\u2139\uFE0F The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`.',
+ action: parsers.booleanParser,
+ default: false,
+ },
encryptionKey: {
env: 'PARSE_SERVER_ENCRYPTION_KEY',
help: 'Key for encrypting your files',
@@ -311,13 +338,13 @@ module.exports.ParseServerOptions = {
maintenanceKey: {
env: 'PARSE_SERVER_MAINTENANCE_KEY',
help:
- '(Optional) The maintenance key is used for modifying internal fields of Parse Server.
\u26A0\uFE0F This key is not intended to be used as part of a regular operation of Parse Server. This key is intended to conduct out-of-band changes such as one-time migrations or data correction tasks. Internal fields are not officially documented and may change at any time without publication in release changelogs. We strongly advice not to rely on internal fields as part of your regular operation and to investigate the implications of any planned changes *directly in the source code* of your current version of Parse Server.',
+ '(Optional) The maintenance key is used for modifying internal and read-only fields of Parse Server.
\u26A0\uFE0F This key is not intended to be used as part of a regular operation of Parse Server. This key is intended to conduct out-of-band changes such as one-time migrations or data correction tasks. Internal fields are not officially documented and may change at any time without publication in release changelogs. We strongly advice not to rely on internal fields as part of your regular operation and to investigate the implications of any planned changes *directly in the source code* of your current version of Parse Server.',
required: true,
},
maintenanceKeyIps: {
env: 'PARSE_SERVER_MAINTENANCE_KEY_IPS',
help:
- "(Optional) Restricts the use of maintenance key permissions to a list of IP addresses.
This option accepts a list of single IP addresses, for example:
`['10.0.0.1', '10.0.0.2']`
You can also use CIDR notation to specify an IP address range, for example:
`['10.0.1.0/24']`
Special cases:
- Setting an empty array `[]` means that `maintenanceKey` cannot be used even in Parse Server Cloud Code.
- Setting `['0.0.0.0/0']` means disabling the filter and the maintenance key can be used from any IP address.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server itself, is allowed to use the maintenance key.",
+ "(Optional) Restricts the use of maintenance key permissions to a list of IP addresses or ranges.
This option accepts a list of single IP addresses, for example `['10.0.0.1', '10.0.0.2']`. You can also use CIDR notation to specify an IP address range, for example `['10.0.1.0/24']`.
Special scenarios:
- Setting an empty array `[]` means that the maintenance key cannot be used even in Parse Server Cloud Code. This value cannot be set via an environment variable as there is no way to pass an empty array to Parse Server via an environment variable.
- Setting `['0.0.0.0/0', '::0']` means to allow any IPv4 and IPv6 address to use the maintenance key and effectively disables the IP filter.
Considerations:
- IPv4 and IPv6 addresses are not compared against each other. Each IP version (IPv4 and IPv6) needs to be considered separately. For example, `['0.0.0.0/0']` allows any IPv4 address and blocks every IPv6 address. Conversely, `['::0']` allows any IPv6 address and blocks every IPv4 address.
- Keep in mind that the IP version in use depends on the network stack of the environment in which Parse Server runs. A local environment may use a different IP version than a remote environment. For example, it's possible that locally the value `['0.0.0.0/0']` allows the request IP because the environment is using IPv4, but when Parse Server is deployed remotely the request IP is blocked because the remote environment is using IPv6.
- When setting the option via an environment variable the notation is a comma-separated string, for example `\"0.0.0.0/0,::0\"`.
- IPv6 zone indices (`%` suffix) are not supported, for example `fe80::1%eth0`, `fe80::1%1` or `::1%lo`.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server instance on which Parse Server runs, is allowed to use the maintenance key.",
action: parsers.arrayParser,
default: ['127.0.0.1', '::1'],
},
@@ -329,7 +356,7 @@ module.exports.ParseServerOptions = {
masterKeyIps: {
env: 'PARSE_SERVER_MASTER_KEY_IPS',
help:
- "(Optional) Restricts the use of master key permissions to a list of IP addresses.
This option accepts a list of single IP addresses, for example:
`['10.0.0.1', '10.0.0.2']`
You can also use CIDR notation to specify an IP address range, for example:
`['10.0.1.0/24']`
Special cases:
- Setting an empty array `[]` means that `masterKey` cannot be used even in Parse Server Cloud Code.
- Setting `['0.0.0.0/0']` means disabling the filter and the master key can be used from any IP address.
To connect Parse Dashboard from a different server requires to add the IP address of the server that hosts Parse Dashboard because Parse Dashboard uses the master key.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server itself, is allowed to use the master key.",
+ "(Optional) Restricts the use of master key permissions to a list of IP addresses or ranges.
This option accepts a list of single IP addresses, for example `['10.0.0.1', '10.0.0.2']`. You can also use CIDR notation to specify an IP address range, for example `['10.0.1.0/24']`.
Special scenarios:
- Setting an empty array `[]` means that the master key cannot be used even in Parse Server Cloud Code. This value cannot be set via an environment variable as there is no way to pass an empty array to Parse Server via an environment variable.
- Setting `['0.0.0.0/0', '::0']` means to allow any IPv4 and IPv6 address to use the master key and effectively disables the IP filter.
Considerations:
- IPv4 and IPv6 addresses are not compared against each other. Each IP version (IPv4 and IPv6) needs to be considered separately. For example, `['0.0.0.0/0']` allows any IPv4 address and blocks every IPv6 address. Conversely, `['::0']` allows any IPv6 address and blocks every IPv4 address.
- Keep in mind that the IP version in use depends on the network stack of the environment in which Parse Server runs. A local environment may use a different IP version than a remote environment. For example, it's possible that locally the value `['0.0.0.0/0']` allows the request IP because the environment is using IPv4, but when Parse Server is deployed remotely the request IP is blocked because the remote environment is using IPv6.
- When setting the option via an environment variable the notation is a comma-separated string, for example `\"0.0.0.0/0,::0\"`.
- IPv6 zone indices (`%` suffix) are not supported, for example `fe80::1%eth0`, `fe80::1%1` or `::1%lo`.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server instance on which Parse Server runs, is allowed to use the master key.",
action: parsers.arrayParser,
default: ['127.0.0.1', '::1'],
},
@@ -496,6 +523,12 @@ module.exports.ParseServerOptions = {
action: parsers.objectParser,
default: {},
},
+ sendUserEmailVerification: {
+ env: 'PARSE_SERVER_SEND_USER_EMAIL_VERIFICATION',
+ help:
+ 'Set to `false` to prevent sending of verification email. Supports a function with a return value of `true` or `false` for conditional email sending.
Default is `true`.
',
+ default: true,
+ },
serverCloseComplete: {
env: 'PARSE_SERVER_SERVER_CLOSE_COMPLETE',
help: 'Callback when server has closed',
@@ -542,8 +575,7 @@ module.exports.ParseServerOptions = {
verifyUserEmails: {
env: 'PARSE_SERVER_VERIFY_USER_EMAILS',
help:
- 'Set to `true` to require users to verify their email address to complete the sign-up process.
Default is `false`.',
- action: parsers.booleanParser,
+ 'Set to `true` to require users to verify their email address to complete the sign-up process. Supports a function with a return value of `true` or `false` for conditional verification.
Default is `false`.',
default: false,
},
webhookKey: {
diff --git a/src/Options/docs.js b/src/Options/docs.js
index 847e7df944..643123c253 100644
--- a/src/Options/docs.js
+++ b/src/Options/docs.js
@@ -20,7 +20,7 @@
* @property {Adapter} analyticsAdapter Adapter module for the analytics
* @property {String} appId Your Parse Application ID
* @property {String} appName Sets the app name
- * @property {AuthAdapter[]} auth Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication
+ * @property {Object} auth Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication
* @property {Adapter} cacheAdapter Adapter module for the cache
* @property {Number} cacheMaxSize Sets the maximum size for the in memory cache, defaults to 10000
* @property {Number} cacheTTL Sets the TTL for the in memory cache (in ms), defaults to 5000 (5 seconds)
@@ -28,6 +28,8 @@
* @property {String} cloud Full path to your cloud code main.js
* @property {Number|Boolean} cluster Run with cluster, optionally set the number of processes default to os.cpus().length
* @property {String} collectionPrefix A collection prefix for the classes
+ * @property {Boolean} convertEmailToLowercase Optional. If set to `true`, the `email` property of a user is automatically converted to lowercase before being stored in the database. Consequently, queries must match the case as stored in the database, which would be lowercase in this scenario. If `false`, the `email` property is stored as set, without any case modifications. Default is `false`.
+ * @property {Boolean} convertUsernameToLowercase Optional. If set to `true`, the `username` property of a user is automatically converted to lowercase before being stored in the database. Consequently, queries must match the case as stored in the database, which would be lowercase in this scenario. If `false`, the `username` property is stored as set, without any case modifications. Default is `false`.
* @property {CustomPagesOptions} customPages custom pages for password validation and reset
* @property {Adapter} databaseAdapter Adapter module for the database; any options that are not explicitly described here are passed directly to the database client.
* @property {DatabaseOptions} databaseOptions Options to pass to the database client
@@ -39,7 +41,9 @@
* @property {Boolean} emailVerifyTokenReuseIfValid Set to `true` if a email verification token should be reused in case another token is requested but there is a token that is still valid, i.e. has not expired. This avoids the often observed issue that a user requests multiple emails and does not know which link contains a valid token because each newly generated token would invalidate the previous token.
Default is `false`.
Requires option `verifyUserEmails: true`.
* @property {Number} emailVerifyTokenValidityDuration Set the validity duration of the email verification token in seconds after which the token expires. The token is used in the link that is set in the email. After the token expires, the link becomes invalid and a new link has to be sent. If the option is not set or set to `undefined`, then the token never expires.
For example, to expire the token after 2 hours, set a value of 7200 seconds (= 60 seconds * 60 minutes * 2 hours).
Default is `undefined`.
Requires option `verifyUserEmails: true`.
* @property {Boolean} enableAnonymousUsers Enable (or disable) anonymous users, defaults to true
+ * @property {Boolean} enableCollationCaseComparison Optional. If set to `true`, the collation rule of case comparison for queries and indexes is enabled. Enable this option to run Parse Server with MongoDB Atlas Serverless or AWS Amazon DocumentDB. If `false`, the collation rule of case comparison is disabled. Default is `false`.
* @property {Boolean} enableExpressErrorHandler Enables the default express error handler for all errors
+ * @property {Boolean} encodeParseObjectInCloudFunction If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.
ℹ️ The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`.
* @property {String} encryptionKey Key for encrypting your files
* @property {Boolean} enforcePrivateUsers Set to true if new users should be created without public read and write access.
* @property {Boolean} expireInactiveSessions Sets whether we should expire the inactive sessions, defaults to true. If false, all new sessions are created with no expiration date.
@@ -59,10 +63,10 @@
* @property {String} logLevel Sets the level for logs
* @property {LogLevels} logLevels (Optional) Overrides the log levels used internally by Parse Server to log events.
* @property {String} logsFolder Folder for the logs (defaults to './logs'); set to null to disable file based logging
- * @property {String} maintenanceKey (Optional) The maintenance key is used for modifying internal fields of Parse Server.
⚠️ This key is not intended to be used as part of a regular operation of Parse Server. This key is intended to conduct out-of-band changes such as one-time migrations or data correction tasks. Internal fields are not officially documented and may change at any time without publication in release changelogs. We strongly advice not to rely on internal fields as part of your regular operation and to investigate the implications of any planned changes *directly in the source code* of your current version of Parse Server.
- * @property {String[]} maintenanceKeyIps (Optional) Restricts the use of maintenance key permissions to a list of IP addresses.
This option accepts a list of single IP addresses, for example:
`['10.0.0.1', '10.0.0.2']`
You can also use CIDR notation to specify an IP address range, for example:
`['10.0.1.0/24']`
Special cases:
- Setting an empty array `[]` means that `maintenanceKey` cannot be used even in Parse Server Cloud Code.
- Setting `['0.0.0.0/0']` means disabling the filter and the maintenance key can be used from any IP address.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server itself, is allowed to use the maintenance key.
+ * @property {String} maintenanceKey (Optional) The maintenance key is used for modifying internal and read-only fields of Parse Server.
⚠️ This key is not intended to be used as part of a regular operation of Parse Server. This key is intended to conduct out-of-band changes such as one-time migrations or data correction tasks. Internal fields are not officially documented and may change at any time without publication in release changelogs. We strongly advice not to rely on internal fields as part of your regular operation and to investigate the implications of any planned changes *directly in the source code* of your current version of Parse Server.
+ * @property {String[]} maintenanceKeyIps (Optional) Restricts the use of maintenance key permissions to a list of IP addresses or ranges.
This option accepts a list of single IP addresses, for example `['10.0.0.1', '10.0.0.2']`. You can also use CIDR notation to specify an IP address range, for example `['10.0.1.0/24']`.
Special scenarios:
- Setting an empty array `[]` means that the maintenance key cannot be used even in Parse Server Cloud Code. This value cannot be set via an environment variable as there is no way to pass an empty array to Parse Server via an environment variable.
- Setting `['0.0.0.0/0', '::0']` means to allow any IPv4 and IPv6 address to use the maintenance key and effectively disables the IP filter.
Considerations:
- IPv4 and IPv6 addresses are not compared against each other. Each IP version (IPv4 and IPv6) needs to be considered separately. For example, `['0.0.0.0/0']` allows any IPv4 address and blocks every IPv6 address. Conversely, `['::0']` allows any IPv6 address and blocks every IPv4 address.
- Keep in mind that the IP version in use depends on the network stack of the environment in which Parse Server runs. A local environment may use a different IP version than a remote environment. For example, it's possible that locally the value `['0.0.0.0/0']` allows the request IP because the environment is using IPv4, but when Parse Server is deployed remotely the request IP is blocked because the remote environment is using IPv6.
- When setting the option via an environment variable the notation is a comma-separated string, for example `"0.0.0.0/0,::0"`.
- IPv6 zone indices (`%` suffix) are not supported, for example `fe80::1%eth0`, `fe80::1%1` or `::1%lo`.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server instance on which Parse Server runs, is allowed to use the maintenance key.
* @property {String} masterKey Your Parse Master Key
- * @property {String[]} masterKeyIps (Optional) Restricts the use of master key permissions to a list of IP addresses.
This option accepts a list of single IP addresses, for example:
`['10.0.0.1', '10.0.0.2']`
You can also use CIDR notation to specify an IP address range, for example:
`['10.0.1.0/24']`
Special cases:
- Setting an empty array `[]` means that `masterKey` cannot be used even in Parse Server Cloud Code.
- Setting `['0.0.0.0/0']` means disabling the filter and the master key can be used from any IP address.
To connect Parse Dashboard from a different server requires to add the IP address of the server that hosts Parse Dashboard because Parse Dashboard uses the master key.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server itself, is allowed to use the master key.
+ * @property {String[]} masterKeyIps (Optional) Restricts the use of master key permissions to a list of IP addresses or ranges.
This option accepts a list of single IP addresses, for example `['10.0.0.1', '10.0.0.2']`. You can also use CIDR notation to specify an IP address range, for example `['10.0.1.0/24']`.
Special scenarios:
- Setting an empty array `[]` means that the master key cannot be used even in Parse Server Cloud Code. This value cannot be set via an environment variable as there is no way to pass an empty array to Parse Server via an environment variable.
- Setting `['0.0.0.0/0', '::0']` means to allow any IPv4 and IPv6 address to use the master key and effectively disables the IP filter.
Considerations:
- IPv4 and IPv6 addresses are not compared against each other. Each IP version (IPv4 and IPv6) needs to be considered separately. For example, `['0.0.0.0/0']` allows any IPv4 address and blocks every IPv6 address. Conversely, `['::0']` allows any IPv6 address and blocks every IPv4 address.
- Keep in mind that the IP version in use depends on the network stack of the environment in which Parse Server runs. A local environment may use a different IP version than a remote environment. For example, it's possible that locally the value `['0.0.0.0/0']` allows the request IP because the environment is using IPv4, but when Parse Server is deployed remotely the request IP is blocked because the remote environment is using IPv6.
- When setting the option via an environment variable the notation is a comma-separated string, for example `"0.0.0.0/0,::0"`.
- IPv6 zone indices (`%` suffix) are not supported, for example `fe80::1%eth0`, `fe80::1%1` or `::1%lo`.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server instance on which Parse Server runs, is allowed to use the master key.
* @property {Number} maxLimit Max value for limit option on queries, defaults to unlimited
* @property {Number|String} maxLogFiles Maximum number of logs to keep. If not set, no logs will be removed. This can be a number of files or number of days. If using days, add 'd' as the suffix. (default: null)
* @property {String} maxUploadSize Max file size for uploads, defaults to 20mb
@@ -89,6 +93,7 @@
* @property {Boolean} scheduledPush Configuration for push scheduling, defaults to false.
* @property {SchemaOptions} schema Defined schema
* @property {SecurityOptions} security The security options to identify and report weak security settings.
+ * @property {Boolean} sendUserEmailVerification Set to `false` to prevent sending of verification email. Supports a function with a return value of `true` or `false` for conditional email sending.
Default is `true`.
* @property {Function} serverCloseComplete Callback when server has closed
* @property {String} serverURL URL to your parse server with http:// or https://.
* @property {Number} sessionLength Session duration, in seconds, defaults to 1 year
@@ -97,7 +102,7 @@
* @property {Any} trustProxy The trust proxy settings. It is important to understand the exact setup of the reverse proxy, since this setting will trust values provided in the Parse Server API request. See the express trust proxy settings documentation. Defaults to `false`.
* @property {String[]} userSensitiveFields Personally identifiable information fields in the user table the should be removed for non-authorized users. Deprecated @see protectedFields
* @property {Boolean} verbose Set the logging to verbose
- * @property {Boolean} verifyUserEmails Set to `true` to require users to verify their email address to complete the sign-up process.
Default is `false`.
+ * @property {Boolean} verifyUserEmails Set to `true` to require users to verify their email address to complete the sign-up process. Supports a function with a return value of `true` or `false` for conditional verification.
Default is `false`.
* @property {String} webhookKey Key sent with outgoing webhook calls
*/
diff --git a/src/Options/index.js b/src/Options/index.js
index 87813147f7..cfda946a05 100644
--- a/src/Options/index.js
+++ b/src/Options/index.js
@@ -47,16 +47,16 @@ export interface ParseServerOptions {
appId: string;
/* Your Parse Master Key */
masterKey: string;
- /* (Optional) The maintenance key is used for modifying internal fields of Parse Server.
⚠️ This key is not intended to be used as part of a regular operation of Parse Server. This key is intended to conduct out-of-band changes such as one-time migrations or data correction tasks. Internal fields are not officially documented and may change at any time without publication in release changelogs. We strongly advice not to rely on internal fields as part of your regular operation and to investigate the implications of any planned changes *directly in the source code* of your current version of Parse Server. */
+ /* (Optional) The maintenance key is used for modifying internal and read-only fields of Parse Server.
⚠️ This key is not intended to be used as part of a regular operation of Parse Server. This key is intended to conduct out-of-band changes such as one-time migrations or data correction tasks. Internal fields are not officially documented and may change at any time without publication in release changelogs. We strongly advice not to rely on internal fields as part of your regular operation and to investigate the implications of any planned changes *directly in the source code* of your current version of Parse Server. */
maintenanceKey: string;
/* URL to your parse server with http:// or https://.
:ENV: PARSE_SERVER_URL */
serverURL: string;
- /* (Optional) Restricts the use of master key permissions to a list of IP addresses.
This option accepts a list of single IP addresses, for example:
`['10.0.0.1', '10.0.0.2']`
You can also use CIDR notation to specify an IP address range, for example:
`['10.0.1.0/24']`
Special cases:
- Setting an empty array `[]` means that `masterKey` cannot be used even in Parse Server Cloud Code.
- Setting `['0.0.0.0/0']` means disabling the filter and the master key can be used from any IP address.
To connect Parse Dashboard from a different server requires to add the IP address of the server that hosts Parse Dashboard because Parse Dashboard uses the master key.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server itself, is allowed to use the master key.
+ /* (Optional) Restricts the use of master key permissions to a list of IP addresses or ranges.
This option accepts a list of single IP addresses, for example `['10.0.0.1', '10.0.0.2']`. You can also use CIDR notation to specify an IP address range, for example `['10.0.1.0/24']`.
Special scenarios:
- Setting an empty array `[]` means that the master key cannot be used even in Parse Server Cloud Code. This value cannot be set via an environment variable as there is no way to pass an empty array to Parse Server via an environment variable.
- Setting `['0.0.0.0/0', '::0']` means to allow any IPv4 and IPv6 address to use the master key and effectively disables the IP filter.
Considerations:
- IPv4 and IPv6 addresses are not compared against each other. Each IP version (IPv4 and IPv6) needs to be considered separately. For example, `['0.0.0.0/0']` allows any IPv4 address and blocks every IPv6 address. Conversely, `['::0']` allows any IPv6 address and blocks every IPv4 address.
- Keep in mind that the IP version in use depends on the network stack of the environment in which Parse Server runs. A local environment may use a different IP version than a remote environment. For example, it's possible that locally the value `['0.0.0.0/0']` allows the request IP because the environment is using IPv4, but when Parse Server is deployed remotely the request IP is blocked because the remote environment is using IPv6.
- When setting the option via an environment variable the notation is a comma-separated string, for example `"0.0.0.0/0,::0"`.
- IPv6 zone indices (`%` suffix) are not supported, for example `fe80::1%eth0`, `fe80::1%1` or `::1%lo`.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server instance on which Parse Server runs, is allowed to use the master key.
:DEFAULT: ["127.0.0.1","::1"] */
masterKeyIps: ?(string[]);
- /* (Optional) Restricts the use of maintenance key permissions to a list of IP addresses.
This option accepts a list of single IP addresses, for example:
`['10.0.0.1', '10.0.0.2']`
You can also use CIDR notation to specify an IP address range, for example:
`['10.0.1.0/24']`
Special cases:
- Setting an empty array `[]` means that `maintenanceKey` cannot be used even in Parse Server Cloud Code.
- Setting `['0.0.0.0/0']` means disabling the filter and the maintenance key can be used from any IP address.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server itself, is allowed to use the maintenance key.
- :DEFAULT: ["127.0.0.1","::1"] */
+ /* (Optional) Restricts the use of maintenance key permissions to a list of IP addresses or ranges.
This option accepts a list of single IP addresses, for example `['10.0.0.1', '10.0.0.2']`. You can also use CIDR notation to specify an IP address range, for example `['10.0.1.0/24']`.
Special scenarios:
- Setting an empty array `[]` means that the maintenance key cannot be used even in Parse Server Cloud Code. This value cannot be set via an environment variable as there is no way to pass an empty array to Parse Server via an environment variable.
- Setting `['0.0.0.0/0', '::0']` means to allow any IPv4 and IPv6 address to use the maintenance key and effectively disables the IP filter.
Considerations:
- IPv4 and IPv6 addresses are not compared against each other. Each IP version (IPv4 and IPv6) needs to be considered separately. For example, `['0.0.0.0/0']` allows any IPv4 address and blocks every IPv6 address. Conversely, `['::0']` allows any IPv6 address and blocks every IPv4 address.
- Keep in mind that the IP version in use depends on the network stack of the environment in which Parse Server runs. A local environment may use a different IP version than a remote environment. For example, it's possible that locally the value `['0.0.0.0/0']` allows the request IP because the environment is using IPv4, but when Parse Server is deployed remotely the request IP is blocked because the remote environment is using IPv6.
- When setting the option via an environment variable the notation is a comma-separated string, for example `"0.0.0.0/0,::0"`.
- IPv6 zone indices (`%` suffix) are not supported, for example `fe80::1%eth0`, `fe80::1%1` or `::1%lo`.
Defaults to `['127.0.0.1', '::1']` which means that only `localhost`, the server instance on which Parse Server runs, is allowed to use the maintenance key.
+ :DEFAULT: ["127.0.0.1","::1"] */
maintenanceKeyIps: ?(string[]);
/* Sets the app name */
appName: ?string;
@@ -103,6 +103,15 @@ export interface ParseServerOptions {
databaseOptions: ?DatabaseOptions;
/* Adapter module for the database; any options that are not explicitly described here are passed directly to the database client. */
databaseAdapter: ?Adapter;
+ /* Optional. If set to `true`, the collation rule of case comparison for queries and indexes is enabled. Enable this option to run Parse Server with MongoDB Atlas Serverless or AWS Amazon DocumentDB. If `false`, the collation rule of case comparison is disabled. Default is `false`.
+ :DEFAULT: false */
+ enableCollationCaseComparison: ?boolean;
+ /* Optional. If set to `true`, the `email` property of a user is automatically converted to lowercase before being stored in the database. Consequently, queries must match the case as stored in the database, which would be lowercase in this scenario. If `false`, the `email` property is stored as set, without any case modifications. Default is `false`.
+ :DEFAULT: false */
+ convertEmailToLowercase: ?boolean;
+ /* Optional. If set to `true`, the `username` property of a user is automatically converted to lowercase before being stored in the database. Consequently, queries must match the case as stored in the database, which would be lowercase in this scenario. If `false`, the `username` property is stored as set, without any case modifications. Default is `false`.
+ :DEFAULT: false */
+ convertUsernameToLowercase: ?boolean;
/* Full path to your cloud code main.js */
cloud: ?string;
/* A collection prefix for the classes
@@ -149,15 +158,15 @@ export interface ParseServerOptions {
allowCustomObjectId: ?boolean;
/* Configuration for your authentication providers, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication
:ENV: PARSE_SERVER_AUTH_PROVIDERS */
- auth: ?(AuthAdapter[]);
+ auth: ?{ [string]: AuthAdapter };
/* Max file size for uploads, defaults to 20mb
:DEFAULT: 20mb */
maxUploadSize: ?string;
- /* Set to `true` to require users to verify their email address to complete the sign-up process.
+ /* Set to `true` to require users to verify their email address to complete the sign-up process. Supports a function with a return value of `true` or `false` for conditional verification.
Default is `false`.
:DEFAULT: false */
- verifyUserEmails: ?boolean;
+ verifyUserEmails: ?(boolean | void);
/* Set to `true` to prevent a user from logging in if the email has not yet been verified and email verification is required.
Default is `false`.
@@ -188,6 +197,12 @@ export interface ParseServerOptions {
Requires option `verifyUserEmails: true`.
:DEFAULT: false */
emailVerifyTokenReuseIfValid: ?boolean;
+ /* Set to `false` to prevent sending of verification email. Supports a function with a return value of `true` or `false` for conditional email sending.
+
+ Default is `true`.
+
+ :DEFAULT: true */
+ sendUserEmailVerification: ?(boolean | void);
/* The account lockout policy for failed login attempts. */
accountLockout: ?AccountLockoutOptions;
/* The password policy for enforcing password related rules. */
@@ -196,6 +211,9 @@ export interface ParseServerOptions {
cacheAdapter: ?Adapter;
/* Adapter module for email sending */
emailAdapter: ?Adapter;
+ /* If set to `true`, a `Parse.Object` that is in the payload when calling a Cloud Function will be converted to an instance of `Parse.Object`. If `false`, the object will not be converted and instead be a plain JavaScript object, which contains the raw data of a `Parse.Object` but is not an actual instance of `Parse.Object`. Default is `false`.
ℹ️ The expected behavior would be that the object is converted to an instance of `Parse.Object`, so you would normally set this option to `true`. The default is `false` because this is a temporary option that has been introduced to avoid a breaking change when fixing a bug where JavaScript objects are not converted to actual instances of `Parse.Object`.
+ :DEFAULT: false */
+ encodeParseObjectInCloudFunction: ?boolean;
/* Public URL to your parse server with http:// or https://.
:ENV: PARSE_PUBLIC_SERVER_URL */
publicServerURL: ?string;
diff --git a/src/ParseServer.js b/src/ParseServer.js
index 6465e1f3c9..91d151b3f9 100644
--- a/src/ParseServer.js
+++ b/src/ParseServer.js
@@ -75,6 +75,8 @@ class ParseServer {
const allControllers = controllers.getControllers(options);
options.state = 'initialized';
this.config = Config.put(Object.assign({}, options, allControllers));
+ this.config.masterKeyIpsStore = new Map();
+ this.config.maintenanceKeyIpsStore = new Map();
logging.setLogger(allControllers.loggerController);
}
diff --git a/src/RestQuery.js b/src/RestQuery.js
index fe3617eb1b..5af678bb96 100644
--- a/src/RestQuery.js
+++ b/src/RestQuery.js
@@ -6,6 +6,8 @@ var Parse = require('parse/node').Parse;
const triggers = require('./triggers');
const { continueWhile } = require('parse/lib/node/promiseUtils');
const AlwaysSelectedKeys = ['objectId', 'createdAt', 'updatedAt', 'ACL'];
+const { enforceRoleSecurity } = require('./SharedRest');
+
// restOptions can include:
// skip
// limit
@@ -18,7 +20,80 @@ const AlwaysSelectedKeys = ['objectId', 'createdAt', 'updatedAt', 'ACL'];
// readPreference
// includeReadPreference
// subqueryReadPreference
-function RestQuery(
+/**
+ * Use to perform a query on a class. It will run security checks and triggers.
+ * @param options
+ * @param options.method {RestQuery.Method} The type of query to perform
+ * @param options.config {ParseServerConfiguration} The server configuration
+ * @param options.auth {Auth} The auth object for the request
+ * @param options.className {string} The name of the class to query
+ * @param options.restWhere {object} The where object for the query
+ * @param options.restOptions {object} The options object for the query
+ * @param options.clientSDK {string} The client SDK that is performing the query
+ * @param options.runAfterFind {boolean} Whether to run the afterFind trigger
+ * @param options.runBeforeFind {boolean} Whether to run the beforeFind trigger
+ * @param options.context {object} The context object for the query
+ * @returns {Promise<_UnsafeRestQuery>} A promise that is resolved with the _UnsafeRestQuery object
+ */
+async function RestQuery({
+ method,
+ config,
+ auth,
+ className,
+ restWhere = {},
+ restOptions = {},
+ clientSDK,
+ runAfterFind = true,
+ runBeforeFind = true,
+ context,
+}) {
+ if (![RestQuery.Method.find, RestQuery.Method.get].includes(method)) {
+ throw new Parse.Error(Parse.Error.INVALID_QUERY, 'bad query type');
+ }
+ enforceRoleSecurity(method, className, auth);
+ const result = runBeforeFind
+ ? await triggers.maybeRunQueryTrigger(
+ triggers.Types.beforeFind,
+ className,
+ restWhere,
+ restOptions,
+ config,
+ auth,
+ context,
+ method === RestQuery.Method.get
+ )
+ : Promise.resolve({ restWhere, restOptions });
+
+ return new _UnsafeRestQuery(
+ config,
+ auth,
+ className,
+ result.restWhere || restWhere,
+ result.restOptions || restOptions,
+ clientSDK,
+ runAfterFind,
+ context
+ );
+}
+
+RestQuery.Method = Object.freeze({
+ get: 'get',
+ find: 'find',
+});
+
+/**
+ * _UnsafeRestQuery is meant for specific internal usage only. When you need to skip security checks or some triggers.
+ * Don't use it if you don't know what you are doing.
+ * @param config
+ * @param auth
+ * @param className
+ * @param restWhere
+ * @param restOptions
+ * @param clientSDK
+ * @param runAfterFind
+ * @param context
+ */
+function _UnsafeRestQuery(
config,
auth,
className,
@@ -197,7 +272,7 @@ function RestQuery(
// Returns a promise for the response - an object with optional keys
// 'results' and 'count'.
// TODO: consolidate the replaceX functions
-RestQuery.prototype.execute = function (executeOptions) {
+_UnsafeRestQuery.prototype.execute = function (executeOptions) {
return Promise.resolve()
.then(() => {
return this.buildRestWhere();
@@ -231,7 +306,7 @@ RestQuery.prototype.execute = function (executeOptions) {
});
};
-RestQuery.prototype.each = function (callback) {
+_UnsafeRestQuery.prototype.each = function (callback) {
const { config, auth, className, restWhere, restOptions, clientSDK } = this;
// if the limit is set, use it
restOptions.limit = restOptions.limit || 100;
@@ -243,7 +318,9 @@ RestQuery.prototype.each = function (callback) {
return !finished;
},
async () => {
- const query = new RestQuery(
+ // Safe here to use _UnsafeRestQuery because the security was already
+ // checked during "await RestQuery()"
+ const query = new _UnsafeRestQuery(
config,
auth,
className,
@@ -265,7 +342,7 @@ RestQuery.prototype.each = function (callback) {
);
};
-RestQuery.prototype.buildRestWhere = function () {
+_UnsafeRestQuery.prototype.buildRestWhere = function () {
return Promise.resolve()
.then(() => {
return this.getUserAndRoleACL();
@@ -294,7 +371,7 @@ RestQuery.prototype.buildRestWhere = function () {
};
// Uses the Auth object to get the list of roles, adds the user id
-RestQuery.prototype.getUserAndRoleACL = function () {
+_UnsafeRestQuery.prototype.getUserAndRoleACL = function () {
if (this.auth.isMaster) {
return Promise.resolve();
}
@@ -313,7 +390,7 @@ RestQuery.prototype.getUserAndRoleACL = function () {
// Changes the className if redirectClassNameForKey is set.
// Returns a promise.
-RestQuery.prototype.redirectClassNameForKey = function () {
+_UnsafeRestQuery.prototype.redirectClassNameForKey = function () {
if (!this.redirectKey) {
return Promise.resolve();
}
@@ -328,7 +405,7 @@ RestQuery.prototype.redirectClassNameForKey = function () {
};
// Validates this operation against the allowClientClassCreation config.
-RestQuery.prototype.validateClientClassCreation = function () {
+_UnsafeRestQuery.prototype.validateClientClassCreation = function () {
if (
this.config.allowClientClassCreation === false &&
!this.auth.isMaster &&
@@ -371,7 +448,7 @@ function transformInQuery(inQueryObject, className, results) {
// $inQuery clause.
// The $inQuery clause turns into an $in with values that are just
// pointers to the objects returned in the subquery.
-RestQuery.prototype.replaceInQuery = function () {
+_UnsafeRestQuery.prototype.replaceInQuery = async function () {
var inQueryObject = findObjectWithKey(this.restWhere, '$inQuery');
if (!inQueryObject) {
return;
@@ -394,13 +471,15 @@ RestQuery.prototype.replaceInQuery = function () {
additionalOptions.readPreference = this.restOptions.readPreference;
}
- var subquery = new RestQuery(
- this.config,
- this.auth,
- inQueryValue.className,
- inQueryValue.where,
- additionalOptions
- );
+ const subquery = await RestQuery({
+ method: RestQuery.Method.find,
+ config: this.config,
+ auth: this.auth,
+ className: inQueryValue.className,
+ restWhere: inQueryValue.where,
+ restOptions: additionalOptions,
+ context: this.context,
+ });
return subquery.execute().then(response => {
transformInQuery(inQueryObject, subquery.className, response.results);
// Recurse to repeat
@@ -429,7 +508,7 @@ function transformNotInQuery(notInQueryObject, className, results) {
// $notInQuery clause.
// The $notInQuery clause turns into a $nin with values that are just
// pointers to the objects returned in the subquery.
-RestQuery.prototype.replaceNotInQuery = function () {
+_UnsafeRestQuery.prototype.replaceNotInQuery = async function () {
var notInQueryObject = findObjectWithKey(this.restWhere, '$notInQuery');
if (!notInQueryObject) {
return;
@@ -452,13 +531,16 @@ RestQuery.prototype.replaceNotInQuery = function () {
additionalOptions.readPreference = this.restOptions.readPreference;
}
- var subquery = new RestQuery(
- this.config,
- this.auth,
- notInQueryValue.className,
- notInQueryValue.where,
- additionalOptions
- );
+ const subquery = await RestQuery({
+ method: RestQuery.Method.find,
+ config: this.config,
+ auth: this.auth,
+ className: notInQueryValue.className,
+ restWhere: notInQueryValue.where,
+ restOptions: additionalOptions,
+ context: this.context,
+ });
+
return subquery.execute().then(response => {
transformNotInQuery(notInQueryObject, subquery.className, response.results);
// Recurse to repeat
@@ -492,7 +574,7 @@ const transformSelect = (selectObject, key, objects) => {
// The $select clause turns into an $in with values selected out of
// the subquery.
// Returns a possible-promise.
-RestQuery.prototype.replaceSelect = function () {
+_UnsafeRestQuery.prototype.replaceSelect = async function () {
var selectObject = findObjectWithKey(this.restWhere, '$select');
if (!selectObject) {
return;
@@ -522,13 +604,16 @@ RestQuery.prototype.replaceSelect = function () {
additionalOptions.readPreference = this.restOptions.readPreference;
}
- var subquery = new RestQuery(
- this.config,
- this.auth,
- selectValue.query.className,
- selectValue.query.where,
- additionalOptions
- );
+ const subquery = await RestQuery({
+ method: RestQuery.Method.find,
+ config: this.config,
+ auth: this.auth,
+ className: selectValue.query.className,
+ restWhere: selectValue.query.where,
+ restOptions: additionalOptions,
+ context: this.context,
+ });
+
return subquery.execute().then(response => {
transformSelect(selectObject, selectValue.key, response.results);
// Keep replacing $select clauses
@@ -554,7 +639,7 @@ const transformDontSelect = (dontSelectObject, key, objects) => {
// The $dontSelect clause turns into an $nin with values selected out of
// the subquery.
// Returns a possible-promise.
-RestQuery.prototype.replaceDontSelect = function () {
+_UnsafeRestQuery.prototype.replaceDontSelect = async function () {
var dontSelectObject = findObjectWithKey(this.restWhere, '$dontSelect');
if (!dontSelectObject) {
return;
@@ -582,13 +667,16 @@ RestQuery.prototype.replaceDontSelect = function () {
additionalOptions.readPreference = this.restOptions.readPreference;
}
- var subquery = new RestQuery(
- this.config,
- this.auth,
- dontSelectValue.query.className,
- dontSelectValue.query.where,
- additionalOptions
- );
+ const subquery = await RestQuery({
+ method: RestQuery.Method.find,
+ config: this.config,
+ auth: this.auth,
+ className: dontSelectValue.query.className,
+ restWhere: dontSelectValue.query.where,
+ restOptions: additionalOptions,
+ context: this.context,
+ });
+
return subquery.execute().then(response => {
transformDontSelect(dontSelectObject, dontSelectValue.key, response.results);
// Keep replacing $dontSelect clauses
@@ -596,7 +684,7 @@ RestQuery.prototype.replaceDontSelect = function () {
});
};
-RestQuery.prototype.cleanResultAuthData = function (result) {
+_UnsafeRestQuery.prototype.cleanResultAuthData = function (result) {
delete result.password;
if (result.authData) {
Object.keys(result.authData).forEach(provider => {
@@ -635,7 +723,7 @@ const replaceEqualityConstraint = constraint => {
return constraint;
};
-RestQuery.prototype.replaceEquality = function () {
+_UnsafeRestQuery.prototype.replaceEquality = function () {
if (typeof this.restWhere !== 'object') {
return;
}
@@ -646,7 +734,7 @@ RestQuery.prototype.replaceEquality = function () {
// Returns a promise for whether it was successful.
// Populates this.response with an object that only has 'results'.
-RestQuery.prototype.runFind = function (options = {}) {
+_UnsafeRestQuery.prototype.runFind = function (options = {}) {
if (this.findOptions.limit === 0) {
this.response = { results: [] };
return Promise.resolve();
@@ -682,7 +770,7 @@ RestQuery.prototype.runFind = function (options = {}) {
// Returns a promise for whether it was successful.
// Populates this.response.count with the count
-RestQuery.prototype.runCount = function () {
+_UnsafeRestQuery.prototype.runCount = function () {
if (!this.doCount) {
return;
}
@@ -694,7 +782,7 @@ RestQuery.prototype.runCount = function () {
});
};
-RestQuery.prototype.denyProtectedFields = async function () {
+_UnsafeRestQuery.prototype.denyProtectedFields = async function () {
if (this.auth.isMaster) {
return;
}
@@ -719,7 +807,7 @@ RestQuery.prototype.denyProtectedFields = async function () {
};
// Augments this.response with all pointers on an object
-RestQuery.prototype.handleIncludeAll = function () {
+_UnsafeRestQuery.prototype.handleIncludeAll = function () {
if (!this.includeAll) {
return;
}
@@ -748,7 +836,7 @@ RestQuery.prototype.handleIncludeAll = function () {
};
// Updates property `this.keys` to contain all keys but the ones unselected.
-RestQuery.prototype.handleExcludeKeys = function () {
+_UnsafeRestQuery.prototype.handleExcludeKeys = function () {
if (!this.excludeKeys) {
return;
}
@@ -766,7 +854,7 @@ RestQuery.prototype.handleExcludeKeys = function () {
};
// Augments this.response with data at the paths provided in this.include.
-RestQuery.prototype.handleInclude = function () {
+_UnsafeRestQuery.prototype.handleInclude = function () {
if (this.include.length == 0) {
return;
}
@@ -776,6 +864,7 @@ RestQuery.prototype.handleInclude = function () {
this.auth,
this.response,
this.include[0],
+ this.context,
this.restOptions
);
if (pathResponse.then) {
@@ -793,7 +882,7 @@ RestQuery.prototype.handleInclude = function () {
};
//Returns a promise of a processed set of results
-RestQuery.prototype.runAfterFindTrigger = function () {
+_UnsafeRestQuery.prototype.runAfterFindTrigger = function () {
if (!this.response) {
return;
}
@@ -845,7 +934,7 @@ RestQuery.prototype.runAfterFindTrigger = function () {
});
};
-RestQuery.prototype.handleAuthAdapters = async function () {
+_UnsafeRestQuery.prototype.handleAuthAdapters = async function () {
if (this.className !== '_User' || this.findOptions.explain) {
return;
}
@@ -862,7 +951,7 @@ RestQuery.prototype.handleAuthAdapters = async function () {
// Adds included values to the response.
// Path is a list of field names.
// Returns a promise for an augmented response.
-function includePath(config, auth, response, path, restOptions = {}) {
+function includePath(config, auth, response, path, context, restOptions = {}) {
var pointers = findPointers(response.results, path);
if (pointers.length == 0) {
return response;
@@ -927,7 +1016,7 @@ function includePath(config, auth, response, path, restOptions = {}) {
includeRestOptions.readPreference = restOptions.readPreference;
}
- const queryPromises = Object.keys(pointersHash).map(className => {
+ const queryPromises = Object.keys(pointersHash).map(async className => {
const objectIds = Array.from(pointersHash[className]);
let where;
if (objectIds.length === 1) {
@@ -935,7 +1024,15 @@ function includePath(config, auth, response, path, restOptions = {}) {
} else {
where = { objectId: { $in: objectIds } };
}
- var query = new RestQuery(config, auth, className, where, includeRestOptions);
+ const query = await RestQuery({
+ method: objectIds.length === 1 ? RestQuery.Method.get : RestQuery.Method.find,
+ config,
+ auth,
+ className,
+ restWhere: where,
+ restOptions: includeRestOptions,
+ context: context,
+ });
return query.execute({ op: 'get' }).then(results => {
results.className = className;
return Promise.resolve(results);
@@ -975,11 +1072,7 @@ function includePath(config, auth, response, path, restOptions = {}) {
// Returns a list of pointers in REST format.
function findPointers(object, path) {
if (object instanceof Array) {
- var answer = [];
- for (var x of object) {
- answer = answer.concat(findPointers(x, path));
- }
- return answer;
+ return object.map(x => findPointers(x, path)).flat();
}
if (typeof object !== 'object' || !object) {
@@ -1066,3 +1159,5 @@ function findObjectWithKey(root, key) {
}
module.exports = RestQuery;
+// For tests
+module.exports._UnsafeRestQuery = _UnsafeRestQuery;
diff --git a/src/RestWrite.js b/src/RestWrite.js
index f7c6a53592..0601840abd 100644
--- a/src/RestWrite.js
+++ b/src/RestWrite.js
@@ -64,8 +64,6 @@ function RestWrite(config, auth, className, query, data, originalData, clientSDK
}
}
- this.checkProhibitedKeywords(data);
-
// When the operation is complete, this.response may have several
// fields.
// response: the actual data to be returned
@@ -113,6 +111,9 @@ RestWrite.prototype.execute = function () {
.then(() => {
return this.validateAuthData();
})
+ .then(() => {
+ return this.checkRestrictedFields();
+ })
.then(() => {
return this.runBeforeSaveTrigger();
})
@@ -301,7 +302,11 @@ RestWrite.prototype.runBeforeSaveTrigger = function () {
delete this.data.objectId;
}
}
- this.checkProhibitedKeywords(this.data);
+ try {
+ Utils.checkProhibitedKeywords(this.config, this.data);
+ } catch (error) {
+ throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, error);
+ }
});
};
@@ -363,9 +368,36 @@ RestWrite.prototype.setRequiredFieldsIfNeeded = function () {
};
// Add default fields
- this.data.updatedAt = this.updatedAt;
if (!this.query) {
- this.data.createdAt = this.updatedAt;
+ // allow customizing createdAt and updatedAt when using maintenance key
+ if (
+ this.auth.isMaintenance &&
+ this.data.createdAt &&
+ this.data.createdAt.__type === 'Date'
+ ) {
+ this.data.createdAt = this.data.createdAt.iso;
+
+ if (this.data.updatedAt && this.data.updatedAt.__type === 'Date') {
+ const createdAt = new Date(this.data.createdAt);
+ const updatedAt = new Date(this.data.updatedAt.iso);
+
+ if (updatedAt < createdAt) {
+ throw new Parse.Error(
+ Parse.Error.VALIDATION_ERROR,
+ 'updatedAt cannot occur before createdAt'
+ );
+ }
+
+ this.data.updatedAt = this.data.updatedAt.iso;
+ }
+ // if no updatedAt is provided, set it to createdAt to match default behavior
+ else {
+ this.data.updatedAt = this.data.createdAt;
+ }
+ } else {
+ this.data.updatedAt = this.updatedAt;
+ this.data.createdAt = this.updatedAt;
+ }
// Only assign new objectId if we are creating new object
if (!this.data.objectId) {
@@ -377,6 +409,8 @@ RestWrite.prototype.setRequiredFieldsIfNeeded = function () {
});
}
} else if (schema) {
+ this.data.updatedAt = this.updatedAt;
+
Object.keys(this.data).forEach(fieldName => {
setRequiredFieldIfNeeded(fieldName, false);
});
@@ -553,6 +587,7 @@ RestWrite.prototype.handleAuthData = async function (authData) {
// we need to be sure that the user has provided
// required authData
Auth.checkIfUserHasProvidedConfiguredProvidersForLogin(
+ { config: this.config, auth: this.auth },
authData,
userResult.authData,
this.config
@@ -603,35 +638,47 @@ RestWrite.prototype.handleAuthData = async function (authData) {
}
};
-// The non-third-party parts of User transformation
-RestWrite.prototype.transformUser = function () {
- var promise = Promise.resolve();
+RestWrite.prototype.checkRestrictedFields = async function () {
if (this.className !== '_User') {
- return promise;
+ return;
}
if (!this.auth.isMaintenance && !this.auth.isMaster && 'emailVerified' in this.data) {
const error = `Clients aren't allowed to manually update email verification.`;
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
}
+};
+
+// The non-third-party parts of User transformation
+RestWrite.prototype.transformUser = async function () {
+ var promise = Promise.resolve();
+ if (this.className !== '_User') {
+ return promise;
+ }
// Do not cleanup session if objectId is not set
if (this.query && this.objectId()) {
// If we're updating a _User object, we need to clear out the cache for that user. Find all their
// session tokens, and remove them from the cache.
- promise = new RestQuery(this.config, Auth.master(this.config), '_Session', {
- user: {
- __type: 'Pointer',
- className: '_User',
- objectId: this.objectId(),
+ const query = await RestQuery({
+ method: RestQuery.Method.find,
+ config: this.config,
+ auth: Auth.master(this.config),
+ className: '_Session',
+ runBeforeFind: false,
+ restWhere: {
+ user: {
+ __type: 'Pointer',
+ className: '_User',
+ objectId: this.objectId(),
+ },
},
- })
- .execute()
- .then(results => {
- results.results.forEach(session =>
- this.config.cacheController.user.del(session.sessionToken)
- );
- });
+ });
+ promise = query.execute().then(results => {
+ results.results.forEach(session =>
+ this.config.cacheController.user.del(session.sessionToken)
+ );
+ });
}
return promise
@@ -751,8 +798,15 @@ RestWrite.prototype._validateEmail = function () {
Object.keys(this.data.authData)[0] === 'anonymous')
) {
// We updated the email, send a new validation
- this.storage['sendVerificationEmail'] = true;
- this.config.userController.setEmailVerifyToken(this.data);
+ const { originalObject, updatedObject } = this.buildParseObjects();
+ const request = {
+ original: originalObject,
+ object: updatedObject,
+ master: this.auth.isMaster,
+ ip: this.config.ip,
+ installationId: this.auth.installationId,
+ };
+ return this.config.userController.setEmailVerifyToken(this.data, request, this.storage);
}
});
};
@@ -864,7 +918,7 @@ RestWrite.prototype._validatePasswordHistory = function () {
return Promise.resolve();
};
-RestWrite.prototype.createSessionTokenIfNeeded = function () {
+RestWrite.prototype.createSessionTokenIfNeeded = async function () {
if (this.className !== '_User') {
return;
}
@@ -876,14 +930,33 @@ RestWrite.prototype.createSessionTokenIfNeeded = function () {
if (this.auth.user && this.data.authData) {
return;
}
- if (
- !this.storage.authProvider && // signup call, with
- this.config.preventLoginWithUnverifiedEmail && // no login without verification
- this.config.verifyUserEmails
- ) {
- // verification is on
- this.storage.rejectSignup = true;
- return;
+ // If sign-up call
+ if (!this.storage.authProvider) {
+ // Create request object for verification functions
+ const { originalObject, updatedObject } = this.buildParseObjects();
+ const request = {
+ original: originalObject,
+ object: updatedObject,
+ master: this.auth.isMaster,
+ ip: this.config.ip,
+ installationId: this.auth.installationId,
+ };
+ // Get verification conditions which can be booleans or functions; the purpose of this async/await
+ // structure is to avoid unnecessarily executing subsequent functions if previous ones fail in the
+ // conditional statement below, as a developer may decide to execute expensive operations in them
+ const verifyUserEmails = async () =>
+ this.config.verifyUserEmails === true ||
+ (typeof this.config.verifyUserEmails === 'function' &&
+ (await Promise.resolve(this.config.verifyUserEmails(request))) === true);
+ const preventLoginWithUnverifiedEmail = async () =>
+ this.config.preventLoginWithUnverifiedEmail === true ||
+ (typeof this.config.preventLoginWithUnverifiedEmail === 'function' &&
+ (await Promise.resolve(this.config.preventLoginWithUnverifiedEmail(request))) === true);
+ // If verification is required
+ if ((await verifyUserEmails()) && (await preventLoginWithUnverifiedEmail())) {
+ this.storage.rejectSignup = true;
+ return;
+ }
}
return this.createSessionToken();
};
@@ -1010,7 +1083,7 @@ RestWrite.prototype.handleFollowup = function () {
if (this.storage && this.storage['sendVerificationEmail']) {
delete this.storage['sendVerificationEmail'];
// Fire and forget!
- this.config.userController.sendVerificationEmail(this.data);
+ this.config.userController.sendVerificationEmail(this.data, { auth: this.auth });
return this.handleFollowup.bind(this);
}
};
@@ -1764,20 +1837,5 @@ RestWrite.prototype._updateResponseWithData = function (response, data) {
return response;
};
-RestWrite.prototype.checkProhibitedKeywords = function (data) {
- if (this.config.requestKeywordDenylist) {
- // Scan request data for denied keywords
- for (const keyword of this.config.requestKeywordDenylist) {
- const match = Utils.objectContainsKeyValue(data, keyword.key, keyword.value);
- if (match) {
- throw new Parse.Error(
- Parse.Error.INVALID_KEY_NAME,
- `Prohibited keyword in request data: ${JSON.stringify(keyword)}.`
- );
- }
- }
- }
-};
-
export default RestWrite;
module.exports = RestWrite;
diff --git a/src/Routers/FilesRouter.js b/src/Routers/FilesRouter.js
index ed48a28a68..332cd75748 100644
--- a/src/Routers/FilesRouter.js
+++ b/src/Routers/FilesRouter.js
@@ -147,7 +147,7 @@ export class FilesRouter {
if (ext === '*') {
return true;
}
- const regex = new RegExp(fileExtensions);
+ const regex = new RegExp(ext);
if (regex.test(extension)) {
return true;
}
@@ -155,13 +155,13 @@ export class FilesRouter {
};
let extension = contentType;
if (filename && filename.includes('.')) {
- extension = filename.split('.')[1];
+ extension = filename.substring(filename.lastIndexOf('.') + 1);
} else if (contentType && contentType.includes('/')) {
extension = contentType.split('/')[1];
}
- extension = extension.split(' ').join('');
+ extension = extension?.split(' ')?.join('');
- if (!isValidExtension(extension)) {
+ if (extension && !isValidExtension(extension)) {
next(
new Parse.Error(
Parse.Error.FILE_SAVE_ERROR,
@@ -175,22 +175,13 @@ export class FilesRouter {
const base64 = req.body.toString('base64');
const file = new Parse.File(filename, { base64 }, contentType);
const { metadata = {}, tags = {} } = req.fileData || {};
- if (req.config && req.config.requestKeywordDenylist) {
+ try {
// Scan request data for denied keywords
- for (const keyword of req.config.requestKeywordDenylist) {
- const match =
- Utils.objectContainsKeyValue(metadata, keyword.key, keyword.value) ||
- Utils.objectContainsKeyValue(tags, keyword.key, keyword.value);
- if (match) {
- next(
- new Parse.Error(
- Parse.Error.INVALID_KEY_NAME,
- `Prohibited keyword in request data: ${JSON.stringify(keyword)}.`
- )
- );
- return;
- }
- }
+ Utils.checkProhibitedKeywords(config, metadata);
+ Utils.checkProhibitedKeywords(config, tags);
+ } catch (error) {
+ next(new Parse.Error(Parse.Error.INVALID_KEY_NAME, error));
+ return;
}
file.setTags(tags);
file.setMetadata(metadata);
diff --git a/src/Routers/FunctionsRouter.js b/src/Routers/FunctionsRouter.js
index da69d54e0c..eab76eeb1b 100644
--- a/src/Routers/FunctionsRouter.js
+++ b/src/Routers/FunctionsRouter.js
@@ -9,30 +9,30 @@ import { jobStatusHandler } from '../StatusHandler';
import _ from 'lodash';
import { logger } from '../logger';
-function parseObject(obj) {
+function parseObject(obj, config) {
if (Array.isArray(obj)) {
return obj.map(item => {
- return parseObject(item);
+ return parseObject(item, config);
});
} else if (obj && obj.__type == 'Date') {
return Object.assign(new Date(obj.iso), obj);
} else if (obj && obj.__type == 'File') {
return Parse.File.fromJSON(obj);
- } else if (obj && obj.__type == 'Pointer') {
+ } else if (obj && obj.__type == 'Pointer' && config.encodeParseObjectInCloudFunction) {
return Parse.Object.fromJSON({
__type: 'Pointer',
className: obj.className,
objectId: obj.objectId,
});
} else if (obj && typeof obj === 'object') {
- return parseParams(obj);
+ return parseParams(obj, config);
} else {
return obj;
}
}
-function parseParams(params) {
- return _.mapValues(params, parseObject);
+function parseParams(params, config) {
+ return _.mapValues(params, item => parseObject(item, config));
}
export class FunctionsRouter extends PromiseRouter {
@@ -66,7 +66,7 @@ export class FunctionsRouter extends PromiseRouter {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, 'Invalid job.');
}
let params = Object.assign({}, req.body, req.query);
- params = parseParams(params);
+ params = parseParams(params, req.config);
const request = {
params: params,
log: req.config.loggerController,
@@ -126,7 +126,7 @@ export class FunctionsRouter extends PromiseRouter {
throw new Parse.Error(Parse.Error.SCRIPT_FAILED, `Invalid function: "${functionName}"`);
}
let params = Object.assign({}, req.body, req.query);
- params = parseParams(params);
+ params = parseParams(params, req.config);
const request = {
params: params,
master: req.auth && req.auth.isMaster,
diff --git a/src/Routers/PagesRouter.js b/src/Routers/PagesRouter.js
index 5d5a1467a7..79a487b6e4 100644
--- a/src/Routers/PagesRouter.js
+++ b/src/Routers/PagesRouter.js
@@ -125,7 +125,7 @@ export class PagesRouter extends PromiseRouter {
const userController = config.userController;
- return userController.resendVerificationEmail(username).then(
+ return userController.resendVerificationEmail(username, req).then(
() => {
return this.goToPage(req, pages.emailVerificationSendSuccess);
},
diff --git a/src/Routers/PublicAPIRouter.js b/src/Routers/PublicAPIRouter.js
index 5009ee7d22..ddef76a5b8 100644
--- a/src/Routers/PublicAPIRouter.js
+++ b/src/Routers/PublicAPIRouter.js
@@ -63,7 +63,7 @@ export class PublicAPIRouter extends PromiseRouter {
const userController = config.userController;
- return userController.resendVerificationEmail(username).then(
+ return userController.resendVerificationEmail(username, req).then(
() => {
return Promise.resolve({
status: 302,
diff --git a/src/Routers/UsersRouter.js b/src/Routers/UsersRouter.js
index feca46e802..9fb633049b 100644
--- a/src/Routers/UsersRouter.js
+++ b/src/Routers/UsersRouter.js
@@ -126,7 +126,7 @@ export class UsersRouter extends ClassesRouter {
const accountLockoutPolicy = new AccountLockout(user, req.config);
return accountLockoutPolicy.handleLoginAttempt(isValidPassword);
})
- .then(() => {
+ .then(async () => {
if (!isValidPassword) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
}
@@ -137,9 +137,28 @@ export class UsersRouter extends ClassesRouter {
if (!req.auth.isMaster && user.ACL && Object.keys(user.ACL).length == 0) {
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
}
+ // Create request object for verification functions
+ const request = {
+ master: req.auth.isMaster,
+ ip: req.config.ip,
+ installationId: req.auth.installationId,
+ object: Parse.User.fromJSON(Object.assign({ className: '_User' }, user)),
+ };
+ // Get verification conditions which can be booleans or functions; the purpose of this async/await
+ // structure is to avoid unnecessarily executing subsequent functions if previous ones fail in the
+ // conditional statement below, as a developer may decide to execute expensive operations in them
+ const verifyUserEmails = async () =>
+ req.config.verifyUserEmails === true ||
+ (typeof req.config.verifyUserEmails === 'function' &&
+ (await Promise.resolve(req.config.verifyUserEmails(request))) === true);
+ const preventLoginWithUnverifiedEmail = async () =>
+ req.config.preventLoginWithUnverifiedEmail === true ||
+ (typeof req.config.preventLoginWithUnverifiedEmail === 'function' &&
+ (await Promise.resolve(req.config.preventLoginWithUnverifiedEmail(request))) ===
+ true);
if (
- req.config.verifyUserEmails &&
- req.config.preventLoginWithUnverifiedEmail &&
+ (await verifyUserEmails()) &&
+ (await preventLoginWithUnverifiedEmail()) &&
!user.emailVerified
) {
throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.');
@@ -189,7 +208,12 @@ export class UsersRouter extends ClassesRouter {
const user = await this._authenticateUserFromRequest(req);
const authData = req.body && req.body.authData;
// Check if user has provided their required auth providers
- Auth.checkIfUserHasProvidedConfiguredProvidersForLogin(authData, user.authData, req.config);
+ Auth.checkIfUserHasProvidedConfiguredProvidersForLogin(
+ req,
+ authData,
+ user.authData,
+ req.config
+ );
let authDataResponse;
let validatedAuthData;
@@ -254,7 +278,8 @@ export class UsersRouter extends ClassesRouter {
req.auth,
Parse.User.fromJSON(Object.assign({ className: '_User' }, user)),
null,
- req.config
+ req.config,
+ req.info.context
);
// If we have some new validated authData update directly
@@ -286,7 +311,8 @@ export class UsersRouter extends ClassesRouter {
{ ...req.auth, user: afterLoginUser },
afterLoginUser,
null,
- req.config
+ req.config,
+ req.info.context
);
if (authDataResponse) {
@@ -447,7 +473,7 @@ export class UsersRouter extends ClassesRouter {
}
}
- handleVerificationEmailRequest(req) {
+ async handleVerificationEmailRequest(req) {
this._throwOnBadEmailConfig(req);
const { email } = req.body;
@@ -461,25 +487,35 @@ export class UsersRouter extends ClassesRouter {
);
}
- return req.config.database.find('_User', { email: email }).then(results => {
- if (!results.length || results.length < 1) {
- throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, `No user found with email ${email}`);
- }
- const user = results[0];
+ const results = await req.config.database.find(
+ '_User',
+ { email: email },
+ {},
+ Auth.maintenance(req.config)
+ );
+ if (!results.length || results.length < 1) {
+ throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, `No user found with email ${email}`);
+ }
+ const user = results[0];
- // remove password field, messes with saving on postgres
- delete user.password;
+ // remove password field, messes with saving on postgres
+ delete user.password;
- if (user.emailVerified) {
- throw new Parse.Error(Parse.Error.OTHER_CAUSE, `Email ${email} is already verified.`);
- }
+ if (user.emailVerified) {
+ throw new Parse.Error(Parse.Error.OTHER_CAUSE, `Email ${email} is already verified.`);
+ }
- const userController = req.config.userController;
- return userController.regenerateEmailVerifyToken(user).then(() => {
- userController.sendVerificationEmail(user);
- return { response: {} };
- });
- });
+ const userController = req.config.userController;
+ const send = await userController.regenerateEmailVerifyToken(
+ user,
+ req.auth.isMaster,
+ req.auth.installationId,
+ req.ip
+ );
+ if (send) {
+ userController.sendVerificationEmail(user, req);
+ }
+ return { response: {} };
}
async handleChallenge(req) {
diff --git a/src/SharedRest.js b/src/SharedRest.js
new file mode 100644
index 0000000000..0b4a07c320
--- /dev/null
+++ b/src/SharedRest.js
@@ -0,0 +1,37 @@
+const classesWithMasterOnlyAccess = [
+ '_JobStatus',
+ '_PushStatus',
+ '_Hooks',
+ '_GlobalConfig',
+ '_JobSchedule',
+ '_Idempotency',
+];
+// Disallowing access to the _Role collection except by master key
+function enforceRoleSecurity(method, className, auth) {
+ if (className === '_Installation' && !auth.isMaster && !auth.isMaintenance) {
+ if (method === 'delete' || method === 'find') {
+ const error = `Clients aren't allowed to perform the ${method} operation on the installation collection.`;
+ throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
+ }
+ }
+
+ //all volatileClasses are masterKey only
+ if (
+ classesWithMasterOnlyAccess.indexOf(className) >= 0 &&
+ !auth.isMaster &&
+ !auth.isMaintenance
+ ) {
+ const error = `Clients aren't allowed to perform the ${method} operation on the ${className} collection.`;
+ throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
+ }
+
+ // readOnly masterKey is not allowed
+ if (auth.isReadOnly && (method === 'delete' || method === 'create' || method === 'update')) {
+ const error = `read-only masterKey isn't allowed to perform the ${method} operation.`;
+ throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
+ }
+}
+
+module.exports = {
+ enforceRoleSecurity,
+};
diff --git a/src/Utils.js b/src/Utils.js
index d5a255a5ca..efeae58f3f 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -358,6 +358,18 @@ class Utils {
}
return false;
}
+
+ static checkProhibitedKeywords(config, data) {
+ if (config?.requestKeywordDenylist) {
+ // Scan request data for denied keywords
+ for (const keyword of config.requestKeywordDenylist) {
+ const match = Utils.objectContainsKeyValue(data, keyword.key, keyword.value);
+ if (match) {
+ throw `Prohibited keyword in request data: ${JSON.stringify(keyword)}.`;
+ }
+ }
+ }
+ }
}
module.exports = Utils;
diff --git a/src/cli/utils/runner.js b/src/cli/utils/runner.js
index d74a7a5928..0cbbb42e58 100644
--- a/src/cli/utils/runner.js
+++ b/src/cli/utils/runner.js
@@ -1,13 +1,15 @@
import program from './commander';
function logStartupOptions(options) {
+ if (!options.verbose) {
+ return;
+ }
+ // Keys that may include sensitive information that will be redacted in logs
+ const keysToRedact = ['databaseURI', 'masterKey', 'maintenanceKey', 'push'];
for (const key in options) {
let value = options[key];
- if (key == 'masterKey') {
- value = '***REDACTED***';
- }
- if (key == 'push' && options.verbose != true) {
- value = '***REDACTED***';
+ if (keysToRedact.includes(key)) {
+ value = '';
}
if (typeof value === 'object') {
try {
diff --git a/src/index.js b/src/index.js
index dcfe9b4c7e..0c9069d6b5 100644
--- a/src/index.js
+++ b/src/index.js
@@ -7,7 +7,6 @@ import LRUCacheAdapter from './Adapters/Cache/LRUCache.js';
import * as TestUtils from './TestUtils';
import * as SchemaMigrations from './SchemaMigrations/Migrations';
import AuthAdapter from './Adapters/Auth/AuthAdapter';
-
import { useExternal } from './deprecated';
import { getLogger } from './logger';
import { PushWorker } from './Push/PushWorker';
diff --git a/src/middlewares.js b/src/middlewares.js
index a7e309b0cc..d4edb37760 100644
--- a/src/middlewares.js
+++ b/src/middlewares.js
@@ -10,9 +10,9 @@ import PostgresStorageAdapter from './Adapters/Storage/Postgres/PostgresStorageA
import rateLimit from 'express-rate-limit';
import { RateLimitOptions } from './Options/Definitions';
import { pathToRegexp } from 'path-to-regexp';
-import ipRangeCheck from 'ip-range-check';
import RedisStore from 'rate-limit-redis';
import { createClient } from 'redis';
+import { BlockList, isIPv4 } from 'net';
export const DEFAULT_ALLOWED_HEADERS =
'X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-Parse-Request-Id, Content-Type, Pragma, Cache-Control';
@@ -23,6 +23,46 @@ const getMountForRequest = function (req) {
return req.protocol + '://' + req.get('host') + mountPath;
};
+const getBlockList = (ipRangeList, store) => {
+ if (store.get('blockList')) return store.get('blockList');
+ const blockList = new BlockList();
+ ipRangeList.forEach(fullIp => {
+ if (fullIp === '::/0' || fullIp === '::') {
+ store.set('allowAllIpv6', true);
+ return;
+ }
+ if (fullIp === '0.0.0.0/0' || fullIp === '0.0.0.0') {
+ store.set('allowAllIpv4', true);
+ return;
+ }
+ const [ip, mask] = fullIp.split('/');
+ if (!mask) {
+ blockList.addAddress(ip, isIPv4(ip) ? 'ipv4' : 'ipv6');
+ } else {
+ blockList.addSubnet(ip, Number(mask), isIPv4(ip) ? 'ipv4' : 'ipv6');
+ }
+ });
+ store.set('blockList', blockList);
+ return blockList;
+};
+
+export const checkIp = (ip, ipRangeList, store) => {
+ const incomingIpIsV4 = isIPv4(ip);
+ const blockList = getBlockList(ipRangeList, store);
+
+ if (store.get(ip)) return true;
+ if (store.get('allowAllIpv4') && incomingIpIsV4) return true;
+ if (store.get('allowAllIpv6') && !incomingIpIsV4) return true;
+ const result = blockList.check(ip, incomingIpIsV4 ? 'ipv4' : 'ipv6');
+
+ // If the ip is in the list, we store the result in the store
+ // so we have a optimized path for the next request
+ if (ipRangeList.includes(ip) && result) {
+ store.set(ip, result);
+ }
+ return result;
+};
+
// Checks that the request is authorized for this app and checks user
// auth too.
// The bodyparser should run before this middleware.
@@ -183,7 +223,7 @@ export function handleParseHeaders(req, res, next) {
const isMaintenance =
req.config.maintenanceKey && info.maintenanceKey === req.config.maintenanceKey;
if (isMaintenance) {
- if (ipRangeCheck(clientIp, req.config.maintenanceKeyIps || [])) {
+ if (checkIp(clientIp, req.config.maintenanceKeyIps || [], req.config.maintenanceKeyIpsStore)) {
req.auth = new auth.Auth({
config: req.config,
installationId: info.installationId,
@@ -199,7 +239,8 @@ export function handleParseHeaders(req, res, next) {
}
let isMaster = info.masterKey === req.config.masterKey;
- if (isMaster && !ipRangeCheck(clientIp, req.config.masterKeyIps || [])) {
+
+ if (isMaster && !checkIp(clientIp, req.config.masterKeyIps || [], req.config.masterKeyIpsStore)) {
const log = req.config?.loggerController || defaultLogger;
log.error(
`Request using master key rejected as the request IP address '${clientIp}' is not set in Parse Server option 'masterKeyIps'.`
@@ -301,7 +342,7 @@ const handleRateLimit = async (req, res, next) => {
export const handleParseSession = async (req, res, next) => {
try {
const info = req.info;
- if (req.auth) {
+ if (req.auth || req.url === '/sessions/me') {
next();
return;
}
diff --git a/src/rest.js b/src/rest.js
index e1e53668a6..1f9dbacb73 100644
--- a/src/rest.js
+++ b/src/rest.js
@@ -12,6 +12,7 @@ var Parse = require('parse/node').Parse;
var RestQuery = require('./RestQuery');
var RestWrite = require('./RestWrite');
var triggers = require('./triggers');
+const { enforceRoleSecurity } = require('./SharedRest');
function checkTriggers(className, config, types) {
return types.some(triggerType => {
@@ -24,65 +25,34 @@ function checkLiveQuery(className, config) {
}
// Returns a promise for an object with optional keys 'results' and 'count'.
-function find(config, auth, className, restWhere, restOptions, clientSDK, context) {
- enforceRoleSecurity('find', className, auth);
- return triggers
- .maybeRunQueryTrigger(
- triggers.Types.beforeFind,
- className,
- restWhere,
- restOptions,
- config,
- auth,
- context
- )
- .then(result => {
- restWhere = result.restWhere || restWhere;
- restOptions = result.restOptions || restOptions;
- const query = new RestQuery(
- config,
- auth,
- className,
- restWhere,
- restOptions,
- clientSDK,
- true,
- context
- );
- return query.execute();
- });
-}
+const find = async (config, auth, className, restWhere, restOptions, clientSDK, context) => {
+ const query = await RestQuery({
+ method: RestQuery.Method.find,
+ config,
+ auth,
+ className,
+ restWhere,
+ restOptions,
+ clientSDK,
+ context,
+ });
+ return query.execute();
+};
// get is just like find but only queries an objectId.
-const get = (config, auth, className, objectId, restOptions, clientSDK, context) => {
+const get = async (config, auth, className, objectId, restOptions, clientSDK, context) => {
var restWhere = { objectId };
- enforceRoleSecurity('get', className, auth);
- return triggers
- .maybeRunQueryTrigger(
- triggers.Types.beforeFind,
- className,
- restWhere,
- restOptions,
- config,
- auth,
- context,
- true
- )
- .then(result => {
- restWhere = result.restWhere || restWhere;
- restOptions = result.restOptions || restOptions;
- const query = new RestQuery(
- config,
- auth,
- className,
- restWhere,
- restOptions,
- clientSDK,
- true,
- context
- );
- return query.execute();
- });
+ const query = await RestQuery({
+ method: RestQuery.Method.get,
+ config,
+ auth,
+ className,
+ restWhere,
+ restOptions,
+ clientSDK,
+ context,
+ });
+ return query.execute();
};
// Returns a promise that doesn't resolve to any useful value.
@@ -101,35 +71,40 @@ function del(config, auth, className, objectId, context) {
let schemaController;
return Promise.resolve()
- .then(() => {
+ .then(async () => {
const hasTriggers = checkTriggers(className, config, ['beforeDelete', 'afterDelete']);
const hasLiveQuery = checkLiveQuery(className, config);
if (hasTriggers || hasLiveQuery || className == '_Session') {
- return new RestQuery(config, auth, className, { objectId })
- .execute({ op: 'delete' })
- .then(response => {
- if (response && response.results && response.results.length) {
- const firstResult = response.results[0];
- firstResult.className = className;
- if (className === '_Session' && !auth.isMaster && !auth.isMaintenance) {
- if (!auth.user || firstResult.user.objectId !== auth.user.id) {
- throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token');
- }
+ const query = await RestQuery({
+ method: RestQuery.Method.get,
+ config,
+ auth,
+ className,
+ restWhere: { objectId },
+ });
+ return query.execute({ op: 'delete' }).then(response => {
+ if (response && response.results && response.results.length) {
+ const firstResult = response.results[0];
+ firstResult.className = className;
+ if (className === '_Session' && !auth.isMaster && !auth.isMaintenance) {
+ if (!auth.user || firstResult.user.objectId !== auth.user.id) {
+ throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token');
}
- var cacheAdapter = config.cacheController;
- cacheAdapter.user.del(firstResult.sessionToken);
- inflatedObject = Parse.Object.fromJSON(firstResult);
- return triggers.maybeRunTrigger(
- triggers.Types.beforeDelete,
- auth,
- inflatedObject,
- null,
- config,
- context
- );
}
- throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found for delete.');
- });
+ var cacheAdapter = config.cacheController;
+ cacheAdapter.user.del(firstResult.sessionToken);
+ inflatedObject = Parse.Object.fromJSON(firstResult);
+ return triggers.maybeRunTrigger(
+ triggers.Types.beforeDelete,
+ auth,
+ inflatedObject,
+ null,
+ config,
+ context
+ );
+ }
+ throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found for delete.');
+ });
}
return Promise.resolve({});
})
@@ -193,21 +168,22 @@ function update(config, auth, className, restWhere, restObject, clientSDK, conte
enforceRoleSecurity('update', className, auth);
return Promise.resolve()
- .then(() => {
+ .then(async () => {
const hasTriggers = checkTriggers(className, config, ['beforeSave', 'afterSave']);
const hasLiveQuery = checkLiveQuery(className, config);
if (hasTriggers || hasLiveQuery) {
// Do not use find, as it runs the before finds
- return new RestQuery(
+ const query = await RestQuery({
+ method: RestQuery.Method.get,
config,
auth,
className,
restWhere,
- undefined,
- undefined,
- false,
- context
- ).execute({
+ runAfterFind: false,
+ runBeforeFind: false,
+ context,
+ });
+ return query.execute({
op: 'update',
});
}
@@ -248,40 +224,6 @@ function handleSessionMissingError(error, className, auth) {
throw error;
}
-const classesWithMasterOnlyAccess = [
- '_JobStatus',
- '_PushStatus',
- '_Hooks',
- '_GlobalConfig',
- '_JobSchedule',
- '_Idempotency',
-];
-// Disallowing access to the _Role collection except by master key
-function enforceRoleSecurity(method, className, auth) {
- if (className === '_Installation' && !auth.isMaster && !auth.isMaintenance) {
- if (method === 'delete' || method === 'find') {
- const error = `Clients aren't allowed to perform the ${method} operation on the installation collection.`;
- throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
- }
- }
-
- //all volatileClasses are masterKey only
- if (
- classesWithMasterOnlyAccess.indexOf(className) >= 0 &&
- !auth.isMaster &&
- !auth.isMaintenance
- ) {
- const error = `Clients aren't allowed to perform the ${method} operation on the ${className} collection.`;
- throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
- }
-
- // readOnly masterKey is not allowed
- if (auth.isReadOnly && (method === 'delete' || method === 'create' || method === 'update')) {
- const error = `read-only masterKey isn't allowed to perform the ${method} operation.`;
- throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
- }
-}
-
module.exports = {
create,
del,
diff --git a/src/triggers.js b/src/triggers.js
index b5f11435df..5c4755af54 100644
--- a/src/triggers.js
+++ b/src/triggers.js
@@ -270,6 +270,8 @@ export function getRequestObject(
triggerType === Types.afterSave ||
triggerType === Types.beforeDelete ||
triggerType === Types.afterDelete ||
+ triggerType === Types.beforeLogin ||
+ triggerType === Types.afterLogin ||
triggerType === Types.afterFind
) {
// Set a copy of the context on the request object.