diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dc27805e5f..756e4e2419 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,10 +1,12 @@
name: ci
on:
push:
- branches: [ release*, alpha, beta ]
+ branches: [ release, alpha, beta, next-major, 'release-[0-9]+.x.x' ]
pull_request:
branches:
- '**'
+ paths-ignore:
+ - '**/**.md'
env:
NODE_VERSION: 19.3.0
PARSE_SERVER_TEST_TIMEOUT: 20000
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 47c286c8ce..3d70f6aa63 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,6 +11,10 @@
- [Review Feedback](#review-feedback)
- [Merge Readiness](#merge-readiness)
- [Review Validity](#review-validity)
+ - [Code Ownership](#code-ownership)
+ - [Access Permissions](#access-permissions)
+ - [New Private Repository](#new-private-repository)
+ - [New Public Repository](#new-public-repository)
- [Environment Setup](#environment-setup)
- [Recommended Tools](#recommended-tools)
- [Setting up your local machine](#setting-up-your-local-machine)
@@ -34,6 +38,8 @@
- [Breaking Change](#breaking-change-1)
- [Reverting](#reverting)
- [Security Vulnerability](#security-vulnerability)
+ - [Local Testing](#local-testing)
+ - [Merging](#merging-1)
- [Releasing](#releasing)
- [General Considerations](#general-considerations)
- [Major Release / Long-Term-Support](#major-release--long-term-support)
@@ -143,6 +149,30 @@ It's contrary to an open, collaborative environment to expect others to be invol
Your arguments must focus on the issue, not on your assumption of someone else's personal experience. We will take immediate and appropriate action in case of personal attacks, regardless of your previous contributions. Personal attacks are not permissible. If you became a victim of personal attacks, you can privately [report](https://docs.github.com/en/communities/maintaining-your-safety-on-github/reporting-abuse-or-spam) the GitHub comment to the Parse Platform PMC.
+### Code Ownership
+
+> *Can I open a new pull request based on another author's pull request?*
+
+If your pull request contains work from someone else then you are required to get their permission to use their work in your pull request. Please make sure to observe the [license](LICENSE) for more details. In addition, as an appreciative gesture you should clearly mention that your pull request is based on another pull request with a link in the top-most comment of your pull request. To avoid this issue we encourage contributors to collaborate on a single pull request to preserve the commit history and clearly identify each author's contribution. To do so, you can review the other author's pull request and submit your code suggestions, or ask the original author to grant you write access to their repository to also be able to make commits directly to their pull request.
+
+### Access Permissions
+
+> *Can I get write access to the repository to make changes faster?*
+
+Keeping our products safe and secure is one of your top priorities. Our security policy mandates that write access to repositories is only provided to as few people as necessary. All usual contributions can be made via public pull requests. If you think you need write access, contact the repository team and explain in detail what the constraint is that you are trying to overcome. We want to make contributing for you as easy as possible. If there are any bottlenecks that are slowing you down we are happy to receive your feedback to see where we can improve.
+
+### New Private Repository
+
+> *Can I get a new private repository within the Parse Platform organization to work on some stuff?*
+
+Private repositories are not provided unless there is a significant constraint or requirement that makes it necessary. For example, when collaborating on fixing a security vulnerability we provide private repositories to allow collaborators to share sensitive information within a select group.
+
+### New Public Repository
+
+> *Can I get a new public repository within the Parse Platform organization to work on some stuff?*
+
+First of all, we appreciate your contribution. In rare cases, where we consider it beneficial to the advancement of the repository, a new public repository for a specific purpose may be provided, for example for increased visibility or to provide the organization's GitHub ressources. In other cases, we encourage you to start your contribution in a personal repository of your own GitHub account, and later transfer it to the Parse Platform organization. We will be happy to assist you in the repository transfer.
+
## Environment Setup
### Recommended Tools
@@ -496,7 +526,6 @@ The following changes are done in the `alpha` branch, before publishing the last
- Make sure all [deprecations](https://github.com/parse-community/parse-server/blob/alpha/DEPRECATIONS.md) are reflected in code, old code is removed and the deprecations table is updated.
- Add the future LTS branch `release-#.x.x` to the branch list in [release.config.js](https://github.com/parse-community/parse-server/blob/alpha/release.config.js) so that the branch will later be recognized for release automation.
-
### Publishing Release (forward-merge):
1. Create new temporary branch `build` on branch `beta`.
@@ -547,6 +576,7 @@ The following changes are done in the `alpha` branch, before publishing the last
1. Create LTS branch `release-#.x.x` off the latest version tag on `release` branch.
2. Create temporary branch `build-release` off branch `beta` and create a pull request with `release` as the base branch.
3. Merge branch `build-release` into `release`. Given that there will be breaking changes, a new major release will be created. In the unlikely case that there have been no breaking changes between the previous major release and the upcoming release, a major version increment has to be triggered manually. See the docs of the release automation framework for how to do that.
+4. Add newly created LTS branch `release-#.x.x` from step 1 to [Snyk](https://snyk.io) so that Snyk opens pull requests for the LTS branch; remove previously existing LTS branch `release-#.x.x` from Snyk.
## Versioning
diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md
index a2b4c268d6..b9b1925b78 100644
--- a/changelogs/CHANGELOG_alpha.md
+++ b/changelogs/CHANGELOG_alpha.md
@@ -1,3 +1,91 @@
+# [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)
+
+
+### Features
+
+* 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))
+
+# [6.1.0-alpha.19](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.18...6.1.0-alpha.19) (2023-06-08)
+
+
+### Bug Fixes
+
+* 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))
+
+# [6.1.0-alpha.18](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.17...6.1.0-alpha.18) (2023-06-08)
+
+
+### Features
+
+* 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))
+
+# [6.1.0-alpha.17](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.16...6.1.0-alpha.17) (2023-06-07)
+
+
+### Features
+
+* 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))
+
+# [6.1.0-alpha.16](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.15...6.1.0-alpha.16) (2023-05-28)
+
+
+### Reverts
+
+* fix: Inaccurate table total row count for PostgreSQL ([6722110](https://github.com/parse-community/parse-server/commit/6722110f203bc5fdcaa68cdf091cf9e7b48d1cff))
+
+# [6.1.0-alpha.15](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.14...6.1.0-alpha.15) (2023-05-28)
+
+
+### Bug Fixes
+
+* 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))
+
+# [6.1.0-alpha.14](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.13...6.1.0-alpha.14) (2023-05-27)
+
+
+### Bug Fixes
+
+* 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
+
+* 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))
+
+# [6.1.0-alpha.13](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.12...6.1.0-alpha.13) (2023-05-25)
+
+
+### Bug Fixes
+
+* 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))
+
+# [6.1.0-alpha.12](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.11...6.1.0-alpha.12) (2023-05-19)
+
+
+### Bug Fixes
+
+* 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))
+
+# [6.1.0-alpha.11](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.10...6.1.0-alpha.11) (2023-05-17)
+
+
+### 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))
+
+# [6.1.0-alpha.10](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.9...6.1.0-alpha.10) (2023-05-12)
+
+
+### 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))
+
+# [6.1.0-alpha.9](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.8...6.1.0-alpha.9) (2023-05-09)
+
+
+### Features
+
+* 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))
+
# [6.1.0-alpha.8](https://github.com/parse-community/parse-server/compare/6.1.0-alpha.7...6.1.0-alpha.8) (2023-05-01)
diff --git a/ci/definitionsCheck.js b/ci/definitionsCheck.js
index 735d9c0b9d..e73473a984 100644
--- a/ci/definitionsCheck.js
+++ b/ci/definitionsCheck.js
@@ -1,27 +1,14 @@
const fs = require('fs').promises;
const { exec } = require('child_process');
const core = require('@actions/core');
-const { nextTick } = require('process');
-const { AbortController } = require("node-abort-controller");
+const util = require('util');
(async () => {
const [currentDefinitions, currentDocs] = await Promise.all([
fs.readFile('./src/Options/Definitions.js', 'utf8'),
fs.readFile('./src/Options/docs.js', 'utf8'),
]);
- exec('npm run definitions');
- const ac = new AbortController();
- const { signal } = ac;
- const watcher = fs.watch('./src/Options/docs.js', {signal});
- let i = 0;
- // eslint-disable-next-line
- for await (const _ of watcher) {
- i++;
- if (i === 3) {
- ac.abort();
- break;
- }
- }
- await new Promise(resolve => nextTick(resolve));
+ const execute = util.promisify(exec);
+ await execute('npm run definitions');
const [newDefinitions, newDocs] = await Promise.all([
fs.readFile('./src/Options/Definitions.js', 'utf8'),
fs.readFile('./src/Options/docs.js', 'utf8'),
diff --git a/jsdoc-conf.json b/jsdoc-conf.json
index efbaa0a37c..4a1e5de846 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": "
",
+ "title": "Parse Server",
"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 c1d20e3b7d..39a7a982ae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,29 +1,29 @@
{
"name": "parse-server",
- "version": "6.2.0",
+ "version": "6.1.0-alpha.20",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "parse-server",
- "version": "6.2.0",
+ "version": "6.1.0-alpha.20",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
- "@babel/eslint-parser": "7.19.1",
- "@graphql-tools/merge": "8.3.6",
+ "@babel/eslint-parser": "7.21.8",
+ "@graphql-tools/merge": "8.4.1",
"@graphql-tools/schema": "9.0.4",
"@graphql-tools/utils": "8.12.0",
"@graphql-yoga/node": "2.6.0",
"@parse/fs-files-adapter": "1.2.2",
- "@parse/push-adapter": "4.1.2",
+ "@parse/push-adapter": "4.1.3",
"bcryptjs": "2.4.3",
- "body-parser": "1.20.1",
- "commander": "5.1.0",
+ "body-parser": "1.20.2",
+ "commander": "10.0.1",
"cors": "2.8.5",
"deepcopy": "2.1.0",
"express": "4.18.2",
- "express-rate-limit": "6.6.0",
+ "express-rate-limit": "6.7.0",
"follow-redirects": "1.15.2",
"graphql": "16.6.0",
"graphql-list-fields": "2.0.2",
@@ -35,24 +35,24 @@
"jwks-rsa": "2.1.5",
"ldapjs": "2.3.3",
"lodash": "4.17.21",
- "lru-cache": "7.12.0",
+ "lru-cache": "9.1.1",
"mime": "3.0.0",
"mongodb": "4.10.0",
"mustache": "4.2.0",
- "parse": "4.0.1",
- "path-to-regexp": "0.1.7",
+ "parse": "4.1.0",
+ "path-to-regexp": "6.2.1",
"pg-monitor": "2.0.0",
- "pg-promise": "11.3.0",
+ "pg-promise": "11.5.0",
"pluralize": "8.0.0",
- "rate-limit-redis": "3.0.1",
- "redis": "4.0.6",
- "semver": "7.3.8",
+ "rate-limit-redis": "3.0.2",
+ "redis": "4.6.6",
+ "semver": "^7.5.1",
"subscriptions-transport-ws": "0.11.0",
"tv4": "1.3.0",
"uuid": "9.0.0",
- "winston": "3.8.1",
+ "winston": "3.8.2",
"winston-daily-rotate-file": "4.7.1",
- "ws": "8.9.0"
+ "ws": "8.13.0"
},
"bin": {
"parse-server": "bin/parse-server"
@@ -75,7 +75,7 @@
"all-node-versions": "11.3.0",
"apollo-upload-client": "17.0.0",
"bcrypt-nodejs": "0.0.3",
- "clean-jsdoc-theme": "^4.2.7",
+ "clean-jsdoc-theme": "4.2.7",
"cross-env": "7.0.2",
"deep-diff": "1.0.2",
"eslint": "8.26.0",
@@ -299,9 +299,9 @@
}
},
"node_modules/@babel/eslint-parser": {
- "version": "7.19.1",
- "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz",
- "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==",
+ "version": "7.21.8",
+ "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.8.tgz",
+ "integrity": "sha512-HLhI+2q+BP3sf78mFUZNCGc10KEmoUqtUT1OCdMZsN+qr4qFeLUod62/zAnF3jNQstwyasDkZnVXwfK2Bml7MQ==",
"dependencies": {
"@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
"eslint-visitor-keys": "^2.1.0",
@@ -1775,6 +1775,7 @@
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz",
"integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==",
+ "dev": true,
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
@@ -1783,12 +1784,12 @@
}
},
"node_modules/@babel/runtime-corejs3": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz",
- "integrity": "sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==",
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz",
+ "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==",
"dependencies": {
- "core-js-pure": "^3.20.2",
- "regenerator-runtime": "^0.13.4"
+ "core-js-pure": "^3.25.1",
+ "regenerator-runtime": "^0.13.11"
},
"engines": {
"node": ">=6.9.0"
@@ -1982,11 +1983,23 @@
}
},
"node_modules/@graphql-tools/merge": {
- "version": "8.3.6",
- "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.3.6.tgz",
- "integrity": "sha512-uUBokxXi89bj08P+iCvQk3Vew4vcfL5ZM6NTylWi8PIpoq4r5nJ625bRuN8h2uubEdRiH8ntN9M4xkd/j7AybQ==",
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.1.tgz",
+ "integrity": "sha512-hssnPpZ818mxgl5+GfyOOSnnflAxiaTn1A1AojZcIbh4J52sS1Q0gSuBR5VrnUDjuxiqoCotpXdAQl+K+U6KLQ==",
"dependencies": {
- "@graphql-tools/utils": "8.12.0",
+ "@graphql-tools/utils": "^9.2.1",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+ }
+ },
+ "node_modules/@graphql-tools/merge/node_modules/@graphql-tools/utils": {
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz",
+ "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==",
+ "dependencies": {
+ "@graphql-typed-document-node/core": "^3.1.1",
"tslib": "^2.4.0"
},
"peerDependencies": {
@@ -2007,6 +2020,18 @@
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
+ "node_modules/@graphql-tools/schema/node_modules/@graphql-tools/merge": {
+ "version": "8.3.6",
+ "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.3.6.tgz",
+ "integrity": "sha512-uUBokxXi89bj08P+iCvQk3Vew4vcfL5ZM6NTylWi8PIpoq4r5nJ625bRuN8h2uubEdRiH8ntN9M4xkd/j7AybQ==",
+ "dependencies": {
+ "@graphql-tools/utils": "8.12.0",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+ }
+ },
"node_modules/@graphql-tools/utils": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.12.0.tgz",
@@ -2314,60 +2339,6 @@
"eslint-scope": "5.1.1"
}
},
- "node_modules/@node-redis/bloom": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@node-redis/bloom/-/bloom-1.0.1.tgz",
- "integrity": "sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw==",
- "peerDependencies": {
- "@node-redis/client": "^1.0.0"
- }
- },
- "node_modules/@node-redis/client": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@node-redis/client/-/client-1.0.5.tgz",
- "integrity": "sha512-ESZ3bd1f+od62h4MaBLKum+klVJfA4wAeLHcVQBkoXa1l0viFesOWnakLQqKg+UyrlJhZmXJWtu0Y9v7iTMrig==",
- "dependencies": {
- "cluster-key-slot": "1.1.0",
- "generic-pool": "3.8.2",
- "redis-parser": "3.0.0",
- "yallist": "4.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@node-redis/graph": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@node-redis/graph/-/graph-1.0.0.tgz",
- "integrity": "sha512-mRSo8jEGC0cf+Rm7q8mWMKKKqkn6EAnA9IA2S3JvUv/gaWW/73vil7GLNwion2ihTptAm05I9LkepzfIXUKX5g==",
- "peerDependencies": {
- "@node-redis/client": "^1.0.0"
- }
- },
- "node_modules/@node-redis/json": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@node-redis/json/-/json-1.0.2.tgz",
- "integrity": "sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g==",
- "peerDependencies": {
- "@node-redis/client": "^1.0.0"
- }
- },
- "node_modules/@node-redis/search": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@node-redis/search/-/search-1.0.5.tgz",
- "integrity": "sha512-MCOL8iCKq4v+3HgEQv8zGlSkZyXSXtERgrAJ4TSryIG/eLFy84b57KmNNa/V7M1Q2Wd2hgn2nPCGNcQtk1R1OQ==",
- "peerDependencies": {
- "@node-redis/client": "^1.0.0"
- }
- },
- "node_modules/@node-redis/time-series": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@node-redis/time-series/-/time-series-1.0.2.tgz",
- "integrity": "sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA==",
- "peerDependencies": {
- "@node-redis/client": "^1.0.0"
- }
- },
"node_modules/@node-rs/bcrypt": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.1.0.tgz",
@@ -2839,9 +2810,9 @@
}
},
"node_modules/@parse/push-adapter": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.2.tgz",
- "integrity": "sha512-034vZTlAzgdfefIY4+Q4j8DHS/VwUAIVoh1JeRkHNfyQmUQ++uKbQbUQdJ/nf11HHS69kwLENs13BmhlHMpyHQ==",
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.3.tgz",
+ "integrity": "sha512-Oy53ag7DpUva5dUWwP6tNEsrxv2xU9QIk+rb84q1DIm1qVgo2yl4oXcZ3FPG2Ks/NYURbv4w+z9oaSgVfyBRfQ==",
"dependencies": {
"@parse/node-apn": "5.1.3",
"@parse/node-gcm": "1.0.2",
@@ -2926,6 +2897,59 @@
}
}
},
+ "node_modules/@redis/bloom": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
+ "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/client": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz",
+ "integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==",
+ "dependencies": {
+ "cluster-key-slot": "1.1.2",
+ "generic-pool": "3.9.0",
+ "yallist": "4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@redis/graph": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz",
+ "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/json": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz",
+ "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/search": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz",
+ "integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
+ "node_modules/@redis/time-series": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz",
+ "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==",
+ "peerDependencies": {
+ "@redis/client": "^1.0.0"
+ }
+ },
"node_modules/@repeaterjs/repeater": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz",
@@ -4067,9 +4091,9 @@
}
},
"node_modules/assert-options": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.0.tgz",
- "integrity": "sha512-qSELrEaEz4sGwTs4Qh+swQkjiHAysC4rot21+jzXU86dJzNG+FDqBzyS3ohSoTRf4ZLA3FSwxQdiuNl5NXUtvA==",
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.1.tgz",
+ "integrity": "sha512-5lNGRB5g5i2bGIzb+J1QQE1iKU/WEMVBReFIc5pPDWjcPj23otPL0eI6PB2v7QPi0qU6Mhym5D3y0ZiSIOf3GA==",
"engines": {
"node": ">=10.0.0"
}
@@ -4363,12 +4387,12 @@
"dev": true
},
"node_modules/body-parser": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
- "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dependencies": {
"bytes": "3.1.2",
- "content-type": "~1.0.4",
+ "content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
@@ -4376,7 +4400,7 @@
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
- "raw-body": "2.5.1",
+ "raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
@@ -5046,9 +5070,9 @@
}
},
"node_modules/cluster-key-slot": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz",
- "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
+ "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
"engines": {
"node": ">=0.10.0"
}
@@ -5173,11 +5197,11 @@
}
},
"node_modules/commander": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
- "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"engines": {
- "node": ">= 6"
+ "node": ">=14"
}
},
"node_modules/commondir": {
@@ -5247,9 +5271,9 @@
}
},
"node_modules/content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"engines": {
"node": ">= 0.6"
}
@@ -7268,9 +7292,9 @@
}
},
"node_modules/express-rate-limit": {
- "version": "6.6.0",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz",
- "integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==",
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
+ "integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
"engines": {
"node": ">= 12.9.0"
},
@@ -7278,6 +7302,29 @@
"express": "^4 || ^5"
}
},
+ "node_modules/express/node_modules/body-parser": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
+ "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -7291,6 +7338,25 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
+ "node_modules/express/node_modules/path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ },
+ "node_modules/express/node_modules/raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/ext": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
@@ -8223,9 +8289,9 @@
}
},
"node_modules/generic-pool": {
- "version": "3.8.2",
- "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz",
- "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==",
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
+ "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
"engines": {
"node": ">= 4"
}
@@ -9117,9 +9183,9 @@
}
},
"node_modules/idb-keyval": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.0.3.tgz",
- "integrity": "sha512-yh8V7CnE6EQMu9YDwQXhRxwZh4nv+8xm/HV4ZqK4IiYFJBWYGjJuykADJbSP+F/GDXUBwCSSNn/14IpGL81TuA==",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz",
+ "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==",
"dependencies": {
"safari-14-idb-fix": "^3.0.0"
}
@@ -10398,6 +10464,15 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "node_modules/lint-staged/node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/lint-staged/node_modules/cosmiconfig": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
@@ -11019,11 +11094,11 @@
}
},
"node_modules/lru-cache": {
- "version": "7.12.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.12.0.tgz",
- "integrity": "sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw==",
+ "version": "9.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz",
+ "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==",
"engines": {
- "node": ">=12"
+ "node": "14 || >=16.14"
}
},
"node_modules/lru-memoizer": {
@@ -15138,11 +15213,6 @@
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
},
- "bin": {
- "sshpk-conv": "bin/sshpk-conv",
- "sshpk-sign": "bin/sshpk-sign",
- "sshpk-verify": "bin/sshpk-verify"
- },
"engines": {
"node": ">=0.10.0"
}
@@ -16052,20 +16122,19 @@
}
},
"node_modules/parse": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/parse/-/parse-4.0.1.tgz",
- "integrity": "sha512-ctv7zaVKlQIBSbarorB7TH3yacDzCvgWBP4ccpLKxlpe21QlaY88kv9V7ca7JdG/Txb3qWug4MwepQoPogXB6Q==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/parse/-/parse-4.1.0.tgz",
+ "integrity": "sha512-s0Ti+nWrKWj9DlFcmkEE05fGwa/K5ycZSdqCz01F8YL7Hevqv4WLXAmYGOwzq5UJSZ005seKgb20KwVwLdy/Zg==",
"dependencies": {
- "@babel/runtime": "7.18.0",
- "@babel/runtime-corejs3": "7.17.8",
- "idb-keyval": "6.0.3",
+ "@babel/runtime-corejs3": "7.21.0",
+ "idb-keyval": "6.2.0",
"react-native-crypto-js": "1.0.0",
- "uuid": "3.4.0",
- "ws": "8.6.0",
+ "uuid": "9.0.0",
+ "ws": "8.12.0",
"xmlhttprequest": "1.8.0"
},
"engines": {
- "node": ">=14.21.0 <17 || >=18 <19"
+ "node": ">=14.21.0 <17 || >=18 <20"
},
"optionalDependencies": {
"crypto-js": "4.1.1"
@@ -16098,25 +16167,16 @@
"node": ">=6"
}
},
- "node_modules/parse/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/node_modules/ws": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
- "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz",
+ "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -16183,9 +16243,9 @@
"dev": true
},
"node_modules/path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
+ "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
},
"node_modules/path-type": {
"version": "4.0.0",
@@ -16208,14 +16268,14 @@
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"node_modules/pg": {
- "version": "8.9.0",
- "resolved": "https://registry.npmjs.org/pg/-/pg-8.9.0.tgz",
- "integrity": "sha512-ZJM+qkEbtOHRuXjmvBtOgNOXOtLSbxiMiUVMgE4rV6Zwocy03RicCVvDXgx8l4Biwo8/qORUnEqn2fdQzV7KCg==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.0.tgz",
+ "integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==",
"dependencies": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
- "pg-connection-string": "^2.5.0",
- "pg-pool": "^3.5.2",
+ "pg-connection-string": "^2.6.0",
+ "pg-pool": "^3.6.0",
"pg-protocol": "^1.6.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
@@ -16223,6 +16283,9 @@
"engines": {
"node": ">= 8.0.0"
},
+ "optionalDependencies": {
+ "pg-cloudflare": "^1.1.0"
+ },
"peerDependencies": {
"pg-native": ">=3.0.1"
},
@@ -16232,10 +16295,16 @@
}
}
},
+ "node_modules/pg-cloudflare": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz",
+ "integrity": "sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==",
+ "optional": true
+ },
"node_modules/pg-connection-string": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
- "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.0.tgz",
+ "integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg=="
},
"node_modules/pg-int8": {
"version": "1.0.1",
@@ -16246,11 +16315,11 @@
}
},
"node_modules/pg-minify": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz",
- "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg==",
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.3.tgz",
+ "integrity": "sha512-NoSsPqXxbkD8RIe+peQCqiea4QzXgosdTKY8p7PsbbGsh2F8TifDj/vJxfuR8qJwNYrijdSs7uf0tAe6WOyCsQ==",
"engines": {
- "node": ">=8.0"
+ "node": ">=12.0.0"
}
},
"node_modules/pg-monitor": {
@@ -16320,22 +16389,22 @@
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"node_modules/pg-pool": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz",
- "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz",
+ "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-promise": {
- "version": "11.3.0",
- "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.3.0.tgz",
- "integrity": "sha512-A2CYmax5gsqVAO2N0ET9oPRCPX3kpKymj9qLVK7+jszlJL6l8uJDq/DGqLpxNi5VHwK7Dmm2WNRdrwkh1xuaxQ==",
+ "version": "11.5.0",
+ "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.5.0.tgz",
+ "integrity": "sha512-ZfhntV6Yoc3S0hQWOlEodk5fEmF9ADxKl0vNvBnZgzvLt73uY29wVaNBz2AZK2J0gVmm/zhO51RXPtI4MgKkSQ==",
"dependencies": {
- "assert-options": "0.8.0",
- "pg": "8.9.0",
- "pg-minify": "1.6.2",
- "spex": "3.2.0"
+ "assert-options": "0.8.1",
+ "pg": "8.11.0",
+ "pg-minify": "1.6.3",
+ "spex": "3.3.0"
},
"engines": {
"node": ">=14.0"
@@ -16370,9 +16439,9 @@
}
},
"node_modules/pgpass/node_modules/split2": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz",
- "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"engines": {
"node": ">= 10.x"
}
@@ -16886,9 +16955,9 @@
}
},
"node_modules/rate-limit-redis": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/rate-limit-redis/-/rate-limit-redis-3.0.1.tgz",
- "integrity": "sha512-L6yhOUBrAZ8VEMX9DwlM3X6hfm8yq+gBO4LoOW7+JgmNq59zE7QmLz4v5VnwYPvLeSh/e7PDcrzUI3UumJw1iw==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rate-limit-redis/-/rate-limit-redis-3.0.2.tgz",
+ "integrity": "sha512-4SBK6AzIr9PKkCF4HmSDcJH2O2KKMF3fZEcsbNMXyaL5I9d6X71uOreUldFRiyrRyP+qkQrTxzJ38ZKKN+sScw==",
"engines": {
"node": ">= 14.5.0"
},
@@ -16897,9 +16966,9 @@
}
},
"node_modules/raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -17274,35 +17343,16 @@
}
},
"node_modules/redis": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/redis/-/redis-4.0.6.tgz",
- "integrity": "sha512-IaPAxgF5dV0jx+A9l6yd6R9/PAChZIoAskDVRzUODeLDNhsMlq7OLLTmu0AwAr0xjrJ1bibW5xdpRwqIQ8Q0Xg==",
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.6.tgz",
+ "integrity": "sha512-aLs2fuBFV/VJ28oLBqYykfnhGGkFxvx0HdCEBYdJ99FFbSEMZ7c1nVKwR6ZRv+7bb7JnC0mmCzaqu8frgOYhpA==",
"dependencies": {
- "@node-redis/bloom": "1.0.1",
- "@node-redis/client": "1.0.5",
- "@node-redis/graph": "1.0.0",
- "@node-redis/json": "1.0.2",
- "@node-redis/search": "1.0.5",
- "@node-redis/time-series": "1.0.2"
- }
- },
- "node_modules/redis-errors": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
- "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/redis-parser": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
- "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
- "dependencies": {
- "redis-errors": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
+ "@redis/bloom": "1.2.0",
+ "@redis/client": "1.5.7",
+ "@redis/graph": "1.1.0",
+ "@redis/json": "1.0.4",
+ "@redis/search": "1.1.2",
+ "@redis/time-series": "1.0.4"
}
},
"node_modules/regenerate": {
@@ -18123,9 +18173,9 @@
}
},
"node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "version": "7.5.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
+ "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -18753,11 +18803,11 @@
"dev": true
},
"node_modules/spex": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz",
- "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/spex/-/spex-3.3.0.tgz",
+ "integrity": "sha512-VNiXjFp6R4ldPbVRYbpxlD35yRHceecVXlct1J4/X80KuuPnW2AXMq3sGwhnJOhKkUsOxAT6nRGfGE5pocVw5w==",
"engines": {
- "node": ">=4.5"
+ "node": ">=10.0.0"
}
},
"node_modules/split": {
@@ -20285,10 +20335,11 @@
}
},
"node_modules/winston": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.1.tgz",
- "integrity": "sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w==",
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz",
+ "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
"dependencies": {
+ "@colors/colors": "1.5.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
@@ -20439,15 +20490,15 @@
}
},
"node_modules/ws": {
- "version": "8.9.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
- "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+ "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -20778,9 +20829,9 @@
}
},
"@babel/eslint-parser": {
- "version": "7.19.1",
- "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.19.1.tgz",
- "integrity": "sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==",
+ "version": "7.21.8",
+ "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.8.tgz",
+ "integrity": "sha512-HLhI+2q+BP3sf78mFUZNCGc10KEmoUqtUT1OCdMZsN+qr4qFeLUod62/zAnF3jNQstwyasDkZnVXwfK2Bml7MQ==",
"requires": {
"@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
"eslint-visitor-keys": "^2.1.0",
@@ -21813,17 +21864,18 @@
"version": "7.18.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.0.tgz",
"integrity": "sha512-YMQvx/6nKEaucl0MY56mwIG483xk8SDNdlUwb2Ts6FUpr7fm85DxEmsY18LXBNhcTz6tO6JwZV8w1W06v8UKeg==",
+ "dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@babel/runtime-corejs3": {
- "version": "7.17.8",
- "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.8.tgz",
- "integrity": "sha512-ZbYSUvoSF6dXZmMl/CYTMOvzIFnbGfv4W3SEHYgMvNsFTeLaF2gkGAF4K2ddmtSK4Emej+0aYcnSC6N5dPCXUQ==",
+ "version": "7.21.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.21.0.tgz",
+ "integrity": "sha512-TDD4UJzos3JJtM+tHX+w2Uc+KWj7GV+VKKFdMVd2Rx8sdA19hcc3P3AHFYd5LVOw+pYuSd5lICC3gm52B6Rwxw==",
"requires": {
- "core-js-pure": "^3.20.2",
- "regenerator-runtime": "^0.13.4"
+ "core-js-pure": "^3.25.1",
+ "regenerator-runtime": "^0.13.11"
}
},
"@babel/template": {
@@ -21972,12 +22024,23 @@
}
},
"@graphql-tools/merge": {
- "version": "8.3.6",
- "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.3.6.tgz",
- "integrity": "sha512-uUBokxXi89bj08P+iCvQk3Vew4vcfL5ZM6NTylWi8PIpoq4r5nJ625bRuN8h2uubEdRiH8ntN9M4xkd/j7AybQ==",
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.1.tgz",
+ "integrity": "sha512-hssnPpZ818mxgl5+GfyOOSnnflAxiaTn1A1AojZcIbh4J52sS1Q0gSuBR5VrnUDjuxiqoCotpXdAQl+K+U6KLQ==",
"requires": {
- "@graphql-tools/utils": "8.12.0",
+ "@graphql-tools/utils": "^9.2.1",
"tslib": "^2.4.0"
+ },
+ "dependencies": {
+ "@graphql-tools/utils": {
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz",
+ "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==",
+ "requires": {
+ "@graphql-typed-document-node/core": "^3.1.1",
+ "tslib": "^2.4.0"
+ }
+ }
}
},
"@graphql-tools/schema": {
@@ -21989,6 +22052,17 @@
"@graphql-tools/utils": "8.12.0",
"tslib": "^2.4.0",
"value-or-promise": "1.0.11"
+ },
+ "dependencies": {
+ "@graphql-tools/merge": {
+ "version": "8.3.6",
+ "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.3.6.tgz",
+ "integrity": "sha512-uUBokxXi89bj08P+iCvQk3Vew4vcfL5ZM6NTylWi8PIpoq4r5nJ625bRuN8h2uubEdRiH8ntN9M4xkd/j7AybQ==",
+ "requires": {
+ "@graphql-tools/utils": "8.12.0",
+ "tslib": "^2.4.0"
+ }
+ }
}
},
"@graphql-tools/utils": {
@@ -22233,47 +22307,6 @@
"eslint-scope": "5.1.1"
}
},
- "@node-redis/bloom": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@node-redis/bloom/-/bloom-1.0.1.tgz",
- "integrity": "sha512-mXEBvEIgF4tUzdIN89LiYsbi6//EdpFA7L8M+DHCvePXg+bfHWi+ct5VI6nHUFQE5+ohm/9wmgihCH3HSkeKsw==",
- "requires": {}
- },
- "@node-redis/client": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@node-redis/client/-/client-1.0.5.tgz",
- "integrity": "sha512-ESZ3bd1f+od62h4MaBLKum+klVJfA4wAeLHcVQBkoXa1l0viFesOWnakLQqKg+UyrlJhZmXJWtu0Y9v7iTMrig==",
- "requires": {
- "cluster-key-slot": "1.1.0",
- "generic-pool": "3.8.2",
- "redis-parser": "3.0.0",
- "yallist": "4.0.0"
- }
- },
- "@node-redis/graph": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@node-redis/graph/-/graph-1.0.0.tgz",
- "integrity": "sha512-mRSo8jEGC0cf+Rm7q8mWMKKKqkn6EAnA9IA2S3JvUv/gaWW/73vil7GLNwion2ihTptAm05I9LkepzfIXUKX5g==",
- "requires": {}
- },
- "@node-redis/json": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@node-redis/json/-/json-1.0.2.tgz",
- "integrity": "sha512-qVRgn8WfG46QQ08CghSbY4VhHFgaTY71WjpwRBGEuqGPfWwfRcIf3OqSpR7Q/45X+v3xd8mvYjywqh0wqJ8T+g==",
- "requires": {}
- },
- "@node-redis/search": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@node-redis/search/-/search-1.0.5.tgz",
- "integrity": "sha512-MCOL8iCKq4v+3HgEQv8zGlSkZyXSXtERgrAJ4TSryIG/eLFy84b57KmNNa/V7M1Q2Wd2hgn2nPCGNcQtk1R1OQ==",
- "requires": {}
- },
- "@node-redis/time-series": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@node-redis/time-series/-/time-series-1.0.2.tgz",
- "integrity": "sha512-HGQ8YooJ8Mx7l28tD7XjtB3ImLEjlUxG1wC1PAjxu6hPJqjPshUZxAICzDqDjtIbhDTf48WXXUcx8TQJB1XTKA==",
- "requires": {}
- },
"@node-rs/bcrypt": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@node-rs/bcrypt/-/bcrypt-1.1.0.tgz",
@@ -22609,9 +22642,9 @@
}
},
"@parse/push-adapter": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.2.tgz",
- "integrity": "sha512-034vZTlAzgdfefIY4+Q4j8DHS/VwUAIVoh1JeRkHNfyQmUQ++uKbQbUQdJ/nf11HHS69kwLENs13BmhlHMpyHQ==",
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.3.tgz",
+ "integrity": "sha512-Oy53ag7DpUva5dUWwP6tNEsrxv2xU9QIk+rb84q1DIm1qVgo2yl4oXcZ3FPG2Ks/NYURbv4w+z9oaSgVfyBRfQ==",
"requires": {
"@parse/node-apn": "5.1.3",
"@parse/node-gcm": "1.0.2",
@@ -22669,6 +22702,46 @@
}
}
},
+ "@redis/bloom": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
+ "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
+ "requires": {}
+ },
+ "@redis/client": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz",
+ "integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==",
+ "requires": {
+ "cluster-key-slot": "1.1.2",
+ "generic-pool": "3.9.0",
+ "yallist": "4.0.0"
+ }
+ },
+ "@redis/graph": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz",
+ "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==",
+ "requires": {}
+ },
+ "@redis/json": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz",
+ "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==",
+ "requires": {}
+ },
+ "@redis/search": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz",
+ "integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==",
+ "requires": {}
+ },
+ "@redis/time-series": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz",
+ "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==",
+ "requires": {}
+ },
"@repeaterjs/repeater": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz",
@@ -23578,9 +23651,9 @@
}
},
"assert-options": {
- "version": "0.8.0",
- "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.0.tgz",
- "integrity": "sha512-qSELrEaEz4sGwTs4Qh+swQkjiHAysC4rot21+jzXU86dJzNG+FDqBzyS3ohSoTRf4ZLA3FSwxQdiuNl5NXUtvA=="
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/assert-options/-/assert-options-0.8.1.tgz",
+ "integrity": "sha512-5lNGRB5g5i2bGIzb+J1QQE1iKU/WEMVBReFIc5pPDWjcPj23otPL0eI6PB2v7QPi0qU6Mhym5D3y0ZiSIOf3GA=="
},
"assert-plus": {
"version": "1.0.0",
@@ -23809,12 +23882,12 @@
"dev": true
},
"body-parser": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
- "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "version": "1.20.2",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
+ "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"requires": {
"bytes": "3.1.2",
- "content-type": "~1.0.4",
+ "content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
@@ -23822,7 +23895,7 @@
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
- "raw-body": "2.5.1",
+ "raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
@@ -24333,9 +24406,9 @@
}
},
"cluster-key-slot": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz",
- "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw=="
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
+ "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="
},
"code-point-at": {
"version": "1.1.0",
@@ -24432,9 +24505,9 @@
}
},
"commander": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
- "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="
},
"commondir": {
"version": "1.0.1",
@@ -24500,9 +24573,9 @@
}
},
"content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
},
"conventional-changelog-angular": {
"version": "5.0.13",
@@ -26092,6 +26165,25 @@
"vary": "~1.1.2"
},
"dependencies": {
+ "body-parser": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
+ "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "requires": {
+ "bytes": "3.1.2",
+ "content-type": "~1.0.4",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "on-finished": "2.4.1",
+ "qs": "6.11.0",
+ "raw-body": "2.5.1",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ }
+ },
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -26104,13 +26196,29 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ },
+ "raw-body": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
+ "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "requires": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ }
}
}
},
"express-rate-limit": {
- "version": "6.6.0",
- "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz",
- "integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==",
+ "version": "6.7.0",
+ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
+ "integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
"requires": {}
},
"ext": {
@@ -26807,9 +26915,9 @@
}
},
"generic-pool": {
- "version": "3.8.2",
- "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz",
- "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg=="
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
+ "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g=="
},
"gensync": {
"version": "1.0.0-beta.2",
@@ -27490,9 +27598,9 @@
}
},
"idb-keyval": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.0.3.tgz",
- "integrity": "sha512-yh8V7CnE6EQMu9YDwQXhRxwZh4nv+8xm/HV4ZqK4IiYFJBWYGjJuykADJbSP+F/GDXUBwCSSNn/14IpGL81TuA==",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz",
+ "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==",
"requires": {
"safari-14-idb-fix": "^3.0.0"
}
@@ -28486,6 +28594,12 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
+ "commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true
+ },
"cosmiconfig": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
@@ -28991,9 +29105,9 @@
"dev": true
},
"lru-cache": {
- "version": "7.12.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.12.0.tgz",
- "integrity": "sha512-OIP3DwzRZDfLg9B9VP/huWBlpvbkmbfiBy8xmsXp4RPmE4A3MhwNozc5ZJ3fWnSg8fDcdlE/neRTPG2ycEKliw=="
+ "version": "9.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz",
+ "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A=="
},
"lru-memoizer": {
"version": "2.1.4",
@@ -32725,29 +32839,23 @@
}
},
"parse": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/parse/-/parse-4.0.1.tgz",
- "integrity": "sha512-ctv7zaVKlQIBSbarorB7TH3yacDzCvgWBP4ccpLKxlpe21QlaY88kv9V7ca7JdG/Txb3qWug4MwepQoPogXB6Q==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/parse/-/parse-4.1.0.tgz",
+ "integrity": "sha512-s0Ti+nWrKWj9DlFcmkEE05fGwa/K5ycZSdqCz01F8YL7Hevqv4WLXAmYGOwzq5UJSZ005seKgb20KwVwLdy/Zg==",
"requires": {
- "@babel/runtime": "7.18.0",
- "@babel/runtime-corejs3": "7.17.8",
+ "@babel/runtime-corejs3": "7.21.0",
"crypto-js": "4.1.1",
- "idb-keyval": "6.0.3",
+ "idb-keyval": "6.2.0",
"react-native-crypto-js": "1.0.0",
- "uuid": "3.4.0",
- "ws": "8.6.0",
+ "uuid": "9.0.0",
+ "ws": "8.12.0",
"xmlhttprequest": "1.8.0"
},
"dependencies": {
- "uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
- },
"ws": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz",
- "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==",
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz",
+ "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==",
"requires": {}
}
}
@@ -32811,9 +32919,9 @@
"dev": true
},
"path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz",
+ "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw=="
},
"path-type": {
"version": "4.0.0",
@@ -32833,23 +32941,30 @@
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"pg": {
- "version": "8.9.0",
- "resolved": "https://registry.npmjs.org/pg/-/pg-8.9.0.tgz",
- "integrity": "sha512-ZJM+qkEbtOHRuXjmvBtOgNOXOtLSbxiMiUVMgE4rV6Zwocy03RicCVvDXgx8l4Biwo8/qORUnEqn2fdQzV7KCg==",
+ "version": "8.11.0",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.0.tgz",
+ "integrity": "sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==",
"requires": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
- "pg-connection-string": "^2.5.0",
- "pg-pool": "^3.5.2",
+ "pg-cloudflare": "^1.1.0",
+ "pg-connection-string": "^2.6.0",
+ "pg-pool": "^3.6.0",
"pg-protocol": "^1.6.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
}
},
+ "pg-cloudflare": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz",
+ "integrity": "sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==",
+ "optional": true
+ },
"pg-connection-string": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
- "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.0.tgz",
+ "integrity": "sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg=="
},
"pg-int8": {
"version": "1.0.1",
@@ -32857,9 +32972,9 @@
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
},
"pg-minify": {
- "version": "1.6.2",
- "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.2.tgz",
- "integrity": "sha512-1KdmFGGTP6jplJoI8MfvRlfvMiyBivMRP7/ffh4a11RUFJ7kC2J0ZHlipoKiH/1hz+DVgceon9U2qbaHpPeyPg=="
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/pg-minify/-/pg-minify-1.6.3.tgz",
+ "integrity": "sha512-NoSsPqXxbkD8RIe+peQCqiea4QzXgosdTKY8p7PsbbGsh2F8TifDj/vJxfuR8qJwNYrijdSs7uf0tAe6WOyCsQ=="
},
"pg-monitor": {
"version": "2.0.0",
@@ -32924,20 +33039,20 @@
}
},
"pg-pool": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.5.2.tgz",
- "integrity": "sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w==",
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.0.tgz",
+ "integrity": "sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==",
"requires": {}
},
"pg-promise": {
- "version": "11.3.0",
- "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.3.0.tgz",
- "integrity": "sha512-A2CYmax5gsqVAO2N0ET9oPRCPX3kpKymj9qLVK7+jszlJL6l8uJDq/DGqLpxNi5VHwK7Dmm2WNRdrwkh1xuaxQ==",
+ "version": "11.5.0",
+ "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-11.5.0.tgz",
+ "integrity": "sha512-ZfhntV6Yoc3S0hQWOlEodk5fEmF9ADxKl0vNvBnZgzvLt73uY29wVaNBz2AZK2J0gVmm/zhO51RXPtI4MgKkSQ==",
"requires": {
- "assert-options": "0.8.0",
- "pg": "8.9.0",
- "pg-minify": "1.6.2",
- "spex": "3.2.0"
+ "assert-options": "0.8.1",
+ "pg": "8.11.0",
+ "pg-minify": "1.6.3",
+ "spex": "3.3.0"
}
},
"pg-protocol": {
@@ -32966,9 +33081,9 @@
},
"dependencies": {
"split2": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-4.1.0.tgz",
- "integrity": "sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ=="
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="
}
}
},
@@ -33342,15 +33457,15 @@
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"rate-limit-redis": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/rate-limit-redis/-/rate-limit-redis-3.0.1.tgz",
- "integrity": "sha512-L6yhOUBrAZ8VEMX9DwlM3X6hfm8yq+gBO4LoOW7+JgmNq59zE7QmLz4v5VnwYPvLeSh/e7PDcrzUI3UumJw1iw==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rate-limit-redis/-/rate-limit-redis-3.0.2.tgz",
+ "integrity": "sha512-4SBK6AzIr9PKkCF4HmSDcJH2O2KKMF3fZEcsbNMXyaL5I9d6X71uOreUldFRiyrRyP+qkQrTxzJ38ZKKN+sScw==",
"requires": {}
},
"raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"requires": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -33657,29 +33772,16 @@
}
},
"redis": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/redis/-/redis-4.0.6.tgz",
- "integrity": "sha512-IaPAxgF5dV0jx+A9l6yd6R9/PAChZIoAskDVRzUODeLDNhsMlq7OLLTmu0AwAr0xjrJ1bibW5xdpRwqIQ8Q0Xg==",
+ "version": "4.6.6",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-4.6.6.tgz",
+ "integrity": "sha512-aLs2fuBFV/VJ28oLBqYykfnhGGkFxvx0HdCEBYdJ99FFbSEMZ7c1nVKwR6ZRv+7bb7JnC0mmCzaqu8frgOYhpA==",
"requires": {
- "@node-redis/bloom": "1.0.1",
- "@node-redis/client": "1.0.5",
- "@node-redis/graph": "1.0.0",
- "@node-redis/json": "1.0.2",
- "@node-redis/search": "1.0.5",
- "@node-redis/time-series": "1.0.2"
- }
- },
- "redis-errors": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
- "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="
- },
- "redis-parser": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
- "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
- "requires": {
- "redis-errors": "^1.0.0"
+ "@redis/bloom": "1.2.0",
+ "@redis/client": "1.5.7",
+ "@redis/graph": "1.1.0",
+ "@redis/json": "1.0.4",
+ "@redis/search": "1.1.2",
+ "@redis/time-series": "1.0.4"
}
},
"regenerate": {
@@ -34299,9 +34401,9 @@
}
},
"semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "version": "7.5.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz",
+ "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==",
"requires": {
"lru-cache": "^6.0.0"
},
@@ -34816,9 +34918,9 @@
"dev": true
},
"spex": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/spex/-/spex-3.2.0.tgz",
- "integrity": "sha512-9srjJM7NaymrpwMHvSmpDeIK5GoRMX/Tq0E8aOlDPS54dDnDUIp30DrP9SphMPEETDLzEM9+4qo+KipmbtPecg=="
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/spex/-/spex-3.3.0.tgz",
+ "integrity": "sha512-VNiXjFp6R4ldPbVRYbpxlD35yRHceecVXlct1J4/X80KuuPnW2AXMq3sGwhnJOhKkUsOxAT6nRGfGE5pocVw5w=="
},
"split": {
"version": "1.0.1",
@@ -35997,10 +36099,11 @@
}
},
"winston": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.1.tgz",
- "integrity": "sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w==",
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz",
+ "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==",
"requires": {
+ "@colors/colors": "1.5.0",
"@dabh/diagnostics": "^2.0.2",
"async": "^3.2.3",
"is-stream": "^2.0.0",
@@ -36124,9 +36227,9 @@
}
},
"ws": {
- "version": "8.9.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz",
- "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==",
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+ "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
"requires": {}
},
"xmlcreate": {
diff --git a/package.json b/package.json
index 16ae61cc3f..b5a8ebc75e 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "parse-server",
- "version": "6.2.0",
+ "version": "6.1.0-alpha.20",
"description": "An express module providing a Parse-compatible API server",
"main": "lib/index.js",
"repository": {
@@ -19,20 +19,20 @@
],
"license": "Apache-2.0",
"dependencies": {
- "@babel/eslint-parser": "7.19.1",
- "@graphql-tools/merge": "8.3.6",
+ "@babel/eslint-parser": "7.21.8",
+ "@graphql-tools/merge": "8.4.1",
"@graphql-tools/schema": "9.0.4",
"@graphql-tools/utils": "8.12.0",
"@graphql-yoga/node": "2.6.0",
"@parse/fs-files-adapter": "1.2.2",
- "@parse/push-adapter": "4.1.2",
+ "@parse/push-adapter": "4.1.3",
"bcryptjs": "2.4.3",
- "body-parser": "1.20.1",
- "commander": "5.1.0",
+ "body-parser": "1.20.2",
+ "commander": "10.0.1",
"cors": "2.8.5",
"deepcopy": "2.1.0",
"express": "4.18.2",
- "express-rate-limit": "6.6.0",
+ "express-rate-limit": "6.7.0",
"follow-redirects": "1.15.2",
"graphql": "16.6.0",
"graphql-list-fields": "2.0.2",
@@ -44,24 +44,24 @@
"jwks-rsa": "2.1.5",
"ldapjs": "2.3.3",
"lodash": "4.17.21",
- "lru-cache": "7.12.0",
+ "lru-cache": "9.1.1",
"mime": "3.0.0",
"mongodb": "4.10.0",
"mustache": "4.2.0",
- "parse": "4.0.1",
- "path-to-regexp": "0.1.7",
+ "parse": "4.1.0",
+ "path-to-regexp": "6.2.1",
"pg-monitor": "2.0.0",
- "pg-promise": "11.3.0",
+ "pg-promise": "11.5.0",
"pluralize": "8.0.0",
- "rate-limit-redis": "3.0.1",
- "redis": "4.0.6",
- "semver": "7.3.8",
+ "rate-limit-redis": "3.0.2",
+ "redis": "4.6.6",
+ "semver": "7.5.1",
"subscriptions-transport-ws": "0.11.0",
"tv4": "1.3.0",
"uuid": "9.0.0",
- "winston": "3.8.1",
+ "winston": "3.8.2",
"winston-daily-rotate-file": "4.7.1",
- "ws": "8.9.0"
+ "ws": "8.13.0"
},
"devDependencies": {
"@actions/core": "1.9.1",
diff --git a/spec/Auth.spec.js b/spec/Auth.spec.js
index 5ed6bfe941..26421487df 100644
--- a/spec/Auth.spec.js
+++ b/spec/Auth.spec.js
@@ -94,6 +94,35 @@ describe('Auth', () => {
});
});
+ it('can use extendSessionOnUse', async () => {
+ await reconfigureServer({
+ extendSessionOnUse: true,
+ });
+
+ const user = new Parse.User();
+ await user.signUp({
+ username: 'hello',
+ password: 'password',
+ });
+ const session = await new Parse.Query(Parse.Session).first();
+ const updatedAt = new Date('2010');
+ const expiry = new Date();
+ expiry.setHours(expiry.getHours() + 1);
+
+ await Parse.Server.database.update(
+ '_Session',
+ { objectId: session.id },
+ {
+ expiresAt: { __type: 'Date', iso: expiry.toISOString() },
+ updatedAt: updatedAt.toISOString(),
+ }
+ );
+ await session.fetch();
+ await new Promise(resolve => setTimeout(resolve, 1000));
+ await session.fetch();
+ expect(session.get('expiresAt') > expiry).toBeTrue();
+ });
+
it('should load auth without a config', async () => {
const user = new Parse.User();
await user.signUp({
diff --git a/spec/CLI.spec.js b/spec/CLI.spec.js
index 9affc31016..20667fd349 100644
--- a/spec/CLI.spec.js
+++ b/spec/CLI.spec.js
@@ -74,7 +74,7 @@ describe('commander additions', () => {
done();
});
- it('should load properly use args over env', done => {
+ it('should load properly use args over env', () => {
commander.loadDefinitions(testDefinitions);
commander.parse(['node', './CLI.spec.js', '--arg0', 'arg0Value', '--arg4', ''], {
PROGRAM_ARG_0: 'arg0ENVValue',
@@ -86,7 +86,6 @@ describe('commander additions', () => {
expect(commander.arg1).toEqual('arg1ENVValue');
expect(commander.arg2).toEqual(4);
expect(commander.arg4).toEqual('');
- done();
});
it('should fail in action as port is invalid', done => {
diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js
index c02999ad51..a8795a4e84 100644
--- a/spec/CloudCode.spec.js
+++ b/spec/CloudCode.spec.js
@@ -95,7 +95,8 @@ describe('Cloud Code', () => {
it('can get config', () => {
const config = Parse.Server;
let currentConfig = Config.get('test');
- expect(Object.keys(config)).toEqual(Object.keys(currentConfig));
+ const server = require('../lib/cloud-code/Parse.Server');
+ expect(Object.keys(config)).toEqual(Object.keys({ ...currentConfig, ...server }));
config.silent = false;
Parse.Server = config;
currentConfig = Config.get('test');
@@ -1352,6 +1353,27 @@ describe('Cloud Code', () => {
});
});
+ it('allow cloud to 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).toBeTrue();
+ req.params.object.set('deleted', true);
+ await req.params.object.save(null, { useMasterKey: true });
+ return 'Object deleted';
+ },
+ {
+ requireMaster: true,
+ }
+ );
+ await Parse.Cloud.run('deleteAccount', { object: user.toPointer() }, { useMasterKey: true });
+ });
+
it('beforeSave should not affect fetched pointers', done => {
Parse.Cloud.beforeSave('BeforeSaveUnchanged', () => {});
diff --git a/spec/CloudCodeLogger.spec.js b/spec/CloudCodeLogger.spec.js
index 2cde9de640..b4dd5a42d8 100644
--- a/spec/CloudCodeLogger.spec.js
+++ b/spec/CloudCodeLogger.spec.js
@@ -182,6 +182,42 @@ describe('Cloud Code Logger', () => {
});
});
+ it('should log cloud function execution using the custom log level', async done => {
+ Parse.Cloud.define('aFunction', () => {
+ return 'it worked!';
+ });
+
+ Parse.Cloud.define('bFunction', () => {
+ throw new Error('Failed');
+ });
+
+ await Parse.Cloud.run('aFunction', { foo: 'bar' }).then(() => {
+ const log = spy.calls.allArgs().find(log => log[1].startsWith('Ran cloud function '))?.[0];
+ expect(log).toEqual('info');
+ });
+
+ await reconfigureServer({
+ silent: true,
+ logLevels: {
+ cloudFunctionSuccess: 'warn',
+ cloudFunctionError: 'info',
+ },
+ });
+
+ spy = spyOn(Config.get('test').loggerController.adapter, 'log').and.callThrough();
+
+ try {
+ await Parse.Cloud.run('bFunction', { foo: 'bar' });
+ throw new Error('bFunction should have failed');
+ } catch {
+ const log = spy.calls
+ .allArgs()
+ .find(log => log[1].startsWith('Failed running cloud function bFunction for '))?.[0];
+ expect(log).toEqual('info');
+ done();
+ }
+ });
+
it('should log cloud function triggers using the custom log level', async () => {
Parse.Cloud.beforeSave('TestClass', () => {});
Parse.Cloud.afterSave('TestClass', () => {});
diff --git a/spec/FilesController.spec.js b/spec/FilesController.spec.js
index 8fee5aca2f..a16451f3ef 100644
--- a/spec/FilesController.spec.js
+++ b/spec/FilesController.spec.js
@@ -55,6 +55,8 @@ describe('FilesController', () => {
const config = Config.get(Parse.applicationId);
expect(config.database.adapter._mongoOptions.retryWrites).toBeTrue();
expect(config.filesController.adapter._mongoOptions.retryWrites).toBeTrue();
+ expect(config.filesController.adapter._mongoOptions.enableSchemaHooks).toBeUndefined();
+ expect(config.filesController.adapter._mongoOptions.schemaCacheTtl).toBeUndefined();
});
it('should create a server log on failure', done => {
diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js
index 419bfdb98d..7e9c84a59e 100644
--- a/spec/GridFSBucketStorageAdapter.spec.js
+++ b/spec/GridFSBucketStorageAdapter.spec.js
@@ -20,6 +20,22 @@ describe_only_db('mongo')('GridFSBucket', () => {
await db.dropDatabase();
});
+ it('should connect to mongo with the supported database options', async () => {
+ const databaseURI = 'mongodb://localhost:27017/parse';
+ const gfsAdapter = new GridFSBucketAdapter(databaseURI, {
+ retryWrites: true,
+ // these are not supported by the mongo client
+ enableSchemaHooks: true,
+ schemaCacheTtl: 5000,
+ maxTimeMS: 30000,
+ });
+
+ const db = await gfsAdapter._connect();
+ const status = await db.admin().serverStatus();
+ expect(status.connections.current > 0).toEqual(true);
+ expect(db.options?.retryWrites).toEqual(true);
+ });
+
it('should save an encrypted file that can only be decrypted by a GridFS adapter with the encryptionKey', async () => {
const unencryptedAdapter = new GridFSBucketAdapter(databaseURI);
const encryptedAdapter = new GridFSBucketAdapter(
diff --git a/spec/ParseHooks.spec.js b/spec/ParseHooks.spec.js
index d5d980d3d0..f4bcc2e440 100644
--- a/spec/ParseHooks.spec.js
+++ b/spec/ParseHooks.spec.js
@@ -208,7 +208,7 @@ describe('Hooks', () => {
expect(err).not.toBe(null);
if (err) {
expect(err.code).toBe(143);
- expect(err.message).toBe('function name: my_new_function already exits');
+ expect(err.message).toBe('function name: my_new_function already exists');
}
return Parse.Hooks.removeFunction('my_new_function');
}
diff --git a/spec/ParseLiveQuery.spec.js b/spec/ParseLiveQuery.spec.js
index 38259f50d0..015725ac46 100644
--- a/spec/ParseLiveQuery.spec.js
+++ b/spec/ParseLiveQuery.spec.js
@@ -2,6 +2,8 @@
const Auth = require('../lib/Auth');
const UserController = require('../lib/Controllers/UserController').UserController;
const Config = require('../lib/Config');
+const ParseServer = require('../lib/index').ParseServer;
+const triggers = require('../lib/triggers');
const validatorFail = () => {
throw 'you are not authorized';
};
@@ -1212,4 +1214,59 @@ describe('ParseLiveQuery', function () {
object.set({ location: secondPoint });
await object.save();
});
+
+ it('does shutdown liveQuery server', async () => {
+ await reconfigureServer({ appId: 'test_app_id' });
+ const config = {
+ appId: 'hello_test',
+ masterKey: 'world',
+ port: 1345,
+ mountPath: '/1',
+ serverURL: 'http://localhost:1345/1',
+ liveQuery: {
+ classNames: ['Yolo'],
+ },
+ startLiveQueryServer: true,
+ };
+ if (process.env.PARSE_SERVER_TEST_DB === 'postgres') {
+ config.databaseAdapter = new databaseAdapter.constructor({
+ uri: databaseURI,
+ collectionPrefix: 'test_',
+ });
+ config.filesAdapter = defaultConfiguration.filesAdapter;
+ }
+ const server = await ParseServer.startApp(config);
+ const client = await Parse.CoreManager.getLiveQueryController().getDefaultLiveQueryClient();
+ client.serverURL = 'ws://localhost:1345/1';
+ const query = await new Parse.Query('Yolo').subscribe();
+ await Promise.all([
+ server.handleShutdown(),
+ new Promise(resolve => query.on('close', resolve)),
+ ]);
+ await new Promise(resolve => setTimeout(resolve, 100));
+ expect(server.liveQueryServer.server.address()).toBeNull();
+ expect(server.liveQueryServer.subscriber.isOpen).toBeFalse();
+ await new Promise(resolve => server.server.close(resolve));
+ });
+
+ it('prevent afterSave trigger if not exists', async () => {
+ await reconfigureServer({
+ liveQuery: {
+ classNames: ['TestObject'],
+ },
+ startLiveQueryServer: true,
+ verbose: false,
+ silent: true,
+ });
+ spyOn(triggers, 'maybeRunTrigger').and.callThrough();
+ const object1 = new TestObject();
+ const object2 = new TestObject();
+ const object3 = new TestObject();
+ await Parse.Object.saveAll([object1, object2, object3]);
+
+ expect(triggers.maybeRunTrigger).toHaveBeenCalledTimes(0);
+ expect(object1.id).toBeDefined();
+ expect(object2.id).toBeDefined();
+ expect(object3.id).toBeDefined();
+ });
});
diff --git a/spec/QueryTools.spec.js b/spec/QueryTools.spec.js
index dbd3c9a5d3..8dbda98b0a 100644
--- a/spec/QueryTools.spec.js
+++ b/spec/QueryTools.spec.js
@@ -125,6 +125,35 @@ describe('matchesQuery', function () {
expect(matchesQuery(obj, q)).toBe(false);
});
+ it('matches queries with eq constraint', function () {
+ const obj = {
+ objectId: 'Person2',
+ score: 12,
+ name: 'Tom',
+ };
+
+ const q1 = {
+ objectId: {
+ $eq: 'Person2',
+ },
+ };
+
+ const q2 = {
+ score: {
+ $eq: 12,
+ },
+ };
+
+ const q3 = {
+ name: {
+ $eq: 'Tom',
+ },
+ };
+ expect(matchesQuery(obj, q1)).toBe(true);
+ expect(matchesQuery(obj, q2)).toBe(true);
+ expect(matchesQuery(obj, q3)).toBe(true);
+ });
+
it('matches on equality queries', function () {
const day = new Date();
const location = new Parse.GeoPoint({
diff --git a/spec/RateLimit.spec.js b/spec/RateLimit.spec.js
index 894c8fcf82..3c57810702 100644
--- a/spec/RateLimit.spec.js
+++ b/spec/RateLimit.spec.js
@@ -335,6 +335,99 @@ describe('rate limit', () => {
await Parse.Cloud.run('test2');
});
+ describe('zone', () => {
+ const middlewares = require('../lib/middlewares');
+ it('can use global zone', async () => {
+ await reconfigureServer({
+ rateLimit: {
+ requestPath: '*',
+ requestTimeWindow: 10000,
+ requestCount: 1,
+ errorResponseMessage: 'Too many requests',
+ includeInternalRequests: true,
+ zone: Parse.Server.RateLimitZone.global,
+ },
+ });
+ const fakeReq = {
+ originalUrl: 'http://example.com/parse/',
+ url: 'http://example.com/',
+ body: {
+ _ApplicationId: 'test',
+ },
+ headers: {
+ 'X-Parse-Application-Id': 'test',
+ 'X-Parse-REST-API-Key': 'rest',
+ },
+ get: key => {
+ return fakeReq.headers[key];
+ },
+ };
+ fakeReq.ip = '127.0.0.1';
+ let fakeRes = jasmine.createSpyObj('fakeRes', ['end', 'status', 'setHeader', 'json']);
+ await new Promise(resolve => middlewares.handleParseHeaders(fakeReq, fakeRes, resolve));
+ fakeReq.ip = '127.0.0.2';
+ fakeRes = jasmine.createSpyObj('fakeRes', ['end', 'status', 'setHeader']);
+ let resolvingPromise;
+ const promise = new Promise(resolve => {
+ resolvingPromise = resolve;
+ });
+ fakeRes.json = jasmine.createSpy('json').and.callFake(resolvingPromise);
+ middlewares.handleParseHeaders(fakeReq, fakeRes, () => {
+ throw 'Should not call next';
+ });
+ await promise;
+ expect(fakeRes.status).toHaveBeenCalledWith(429);
+ expect(fakeRes.json).toHaveBeenCalledWith({
+ code: Parse.Error.CONNECTION_FAILED,
+ error: 'Too many requests',
+ });
+ });
+
+ it('can use session zone', async () => {
+ await reconfigureServer({
+ rateLimit: {
+ requestPath: '/functions/*',
+ requestTimeWindow: 10000,
+ requestCount: 1,
+ errorResponseMessage: 'Too many requests',
+ includeInternalRequests: true,
+ zone: Parse.Server.RateLimitZone.session,
+ },
+ });
+ Parse.Cloud.define('test', () => 'Abc');
+ await Parse.User.signUp('username', 'password');
+ await Parse.Cloud.run('test');
+ await expectAsync(Parse.Cloud.run('test')).toBeRejectedWith(
+ new Parse.Error(Parse.Error.CONNECTION_FAILED, 'Too many requests')
+ );
+ await Parse.User.logIn('username', 'password');
+ await Parse.Cloud.run('test');
+ });
+
+ it('can use user zone', async () => {
+ await reconfigureServer({
+ rateLimit: {
+ requestPath: '/functions/*',
+ requestTimeWindow: 10000,
+ requestCount: 1,
+ errorResponseMessage: 'Too many requests',
+ includeInternalRequests: true,
+ zone: Parse.Server.RateLimitZone.user,
+ },
+ });
+ Parse.Cloud.define('test', () => 'Abc');
+ await Parse.User.signUp('username', 'password');
+ await Parse.Cloud.run('test');
+ await expectAsync(Parse.Cloud.run('test')).toBeRejectedWith(
+ new Parse.Error(Parse.Error.CONNECTION_FAILED, 'Too many requests')
+ );
+ await Parse.User.logIn('username', 'password');
+ await expectAsync(Parse.Cloud.run('test')).toBeRejectedWith(
+ new Parse.Error(Parse.Error.CONNECTION_FAILED, 'Too many requests')
+ );
+ });
+ });
+
it('can validate rateLimit', async () => {
const Config = require('../lib/Config');
const validateRateLimit = ({ rateLimit }) => Config.validateRateLimit(rateLimit);
@@ -350,6 +443,11 @@ describe('rate limit', () => {
expect(() =>
validateRateLimit({ rateLimit: [{ requestTimeWindow: [], requestPath: 'a' }] })
).toThrow('rateLimit.requestTimeWindow must be a number');
+ expect(() =>
+ validateRateLimit({
+ rateLimit: [{ requestPath: 'a', requestTimeWindow: 1000, requestCount: 3, zone: 'abc' }],
+ })
+ ).toThrow('rateLimit.zone must be one of global, session, user, or ip');
expect(() =>
validateRateLimit({
rateLimit: [
diff --git a/spec/SessionTokenCache.spec.js b/spec/SessionTokenCache.spec.js
index de1b101c56..6b3c83df62 100644
--- a/spec/SessionTokenCache.spec.js
+++ b/spec/SessionTokenCache.spec.js
@@ -47,7 +47,7 @@ describe('SessionTokenCache', function () {
sessionTokenCache.getUserId('sessionToken').then(userIdFromCache => {
expect(userIdFromCache).toBe('userId');
- expect(sessionTokenCache.cache.length).toBe(1);
+ expect(sessionTokenCache.cache.size).toBe(1);
done();
});
});
diff --git a/spec/ValidationAndPasswordsReset.spec.js b/spec/ValidationAndPasswordsReset.spec.js
index 3272f07fc3..ab944e14c1 100644
--- a/spec/ValidationAndPasswordsReset.spec.js
+++ b/spec/ValidationAndPasswordsReset.spec.js
@@ -242,8 +242,7 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
});
});
- it('allows user to login only after user clicks on the link to confirm email address if preventLoginWithUnverifiedEmail is set to true', done => {
- const user = new Parse.User();
+ 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 = {
sendVerificationEmail: options => {
@@ -252,59 +251,32 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
sendPasswordResetEmail: () => Promise.resolve(),
sendMail: () => {},
};
- reconfigureServer({
+ await reconfigureServer({
appName: 'emailing app',
verifyUserEmails: true,
preventLoginWithUnverifiedEmail: true,
emailAdapter: emailAdapter,
publicServerURL: 'http://localhost:8378/1',
- })
- .then(() => {
- user.setPassword('other-password');
- user.setUsername('user');
- user.set('email', 'user@parse.com');
- return user.signUp();
- })
- .then(() => {
- expect(sendEmailOptions).not.toBeUndefined();
- request({
- url: sendEmailOptions.link,
- followRedirects: false,
- }).then(response => {
- expect(response.status).toEqual(302);
- expect(response.text).toEqual(
- 'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user'
- );
- user
- .fetch({ useMasterKey: true })
- .then(
- () => {
- expect(user.get('emailVerified')).toEqual(true);
-
- Parse.User.logIn('user', 'other-password').then(
- user => {
- expect(typeof user).toBe('object');
- expect(user.get('emailVerified')).toBe(true);
- done();
- },
- () => {
- fail('login should have succeeded');
- done();
- }
- );
- },
- err => {
- jfail(err);
- fail('this should not fail');
- done();
- }
- )
- .catch(err => {
- jfail(err);
- done();
- });
- });
- });
+ });
+ let user = new Parse.User();
+ user.setPassword('other-password');
+ user.setUsername('user');
+ user.set('email', 'user@example.com');
+ await user.signUp();
+ expect(sendEmailOptions).not.toBeUndefined();
+ const response = await request({
+ url: sendEmailOptions.link,
+ followRedirects: false,
+ });
+ expect(response.status).toEqual(302);
+ expect(response.text).toEqual(
+ 'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=user'
+ );
+ user = await new Parse.Query(Parse.User).first({ useMasterKey: true });
+ expect(user.get('emailVerified')).toEqual(true);
+ user = await Parse.User.logIn('user', 'other-password');
+ expect(typeof user).toBe('object');
+ expect(user.get('emailVerified')).toBe(true);
});
it('allows user to login if email is not verified but preventLoginWithUnverifiedEmail is set to false', done => {
@@ -345,6 +317,35 @@ describe('Custom Pages, Email Verification, Password Reset', () => {
});
});
+ it('does not allow signup with preventSignupWithUnverified', async () => {
+ let sendEmailOptions;
+ const emailAdapter = {
+ sendVerificationEmail: options => {
+ sendEmailOptions = options;
+ },
+ sendPasswordResetEmail: () => Promise.resolve(),
+ sendMail: () => {},
+ };
+ await reconfigureServer({
+ appName: 'test',
+ publicServerURL: 'http://localhost:1337/1',
+ verifyUserEmails: true,
+ preventLoginWithUnverifiedEmail: true,
+ preventSignupWithUnverifiedEmail: true,
+ emailAdapter,
+ });
+ const newUser = new Parse.User();
+ newUser.setPassword('asdf');
+ newUser.setUsername('zxcv');
+ newUser.set('email', 'test@example.com');
+ await expectAsync(newUser.signUp()).toBeRejectedWith(
+ new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.')
+ );
+ const user = await new Parse.Query(Parse.User).first({ useMasterKey: true });
+ expect(user).toBeDefined();
+ expect(sendEmailOptions).toBeDefined();
+ });
+
it('fails if you include an emailAdapter, set a publicServerURL, but have no appName and send a password reset email', done => {
reconfigureServer({
appName: undefined,
diff --git a/spec/VerifyUserPassword.spec.js b/spec/VerifyUserPassword.spec.js
index 6734dcdb71..eef2485815 100644
--- a/spec/VerifyUserPassword.spec.js
+++ b/spec/VerifyUserPassword.spec.js
@@ -353,8 +353,9 @@ describe('Verify User Password', () => {
done();
});
});
- it('fails to verify password when preventLoginWithUnverifiedEmail is set to true REST API', done => {
- reconfigureServer({
+
+ it('fails to verify password when preventLoginWithUnverifiedEmail is set to true REST API', async () => {
+ await reconfigureServer({
publicServerURL: 'http://localhost:8378/',
appName: 'emailVerify',
verifyUserEmails: true,
@@ -364,28 +365,21 @@ describe('Verify User Password', () => {
apiKey: 'k',
domain: 'd',
}),
- })
- .then(() => {
- const user = new Parse.User();
- return user.save({
- username: 'unverified-user',
- password: 'mypass',
- email: 'unverified-email@user.com',
- });
- })
- .then(() => {
- return verifyPassword('unverified-email@user.com', 'mypass', true);
- })
- .then(res => {
- expect(res.status).toBe(400);
- expect(res.text).toMatch('{"code":205,"error":"User email is not verified."}');
- done();
- })
- .catch(err => {
- fail(err);
- done();
- });
+ });
+ const user = new Parse.User();
+ await user.save({
+ username: 'unverified-user',
+ password: 'mypass',
+ email: 'unverified-email@example.com',
+ });
+ const res = await verifyPassword('unverified-email@example.com', 'mypass', true);
+ expect(res.status).toBe(400);
+ expect(res.data).toEqual({
+ code: Parse.Error.EMAIL_NOT_FOUND,
+ error: 'User email is not verified.',
+ });
});
+
it('verify password lock account if failed verify password attempts are above threshold', done => {
reconfigureServer({
appName: 'lockout threshold',
diff --git a/spec/index.spec.js b/spec/index.spec.js
index 08ef16a77b..66654aaec4 100644
--- a/spec/index.spec.js
+++ b/spec/index.spec.js
@@ -367,6 +367,22 @@ describe('server', () => {
});
});
+ it('should throw when extendSessionOnUse is invalid', async () => {
+ await expectAsync(
+ reconfigureServer({
+ extendSessionOnUse: 'yolo',
+ })
+ ).toBeRejectedWith('extendSessionOnUse must be a boolean value');
+ });
+
+ it('should throw when revokeSessionOnPasswordReset is invalid', async () => {
+ await expectAsync(
+ reconfigureServer({
+ revokeSessionOnPasswordReset: 'yolo',
+ })
+ ).toBeRejectedWith('revokeSessionOnPasswordReset must be a boolean value');
+ });
+
it('fails if the session length is not a number', done => {
reconfigureServer({ sessionLength: 'test' })
.then(done.fail)
diff --git a/src/Adapters/Cache/LRUCache.js b/src/Adapters/Cache/LRUCache.js
index f54d8503f9..129a006376 100644
--- a/src/Adapters/Cache/LRUCache.js
+++ b/src/Adapters/Cache/LRUCache.js
@@ -1,4 +1,4 @@
-import LRU from 'lru-cache';
+import { LRUCache as LRU } from 'lru-cache';
import defaults from '../../defaults';
export class LRUCache {
diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js
index f2b9c48fad..451165789d 100644
--- a/src/Adapters/Files/GridFSBucketAdapter.js
+++ b/src/Adapters/Files/GridFSBucketAdapter.js
@@ -34,7 +34,11 @@ export class GridFSBucketAdapter extends FilesAdapter {
useNewUrlParser: true,
useUnifiedTopology: true,
};
- this._mongoOptions = Object.assign(defaultMongoOptions, mongoOptions);
+ const _mongoOptions = Object.assign(defaultMongoOptions, mongoOptions);
+ for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'maxTimeMS']) {
+ delete _mongoOptions[key];
+ }
+ this._mongoOptions = _mongoOptions;
}
_connect() {
diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
index 78833a026b..2f59819895 100644
--- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
+++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
@@ -212,11 +212,12 @@ export class MongoStorageAdapter implements StorageAdapter {
throw error;
}
- handleShutdown() {
+ async handleShutdown() {
if (!this.client) {
- return Promise.resolve();
+ return;
}
- return this.client.close(false);
+ await this.client.close(false);
+ delete this.connectionPromise;
}
_adaptiveCollection(name: string) {
diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
index 82ac0c20dc..3e8e867799 100644
--- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
+++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js
@@ -1194,7 +1194,9 @@ export class PostgresStorageAdapter implements StorageAdapter {
const now = new Date().getTime();
const helpers = this._pgp.helpers;
debug('deleteAllClasses');
-
+ if (this._client?.$pool.ended) {
+ return;
+ }
await this._client
.task('delete-all-classes', async t => {
try {
diff --git a/src/Auth.js b/src/Auth.js
index abd14391db..96c99cbb1d 100644
--- a/src/Auth.js
+++ b/src/Auth.js
@@ -3,6 +3,8 @@ import { isDeepStrictEqual } from 'util';
import { getRequestObject, resolveError } from './triggers';
import Deprecator from './Deprecator/Deprecator';
import { logger } from './logger';
+import RestQuery from './RestQuery';
+import RestWrite from './RestWrite';
// An Auth object tells you who is requesting something and whether
// the master key was used.
@@ -66,6 +68,46 @@ function nobody(config) {
return new Auth({ config, isMaster: false });
}
+const throttle = {};
+const renewSessionIfNeeded = async ({ config, session, sessionToken }) => {
+ if (!config?.extendSessionOnUse) {
+ return;
+ }
+ clearTimeout(throttle[sessionToken]);
+ throttle[sessionToken] = setTimeout(async () => {
+ try {
+ if (!session) {
+ const { results } = await new RestQuery(
+ config,
+ master(config),
+ '_Session',
+ { sessionToken },
+ { limit: 1 }
+ ).execute();
+ session = results[0];
+ }
+ const lastUpdated = new Date(session?.updatedAt);
+ const yesterday = new Date();
+ yesterday.setDate(yesterday.getDate() - 1);
+ if (lastUpdated > yesterday || !session) {
+ return;
+ }
+ const expiresAt = config.generateSessionExpiresAt();
+ await new RestWrite(
+ config,
+ master(config),
+ '_Session',
+ { objectId: session.objectId },
+ { expiresAt: Parse._encode(expiresAt) }
+ ).execute();
+ } catch (e) {
+ if (e?.code !== Parse.Error.OBJECT_NOT_FOUND) {
+ logger.error('Could not update session expiry: ', e);
+ }
+ }
+ }, 500);
+};
+
// Returns a promise that resolves to an Auth object
const getAuthForSessionToken = async function ({
config,
@@ -78,6 +120,7 @@ const getAuthForSessionToken = async function ({
const userJSON = await cacheController.user.get(sessionToken);
if (userJSON) {
const cachedUser = Parse.Object.fromJSON(userJSON);
+ renewSessionIfNeeded({ config, sessionToken });
return Promise.resolve(
new Auth({
config,
@@ -112,18 +155,20 @@ const getAuthForSessionToken = async function ({
if (results.length !== 1 || !results[0]['user']) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Invalid session token');
}
+ const session = results[0];
const now = new Date(),
- expiresAt = results[0].expiresAt ? new Date(results[0].expiresAt.iso) : undefined;
+ expiresAt = session.expiresAt ? new Date(session.expiresAt.iso) : undefined;
if (expiresAt < now) {
throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token is expired.');
}
- const obj = results[0]['user'];
+ const obj = session.user;
delete obj.password;
obj['className'] = '_User';
obj['sessionToken'] = sessionToken;
if (cacheController) {
cacheController.user.put(sessionToken, obj);
}
+ renewSessionIfNeeded({ config, session, sessionToken });
const userObject = Parse.Object.fromJSON(obj);
return new Auth({
config,
diff --git a/src/Config.js b/src/Config.js
index 1cd941efe9..5e3a49bb35 100644
--- a/src/Config.js
+++ b/src/Config.js
@@ -18,6 +18,7 @@ import {
SchemaOptions,
SecurityOptions,
} from './Options/Definitions';
+import ParseServer from './cloud-code/Parse.Server';
function removeTrailingSlash(str) {
if (!str) {
@@ -86,6 +87,7 @@ export class Config {
logLevels,
rateLimit,
databaseOptions,
+ extendSessionOnUse,
}) {
if (masterKey === readOnlyMasterKey) {
throw new Error('masterKey and readOnlyMasterKey should be different');
@@ -103,6 +105,10 @@ export class Config {
throw 'revokeSessionOnPasswordReset must be a boolean value';
}
+ if (typeof extendSessionOnUse !== 'boolean') {
+ throw 'extendSessionOnUse must be a boolean value';
+ }
+
if (publicServerURL) {
if (!publicServerURL.startsWith('http://') && !publicServerURL.startsWith('https://')) {
throw 'publicServerURL should be a valid HTTPS URL starting with https://';
@@ -604,6 +610,11 @@ export class Config {
if (option.errorResponseMessage && typeof option.errorResponseMessage !== 'string') {
throw `rateLimit.errorResponseMessage must be a string`;
}
+ const options = Object.keys(ParseServer.RateLimitZone);
+ if (option.zone && !options.includes(option.zone)) {
+ const formatter = new Intl.ListFormat('en', { style: 'short', type: 'disjunction' });
+ throw `rateLimit.zone must be one of ${formatter.format(options)}`;
+ }
}
}
diff --git a/src/Controllers/HooksController.js b/src/Controllers/HooksController.js
index 9cc5f427e8..277104ef32 100644
--- a/src/Controllers/HooksController.js
+++ b/src/Controllers/HooksController.js
@@ -144,7 +144,7 @@ export class HooksController {
if (aHook.functionName) {
return this.getFunction(aHook.functionName).then(result => {
if (result) {
- throw new Parse.Error(143, `function name: ${aHook.functionName} already exits`);
+ throw new Parse.Error(143, `function name: ${aHook.functionName} already exists`);
} else {
return this.createOrUpdateHook(aHook);
}
diff --git a/src/LiveQuery/ParseLiveQueryServer.js b/src/LiveQuery/ParseLiveQueryServer.js
index 0b71265f33..d0b535f3a1 100644
--- a/src/LiveQuery/ParseLiveQueryServer.js
+++ b/src/LiveQuery/ParseLiveQueryServer.js
@@ -19,7 +19,7 @@ import {
} from '../triggers';
import { getAuthForSessionToken, Auth } from '../Auth';
import { getCacheController, getDatabaseController } from '../Controllers';
-import LRU from 'lru-cache';
+import { LRUCache as LRU } from 'lru-cache';
import UserRouter from '../Routers/UsersRouter';
import DatabaseController from '../Controllers/DatabaseController';
import { isDeepStrictEqual } from 'util';
@@ -93,6 +93,21 @@ class ParseLiveQueryServer {
}
this._createSubscribers();
}
+
+ async shutdown() {
+ if (this.subscriber.isOpen) {
+ await Promise.all([
+ ...[...this.clients.values()].map(client => client.parseWebSocket.ws.close()),
+ this.parseWebSocketServer.close(),
+ ...Array.from(this.subscriber.subscriptions.keys()).map(key =>
+ this.subscriber.unsubscribe(key)
+ ),
+ this.subscriber.close?.(),
+ ]);
+ }
+ this.subscriber.isOpen = false;
+ }
+
_createSubscribers() {
const messageRecieved = (channel, messageStr) => {
logger.verbose('Subscribe message %j', messageStr);
@@ -518,7 +533,7 @@ class ParseLiveQueryServer {
]);
auth1.auth?.clearRoleCache(sessionToken);
auth2.auth?.clearRoleCache(sessionToken);
- this.authCache.del(sessionToken);
+ this.authCache.delete(sessionToken);
})
);
} catch (e) {
@@ -548,7 +563,7 @@ class ParseLiveQueryServer {
result.error = error;
this.authCache.set(sessionToken, Promise.resolve(result), this.config.cacheTimeout);
} else {
- this.authCache.del(sessionToken);
+ this.authCache.delete(sessionToken);
}
return result;
});
diff --git a/src/LiveQuery/QueryTools.js b/src/LiveQuery/QueryTools.js
index 50d8d3394a..1607278f46 100644
--- a/src/LiveQuery/QueryTools.js
+++ b/src/LiveQuery/QueryTools.js
@@ -247,6 +247,11 @@ function matchesKeyConstraints(object, key, constraints) {
return false;
}
break;
+ case '$eq':
+ if (!equalObjects(object[key], compareTo)) {
+ return false;
+ }
+ break;
case '$ne':
if (equalObjects(object[key], compareTo)) {
return false;
diff --git a/src/LiveQuery/SessionTokenCache.js b/src/LiveQuery/SessionTokenCache.js
index 13b84c7367..a7f52b65a0 100644
--- a/src/LiveQuery/SessionTokenCache.js
+++ b/src/LiveQuery/SessionTokenCache.js
@@ -1,5 +1,5 @@
import Parse from 'parse/node';
-import LRU from 'lru-cache';
+import { LRUCache as LRU } from 'lru-cache';
import logger from '../logger';
function userForSessionToken(sessionToken) {
diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js
index 85dbeaa83f..3815902c51 100644
--- a/src/Options/Definitions.js
+++ b/src/Options/Definitions.js
@@ -227,6 +227,12 @@ module.exports.ParseServerOptions = {
action: parsers.booleanParser,
default: true,
},
+ extendSessionOnUse: {
+ env: 'PARSE_SERVER_EXTEND_SESSION_ON_USE',
+ help: 'Whether Parse Server should automatically extend a valid session by the sessionLength',
+ action: parsers.booleanParser,
+ default: false,
+ },
fileKey: {
env: 'PARSE_SERVER_FILE_KEY',
help: 'Key for your files',
@@ -406,6 +412,13 @@ module.exports.ParseServerOptions = {
action: parsers.booleanParser,
default: false,
},
+ preventSignupWithUnverifiedEmail: {
+ env: 'PARSE_SERVER_PREVENT_SIGNUP_WITH_UNVERIFIED_EMAIL',
+ help:
+ "If set to `true` it prevents a user from signing up if the email has not yet been verified and email verification is required. In that case the server responds to the sign-up with HTTP status 400 and a Parse Error 205 `EMAIL_NOT_FOUND`. If set to `false` the server responds with HTTP status 200, and client SDKs return an unauthenticated Parse User without session token. In that case subsequent requests fail until the user's email address is verified.
Default is `false`.
Requires option `verifyUserEmails: true`.",
+ action: parsers.booleanParser,
+ default: false,
+ },
protectedFields: {
env: 'PARSE_SERVER_PROTECTED_FIELDS',
help: 'Protected fields that should be treated with extra security when fetching details.',
@@ -588,6 +601,11 @@ module.exports.RateLimitOptions = {
'The window of time in milliseconds within which the number of requests set in `requestCount` can be made before the rate limit is applied.',
action: parsers.numberParser('requestTimeWindow'),
},
+ zone: {
+ env: 'PARSE_SERVER_RATE_LIMIT_ZONE',
+ help:
+ "The type of rate limit to apply. The following types are supported:
- `global`: rate limit based on the number of requests made by all users
- `ip`: rate limit based on the IP address of the request
- `user`: rate limit based on the user ID of the request
- `session`: rate limit based on the session token of the request
:default: 'ip'",
+ },
};
module.exports.SecurityOptions = {
checkGroups: {
@@ -1000,6 +1018,16 @@ module.exports.AuthAdapter = {
},
};
module.exports.LogLevels = {
+ cloudFunctionError: {
+ env: 'PARSE_SERVER_LOG_LEVELS_CLOUD_FUNCTION_ERROR',
+ help: 'Log level used by the Cloud Code Functions on error. Default is `error`.',
+ default: 'error',
+ },
+ cloudFunctionSuccess: {
+ env: 'PARSE_SERVER_LOG_LEVELS_CLOUD_FUNCTION_SUCCESS',
+ help: 'Log level used by the Cloud Code Functions on success. Default is `info`.',
+ default: 'info',
+ },
triggerAfter: {
env: 'PARSE_SERVER_LOG_LEVELS_TRIGGER_AFTER',
help:
diff --git a/src/Options/docs.js b/src/Options/docs.js
index 3b48bc2a20..847e7df944 100644
--- a/src/Options/docs.js
+++ b/src/Options/docs.js
@@ -43,6 +43,7 @@
* @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.
+ * @property {Boolean} extendSessionOnUse Whether Parse Server should automatically extend a valid session by the sessionLength
* @property {String} fileKey Key for your files
* @property {Adapter} filesAdapter Adapter module for the files sub-system
* @property {FileUploadOptions} fileUpload Options for file uploads
@@ -76,6 +77,7 @@
* @property {Number} port The port to run the ParseServer, defaults to 1337.
* @property {Boolean} preserveFileName Enable (or disable) the addition of a unique hash to the file names
* @property {Boolean} preventLoginWithUnverifiedEmail 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`.
Requires option `verifyUserEmails: true`.
+ * @property {Boolean} preventSignupWithUnverifiedEmail If set to `true` it prevents a user from signing up if the email has not yet been verified and email verification is required. In that case the server responds to the sign-up with HTTP status 400 and a Parse Error 205 `EMAIL_NOT_FOUND`. If set to `false` the server responds with HTTP status 200, and client SDKs return an unauthenticated Parse User without session token. In that case subsequent requests fail until the user's email address is verified.
Default is `false`.
Requires option `verifyUserEmails: true`.
* @property {ProtectedFields} protectedFields Protected fields that should be treated with extra security when fetching details.
* @property {String} publicServerURL Public URL to your parse server with http:// or https://.
* @property {Any} push Configuration for push, as stringified JSON. See http://docs.parseplatform.org/parse-server/guide/#push-notifications
@@ -109,6 +111,7 @@
* @property {String[]} requestMethods Optional, the HTTP request methods to which the rate limit should be applied, default is all methods.
* @property {String} requestPath The path of the API route to be rate limited. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expression. See: https://expressjs.com/en/guide/routing.html
* @property {Number} requestTimeWindow The window of time in milliseconds within which the number of requests set in `requestCount` can be made before the rate limit is applied.
+ * @property {String} zone The type of rate limit to apply. The following types are supported:
- `global`: rate limit based on the number of requests made by all users
- `ip`: rate limit based on the IP address of the request
- `user`: rate limit based on the user ID of the request
- `session`: rate limit based on the session token of the request
:default: 'ip'
*/
/**
@@ -237,6 +240,8 @@
/**
* @interface LogLevels
+ * @property {String} cloudFunctionError Log level used by the Cloud Code Functions on error. Default is `error`.
+ * @property {String} cloudFunctionSuccess Log level used by the Cloud Code Functions on success. Default is `info`.
* @property {String} triggerAfter Log level used by the Cloud Code Triggers `afterSave`, `afterDelete`, `afterSaveFile`, `afterDeleteFile`, `afterFind`, `afterLogout`. Default is `info`.
* @property {String} triggerBeforeError Log level used by the Cloud Code Triggers `beforeSave`, `beforeSaveFile`, `beforeDeleteFile`, `beforeFind`, `beforeLogin` on error. Default is `error `.
* @property {String} triggerBeforeSuccess Log level used by the Cloud Code Triggers `beforeSave`, `beforeSaveFile`, `beforeDeleteFile`, `beforeFind`, `beforeLogin` on success. Default is `info`.
diff --git a/src/Options/index.js b/src/Options/index.js
index fc4b269f0a..87813147f7 100644
--- a/src/Options/index.js
+++ b/src/Options/index.js
@@ -165,6 +165,13 @@ export interface ParseServerOptions {
Requires option `verifyUserEmails: true`.
:DEFAULT: false */
preventLoginWithUnverifiedEmail: ?boolean;
+ /* If set to `true` it prevents a user from signing up if the email has not yet been verified and email verification is required. In that case the server responds to the sign-up with HTTP status 400 and a Parse Error 205 `EMAIL_NOT_FOUND`. If set to `false` the server responds with HTTP status 200, and client SDKs return an unauthenticated Parse User without session token. In that case subsequent requests fail until the user's email address is verified.
+
+ Default is `false`.
+
+ Requires option `verifyUserEmails: true`.
+ :DEFAULT: false */
+ preventSignupWithUnverifiedEmail: ?boolean;
/* 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).
@@ -203,6 +210,9 @@ export interface ParseServerOptions {
/* Session duration, in seconds, defaults to 1 year
:DEFAULT: 31536000 */
sessionLength: ?number;
+ /* Whether Parse Server should automatically extend a valid session by the sessionLength
+ :DEFAULT: false */
+ extendSessionOnUse: ?boolean;
/* Default value for limit option on queries, defaults to `100`.
:DEFAULT: 100 */
defaultLimit: ?number;
@@ -324,6 +334,17 @@ export interface RateLimitOptions {
/* Optional, the URL of the Redis server to store rate limit data. This allows to rate limit requests for multiple servers by calculating the sum of all requests across all servers. This is useful if multiple servers are processing requests behind a load balancer. For example, the limit of 10 requests is reached if each of 2 servers processed 5 requests.
*/
redisUrl: ?string;
+ /*
+ The type of rate limit to apply. The following types are supported:
+
+ - `global`: rate limit based on the number of requests made by all users
+ - `ip`: rate limit based on the IP address of the request
+ - `user`: rate limit based on the user ID of the request
+ - `session`: rate limit based on the session token of the request
+
+ :default: 'ip'
+ */
+ zone: ?string;
}
export interface SecurityOptions {
@@ -580,4 +601,12 @@ export interface LogLevels {
:DEFAULT: error
*/
triggerBeforeError: ?string;
+ /* Log level used by the Cloud Code Functions on success. Default is `info`.
+ :DEFAULT: info
+ */
+ cloudFunctionSuccess: ?string;
+ /* Log level used by the Cloud Code Functions on error. Default is `error`.
+ :DEFAULT: error
+ */
+ cloudFunctionError: ?string;
}
diff --git a/src/ParseServer.js b/src/ParseServer.js
index 04379ecfd3..6465e1f3c9 100644
--- a/src/ParseServer.js
+++ b/src/ParseServer.js
@@ -168,6 +168,12 @@ class ParseServer {
if (cacheAdapter && typeof cacheAdapter.handleShutdown === 'function') {
promises.push(cacheAdapter.handleShutdown());
}
+ if (this.liveQueryServer?.server?.close) {
+ promises.push(new Promise(resolve => this.liveQueryServer.server.close(resolve)));
+ }
+ if (this.liveQueryServer) {
+ promises.push(this.liveQueryServer.shutdown());
+ }
return (promises.length > 0 ? Promise.all(promises) : Promise.resolve()).then(() => {
if (this.config.serverCloseComplete) {
this.config.serverCloseComplete();
@@ -438,9 +444,11 @@ class ParseServer {
function addParseCloud() {
const ParseCloud = require('./cloud-code/Parse.Cloud');
+ const ParseServer = require('./cloud-code/Parse.Server');
Object.defineProperty(Parse, 'Server', {
get() {
- return Config.get(Parse.applicationId);
+ const conf = Config.get(Parse.applicationId);
+ return { ...conf, ...ParseServer };
},
set(newVal) {
newVal.appId = Parse.applicationId;
diff --git a/src/RestWrite.js b/src/RestWrite.js
index 3a8385e52a..f7c6a53592 100644
--- a/src/RestWrite.js
+++ b/src/RestWrite.js
@@ -160,6 +160,9 @@ RestWrite.prototype.execute = function () {
this.response.response.authDataResponse = this.authDataResponse;
}
}
+ if (this.storage.rejectSignup && this.config.preventSignupWithUnverifiedEmail) {
+ throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.');
+ }
return this.response;
});
};
@@ -879,7 +882,8 @@ RestWrite.prototype.createSessionTokenIfNeeded = function () {
this.config.verifyUserEmails
) {
// verification is on
- return; // do not create the session token in that case!
+ this.storage.rejectSignup = true;
+ return;
}
return this.createSessionToken();
};
@@ -1577,17 +1581,21 @@ RestWrite.prototype.runAfterSaveTrigger = function () {
const { originalObject, updatedObject } = this.buildParseObjects();
updatedObject._handleSaveResponse(this.response.response, this.response.status || 200);
- this.config.database.loadSchema().then(schemaController => {
- // Notifiy LiveQueryServer if possible
- const perms = schemaController.getClassLevelPermissions(updatedObject.className);
- this.config.liveQueryController.onAfterSave(
- updatedObject.className,
- updatedObject,
- originalObject,
- perms
- );
- });
-
+ if (hasLiveQuery) {
+ this.config.database.loadSchema().then(schemaController => {
+ // Notify LiveQueryServer if possible
+ const perms = schemaController.getClassLevelPermissions(updatedObject.className);
+ this.config.liveQueryController.onAfterSave(
+ updatedObject.className,
+ updatedObject,
+ originalObject,
+ perms
+ );
+ });
+ }
+ if (!hasAfterSaveHook) {
+ return Promise.resolve();
+ }
// Run afterSave trigger
return triggers
.maybeRunTrigger(
diff --git a/src/Routers/FunctionsRouter.js b/src/Routers/FunctionsRouter.js
index d239908103..da69d54e0c 100644
--- a/src/Routers/FunctionsRouter.js
+++ b/src/Routers/FunctionsRouter.js
@@ -18,6 +18,12 @@ function parseObject(obj) {
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') {
+ return Parse.Object.fromJSON({
+ __type: 'Pointer',
+ className: obj.className,
+ objectId: obj.objectId,
+ });
} else if (obj && typeof obj === 'object') {
return parseParams(obj);
} else {
@@ -140,7 +146,7 @@ export class FunctionsRouter extends PromiseRouter {
result => {
try {
const cleanResult = logger.truncateLogMessage(JSON.stringify(result.response.result));
- logger.info(
+ logger[req.config.logLevels.cloudFunctionSuccess](
`Ran cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Result: ${cleanResult}`,
{
functionName,
@@ -155,7 +161,7 @@ export class FunctionsRouter extends PromiseRouter {
},
error => {
try {
- logger.error(
+ logger[req.config.logLevels.cloudFunctionError](
`Failed running cloud function ${functionName} for user ${userString} with:\n Input: ${cleanInput}\n Error: ` +
JSON.stringify(error),
{
diff --git a/src/cli/utils/commander.js b/src/cli/utils/commander.js
index 8b8826fe69..75075bb3ac 100644
--- a/src/cli/utils/commander.js
+++ b/src/cli/utils/commander.js
@@ -136,5 +136,5 @@ Command.prototype.getOptions = function () {
}, {});
};
-export default new Command();
+export default new Command().storeOptionsAsProperties();
/* eslint-enable no-console */
diff --git a/src/cloud-code/Parse.Cloud.js b/src/cloud-code/Parse.Cloud.js
index 5540e8d719..01bf65f42c 100644
--- a/src/cloud-code/Parse.Cloud.js
+++ b/src/cloud-code/Parse.Cloud.js
@@ -82,9 +82,9 @@ const getRoute = parseClass => {
'@File': 'files',
}[parseClass] || 'classes';
if (parseClass === '@File') {
- return `/${route}/:id?*`;
+ return `/${route}/:id?(.*)`;
}
- return `/${route}/${parseClass}/:id?*`;
+ return `/${route}/${parseClass}/:id?(.*)`;
};
/** @namespace
* @name Parse
diff --git a/src/cloud-code/Parse.Server.js b/src/cloud-code/Parse.Server.js
new file mode 100644
index 0000000000..71295618f2
--- /dev/null
+++ b/src/cloud-code/Parse.Server.js
@@ -0,0 +1,19 @@
+const ParseServer = {};
+/**
+ * ...
+ *
+ * @memberof Parse.Server
+ * @property {String} global Rate limit based on the number of requests made by all users.
+ * @property {String} session Rate limit based on the sessionToken.
+ * @property {String} user Rate limit based on the user ID.
+ * @property {String} ip Rate limit based on the request ip.
+ * ...
+ */
+ParseServer.RateLimitZone = Object.freeze({
+ global: 'global',
+ session: 'session',
+ user: 'user',
+ ip: 'ip',
+});
+
+module.exports = ParseServer;
diff --git a/src/middlewares.js b/src/middlewares.js
index 2e450f3e03..a7e309b0cc 100644
--- a/src/middlewares.js
+++ b/src/middlewares.js
@@ -9,7 +9,7 @@ import MongoStorageAdapter from './Adapters/Storage/Mongo/MongoStorageAdapter';
import PostgresStorageAdapter from './Adapters/Storage/Postgres/PostgresStorageAdapter';
import rateLimit from 'express-rate-limit';
import { RateLimitOptions } from './Options/Definitions';
-import pathToRegexp from 'path-to-regexp';
+import { pathToRegexp } from 'path-to-regexp';
import ipRangeCheck from 'ip-range-check';
import RedisStore from 'rate-limit-redis';
import { createClient } from 'redis';
@@ -512,8 +512,12 @@ export const addRateLimit = (route, config, cloud) => {
},
});
}
+ let transformPath = route.requestPath.split('/*').join('/(.*)');
+ if (transformPath === '*') {
+ transformPath = '(.*)';
+ }
config.rateLimits.push({
- path: pathToRegexp(route.requestPath),
+ path: pathToRegexp(transformPath),
handler: rateLimit({
windowMs: route.requestTimeWindow,
max: route.requestCount,
@@ -545,7 +549,22 @@ export const addRateLimit = (route, config, cloud) => {
}
return request.auth?.isMaster;
},
- keyGenerator: request => {
+ keyGenerator: async request => {
+ if (route.zone === Parse.Server.RateLimitZone.global) {
+ return request.config.appId;
+ }
+ const token = request.info.sessionToken;
+ if (route.zone === Parse.Server.RateLimitZone.session && token) {
+ return token;
+ }
+ if (route.zone === Parse.Server.RateLimitZone.user && token) {
+ if (!request.auth) {
+ await new Promise(resolve => handleParseSession(request, null, resolve));
+ }
+ if (request.auth?.user?.id && request.zone === 'user') {
+ return request.auth.user.id;
+ }
+ }
return request.config.ip;
},
store: redisStore.store,