From b6a66761f049ce5c9fe0a83d755c85e7da284439 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Mon, 1 Nov 2021 17:28:37 +0100 Subject: [PATCH 01/89] docs: enable badge and changelog for beta release --- CHANGELOG.md | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9777056..7c12e7cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ Details: - Purpose: official release - Suitable environment: production - +- Suitable environment: development ## 🔥 [Alpha Releases][log_alpha] diff --git a/README.md b/README.md index a25752cc..5bd80335 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ [![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) [![npm latest version](https://img.shields.io/npm/v/parse-server/latest.svg)](https://www.npmjs.com/package/parse-server) +[![npm beta version](https://img.shields.io/npm/v/parse-server/beta.svg)](https://www.npmjs.com/package/parse-server) [![npm alpha version](https://img.shields.io/npm/v/parse-server/alpha.svg)](https://www.npmjs.com/package/parse-server) - [![Backers on Open Collective](https://opencollective.com/parse-server/backers/badge.svg)][open-collective-link] [![Sponsors on Open Collective](https://opencollective.com/parse-server/sponsors/badge.svg)][open-collective-link] From 69fd494ab2198cb97eed0e432ca0f13b5f972290 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 3 Nov 2021 23:03:13 +0100 Subject: [PATCH 02/89] docs: add bronze sponsor and add sponsor widgets to README --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5bd80335..f787ab63 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ [![Build Status](https://github.com/parse-community/parse-server/workflows/ci/badge.svg?branch=alpha)](https://github.com/parse-community/parse-server/actions?query=workflow%3Aci+branch%3Aalpha) [![Snyk Badge](https://snyk.io/test/github/parse-community/parse-server/badge.svg)](https://snyk.io/test/github/parse-community/parse-server) [![Coverage](https://img.shields.io/codecov/c/github/parse-community/parse-server/alpha.svg)](https://codecov.io/github/parse-community/parse-server?branch=alpha) +[![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) [![Node Version](https://img.shields.io/badge/nodejs-12,_14,_15-green.svg?logo=node.js&style=flat)](https://nodejs.org) [![MongoDB Version](https://img.shields.io/badge/mongodb-4.0,_4.2,_4.4,_5.0-green.svg?logo=mongodb&style=flat)](https://www.mongodb.com) [![Postgres Version](https://img.shields.io/badge/postgresql-11,_12,_13,_14-green.svg?logo=postgresql&style=flat)](https://www.postgresql.org) -[![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) [![npm latest version](https://img.shields.io/npm/v/parse-server/latest.svg)](https://www.npmjs.com/package/parse-server) [![npm beta version](https://img.shields.io/npm/v/parse-server/beta.svg)](https://www.npmjs.com/package/parse-server) @@ -29,11 +29,15 @@ The full documentation for Parse Server is available in the [wiki](https://githu --- -A big *thank you* to all our backers and sponsors who support the development of Parse Platform! +A big *thank you* 🙏 to all our backers and sponsors who support the development of Parse Platform! -### 💎 Diamond Sponsors - -[![Sponsor](https://opencollective.com/parse-server/sponsor/0/avatar.svg)](https://opencollective.com/parse-server/sponsor/0/website) +### Diamond Sponsors + +![Diamond Sponsors](https://opencollective.com/parse-server/tiers/diamond-sponsor.svg?avatarHeight=70&button=false) + +#### Bronze Sponsors + +![Bronze Sponsors](https://opencollective.com/parse-server/tiers/bronze-sponsor.svg?avatarHeight=36&button=false) --- From 31960b59b04dac5ea967118d6fc3f49850225289 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 3 Nov 2021 23:44:24 +0100 Subject: [PATCH 03/89] docs: fix sponsor links in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f787ab63..77bc0c47 100644 --- a/README.md +++ b/README.md @@ -29,15 +29,15 @@ The full documentation for Parse Server is available in the [wiki](https://githu --- -A big *thank you* 🙏 to all our backers and sponsors who support the development of Parse Platform! +A big *thank you* 🙏 to our [sponsors](#sponsors) and [backers](#backers) who support the development of Parse Platform! ### Diamond Sponsors -![Diamond Sponsors](https://opencollective.com/parse-server/tiers/diamond-sponsor.svg?avatarHeight=70&button=false) +[![Diamond Sponsors](https://opencollective.com/parse-server/tiers/diamond-sponsor.svg?avatarHeight=70&button=false)](https://opencollective.com/parse-server/contribute/diamond-sponsor-10560) #### Bronze Sponsors -![Bronze Sponsors](https://opencollective.com/parse-server/tiers/bronze-sponsor.svg?avatarHeight=36&button=false) +[![Bronze Sponsors](https://opencollective.com/parse-server/tiers/bronze-sponsor.svg?avatarHeight=36&button=false)](https://opencollective.com/parse-server/contribute/bronze-sponsor-10559) --- From 611bd9baaa29bfa25b5a8592c8465f2572ff3f65 Mon Sep 17 00:00:00 2001 From: Corey Date: Sun, 7 Nov 2021 19:30:15 -0500 Subject: [PATCH 04/89] docs: add FS storage to docs (#7681) --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 77bc0c47..5a8a5d7d 100644 --- a/README.md +++ b/README.md @@ -489,11 +489,12 @@ You can also find more adapters maintained by the community by searching on [npm Parse Server allows developers to choose from several options when hosting files: -* `GridFSBucketAdapter`, which is backed by MongoDB; -* `S3Adapter`, which is backed by [Amazon S3](https://aws.amazon.com/s3/); or -* `GCSAdapter`, which is backed by [Google Cloud Storage](https://cloud.google.com/storage/) +* `GridFSBucketAdapter` - which is backed by MongoDB +* `S3Adapter` - which is backed by [Amazon S3](https://aws.amazon.com/s3/) +* `GCSAdapter` - which is backed by [Google Cloud Storage](https://cloud.google.com/storage/) +* `FSAdapter` - local file storage -`GridFSBucketAdapter` is used by default and requires no setup, but if you're interested in using S3 or Google Cloud Storage, additional configuration information is available in the [Parse Server guide](http://docs.parseplatform.org/parse-server/guide/#configuring-file-adapters). +`GridFSBucketAdapter` is used by default and requires no setup, but if you're interested in using Amazon S3, Google Cloud Storage, or local file storage, additional configuration information is available in the [Parse Server guide](http://docs.parseplatform.org/parse-server/guide/#configuring-file-adapters). ## Idempotency Enforcement From b64640c5705f733798783e68d216e957044ef23c Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 10 Nov 2021 16:26:20 +0100 Subject: [PATCH 05/89] revert: refactor: allow ES import for cloud string if package type is module This reverts commit 0225340ccbba2781e49689640ded606a8379dd45. --- .babelrc | 3 +-- spec/CloudCode.spec.js | 8 -------- spec/cloud/cloudCodeModuleFile.js | 3 --- src/ParseServer.js | 6 +----- 4 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 spec/cloud/cloudCodeModuleFile.js diff --git a/.babelrc b/.babelrc index a199154b..9151969b 100644 --- a/.babelrc +++ b/.babelrc @@ -7,8 +7,7 @@ ["@babel/preset-env", { "targets": { "node": "12" - }, - "exclude": ["proposal-dynamic-import"] + } }] ], "sourceMaps": "inline" diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 17968c33..d5e61137 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -39,14 +39,6 @@ describe('Cloud Code', () => { }); }); - it('can load cloud code as a module', async () => { - process.env.npm_package_type = 'module'; - await reconfigureServer({ cloud: './spec/cloud/cloudCodeModuleFile.js' }); - const result = await Parse.Cloud.run('cloudCodeInFile'); - expect(result).toEqual('It is possible to define cloud code in a file.'); - delete process.env.npm_package_type; - }); - it('can create functions', done => { Parse.Cloud.define('hello', () => { return 'Hello world!'; diff --git a/spec/cloud/cloudCodeModuleFile.js b/spec/cloud/cloudCodeModuleFile.js deleted file mode 100644 index a62b4fcc..00000000 --- a/spec/cloud/cloudCodeModuleFile.js +++ /dev/null @@ -1,3 +0,0 @@ -Parse.Cloud.define('cloudCodeInFile', () => { - return 'It is possible to define cloud code in a file.'; -}); diff --git a/src/ParseServer.js b/src/ParseServer.js index dc2af9e7..e6b30d19 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -108,11 +108,7 @@ class ParseServer { if (typeof cloud === 'function') { cloud(Parse); } else if (typeof cloud === 'string') { - if (process.env.npm_package_type === 'module') { - import(path.resolve(process.cwd(), cloud)); - } else { - require(path.resolve(process.cwd(), cloud)); - } + require(path.resolve(process.cwd(), cloud)); } else { throw "argument 'cloud' must either be a string or a function"; } From d35eeb825e4aaabeeeb89690dbaafc7047a7e3c7 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 10 Nov 2021 15:27:17 +0000 Subject: [PATCH 06/89] chore(release): 5.0.0-alpha.6 [skip ci] # [5.0.0-alpha.6](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.5...5.0.0-alpha.6) (2021-11-10) ### Reverts * refactor: allow ES import for cloud string if package type is module ([b64640c](https://github.com/parse-community/parse-server/commit/b64640c5705f733798783e68d216e957044ef23c)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 1d5c4e5e..e86a8479 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.6](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.5...5.0.0-alpha.6) (2021-11-10) + + +### Reverts + +* refactor: allow ES import for cloud string if package type is module ([b64640c](https://github.com/parse-community/parse-server/commit/b64640c5705f733798783e68d216e957044ef23c)) + # [5.0.0-alpha.5](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.4...5.0.0-alpha.5) (2021-11-01) diff --git a/package-lock.json b/package-lock.json index 6b37705a..ef6abb50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.5", + "version": "5.0.0-alpha.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 23c1981c..e6fe9909 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.5", + "version": "5.0.0-alpha.6", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 573558d3adcbcc6222c92003829867e1a73eef94 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Fri, 12 Nov 2021 18:37:03 +0100 Subject: [PATCH 07/89] fix: node engine range has no upper limit to exclude incompatible node versions (#7692) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e6fe9909..d9d57d7f 100644 --- a/package.json +++ b/package.json @@ -135,7 +135,7 @@ "madge:circular": "node_modules/.bin/madge ./src --circular" }, "engines": { - "node": ">=12.20.0" + "node": ">=12.20.0 <16" }, "bin": { "parse-server": "bin/parse-server" From d72717d23a8d34d89fbb2a1593c518466d38ab6d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 12 Nov 2021 17:38:15 +0000 Subject: [PATCH 08/89] chore(release): 5.0.0-alpha.7 [skip ci] # [5.0.0-alpha.7](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.6...5.0.0-alpha.7) (2021-11-12) ### Bug Fixes * node engine range has no upper limit to exclude incompatible node versions ([#7692](https://github.com/parse-community/parse-server/issues/7692)) ([573558d](https://github.com/parse-community/parse-server/commit/573558d3adcbcc6222c92003829867e1a73eef94)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index e86a8479..cd67f722 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.7](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.6...5.0.0-alpha.7) (2021-11-12) + + +### Bug Fixes + +* node engine range has no upper limit to exclude incompatible node versions ([#7692](https://github.com/parse-community/parse-server/issues/7692)) ([573558d](https://github.com/parse-community/parse-server/commit/573558d3adcbcc6222c92003829867e1a73eef94)) + # [5.0.0-alpha.6](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.5...5.0.0-alpha.6) (2021-11-10) diff --git a/package-lock.json b/package-lock.json index ef6abb50..bb8a577f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.6", + "version": "5.0.0-alpha.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d9d57d7f..38147a69 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.6", + "version": "5.0.0-alpha.7", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From e4aa1cb0a0c4c28956d75fc813a752ed6d22a9f2 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sat, 13 Nov 2021 00:47:02 +0100 Subject: [PATCH 09/89] refactor: upgrade follow-redirects from 1.14.2 to 1.14.4 (#7694) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index bb8a577f..b9aa107d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7070,9 +7070,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", - "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==" + "version": "1.14.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", + "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" }, "for-each": { "version": "0.3.3", diff --git a/package.json b/package.json index 38147a69..91424ed8 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "cors": "2.8.5", "deepcopy": "2.1.0", "express": "4.17.1", - "follow-redirects": "1.14.2", + "follow-redirects": "1.14.4", "graphql": "15.6.0", "graphql-list-fields": "2.0.2", "graphql-relay": "0.9.0", From 3d7ed8dfacef0134e25c6090793611f3febcfc19 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sat, 13 Nov 2021 20:11:52 +0100 Subject: [PATCH 10/89] refactor: upgrade @parse/fs-files-adapter from 1.2.0 to 1.2.1 (#7695) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9aa107d..b228ddd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1739,9 +1739,9 @@ } }, "@parse/fs-files-adapter": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.0.tgz", - "integrity": "sha512-kr7Ti2eYOm14p05S86yriJdMtawL6qln3Dn5eekrwY14ih4jrjH/E+QlEpBUSBzN64fluFxciFOyjdbwDGWsGw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.1.tgz", + "integrity": "sha512-jUbmlvql9+5Mz8Q6KSk1jH823MVerhOYK1svayYpF03v75OtDn3p+mAoFvPS5UpRln1kT6BlBnLfw4Hv08SD5Q==" }, "@parse/minami": { "version": "1.0.0", diff --git a/package.json b/package.json index 91424ed8..8729a01e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@graphql-tools/links": "6.2.5", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", - "@parse/fs-files-adapter": "1.2.0", + "@parse/fs-files-adapter": "1.2.1", "@parse/push-adapter": "3.4.1", "apollo-server-express": "2.25.2", "bcryptjs": "2.4.3", From a2fefde4bae6969ed443ba22615a0a232495f2cc Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 14 Nov 2021 03:14:01 +0100 Subject: [PATCH 11/89] refactor: upgrade pg-promise from 10.11.0 to 10.11.1 (#7697) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b228ddd6..f96628ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13680,9 +13680,9 @@ "integrity": "sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==" }, "pg-promise": { - "version": "10.11.0", - "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.11.0.tgz", - "integrity": "sha512-UntgHZNv+gpGJKhh+tzGSGHLkniKWV+ZQ8/SNdtvElsg9Aa7ZJ4Fgyl6pl2x0ZtJ7uFNy+OIq3Z+Ei6iplqTDQ==", + "version": "10.11.1", + "resolved": "https://registry.npmjs.org/pg-promise/-/pg-promise-10.11.1.tgz", + "integrity": "sha512-HAv32WSKf2m2RqHerW5RmANn/mcXIwWXbg/gOfGQcoS0SE+8iBi3Jj4JmoR4PNzSEozo/y/npy4e6F16psOItw==", "requires": { "assert-options": "0.7.0", "pg": "8.7.1", diff --git a/package.json b/package.json index 8729a01e..178a7476 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "mustache": "4.2.0", "parse": "3.3.1", "pg-monitor": "1.4.1", - "pg-promise": "10.11.0", + "pg-promise": "10.11.1", "pluralize": "8.0.0", "redis": "3.1.2", "semver": "7.3.5", From 426ccdc8f325601da58648f1e9432500dacf809b Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 14 Nov 2021 03:31:05 +0100 Subject: [PATCH 12/89] refactor: upgrade ws from 8.2.2 to 8.2.3 (#7698) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f96628ea..a95ba96b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16820,9 +16820,9 @@ } }, "ws": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.2.tgz", - "integrity": "sha512-Q6B6H2oc8QY3llc3cB8kVmQ6pnJWVQbP7Q5algTcIxx7YEpc0oU4NBVHlztA7Ekzfhw2r0rPducMUiCGWKQRzw==" + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" }, "xmlcreate": { "version": "2.0.3", diff --git a/package.json b/package.json index 178a7476..7a26b0d8 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "uuid": "8.3.2", "winston": "3.3.3", "winston-daily-rotate-file": "4.5.5", - "ws": "8.2.2" + "ws": "8.2.3" }, "devDependencies": { "@actions/core": "1.2.6", From 251ff0ef715e12df7c8e3fd6fd742077dab58946 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 14 Nov 2021 04:14:21 +0100 Subject: [PATCH 13/89] refactor: upgrade graphql from 15.6.0 to 15.6.1 (#7696) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a95ba96b..0e733e78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7476,9 +7476,9 @@ "dev": true }, "graphql": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.0.tgz", - "integrity": "sha512-WJR872Zlc9hckiEPhXgyUftXH48jp2EjO5tgBBOyNMRJZ9fviL2mJBD6CAysk6N5S0r9BTs09Qk39nnJBkvOXQ==" + "version": "15.6.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.1.tgz", + "integrity": "sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw==" }, "graphql-extensions": { "version": "0.15.0", diff --git a/package.json b/package.json index 7a26b0d8..0cd3eb41 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "deepcopy": "2.1.0", "express": "4.17.1", "follow-redirects": "1.14.4", - "graphql": "15.6.0", + "graphql": "15.6.1", "graphql-list-fields": "2.0.2", "graphql-relay": "0.9.0", "graphql-tag": "2.12.5", From ae99b928092107169f754d9082b598f14e5266cd Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 17 Nov 2021 13:28:34 +0100 Subject: [PATCH 14/89] refactor: upgrade graphql from 15.6.1 to 15.7.0 (#7704) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0e733e78..9e541d27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7476,9 +7476,9 @@ "dev": true }, "graphql": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.6.1.tgz", - "integrity": "sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw==" + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.7.0.tgz", + "integrity": "sha512-1jvUsS5mSzcgXLTQNQyrP7eKkBZW+HUnmx2LYSnfvkyseVpij8wwO/sFBGgxbkZ+zzFwYQxrHsOana5oMXmMxg==" }, "graphql-extensions": { "version": "0.15.0", diff --git a/package.json b/package.json index 0cd3eb41..b78ebfb9 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "deepcopy": "2.1.0", "express": "4.17.1", "follow-redirects": "1.14.4", - "graphql": "15.6.1", + "graphql": "15.7.0", "graphql-list-fields": "2.0.2", "graphql-relay": "0.9.0", "graphql-tag": "2.12.5", From 45cc58c7e5e640a46c5d508019a3aa81242964b1 Mon Sep 17 00:00:00 2001 From: Marvin ROGER Date: Thu, 18 Nov 2021 23:37:47 +0100 Subject: [PATCH 15/89] feat: add support for Node 16 (#7707) BREAKING CHANGE: Removes official Node 15 support which has reached it end-of-life date. --- .github/workflows/ci.yml | 28 +-- README.md | 3 +- ci/ciCheck.js | 9 +- package-lock.json | 370 +++++++++++++------------------- package.json | 10 +- spec/ParseGraphQLServer.spec.js | 13 +- 6 files changed, 179 insertions(+), 254 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62890394..96ed13b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: branches: - '**' env: - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 PARSE_SERVER_TEST_TIMEOUT: 20000 jobs: check-ci: @@ -105,43 +105,43 @@ jobs: MONGODB_VERSION: 5.0.3 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: MongoDB 4.4, ReplicaSet, WiredTiger MONGODB_VERSION: 4.4.10 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: MongoDB 4.2, ReplicaSet, WiredTiger MONGODB_VERSION: 4.2.17 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: MongoDB 4.0, ReplicaSet, WiredTiger MONGODB_VERSION: 4.0.27 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: MongoDB 4.0, Standalone, MMAPv1 MONGODB_VERSION: 4.0.27 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: mmapv1 - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: Redis Cache PARSE_SERVER_TEST_CACHE: redis MONGODB_VERSION: 4.4.10 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: Node 12 MONGODB_VERSION: 4.4.10 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger NODE_VERSION: 12.22.7 - - name: Node 15 + - name: Node 14 MONGODB_VERSION: 4.4.10 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 15.14.0 + NODE_VERSION: 14.18.1 fail-fast: false name: ${{ matrix.name }} timeout-minutes: 15 @@ -183,19 +183,19 @@ jobs: include: - name: PostgreSQL 11, PostGIS 3.0 POSTGRES_IMAGE: postgis/postgis:11-3.0 - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: PostgreSQL 11, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:11-3.1 - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: PostgreSQL 12, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:12-3.1 - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: PostgreSQL 13, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:13-3.1 - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 - name: PostgreSQL 14, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:14-3.1 - NODE_VERSION: 14.18.1 + NODE_VERSION: 16.13.0 fail-fast: false name: ${{ matrix.name }} timeout-minutes: 15 diff --git a/README.md b/README.md index 5a8a5d7d..73870981 100644 --- a/README.md +++ b/README.md @@ -116,8 +116,7 @@ Parse Server is continuously tested with the most recent releases of Node.js to |------------|----------------|-------------|---------------| | Node.js 12 | 12.22.7 | April 2022 | ✅ Yes | | Node.js 14 | 14.18.1 | April 2023 | ✅ Yes | -| Node.js 15 | 15.14.0 | June 2021 | ✅ Yes | -| Node.js 16 | 16.x.x | April 2024 | ❌ Not tested | +| Node.js 16 | 16.13.0 | April 2024 | ✅ Yes | #### MongoDB Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and only test against versions that are officially supported and have not reached their end-of-life date. diff --git a/ci/ciCheck.js b/ci/ciCheck.js index e1d968be..2ad5c3e8 100644 --- a/ci/ciCheck.js +++ b/ci/ciCheck.js @@ -1,4 +1,4 @@ -'use strict' +'use strict'; const CiVersionCheck = require('./CiVersionCheck'); const mongoVersionList = require('mongodb-version-list'); @@ -14,9 +14,8 @@ async function check() { * Check the MongoDB versions used in test environments. */ async function checkMongoDbVersions() { - const releasedVersions = await new Promise((resolve, reject) => { - mongoVersionList(function(error, versions) { + mongoVersionList(function (error, versions) { if (error) { reject(error); } @@ -47,7 +46,6 @@ async function checkMongoDbVersions() { * Check the Nodejs versions used in test environments. */ async function checkNodeVersions() { - const allVersions = await allNodeVersions(); const releasedVersions = allVersions.versions; @@ -62,7 +60,8 @@ async function checkNodeVersions() { ignoreReleasedVersions: [ '<12.0.0', // These versions have reached their end-of-life support date '>=13.0.0 <14.0.0', // These versions have reached their end-of-life support date - '>=16.0.0', // This version has not been officially released yet + '>=15.0.0 <16.0.0', // These versions have reached their end-of-life support date + '>=17.0.0', // These versions are not officially supported yet ], }).check(); } diff --git a/package-lock.json b/package-lock.json index 9e541d27..b9c7f8ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,10 @@ "dev": true }, "@apollo/client": { - "version": "3.4.8", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.4.8.tgz", - "integrity": "sha512-/cNqTSwc2Dw8q6FDDjdd30+yvhP7rI0Fvl3Hbro0lTtFuhzkevfNyQaI2jAiOrjU6Jc0RbanxULaNrX7UmvjSQ==", + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.4.17.tgz", + "integrity": "sha512-MDt2rwMX1GqodiVEKJqmDmAz8xr0qJmq5PdWeIt0yDaT4GOkKYWZiWkyfhfv3raTk8PyJvbsNG9q2CqmUrlGfg==", + "dev": true, "requires": { "@graphql-typed-document-node/core": "^3.0.0", "@wry/context": "^0.6.0", @@ -26,21 +27,23 @@ "symbol-observable": "^4.0.0", "ts-invariant": "^0.9.0", "tslib": "^2.3.0", - "zen-observable-ts": "^1.1.0" + "zen-observable-ts": "~1.1.0" }, "dependencies": { "@wry/equality": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.2.tgz", "integrity": "sha512-oVMxbUXL48EV/C0/M7gLVsoK6qRHPS85x8zECofEZOVvxGmIPLA9o5Z27cc2PoAyZz1S2VoM2A7FLAnpfGlneA==", + "dev": true, "requires": { "tslib": "^2.3.0" } }, "ts-invariant": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.9.1.tgz", - "integrity": "sha512-hSeYibh29ULlHkuEfukcoiyTct+s2RzczMLTv4x3NWC/YrBy7x7ps5eYq/b4Y3Sb9/uAlf54+/5CAEMVxPhuQw==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.9.3.tgz", + "integrity": "sha512-HinBlTbFslQI0OHP07JLsSXPibSegec6r9ai5xxq/qHYCsIQbzpymLpDhAUsnXcSrDEcd0L62L8vsOEdzM0qlA==", + "dev": true, "requires": { "tslib": "^2.1.0" } @@ -48,12 +51,14 @@ "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true }, "zen-observable-ts": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "dev": true, "requires": { "@types/zen-observable": "0.8.3", "zen-observable": "0.8.15" @@ -1104,6 +1109,7 @@ "version": "7.15.3", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", + "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } @@ -1192,6 +1198,37 @@ "tslib": "~2.0.1" } }, + "@graphql-tools/batch-execute": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.3.1.tgz", + "integrity": "sha512-63kHY8ZdoO5FoeDXYHnAak1R3ysMViMPwWC2XUblFckuVLMUPmB2ONje8rjr2CvzWBHAW8c1Zsex+U3xhKtGIA==", + "requires": { + "@graphql-tools/utils": "^8.5.1", + "dataloader": "2.0.0", + "tslib": "~2.3.0", + "value-or-promise": "1.0.11" + }, + "dependencies": { + "@graphql-tools/utils": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.3.tgz", + "integrity": "sha512-HDNGWFVa8QQkoQB0H1lftvaO1X5xUaUDk1zr1qDe0xN1NL0E/CrQdJ5UKLqOvH4hkqVUPxQsyOoAZFkaH6rLHg==", + "requires": { + "tslib": "~2.3.0" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "value-or-promise": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", + "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==" + } + } + }, "@graphql-tools/delegate": { "version": "6.2.4", "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-6.2.4.tgz", @@ -1206,45 +1243,86 @@ } }, "@graphql-tools/links": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-6.2.5.tgz", - "integrity": "sha512-XeGDioW7F+HK6HHD/zCeF0HRC9s12NfOXAKv1HC0J7D50F4qqMvhdS/OkjzLoBqsgh/Gm8icRc36B5s0rOA9ig==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.1.tgz", + "integrity": "sha512-J0igz42eKh/RQxDZPdEE4YiztY3zWTBcsn/bUtJp52XKNj0EIO0fR6WLEocT6uxgWCNnWYPOQUaf7bEgeW44Vg==", "requires": { - "@graphql-tools/utils": "^7.0.0", - "apollo-link": "1.2.14", - "apollo-upload-client": "14.1.2", - "cross-fetch": "3.0.6", - "form-data": "3.0.0", - "is-promise": "4.0.0", - "tslib": "~2.0.1" + "@graphql-tools/delegate": "^8.4.1", + "@graphql-tools/utils": "^8.5.1", + "apollo-upload-client": "16.0.0", + "cross-fetch": "3.1.4", + "form-data": "4.0.0", + "tslib": "~2.3.0" }, "dependencies": { - "@graphql-tools/utils": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-7.10.0.tgz", - "integrity": "sha512-d334r6bo9mxdSqZW6zWboEnnOOFRrAPVQJ7LkU8/6grglrbcu6WhwCLzHb90E94JI3TD3ricC3YGbUqIi9Xg0w==", + "@graphql-tools/delegate": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.4.2.tgz", + "integrity": "sha512-CjggOhiL4WtyG2I3kux+1/p8lQxSFHBj0gwa0NxnQ6Vsnpw7Ig5VP1ovPnitFuBv2k4QdC37Nj2xv2n7DRn8fw==", "requires": { - "@ardatan/aggregate-error": "0.0.6", - "camel-case": "4.1.2", - "tslib": "~2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.2.0.tgz", - "integrity": "sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==" - } + "@graphql-tools/batch-execute": "^8.3.1", + "@graphql-tools/schema": "^8.3.1", + "@graphql-tools/utils": "^8.5.3", + "dataloader": "2.0.0", + "tslib": "~2.3.0", + "value-or-promise": "1.0.11" + } + }, + "@graphql-tools/merge": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.1.tgz", + "integrity": "sha512-Q240kcUszhXiAYudjuJgNuLgy9CryDP3wp83NOZQezfA6h3ByYKU7xI6DiKrdjyVaGpYN3ppUmdj0uf5GaXzMA==", + "requires": { + "@graphql-tools/utils": "^8.5.1", + "tslib": "~2.3.0" + } + }, + "@graphql-tools/schema": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz", + "integrity": "sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==", + "requires": { + "@graphql-tools/merge": "^8.2.1", + "@graphql-tools/utils": "^8.5.1", + "tslib": "~2.3.0", + "value-or-promise": "1.0.11" + } + }, + "@graphql-tools/utils": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.3.tgz", + "integrity": "sha512-HDNGWFVa8QQkoQB0H1lftvaO1X5xUaUDk1zr1qDe0xN1NL0E/CrQdJ5UKLqOvH4hkqVUPxQsyOoAZFkaH6rLHg==", + "requires": { + "tslib": "~2.3.0" } }, "apollo-upload-client": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-14.1.2.tgz", - "integrity": "sha512-ozaW+4tnVz1rpfwiQwG3RCdCcZ93RV/37ZQbRnObcQ9mjb+zur58sGDPVg9Ef3fiujLmiE/Fe9kdgvIMA3VOjA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-16.0.0.tgz", + "integrity": "sha512-aLhYucyA0T8aBEQ5g+p13qnR9RUyL8xqb8FSZ7e/Kw2KUOsotLUlFluLobqaE7JSUFwc6sKfXIcwB7y4yEjbZg==", "requires": { - "@apollo/client": "^3.1.5", - "@babel/runtime": "^7.11.2", - "extract-files": "^9.0.0" + "extract-files": "^11.0.0" } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "value-or-promise": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.11.tgz", + "integrity": "sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==" } } }, @@ -1387,9 +1465,10 @@ } }, "@graphql-typed-document-node/core": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.0.tgz", - "integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", + "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==", + "dev": true }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -2582,7 +2661,8 @@ "@types/zen-observable": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", - "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==", + "dev": true }, "@typescript-eslint/types": { "version": "4.31.0", @@ -2662,6 +2742,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.6.1.tgz", "integrity": "sha512-LOmVnY1iTU2D8tv4Xf6MVMZZ+juIJ87Kt/plMijjN20NMAXGmH4u8bS1t0uT74cZ5gwpocYueV58YwyI8y+GKw==", + "dev": true, "requires": { "tslib": "^2.3.0" }, @@ -2669,7 +2750,8 @@ "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true } } }, @@ -2692,6 +2774,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.1.tgz", "integrity": "sha512-WwB53ikYudh9pIorgxrkHKrQZcCqNM/Q/bDzZBffEaGUKGuHrRb3zZUT9Sh2qw9yogC7SsdRmQ1ER0pqvd3bfw==", + "dev": true, "requires": { "tslib": "^2.3.0" }, @@ -2699,7 +2782,8 @@ "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true } } }, @@ -2910,24 +2994,6 @@ } } }, - "apollo-cache": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/apollo-cache/-/apollo-cache-1.3.5.tgz", - "integrity": "sha512-1XoDy8kJnyWY/i/+gLTEbYLnoiVtS8y7ikBr/IfmML4Qb+CM7dEEbIUOjnY716WqmZ/UpXIxTfJsY7rMcqiCXA==", - "dev": true, - "requires": { - "apollo-utilities": "^1.3.4", - "tslib": "^1.10.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, "apollo-cache-control": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.14.0.tgz", @@ -2937,76 +3003,6 @@ "apollo-server-plugin-base": "^0.13.0" } }, - "apollo-cache-inmemory": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/apollo-cache-inmemory/-/apollo-cache-inmemory-1.6.6.tgz", - "integrity": "sha512-L8pToTW/+Xru2FFAhkZ1OA9q4V4nuvfoPecBM34DecAugUZEBhI2Hmpgnzq2hTKZ60LAMrlqiASm0aqAY6F8/A==", - "dev": true, - "requires": { - "apollo-cache": "^1.3.5", - "apollo-utilities": "^1.3.4", - "optimism": "^0.10.0", - "ts-invariant": "^0.4.0", - "tslib": "^1.10.0" - }, - "dependencies": { - "@wry/context": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.4.4.tgz", - "integrity": "sha512-LrKVLove/zw6h2Md/KZyWxIkFM6AoyKp71OqpH9Hiip1csjPVoD3tPxlbQUNxEnHENks3UGgNpSBCAfq9KWuag==", - "dev": true, - "requires": { - "@types/node": ">=6", - "tslib": "^1.9.3" - } - }, - "optimism": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.10.3.tgz", - "integrity": "sha512-9A5pqGoQk49H6Vhjb9kPgAeeECfUDF6aIICbMDL23kDLStBn1MWk3YvcZ4xWF9CsSf6XEgvRLkXy4xof/56vVw==", - "dev": true, - "requires": { - "@wry/context": "^0.4.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "apollo-client": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/apollo-client/-/apollo-client-2.6.10.tgz", - "integrity": "sha512-jiPlMTN6/5CjZpJOkGeUV0mb4zxx33uXWdj/xQCfAMkuNAC3HN7CvYDyMHHEzmcQ5GV12LszWoQ/VlxET24CtA==", - "dev": true, - "requires": { - "@types/zen-observable": "^0.8.0", - "apollo-cache": "1.3.5", - "apollo-link": "^1.0.0", - "apollo-utilities": "1.3.4", - "symbol-observable": "^1.0.2", - "ts-invariant": "^0.4.0", - "tslib": "^1.10.0", - "zen-observable": "^0.8.0" - }, - "dependencies": { - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, "apollo-datasource": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.9.0.tgz", @@ -3044,62 +3040,6 @@ } } }, - "apollo-link-http": { - "version": "1.5.17", - "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.17.tgz", - "integrity": "sha512-uWcqAotbwDEU/9+Dm9e1/clO7hTB2kQ/94JYcGouBVLjoKmTeJTUPQKcJGpPwUjZcSqgYicbFqQSoJIW0yrFvg==", - "dev": true, - "requires": { - "apollo-link": "^1.2.14", - "apollo-link-http-common": "^0.2.16", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "apollo-link-http-common": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.16.tgz", - "integrity": "sha512-2tIhOIrnaF4UbQHf7kjeQA/EmSorB7+HyJIIrUjJOKBgnXwuexi8aMecRlqTIDWcyVXCeqLhUnztMa6bOH/jTg==", - "dev": true, - "requires": { - "apollo-link": "^1.2.14", - "ts-invariant": "^0.4.0", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "apollo-link-ws": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/apollo-link-ws/-/apollo-link-ws-1.0.20.tgz", - "integrity": "sha512-mjSFPlQxmoLArpHBeUb2Xj+2HDYeTaJqFGOqQ+I8NVJxgL9lJe84PDWcPah/yMLv3rB7QgBDSuZ0xoRFBPlySw==", - "dev": true, - "requires": { - "apollo-link": "^1.2.14", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, "apollo-reporting-protobuf": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.8.0.tgz", @@ -3300,23 +3240,12 @@ } }, "apollo-upload-client": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-13.0.0.tgz", - "integrity": "sha512-lJ9/bk1BH1lD15WhWRha2J3+LrXrPIX5LP5EwiOUHv8PCORp4EUrcujrA3rI5hZeZygrTX8bshcuMdpqpSrvtA==", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-16.0.0.tgz", + "integrity": "sha512-aLhYucyA0T8aBEQ5g+p13qnR9RUyL8xqb8FSZ7e/Kw2KUOsotLUlFluLobqaE7JSUFwc6sKfXIcwB7y4yEjbZg==", "dev": true, "requires": { - "@babel/runtime": "^7.9.2", - "apollo-link": "^1.2.12", - "apollo-link-http-common": "^0.2.14", - "extract-files": "^8.0.0" - }, - "dependencies": { - "extract-files": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-8.1.0.tgz", - "integrity": "sha512-PTGtfthZK79WUMk+avLmwx3NGdU8+iVFXC2NMGxKsn0MnihOG2lvumj+AZo8CTwTrwjXDgZ5tztbRlEdRjBonQ==", - "dev": true - } + "extract-files": "^11.0.0" } }, "apollo-utilities": { @@ -4004,15 +3933,6 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -4892,9 +4812,9 @@ } }, "cross-fetch": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz", - "integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", + "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", "requires": { "node-fetch": "2.6.1" } @@ -6642,9 +6562,9 @@ } }, "extract-files": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", - "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==" + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", + "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==" }, "extsprintf": { "version": "1.4.0", @@ -7108,6 +7028,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz", "integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==", + "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -7729,6 +7650,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, "requires": { "react-is": "^16.7.0" } @@ -8892,7 +8814,8 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { "version": "3.14.1", @@ -9826,6 +9749,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -13229,6 +13153,7 @@ "version": "0.16.1", "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.1.tgz", "integrity": "sha512-64i+Uw3otrndfq5kaoGNoY7pvOhSsjFEN4bdEFh80MWVk/dbgJfMv7VFDeCT8LxNAlEVhQmdVEbfE7X2nWNIIg==", + "dev": true, "requires": { "@wry/context": "^0.6.0", "@wry/trie": "^0.3.0" @@ -14034,6 +13959,7 @@ "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -14186,7 +14112,8 @@ "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true }, "react-native-crypto-js": { "version": "1.0.0", @@ -15861,7 +15788,8 @@ "symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==" + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true }, "table": { "version": "5.4.6", diff --git a/package.json b/package.json index b78ebfb9..e6d1da25 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "license": "BSD-3-Clause", "dependencies": { "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/links": "6.2.5", + "@graphql-tools/links": "8.2.1", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", @@ -62,6 +62,7 @@ }, "devDependencies": { "@actions/core": "1.2.6", + "@apollo/client": "3.4.17", "@babel/cli": "7.10.0", "@babel/core": "7.10.0", "@babel/plugin-proposal-object-rest-spread": "7.10.0", @@ -75,12 +76,7 @@ "@semantic-release/npm": "7.1.3", "@semantic-release/release-notes-generator": "9.0.3", "all-node-versions": "8.0.0", - "apollo-cache-inmemory": "1.6.6", - "apollo-client": "2.6.10", - "apollo-link": "1.2.14", - "apollo-link-http": "1.5.17", - "apollo-link-ws": "1.0.20", - "apollo-upload-client": "13.0.0", + "apollo-upload-client": "16.0.0", "apollo-utilities": "1.3.4", "babel-eslint": "10.1.0", "bcrypt-nodejs": "0.0.3", diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 52427efc..50f54c55 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -9,13 +9,16 @@ const { updateCLP } = require('./support/dev'); const pluralize = require('pluralize'); const { getMainDefinition } = require('apollo-utilities'); -const { ApolloLink, split } = require('apollo-link'); -const { createHttpLink } = require('apollo-link-http'); -const { InMemoryCache } = require('apollo-cache-inmemory'); const { createUploadLink } = require('apollo-upload-client'); const { SubscriptionClient } = require('subscriptions-transport-ws'); -const { WebSocketLink } = require('apollo-link-ws'); -const ApolloClient = require('apollo-client').default; +const { WebSocketLink } = require('@apollo/client/link/ws'); +const { + ApolloClient, + InMemoryCache, + ApolloLink, + split, + createHttpLink, +} = require('@apollo/client/core'); const gql = require('graphql-tag'); const { toGlobalId } = require('graphql-relay'); const { From fea308a01ad9739b2b430ebe2164b967308b6725 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 18 Nov 2021 22:38:42 +0000 Subject: [PATCH 16/89] chore(release): 5.0.0-alpha.8 [skip ci] # [5.0.0-alpha.8](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.7...5.0.0-alpha.8) (2021-11-18) ### Features * add support for Node 16 ([#7707](https://github.com/parse-community/parse-server/issues/7707)) ([45cc58c](https://github.com/parse-community/parse-server/commit/45cc58c7e5e640a46c5d508019a3aa81242964b1)) ### BREAKING CHANGES * Removes official Node 15 support which has reached it end-of-life date. ([45cc58c](45cc58c)) --- changelogs/CHANGELOG_alpha.md | 12 ++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index cd67f722..e600538a 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,15 @@ +# [5.0.0-alpha.8](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.7...5.0.0-alpha.8) (2021-11-18) + + +### Features + +* add support for Node 16 ([#7707](https://github.com/parse-community/parse-server/issues/7707)) ([45cc58c](https://github.com/parse-community/parse-server/commit/45cc58c7e5e640a46c5d508019a3aa81242964b1)) + + +### BREAKING CHANGES + +* Removes official Node 15 support which has reached it end-of-life date. ([45cc58c](45cc58c)) + # [5.0.0-alpha.7](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.6...5.0.0-alpha.7) (2021-11-12) diff --git a/package-lock.json b/package-lock.json index b9c7f8ac..12f9e74b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.7", + "version": "5.0.0-alpha.8", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e6d1da25..73bb74b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.7", + "version": "5.0.0-alpha.8", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 899da8d765d9a8e2ced42364014d3b3017fd3063 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Thu, 18 Nov 2021 23:44:10 +0100 Subject: [PATCH 17/89] docs: remove node 15 from badge; add node 17 to compatibility table (#7709) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73870981..f2ecce98 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ [![Coverage](https://img.shields.io/codecov/c/github/parse-community/parse-server/alpha.svg)](https://codecov.io/github/parse-community/parse-server?branch=alpha) [![auto-release](https://img.shields.io/badge/%F0%9F%9A%80-auto--release-9e34eb.svg)](https://github.com/parse-community/parse-dashboard/releases) -[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_15-green.svg?logo=node.js&style=flat)](https://nodejs.org) +[![Node Version](https://img.shields.io/badge/nodejs-12,_14,_16-green.svg?logo=node.js&style=flat)](https://nodejs.org) [![MongoDB Version](https://img.shields.io/badge/mongodb-4.0,_4.2,_4.4,_5.0-green.svg?logo=mongodb&style=flat)](https://www.mongodb.com) [![Postgres Version](https://img.shields.io/badge/postgresql-11,_12,_13,_14-green.svg?logo=postgresql&style=flat)](https://www.postgresql.org) @@ -117,6 +117,7 @@ Parse Server is continuously tested with the most recent releases of Node.js to | Node.js 12 | 12.22.7 | April 2022 | ✅ Yes | | Node.js 14 | 14.18.1 | April 2023 | ✅ Yes | | Node.js 16 | 16.13.0 | April 2024 | ✅ Yes | +| Node.js 17 | 17.x | June 2022 | ❌ Not tested | #### MongoDB Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and only test against versions that are officially supported and have not reached their end-of-life date. From 260290409e747414c703ddec755d5cba73be5e83 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 21 Nov 2021 14:49:37 +0100 Subject: [PATCH 18/89] refactor: upgrade follow-redirects from 1.14.4 to 1.14.5 (#7712) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 12f9e74b..3271c179 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6990,9 +6990,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==" + "version": "1.14.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", + "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" }, "for-each": { "version": "0.3.3", diff --git a/package.json b/package.json index 73bb74b0..613a1dc2 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "cors": "2.8.5", "deepcopy": "2.1.0", "express": "4.17.1", - "follow-redirects": "1.14.4", + "follow-redirects": "1.14.5", "graphql": "15.7.0", "graphql-list-fields": "2.0.2", "graphql-relay": "0.9.0", From c789f6c97992f0c68d1c07aae19239932e238701 Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 25 Nov 2021 10:16:46 -0800 Subject: [PATCH 19/89] refactor: test moved to correct test group (#7717) --- spec/CloudCode.spec.js | 38 +++++++++++++-------------- src/Controllers/DatabaseController.js | 4 +-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index d5e61137..c185eac5 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1999,6 +1999,25 @@ describe('beforeFind hooks', () => { }); }); + it('should have object found with nested relational data query', async () => { + const obj1 = Parse.Object.extend('TestObject'); + const obj2 = Parse.Object.extend('TestObject2'); + let item2 = new obj2(); + item2 = await item2.save(); + let item1 = new obj1(); + const relation = item1.relation('rel'); + relation.add(item2); + item1 = await item1.save(); + Parse.Cloud.beforeFind('TestObject', req => { + const additionalQ = new Parse.Query('TestObject'); + additionalQ.equalTo('rel', item2); + return Parse.Query.and(req.query, additionalQ); + }); + const q = new Parse.Query('TestObject'); + const res = await q.first(); + expect(res.id).toEqual(item1.id); + }); + it('should use the modified exclude query', async () => { Parse.Cloud.beforeFind('MyObject', req => { const q = req.query; @@ -3516,23 +3535,4 @@ describe('sendEmail', () => { 'Failed to send email because no mail adapter is configured for Parse Server.' ); }); - - it('should have object found with nested relational data query', async () => { - const obj1 = Parse.Object.extend('TestObject'); - const obj2 = Parse.Object.extend('TestObject2'); - let item2 = new obj2(); - item2 = await item2.save(); - let item1 = new obj1(); - const relation = item1.relation('rel'); - relation.add(item2); - item1 = await item1.save(); - Parse.Cloud.beforeFind('TestObject', req => { - const additionalQ = new Parse.Query('TestObject'); - additionalQ.equalTo('rel', item2); - return Parse.Query.and(req.query, additionalQ); - }); - const q = new Parse.Query('TestObject'); - const res = await q.first(); - expect(res.id).toEqual(item1.id); - }); }); diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 20d5c4ba..158308de 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -972,9 +972,9 @@ class DatabaseController { }); } if (query['$and']) { - const ors = query['$and']; + const ands = query['$and']; return Promise.all( - ors.map((aQuery, index) => { + ands.map((aQuery, index) => { return this.reduceInRelation(className, aQuery, schema).then(aQuery => { query['$and'][index] = aQuery; }); From ed86c807721cc52a1a5a9dea0b768717eec269ed Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Sat, 27 Nov 2021 12:27:08 +0100 Subject: [PATCH 20/89] fix: unable to use objectId size higher than 19 on GraphQL API (#7627) --- package-lock.json | 6 ++-- package.json | 2 +- spec/ParseGraphQLServer.spec.js | 29 +++++++++++++++---- .../Postgres/PostgresStorageAdapter.js | 8 ++++- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3271c179..879c91eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7417,9 +7417,9 @@ "integrity": "sha512-9TSAwcVA3KWw7JWYep5NCk2aw3wl1ayLtbMpmG7l26vh1FZ+gZexNPP+XJfUFyJa71UU0zcKSgtgpsrsA3Xv9Q==" }, "graphql-relay": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.9.0.tgz", - "integrity": "sha512-yNJLCqcjz0XpzpmmckRJCSK8a2ZLwTurwrQ09UyGftONh52PbrGpK1UO4yspvj0c7pC+jkN4ZUqVXG3LRrWkXQ==" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/graphql-relay/-/graphql-relay-0.7.0.tgz", + "integrity": "sha512-P8eS3IbZRhbfbcfud1Q6VPrIru4hchkb15MuOij+WQo9r0chD5NBIxiVjuRE2iG2EMHxIOrZb8LnMe82+YdITA==" }, "graphql-subscriptions": { "version": "1.2.1", diff --git a/package.json b/package.json index 613a1dc2..a1479d3d 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "follow-redirects": "1.14.5", "graphql": "15.7.0", "graphql-list-fields": "2.0.2", - "graphql-relay": "0.9.0", + "graphql-relay": "0.7.0", "graphql-tag": "2.12.5", "graphql-upload": "11.0.0", "intersect": "1.0.1", diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 50f54c55..58b26e4b 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -2287,8 +2287,7 @@ describe('ParseGraphQLServer', () => { expect(nodeResult.data.node2.objectId).toBe(obj2.id); expect(nodeResult.data.node2.someField).toBe('some value 2'); }); - // TODO: (moumouls, davimacedo) Fix flaky test - xit('Id inputs should work either with global id or object id', async () => { + it('Id inputs should work either with global id or object id', async () => { try { await apolloClient.mutate({ mutation: gql` @@ -2595,9 +2594,12 @@ describe('ParseGraphQLServer', () => { .map(value => value.node.someField) .sort() ).toEqual(['some value 22', 'some value 44']); - expect( - findSecondaryObjectsResult.data.secondaryObjects.edges[0].node.id - ).toBeLessThan(findSecondaryObjectsResult.data.secondaryObjects.edges[1].node.id); + // NOTE: Here @davimacedo tried to test RelayID order, but the test is wrong since + // "objectId1" < "objectId2" do not always keep the order when objectId is transformed + // to base64 by Relay + // "SecondaryObject:bBRgmzIRRM" < "SecondaryObject:nTMcuVbATY" true + // base64("SecondaryObject:bBRgmzIRRM"") < base64(""SecondaryObject:nTMcuVbATY"") false + // "U2Vjb25kYXJ5T2JqZWN0OmJCUmdteklSUk0=" < "U2Vjb25kYXJ5T2JqZWN0Om5UTWN1VmJBVFk=" false expect( findSecondaryObjectsResult.data.secondaryObjects.edges[0].node.objectId ).toBeLessThan( @@ -2763,6 +2765,23 @@ describe('ParseGraphQLServer', () => { handleError(e); } }); + it('Id inputs should work either with global id or object id with objectId higher than 19', async () => { + await reconfigureServer({ objectIdSize: 20 }); + const obj = new Parse.Object('SomeClass'); + await obj.save({ name: 'aname', type: 'robot' }); + const result = await apolloClient.query({ + query: gql` + query getSomeClass($id: ID!) { + someClass(id: $id) { + objectId + id + } + } + `, + variables: { id: obj.id }, + }); + expect(result.data.someClass.objectId).toEqual(obj.id); + }); }); }); diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index e6c2bdbb..f787d9f1 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -1807,7 +1807,13 @@ export class PostgresStorageAdapter implements StorageAdapter { if (key === 'ACL') { memo.push('_rperm'); memo.push('_wperm'); - } else if (key.length > 0) { + } else if ( + key.length > 0 && + // Remove selected field not referenced in the schema + // Relation is not a column in postgres + // $score is a Parse special field and is also not a column + ((schema.fields[key] && schema.fields[key].type !== 'Relation') || key === '$score') + ) { memo.push(key); } return memo; From 1b4d9324de6834b98026d3e8af0536af1adf532a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 27 Nov 2021 11:28:15 +0000 Subject: [PATCH 21/89] chore(release): 5.0.0-alpha.9 [skip ci] # [5.0.0-alpha.9](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.8...5.0.0-alpha.9) (2021-11-27) ### Bug Fixes * unable to use objectId size higher than 19 on GraphQL API ([#7627](https://github.com/parse-community/parse-server/issues/7627)) ([ed86c80](https://github.com/parse-community/parse-server/commit/ed86c807721cc52a1a5a9dea0b768717eec269ed)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index e600538a..7407c8ea 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.9](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.8...5.0.0-alpha.9) (2021-11-27) + + +### Bug Fixes + +* unable to use objectId size higher than 19 on GraphQL API ([#7627](https://github.com/parse-community/parse-server/issues/7627)) ([ed86c80](https://github.com/parse-community/parse-server/commit/ed86c807721cc52a1a5a9dea0b768717eec269ed)) + # [5.0.0-alpha.8](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.7...5.0.0-alpha.8) (2021-11-18) diff --git a/package-lock.json b/package-lock.json index 879c91eb..b9127606 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.8", + "version": "5.0.0-alpha.9", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a1479d3d..92684992 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.8", + "version": "5.0.0-alpha.9", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 35ac4c3e68bcf6c5d33002cfd5094a1279bb2bca Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 28 Nov 2021 15:44:33 +0100 Subject: [PATCH 22/89] refactor: upgrade subscriptions-transport-ws from 0.10.0 to 0.11.0 (#7727) --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9127606..5e422bd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15726,9 +15726,9 @@ } }, "subscriptions-transport-ws": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.10.0.tgz", - "integrity": "sha512-k28LhLn3abJ1mowFW+LP4QGggE0e3hrk55zXbMHyAeZkCUYtC0owepiwqMD3zX8DglQVaxnhE760pESrNSEzpg==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.11.0.tgz", + "integrity": "sha512-8D4C6DIH5tGiAIpp5I0wD/xRlNiZAPGHygzCe7VzyzUoxHtawzjNAY9SUTXU05/EY2NMY9/9GF0ycizkXr1CWQ==", "requires": { "backo2": "^1.0.2", "eventemitter3": "^3.1.0", @@ -15743,9 +15743,9 @@ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" }, "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==" + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", + "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==" } } }, diff --git a/package.json b/package.json index 92684992..b927d7cf 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "pluralize": "8.0.0", "redis": "3.1.2", "semver": "7.3.5", - "subscriptions-transport-ws": "0.10.0", + "subscriptions-transport-ws": "0.11.0", "tv4": "1.3.0", "uuid": "8.3.2", "winston": "3.3.3", From 7dad413a175631db32d6f8ef6b36e63a79f0609b Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 29 Nov 2021 17:58:02 +0100 Subject: [PATCH 23/89] refactor: upgrade graphql-tag from 2.12.5 to 2.12.6 (#7726) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5e422bd5..0e9f6f7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7430,9 +7430,9 @@ } }, "graphql-tag": { - "version": "2.12.5", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.5.tgz", - "integrity": "sha512-5xNhP4063d16Pz3HBtKprutsPrmHZi5IdUGOWRxA2B6VF7BIRGOHZ5WQvDmJXZuPcBg7rYwaFxvQYjqkSdR3TQ==", + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", "requires": { "tslib": "^2.1.0" }, diff --git a/package.json b/package.json index b927d7cf..8fd71e9c 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "graphql": "15.7.0", "graphql-list-fields": "2.0.2", "graphql-relay": "0.7.0", - "graphql-tag": "2.12.5", + "graphql-tag": "2.12.6", "graphql-upload": "11.0.0", "intersect": "1.0.1", "jsonwebtoken": "8.5.1", From d4c1f473073764cb0570c633fc4a30669c2ce889 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 29 Nov 2021 18:19:48 +0100 Subject: [PATCH 24/89] fix: upgrade parse from 3.3.1 to 3.4.0 (#7723) --- package-lock.json | 33 +++++++++++++++++++++------------ package.json | 2 +- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0e9f6f7a..2082094e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13436,37 +13436,46 @@ } }, "parse": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/parse/-/parse-3.3.1.tgz", - "integrity": "sha512-jrb8tpeanh49lIXuQYbaJoMzywX9YiBtM17aCvYGfaHYJipSTHABA774t8IZap+F8Pb4GgZ0fM4ObfiuO4395A==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.0.tgz", + "integrity": "sha512-FMZLxPW6PvrBgxkXc9AmnYsFKvPwiS4G2n9OI4mdfiSoNzIVLc+bXzlUdJ+I7hiqHsBTP0BrdQczw2/cnVkJ6w==", "requires": { - "@babel/runtime": "7.14.8", - "@babel/runtime-corejs3": "7.14.6", + "@babel/runtime": "7.15.4", + "@babel/runtime-corejs3": "7.14.7", "crypto-js": "4.1.1", "idb-keyval": "5.0.6", "react-native-crypto-js": "1.0.0", "uuid": "3.4.0", - "ws": "7.5.0", + "ws": "7.5.1", "xmlhttprequest": "1.8.0" }, "dependencies": { "@babel/runtime": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", - "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", + "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", "requires": { "regenerator-runtime": "^0.13.4" } }, + "@babel/runtime-corejs3": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz", + "integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==", + "requires": { + "core-js-pure": "^3.15.0", + "regenerator-runtime": "^0.13.4" + } + }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "ws": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz", - "integrity": "sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw==" + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.1.tgz", + "integrity": "sha512-2c6faOUH/nhoQN6abwMloF7Iyl0ZS2E9HGtsiLrWn0zOOMWlhtDmdf/uihDt6jnuCxgtwGBNy6Onsoy2s2O2Ow==" } } }, diff --git a/package.json b/package.json index 8fd71e9c..ea4a29ca 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "mime": "2.5.2", "mongodb": "3.6.11", "mustache": "4.2.0", - "parse": "3.3.1", + "parse": "3.4.0", "pg-monitor": "1.4.1", "pg-promise": "10.11.1", "pluralize": "8.0.0", From 37ac29d79868916085a97d75f8f33231423808b9 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 29 Nov 2021 17:20:43 +0000 Subject: [PATCH 25/89] chore(release): 5.0.0-alpha.10 [skip ci] # [5.0.0-alpha.10](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.9...5.0.0-alpha.10) (2021-11-29) ### Bug Fixes * upgrade parse from 3.3.1 to 3.4.0 ([#7723](https://github.com/parse-community/parse-server/issues/7723)) ([d4c1f47](https://github.com/parse-community/parse-server/commit/d4c1f473073764cb0570c633fc4a30669c2ce889)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 7407c8ea..0c5056fc 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.10](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.9...5.0.0-alpha.10) (2021-11-29) + + +### Bug Fixes + +* upgrade parse from 3.3.1 to 3.4.0 ([#7723](https://github.com/parse-community/parse-server/issues/7723)) ([d4c1f47](https://github.com/parse-community/parse-server/commit/d4c1f473073764cb0570c633fc4a30669c2ce889)) + # [5.0.0-alpha.9](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.8...5.0.0-alpha.9) (2021-11-27) diff --git a/package-lock.json b/package-lock.json index 2082094e..701d9982 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.9", + "version": "5.0.0-alpha.10", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ea4a29ca..3f0aa3f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.9", + "version": "5.0.0-alpha.10", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From f5ef98bde32083403c0e30a12162fcc1e52cac37 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Tue, 30 Nov 2021 00:50:25 +0100 Subject: [PATCH 26/89] fix: upgrade mime from 2.5.2 to 3.0.0 (#7725) --- package-lock.json | 12 +++++++++--- package.json | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 701d9982..17f53b4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2232,6 +2232,12 @@ "universalify": "^2.0.0" } }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -10177,9 +10183,9 @@ } }, "mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" }, "mime-db": { "version": "1.49.0", diff --git a/package.json b/package.json index 3f0aa3f9..3cca009e 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "ldapjs": "2.3.1", "lodash": "4.17.21", "lru-cache": "5.1.1", - "mime": "2.5.2", + "mime": "3.0.0", "mongodb": "3.6.11", "mustache": "4.2.0", "parse": "3.4.0", From e7c7f44265d4d8a9c62a9e3d6910d31dbb243cf8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 29 Nov 2021 23:51:26 +0000 Subject: [PATCH 27/89] chore(release): 5.0.0-alpha.11 [skip ci] # [5.0.0-alpha.11](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.10...5.0.0-alpha.11) (2021-11-29) ### Bug Fixes * upgrade mime from 2.5.2 to 3.0.0 ([#7725](https://github.com/parse-community/parse-server/issues/7725)) ([f5ef98b](https://github.com/parse-community/parse-server/commit/f5ef98bde32083403c0e30a12162fcc1e52cac37)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 0c5056fc..3953b69e 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.11](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.10...5.0.0-alpha.11) (2021-11-29) + + +### Bug Fixes + +* upgrade mime from 2.5.2 to 3.0.0 ([#7725](https://github.com/parse-community/parse-server/issues/7725)) ([f5ef98b](https://github.com/parse-community/parse-server/commit/f5ef98bde32083403c0e30a12162fcc1e52cac37)) + # [5.0.0-alpha.10](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.9...5.0.0-alpha.10) (2021-11-29) diff --git a/package-lock.json b/package-lock.json index 17f53b4f..ba9b4b95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.10", + "version": "5.0.0-alpha.11", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3cca009e..2b4823df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.10", + "version": "5.0.0-alpha.11", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 6a6248b6cb2e732d17131e18e659943b894ed2f1 Mon Sep 17 00:00:00 2001 From: Ben Devore Date: Mon, 6 Dec 2021 18:52:59 -0500 Subject: [PATCH 28/89] fix: adding or modifying a nested property requires addField permissions (#7679) --- spec/schemas.spec.js | 28 +++++++++++++++++++++++++++ src/Controllers/DatabaseController.js | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index 5180b36c..e8dcc41e 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -1779,6 +1779,34 @@ describe('schemas', () => { }); }); + describe('Nested documents', () => { + beforeAll(async () => { + const testSchema = new Parse.Schema('test_7371'); + testSchema.setCLP({ + create: { ['*']: true }, + update: { ['*']: true }, + addField: {}, + }); + testSchema.addObject('a'); + await testSchema.save(); + }); + + it('addField permission not required for adding a nested property', async () => { + const obj = new Parse.Object('test_7371'); + obj.set('a', {}); + await obj.save(); + obj.set('a.b', 2); + await obj.save(); + }); + it('addField permission not required for modifying a nested property', async () => { + const obj = new Parse.Object('test_7371'); + obj.set('a', { b: 1 }); + await obj.save(); + obj.set('a.b', 2); + await obj.save(); + }); + }); + it('should aceept class-level permission with userid of any length', async done => { await global.reconfigureServer({ customIdSize: 11, diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 158308de..42273b69 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -894,7 +894,7 @@ class DatabaseController { if (object[field] && object[field].__op && object[field].__op === 'Delete') { return false; } - return schemaFields.indexOf(field) < 0; + return schemaFields.indexOf(getRootFieldName(field)) < 0; }); if (newKeys.length > 0) { // adds a marker that new field is being adding during update From ac789c8537dcb775345d2953fd732d4ad864eb61 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 6 Dec 2021 23:54:00 +0000 Subject: [PATCH 29/89] chore(release): 5.0.0-alpha.12 [skip ci] # [5.0.0-alpha.12](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.11...5.0.0-alpha.12) (2021-12-06) ### Bug Fixes * adding or modifying a nested property requires addField permissions ([#7679](https://github.com/parse-community/parse-server/issues/7679)) ([6a6248b](https://github.com/parse-community/parse-server/commit/6a6248b6cb2e732d17131e18e659943b894ed2f1)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 3953b69e..dc0a25ea 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.12](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.11...5.0.0-alpha.12) (2021-12-06) + + +### Bug Fixes + +* adding or modifying a nested property requires addField permissions ([#7679](https://github.com/parse-community/parse-server/issues/7679)) ([6a6248b](https://github.com/parse-community/parse-server/commit/6a6248b6cb2e732d17131e18e659943b894ed2f1)) + # [5.0.0-alpha.11](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.10...5.0.0-alpha.11) (2021-11-29) diff --git a/package-lock.json b/package-lock.json index ba9b4b95..8a367ec9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.11", + "version": "5.0.0-alpha.12", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2b4823df..800b2353 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.11", + "version": "5.0.0-alpha.12", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From ea7c01400f992a1263543706fe49b6174758a2d6 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 8 Dec 2021 11:19:38 +0100 Subject: [PATCH 30/89] fix: node engine compatibility did not include node 16 (#7739) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 800b2353..bd36f2c0 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,7 @@ "madge:circular": "node_modules/.bin/madge ./src --circular" }, "engines": { - "node": ">=12.20.0 <16" + "node": ">=12.20.0 <17" }, "bin": { "parse-server": "bin/parse-server" From 191d80b6677f8ee6f6a0ccd3bde2bf6bb50f9a20 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 8 Dec 2021 10:20:38 +0000 Subject: [PATCH 31/89] chore(release): 5.0.0-alpha.13 [skip ci] # [5.0.0-alpha.13](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.12...5.0.0-alpha.13) (2021-12-08) ### Bug Fixes * node engine compatibility did not include node 16 ([#7739](https://github.com/parse-community/parse-server/issues/7739)) ([ea7c014](https://github.com/parse-community/parse-server/commit/ea7c01400f992a1263543706fe49b6174758a2d6)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index dc0a25ea..e635c16f 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.13](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.12...5.0.0-alpha.13) (2021-12-08) + + +### Bug Fixes + +* node engine compatibility did not include node 16 ([#7739](https://github.com/parse-community/parse-server/issues/7739)) ([ea7c014](https://github.com/parse-community/parse-server/commit/ea7c01400f992a1263543706fe49b6174758a2d6)) + # [5.0.0-alpha.12](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.11...5.0.0-alpha.12) (2021-12-06) diff --git a/package-lock.json b/package-lock.json index 8a367ec9..36af9e81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.12", + "version": "5.0.0-alpha.13", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index bd36f2c0..c4a519e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.12", + "version": "5.0.0-alpha.13", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 9e477591fd2b468286f034caf559261caf953943 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 30 Dec 2021 23:38:26 +0000 Subject: [PATCH 32/89] refactor: upgrade follow-redirects from 1.14.5 to 1.14.6 (#7755) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 36af9e81..37f696f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6996,9 +6996,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.14.5", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", - "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" + "version": "1.14.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", + "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==" }, "for-each": { "version": "0.3.3", diff --git a/package.json b/package.json index c4a519e3..51a3d502 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "cors": "2.8.5", "deepcopy": "2.1.0", "express": "4.17.1", - "follow-redirects": "1.14.5", + "follow-redirects": "1.14.6", "graphql": "15.7.0", "graphql-list-fields": "2.0.2", "graphql-relay": "0.7.0", From 7448521cb9a30e12215ca3cf61f1243a67c4d51c Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sat, 1 Jan 2022 20:22:03 +0000 Subject: [PATCH 33/89] refactor: upgrade body-parser from 1.19.0 to 1.19.1 (#7756) --- package-lock.json | 138 ++++++++++++++++++++++++++++++---------------- package.json | 2 +- 2 files changed, 90 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index 37f696f6..38bf6a39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3645,20 +3645,20 @@ "dev": true }, "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", "requires": { - "bytes": "3.1.0", + "bytes": "3.1.1", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "1.7.2", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" }, "dependencies": { "debug": { @@ -3670,31 +3670,26 @@ } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, @@ -3833,9 +3828,9 @@ } }, "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" }, "cache-base": { "version": "1.0.1", @@ -6398,6 +6393,28 @@ "vary": "~1.1.2" }, "dependencies": { + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -6406,11 +6423,39 @@ "ms": "2.0.0" } }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -14070,37 +14115,32 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", + "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", + "bytes": "3.1.1", + "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, "dependencies": { "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, diff --git a/package.json b/package.json index 51a3d502..41623812 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@parse/push-adapter": "3.4.1", "apollo-server-express": "2.25.2", "bcryptjs": "2.4.3", - "body-parser": "1.19.0", + "body-parser": "1.19.1", "commander": "5.1.0", "cors": "2.8.5", "deepcopy": "2.1.0", From 16b1b2a19714535ca805f2dbb3b561d8f6a519a7 Mon Sep 17 00:00:00 2001 From: Corey Date: Sat, 1 Jan 2022 19:10:54 -0500 Subject: [PATCH 34/89] feat: support relativeTime query constraint on Postgres (#7747) --- spec/MongoTransform.spec.js | 23 +-- spec/ParseQuery.spec.js | 125 +++++++---------- spec/PostgresStorageAdapter.spec.js | 129 +++++++++++++++++ src/Adapters/Storage/Mongo/MongoTransform.js | 131 +---------------- .../Postgres/PostgresStorageAdapter.js | 43 +++++- src/Utils.js | 132 ++++++++++++++++++ 6 files changed, 366 insertions(+), 217 deletions(-) diff --git a/spec/MongoTransform.spec.js b/spec/MongoTransform.spec.js index 6834a6b2..60adb4b7 100644 --- a/spec/MongoTransform.spec.js +++ b/spec/MongoTransform.spec.js @@ -4,6 +4,7 @@ const transform = require('../lib/Adapters/Storage/Mongo/MongoTransform'); const dd = require('deep-diff'); const mongodb = require('mongodb'); +const Utils = require('../lib/Utils'); describe('parseObjectToMongoObjectForCreate', () => { it('a basic number', done => { @@ -592,7 +593,7 @@ describe('relativeTimeToDate', () => { describe('In the future', () => { it('should parse valid natural time', () => { const text = 'in 1 year 2 weeks 12 days 10 hours 24 minutes 30 seconds'; - const { result, status, info } = transform.relativeTimeToDate(text, now); + const { result, status, info } = Utils.relativeTimeToDate(text, now); expect(result.toISOString()).toBe('2018-10-22T23:52:46.617Z'); expect(status).toBe('success'); expect(info).toBe('future'); @@ -602,7 +603,7 @@ describe('relativeTimeToDate', () => { describe('In the past', () => { it('should parse valid natural time', () => { const text = '2 days 12 hours 1 minute 12 seconds ago'; - const { result, status, info } = transform.relativeTimeToDate(text, now); + const { result, status, info } = Utils.relativeTimeToDate(text, now); expect(result.toISOString()).toBe('2017-09-24T01:27:04.617Z'); expect(status).toBe('success'); expect(info).toBe('past'); @@ -612,7 +613,7 @@ describe('relativeTimeToDate', () => { describe('From now', () => { it('should equal current time', () => { const text = 'now'; - const { result, status, info } = transform.relativeTimeToDate(text, now); + const { result, status, info } = Utils.relativeTimeToDate(text, now); expect(result.toISOString()).toBe('2017-09-26T13:28:16.617Z'); expect(status).toBe('success'); expect(info).toBe('present'); @@ -621,54 +622,54 @@ describe('relativeTimeToDate', () => { describe('Error cases', () => { it('should error if string is completely gibberish', () => { - expect(transform.relativeTimeToDate('gibberishasdnklasdnjklasndkl123j123')).toEqual({ + expect(Utils.relativeTimeToDate('gibberishasdnklasdnjklasndkl123j123')).toEqual({ status: 'error', info: "Time should either start with 'in' or end with 'ago'", }); }); it('should error if string contains neither `ago` nor `in`', () => { - expect(transform.relativeTimeToDate('12 hours 1 minute')).toEqual({ + expect(Utils.relativeTimeToDate('12 hours 1 minute')).toEqual({ status: 'error', info: "Time should either start with 'in' or end with 'ago'", }); }); it('should error if there are missing units or numbers', () => { - expect(transform.relativeTimeToDate('in 12 hours 1')).toEqual({ + expect(Utils.relativeTimeToDate('in 12 hours 1')).toEqual({ status: 'error', info: 'Invalid time string. Dangling unit or number.', }); - expect(transform.relativeTimeToDate('12 hours minute ago')).toEqual({ + expect(Utils.relativeTimeToDate('12 hours minute ago')).toEqual({ status: 'error', info: 'Invalid time string. Dangling unit or number.', }); }); it('should error on floating point numbers', () => { - expect(transform.relativeTimeToDate('in 12.3 hours')).toEqual({ + expect(Utils.relativeTimeToDate('in 12.3 hours')).toEqual({ status: 'error', info: "'12.3' is not an integer.", }); }); it('should error if numbers are invalid', () => { - expect(transform.relativeTimeToDate('12 hours 123a minute ago')).toEqual({ + expect(Utils.relativeTimeToDate('12 hours 123a minute ago')).toEqual({ status: 'error', info: "'123a' is not an integer.", }); }); it('should error on invalid interval units', () => { - expect(transform.relativeTimeToDate('4 score 7 years ago')).toEqual({ + expect(Utils.relativeTimeToDate('4 score 7 years ago')).toEqual({ status: 'error', info: "Invalid interval: 'score'", }); }); it("should error when string contains 'ago' and 'in'", () => { - expect(transform.relativeTimeToDate('in 1 day 2 minutes ago')).toEqual({ + expect(Utils.relativeTimeToDate('in 1 day 2 minutes ago')).toEqual({ status: 'error', info: "Time cannot have both 'in' and 'ago'", }); diff --git a/spec/ParseQuery.spec.js b/spec/ParseQuery.spec.js index bf870c92..6de09579 100644 --- a/spec/ParseQuery.spec.js +++ b/spec/ParseQuery.spec.js @@ -4766,7 +4766,7 @@ describe('Parse.Query testing', () => { .catch(done.fail); }); - it_only_db('mongo')('should handle relative times correctly', function (done) { + it('should handle relative times correctly', async () => { const now = Date.now(); const obj1 = new Parse.Object('MyCustomObject', { name: 'obj1', @@ -4777,94 +4777,75 @@ describe('Parse.Query testing', () => { ttl: new Date(now - 2 * 24 * 60 * 60 * 1000), // 2 days ago }); - Parse.Object.saveAll([obj1, obj2]) - .then(() => { - const q = new Parse.Query('MyCustomObject'); - q.greaterThan('ttl', { $relativeTime: 'in 1 day' }); - return q.find({ useMasterKey: true }); - }) - .then(results => { - expect(results.length).toBe(1); - }) - .then(() => { - const q = new Parse.Query('MyCustomObject'); - q.greaterThan('ttl', { $relativeTime: '1 day ago' }); - return q.find({ useMasterKey: true }); - }) - .then(results => { - expect(results.length).toBe(1); - }) - .then(() => { - const q = new Parse.Query('MyCustomObject'); - q.lessThan('ttl', { $relativeTime: '5 days ago' }); - return q.find({ useMasterKey: true }); - }) - .then(results => { - expect(results.length).toBe(0); - }) - .then(() => { - const q = new Parse.Query('MyCustomObject'); - q.greaterThan('ttl', { $relativeTime: '3 days ago' }); - return q.find({ useMasterKey: true }); - }) - .then(results => { - expect(results.length).toBe(2); - }) - .then(() => { - const q = new Parse.Query('MyCustomObject'); - q.greaterThan('ttl', { $relativeTime: 'now' }); - return q.find({ useMasterKey: true }); - }) - .then(results => { - expect(results.length).toBe(1); - }) - .then(() => { - const q = new Parse.Query('MyCustomObject'); - q.greaterThan('ttl', { $relativeTime: 'now' }); - q.lessThan('ttl', { $relativeTime: 'in 1 day' }); - return q.find({ useMasterKey: true }); - }) - .then(results => { - expect(results.length).toBe(0); - }) - .then(() => { - const q = new Parse.Query('MyCustomObject'); - q.greaterThan('ttl', { $relativeTime: '1 year 3 weeks ago' }); - return q.find({ useMasterKey: true }); - }) - .then(results => { - expect(results.length).toBe(2); - }) - .then(done, done.fail); + await Parse.Object.saveAll([obj1, obj2]) + const q1 = new Parse.Query('MyCustomObject'); + q1.greaterThan('ttl', { $relativeTime: 'in 1 day' }); + const results1 = await q1.find({ useMasterKey: true }); + expect(results1.length).toBe(1); + + const q2 = new Parse.Query('MyCustomObject'); + q2.greaterThan('ttl', { $relativeTime: '1 day ago' }); + const results2 = await q2.find({ useMasterKey: true }); + expect(results2.length).toBe(1); + + const q3 = new Parse.Query('MyCustomObject'); + q3.lessThan('ttl', { $relativeTime: '5 days ago' }); + const results3 = await q3.find({ useMasterKey: true }); + expect(results3.length).toBe(0); + + const q4 = new Parse.Query('MyCustomObject'); + q4.greaterThan('ttl', { $relativeTime: '3 days ago' }); + const results4 = await q4.find({ useMasterKey: true }); + expect(results4.length).toBe(2); + + const q5 = new Parse.Query('MyCustomObject'); + q5.greaterThan('ttl', { $relativeTime: 'now' }); + const results5 = await q5.find({ useMasterKey: true }); + expect(results5.length).toBe(1); + + const q6 = new Parse.Query('MyCustomObject'); + q6.greaterThan('ttl', { $relativeTime: 'now' }); + q6.lessThan('ttl', { $relativeTime: 'in 1 day' }); + const results6 = await q6.find({ useMasterKey: true }); + expect(results6.length).toBe(0); + + const q7 = new Parse.Query('MyCustomObject'); + q7.greaterThan('ttl', { $relativeTime: '1 year 3 weeks ago' }); + const results7 = await q7.find({ useMasterKey: true }); + expect(results7.length).toBe(2); }); - it_only_db('mongo')('should error on invalid relative time', function (done) { + it('should error on invalid relative time', async () => { const obj1 = new Parse.Object('MyCustomObject', { name: 'obj1', ttl: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000), // 2 days from now }); - + await obj1.save({ useMasterKey: true }); const q = new Parse.Query('MyCustomObject'); q.greaterThan('ttl', { $relativeTime: '-12 bananas ago' }); - obj1 - .save({ useMasterKey: true }) - .then(() => q.find({ useMasterKey: true })) - .then(done.fail, () => done()); + try { + await q.find({ useMasterKey: true }); + fail("Should have thrown error"); + } catch(error) { + expect(error.code).toBe(Parse.Error.INVALID_JSON); + } }); - it_only_db('mongo')('should error when using $relativeTime on non-Date field', function (done) { + it('should error when using $relativeTime on non-Date field', async () => { const obj1 = new Parse.Object('MyCustomObject', { name: 'obj1', nonDateField: 'abcd', ttl: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000), // 2 days from now }); - + await obj1.save({ useMasterKey: true }); const q = new Parse.Query('MyCustomObject'); q.greaterThan('nonDateField', { $relativeTime: '1 day ago' }); - obj1 - .save({ useMasterKey: true }) - .then(() => q.find({ useMasterKey: true })) - .then(done.fail, () => done()); + try { + await q.find({ useMasterKey: true }); + fail("Should have thrown error"); + } catch(error) { + expect(error.code).toBe(Parse.Error.INVALID_JSON); + } }); it('should match complex structure with dot notation when using matchesKeyInQuery', function (done) { diff --git a/spec/PostgresStorageAdapter.spec.js b/spec/PostgresStorageAdapter.spec.js index b042206d..dfb6bf41 100644 --- a/spec/PostgresStorageAdapter.spec.js +++ b/spec/PostgresStorageAdapter.spec.js @@ -149,6 +149,135 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => { await expectAsync(adapter.getClass('UnknownClass')).toBeRejectedWith(undefined); }); + it('$relativeTime should error on $eq', async () => { + const tableName = '_User'; + const schema = { + fields: { + objectId: { type: 'String' }, + username: { type: 'String' }, + email: { type: 'String' }, + emailVerified: { type: 'Boolean' }, + createdAt: { type: 'Date' }, + updatedAt: { type: 'Date' }, + authData: { type: 'Object' }, + }, + }; + const client = adapter._client; + await adapter.createTable(tableName, schema); + await client.none('INSERT INTO $1:name ($2:name, $3:name) VALUES ($4, $5)', [ + tableName, + 'objectId', + 'username', + 'Bugs', + 'Bunny', + ]); + const database = Config.get(Parse.applicationId).database; + await database.loadSchema({ clearCache: true }); + try { + await database.find( + tableName, + { + createdAt: { + $eq: { + $relativeTime: '12 days ago' + } + } + }, + { } + ); + fail("Should have thrown error"); + } catch(error) { + expect(error.code).toBe(Parse.Error.INVALID_JSON); + } + await dropTable(client, tableName); + }); + + it('$relativeTime should error on $ne', async () => { + const tableName = '_User'; + const schema = { + fields: { + objectId: { type: 'String' }, + username: { type: 'String' }, + email: { type: 'String' }, + emailVerified: { type: 'Boolean' }, + createdAt: { type: 'Date' }, + updatedAt: { type: 'Date' }, + authData: { type: 'Object' }, + }, + }; + const client = adapter._client; + await adapter.createTable(tableName, schema); + await client.none('INSERT INTO $1:name ($2:name, $3:name) VALUES ($4, $5)', [ + tableName, + 'objectId', + 'username', + 'Bugs', + 'Bunny', + ]); + const database = Config.get(Parse.applicationId).database; + await database.loadSchema({ clearCache: true }); + try { + await database.find( + tableName, + { + createdAt: { + $ne: { + $relativeTime: '12 days ago' + } + } + }, + { } + ); + fail("Should have thrown error"); + } catch(error) { + expect(error.code).toBe(Parse.Error.INVALID_JSON); + } + await dropTable(client, tableName); + }); + + it('$relativeTime should error on $exists', async () => { + const tableName = '_User'; + const schema = { + fields: { + objectId: { type: 'String' }, + username: { type: 'String' }, + email: { type: 'String' }, + emailVerified: { type: 'Boolean' }, + createdAt: { type: 'Date' }, + updatedAt: { type: 'Date' }, + authData: { type: 'Object' }, + }, + }; + const client = adapter._client; + await adapter.createTable(tableName, schema); + await client.none('INSERT INTO $1:name ($2:name, $3:name) VALUES ($4, $5)', [ + tableName, + 'objectId', + 'username', + 'Bugs', + 'Bunny', + ]); + const database = Config.get(Parse.applicationId).database; + await database.loadSchema({ clearCache: true }); + try { + await database.find( + tableName, + { + createdAt: { + $exists: { + $relativeTime: '12 days ago' + } + } + }, + { } + ); + fail("Should have thrown error"); + } catch(error) { + expect(error.code).toBe(Parse.Error.INVALID_JSON); + } + await dropTable(client, tableName); + }); + it('should use index for caseInsensitive query using Postgres', async () => { const tableName = '_User'; const schema = { diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 55780777..91ad23fa 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -2,6 +2,7 @@ import log from '../../../logger'; import _ from 'lodash'; var mongodb = require('mongodb'); var Parse = require('parse/node').Parse; +const Utils = require('../../../Utils'); const transformKey = (className, fieldName, schema) => { // Check if the schema is known since it's a built-in field. @@ -634,133 +635,6 @@ function transformTopLevelAtom(atom, field) { } } -function relativeTimeToDate(text, now = new Date()) { - text = text.toLowerCase(); - - let parts = text.split(' '); - - // Filter out whitespace - parts = parts.filter(part => part !== ''); - - const future = parts[0] === 'in'; - const past = parts[parts.length - 1] === 'ago'; - - if (!future && !past && text !== 'now') { - return { - status: 'error', - info: "Time should either start with 'in' or end with 'ago'", - }; - } - - if (future && past) { - return { - status: 'error', - info: "Time cannot have both 'in' and 'ago'", - }; - } - - // strip the 'ago' or 'in' - if (future) { - parts = parts.slice(1); - } else { - // past - parts = parts.slice(0, parts.length - 1); - } - - if (parts.length % 2 !== 0 && text !== 'now') { - return { - status: 'error', - info: 'Invalid time string. Dangling unit or number.', - }; - } - - const pairs = []; - while (parts.length) { - pairs.push([parts.shift(), parts.shift()]); - } - - let seconds = 0; - for (const [num, interval] of pairs) { - const val = Number(num); - if (!Number.isInteger(val)) { - return { - status: 'error', - info: `'${num}' is not an integer.`, - }; - } - - switch (interval) { - case 'yr': - case 'yrs': - case 'year': - case 'years': - seconds += val * 31536000; // 365 * 24 * 60 * 60 - break; - - case 'wk': - case 'wks': - case 'week': - case 'weeks': - seconds += val * 604800; // 7 * 24 * 60 * 60 - break; - - case 'd': - case 'day': - case 'days': - seconds += val * 86400; // 24 * 60 * 60 - break; - - case 'hr': - case 'hrs': - case 'hour': - case 'hours': - seconds += val * 3600; // 60 * 60 - break; - - case 'min': - case 'mins': - case 'minute': - case 'minutes': - seconds += val * 60; - break; - - case 'sec': - case 'secs': - case 'second': - case 'seconds': - seconds += val; - break; - - default: - return { - status: 'error', - info: `Invalid interval: '${interval}'`, - }; - } - } - - const milliseconds = seconds * 1000; - if (future) { - return { - status: 'success', - info: 'future', - result: new Date(now.valueOf() + milliseconds), - }; - } else if (past) { - return { - status: 'success', - info: 'past', - result: new Date(now.valueOf() - milliseconds), - }; - } else { - return { - status: 'success', - info: 'present', - result: new Date(now.valueOf()), - }; - } -} - // Transforms a query constraint from REST API format to Mongo format. // A constraint is something with fields like $lt. // If it is not a valid constraint but it could be a valid something @@ -813,7 +687,7 @@ function transformConstraint(constraint, field, count = false) { ); } - const parserResult = relativeTimeToDate(val.$relativeTime); + const parserResult = Utils.relativeTimeToDate(val.$relativeTime); if (parserResult.status === 'success') { answer[key] = parserResult.result; break; @@ -1556,7 +1430,6 @@ module.exports = { transformUpdate, transformWhere, mongoObjectToParseObject, - relativeTimeToDate, transformConstraint, transformPointerString, }; diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index f787d9f1..de5712b7 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -7,6 +7,9 @@ import _ from 'lodash'; // @flow-disable-next import { v4 as uuidv4 } from 'uuid'; import sql from './sql'; +import { StorageAdapter } from '../StorageAdapter'; +import type { SchemaType, QueryType, QueryOptions } from '../StorageAdapter'; +const Utils = require('../../../Utils'); const PostgresRelationDoesNotExistError = '42P01'; const PostgresDuplicateRelationError = '42P07'; @@ -22,9 +25,6 @@ const debug = function (...args: any) { log.debug.apply(log, args); }; -import { StorageAdapter } from '../StorageAdapter'; -import type { SchemaType, QueryType, QueryOptions } from '../StorageAdapter'; - const parseTypeToPostgresType = type => { switch (type.type) { case 'String': @@ -374,6 +374,11 @@ const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClaus patterns.push( `(${constraintFieldName} <> $${index} OR ${constraintFieldName} IS NULL)` ); + } else if (typeof fieldValue.$ne === 'object' && fieldValue.$ne.$relativeTime) { + throw new Parse.Error( + Parse.Error.INVALID_JSON, + '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators' + ); } else { patterns.push(`($${index}:name <> $${index + 1} OR $${index}:name IS NULL)`); } @@ -399,6 +404,11 @@ const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClaus if (fieldName.indexOf('.') >= 0) { values.push(fieldValue.$eq); patterns.push(`${transformDotField(fieldName)} = $${index++}`); + } else if (typeof fieldValue.$eq === 'object' && fieldValue.$eq.$relativeTime) { + throw new Parse.Error( + Parse.Error.INVALID_JSON, + '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators' + ); } else { values.push(fieldName, fieldValue.$eq); patterns.push(`$${index}:name = $${index + 1}`); @@ -513,7 +523,12 @@ const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClaus } if (typeof fieldValue.$exists !== 'undefined') { - if (fieldValue.$exists) { + if (typeof fieldValue.$exists === 'object' && fieldValue.$exists.$relativeTime) { + throw new Parse.Error( + Parse.Error.INVALID_JSON, + '$relativeTime can only be used with the $lt, $lte, $gt, and $gte operators' + ); + } else if (fieldValue.$exists) { patterns.push(`$${index}:name IS NOT NULL`); } else { patterns.push(`$${index}:name IS NULL`); @@ -757,7 +772,7 @@ const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClaus Object.keys(ParseToPosgresComparator).forEach(cmp => { if (fieldValue[cmp] || fieldValue[cmp] === 0) { const pgComparator = ParseToPosgresComparator[cmp]; - const postgresValue = toPostgresValue(fieldValue[cmp]); + let postgresValue = toPostgresValue(fieldValue[cmp]); let constraintFieldName; if (fieldName.indexOf('.') >= 0) { let castType; @@ -775,6 +790,24 @@ const buildWhereClause = ({ schema, query, index, caseInsensitive }): WhereClaus ? `CAST ((${transformDotField(fieldName)}) AS ${castType})` : transformDotField(fieldName); } else { + if (typeof postgresValue === 'object' && postgresValue.$relativeTime) { + if (schema.fields[fieldName].type !== 'Date') { + throw new Parse.Error( + Parse.Error.INVALID_JSON, + '$relativeTime can only be used with Date field' + ); + } + const parserResult = Utils.relativeTimeToDate(postgresValue.$relativeTime); + if (parserResult.status === 'success') { + postgresValue = toPostgresValue(parserResult.result); + } else { + console.error('Error while parsing relative date', parserResult); + throw new Parse.Error( + Parse.Error.INVALID_JSON, + `bad $relativeTime (${postgresValue.$relativeTime}) value. ${parserResult.info}` + ); + } + } constraintFieldName = `$${index++}:name`; values.push(fieldName); } diff --git a/src/Utils.js b/src/Utils.js index e78d7ddd..c96be084 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -200,6 +200,138 @@ class Utils { } } } + + /** + * Computes the relative date based on a string. + * @param {String} text The string to interpret the date from. + * @param {Date} now The date the string is comparing against. + * @returns {Object} The relative date object. + **/ + static relativeTimeToDate(text, now = new Date()) { + text = text.toLowerCase(); + let parts = text.split(' '); + + // Filter out whitespace + parts = parts.filter(part => part !== ''); + + const future = parts[0] === 'in'; + const past = parts[parts.length - 1] === 'ago'; + + if (!future && !past && text !== 'now') { + return { + status: 'error', + info: "Time should either start with 'in' or end with 'ago'", + }; + } + + if (future && past) { + return { + status: 'error', + info: "Time cannot have both 'in' and 'ago'", + }; + } + + // strip the 'ago' or 'in' + if (future) { + parts = parts.slice(1); + } else { + // past + parts = parts.slice(0, parts.length - 1); + } + + if (parts.length % 2 !== 0 && text !== 'now') { + return { + status: 'error', + info: 'Invalid time string. Dangling unit or number.', + }; + } + + const pairs = []; + while (parts.length) { + pairs.push([parts.shift(), parts.shift()]); + } + + let seconds = 0; + for (const [num, interval] of pairs) { + const val = Number(num); + if (!Number.isInteger(val)) { + return { + status: 'error', + info: `'${num}' is not an integer.`, + }; + } + + switch (interval) { + case 'yr': + case 'yrs': + case 'year': + case 'years': + seconds += val * 31536000; // 365 * 24 * 60 * 60 + break; + + case 'wk': + case 'wks': + case 'week': + case 'weeks': + seconds += val * 604800; // 7 * 24 * 60 * 60 + break; + + case 'd': + case 'day': + case 'days': + seconds += val * 86400; // 24 * 60 * 60 + break; + + case 'hr': + case 'hrs': + case 'hour': + case 'hours': + seconds += val * 3600; // 60 * 60 + break; + + case 'min': + case 'mins': + case 'minute': + case 'minutes': + seconds += val * 60; + break; + + case 'sec': + case 'secs': + case 'second': + case 'seconds': + seconds += val; + break; + + default: + return { + status: 'error', + info: `Invalid interval: '${interval}'`, + }; + } + } + + const milliseconds = seconds * 1000; + if (future) { + return { + status: 'success', + info: 'future', + result: new Date(now.valueOf() + milliseconds), + }; + } else if (past) { + return { + status: 'success', + info: 'past', + result: new Date(now.valueOf() - milliseconds), + }; + } else { + return { + status: 'success', + info: 'present', + result: new Date(now.valueOf()), + }; + } + } } module.exports = Utils; From acfdc54a06fd0e9e33bf2937507ce44d2e8e1b68 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 2 Jan 2022 00:11:48 +0000 Subject: [PATCH 35/89] chore(release): 5.0.0-alpha.14 [skip ci] # [5.0.0-alpha.14](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.13...5.0.0-alpha.14) (2022-01-02) ### Features * support relativeTime query constraint on Postgres ([#7747](https://github.com/parse-community/parse-server/issues/7747)) ([16b1b2a](https://github.com/parse-community/parse-server/commit/16b1b2a19714535ca805f2dbb3b561d8f6a519a7)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index e635c16f..ebeefd38 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.14](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.13...5.0.0-alpha.14) (2022-01-02) + + +### Features + +* support relativeTime query constraint on Postgres ([#7747](https://github.com/parse-community/parse-server/issues/7747)) ([16b1b2a](https://github.com/parse-community/parse-server/commit/16b1b2a19714535ca805f2dbb3b561d8f6a519a7)) + # [5.0.0-alpha.13](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.12...5.0.0-alpha.13) (2021-12-08) diff --git a/package-lock.json b/package-lock.json index 38bf6a39..5f1beddb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.13", + "version": "5.0.0-alpha.14", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 41623812..52d6caf5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.13", + "version": "5.0.0-alpha.14", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From b106ffc994623a07741399e0f4a6d22c5640d24b Mon Sep 17 00:00:00 2001 From: Corey Date: Sat, 1 Jan 2022 19:45:00 -0500 Subject: [PATCH 36/89] ci: test server with PostGIS 3.2 (#7752) --- .github/workflows/ci.yml | 15 +++++++++------ CONTRIBUTING.md | 4 ++-- README.md | 8 ++++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96ed13b0..2463901a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,14 +187,17 @@ jobs: - name: PostgreSQL 11, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:11-3.1 NODE_VERSION: 16.13.0 - - name: PostgreSQL 12, PostGIS 3.1 - POSTGRES_IMAGE: postgis/postgis:12-3.1 + - name: PostgreSQL 11, PostGIS 3.2 + POSTGRES_IMAGE: postgis/postgis:11-3.2 NODE_VERSION: 16.13.0 - - name: PostgreSQL 13, PostGIS 3.1 - POSTGRES_IMAGE: postgis/postgis:13-3.1 + - name: PostgreSQL 12, PostGIS 3.2 + POSTGRES_IMAGE: postgis/postgis:12-3.2 NODE_VERSION: 16.13.0 - - name: PostgreSQL 14, PostGIS 3.1 - POSTGRES_IMAGE: postgis/postgis:14-3.1 + - name: PostgreSQL 13, PostGIS 3.2 + POSTGRES_IMAGE: postgis/postgis:13-3.2 + NODE_VERSION: 16.13.0 + - name: PostgreSQL 14, PostGIS 3.2 + POSTGRES_IMAGE: postgis/postgis:14-3.2 NODE_VERSION: 16.13.0 fail-fast: false name: ${{ matrix.name }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7e620fbc..1605c47e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -154,7 +154,7 @@ If your pull request introduces a change that may affect the storage or retrieva [PostGIS images (select one with v2.2 or higher) on docker dashboard](https://hub.docker.com/r/postgis/postgis) is based off of the official [postgres](https://registry.hub.docker.com/_/postgres/) image and will work out-of-the-box (as long as you create a user with the necessary extensions for each of your Parse databases; see below). To launch the compatible Postgres instance, copy and paste the following line into your shell: ``` -docker run -d --name parse-postgres -p 5432:5432 -e POSTGRES_PASSWORD=password --rm postgis/postgis:13-3.1-alpine && sleep 20 && docker exec -it parse-postgres psql -U postgres -c 'CREATE DATABASE parse_server_postgres_adapter_test_database;' && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION pgcrypto; CREATE EXTENSION postgis;' -d parse_server_postgres_adapter_test_database && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION postgis_topology;' -d parse_server_postgres_adapter_test_database +docker run -d --name parse-postgres -p 5432:5432 -e POSTGRES_PASSWORD=password --rm postgis/postgis:13-3.2-alpine && sleep 20 && docker exec -it parse-postgres psql -U postgres -c 'CREATE DATABASE parse_server_postgres_adapter_test_database;' && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION pgcrypto; CREATE EXTENSION postgis;' -d parse_server_postgres_adapter_test_database && docker exec -it parse-postgres psql -U postgres -c 'CREATE EXTENSION postgis_topology;' -d parse_server_postgres_adapter_test_database ``` To stop the Postgres instance: @@ -162,7 +162,7 @@ To stop the Postgres instance: docker stop parse-postgres ``` -You can also use the [postgis/postgis:13-3.1-alpine](https://hub.docker.com/r/postgis/postgis) image in a Dockerfile and copy this [script](https://github.com/parse-community/parse-server/blob/master/scripts/before_script_postgres.sh) to the image by adding the following lines: +You can also use the [postgis/postgis:13-3.2-alpine](https://hub.docker.com/r/postgis/postgis) image in a Dockerfile and copy this [script](https://github.com/parse-community/parse-server/blob/master/scripts/before_script_postgres.sh) to the image by adding the following lines: ``` #Install additional scripts. These are run in abc order during initial start diff --git a/README.md b/README.md index f2ecce98..86d1247b 100644 --- a/README.md +++ b/README.md @@ -134,10 +134,10 @@ Parse Server is continuously tested with the most recent releases of PostgreSQL | Version | PostGIS Version | End-of-Life | Parse Server Support End | Compatible | |-------------|-----------------|---------------|--------------------------|------------| -| Postgres 11 | 3.0, 3.1 | November 2023 | April 2022 | ✅ Yes | -| Postgres 12 | 3.1 | November 2024 | April 2023 | ✅ Yes | -| Postgres 13 | 3.1 | November 2025 | April 2024 | ✅ Yes | -| Postgres 14 | 3.1 | November 2026 | April 2025 | ✅ Yes | +| Postgres 11 | 3.0, 3.1, 3.2 | November 2023 | April 2022 | ✅ Yes | +| Postgres 12 | 3.2 | November 2024 | April 2023 | ✅ Yes | +| Postgres 13 | 3.2 | November 2025 | April 2024 | ✅ Yes | +| Postgres 14 | 3.2 | November 2026 | April 2025 | ✅ Yes | ### Locally ```bash From 912edacb53c6cd9c05436918072896aaf4cf8107 Mon Sep 17 00:00:00 2001 From: Corey Date: Sun, 2 Jan 2022 08:59:00 -0500 Subject: [PATCH 37/89] test: make GraphQL server test more reliable (#7758) --- spec/ParseGraphQLServer.spec.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 58b26e4b..d204886f 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -2600,11 +2600,19 @@ describe('ParseGraphQLServer', () => { // "SecondaryObject:bBRgmzIRRM" < "SecondaryObject:nTMcuVbATY" true // base64("SecondaryObject:bBRgmzIRRM"") < base64(""SecondaryObject:nTMcuVbATY"") false // "U2Vjb25kYXJ5T2JqZWN0OmJCUmdteklSUk0=" < "U2Vjb25kYXJ5T2JqZWN0Om5UTWN1VmJBVFk=" false + const originalIds = [getSecondaryObjectsResult.data.secondaryObject2.objectId, + getSecondaryObjectsResult.data.secondaryObject4.objectId]; expect( findSecondaryObjectsResult.data.secondaryObjects.edges[0].node.objectId - ).toBeLessThan( + ).not.toBe( findSecondaryObjectsResult.data.secondaryObjects.edges[1].node.objectId ); + expect( + originalIds.includes(findSecondaryObjectsResult.data.secondaryObjects.edges[0].node.objectId) + ).toBeTrue(); + expect( + originalIds.includes(findSecondaryObjectsResult.data.secondaryObjects.edges[1].node.objectId) + ).toBeTrue(); const createPrimaryObjectResult = await apolloClient.mutate({ mutation: gql` From caf4a2341f554b28e3918c53e7e897a3ca47bf8b Mon Sep 17 00:00:00 2001 From: Corey Date: Sun, 2 Jan 2022 09:25:43 -0500 Subject: [PATCH 38/89] feat: support `postgresql` protocol in database URI (#7757) --- spec/PostgresInitOptions.spec.js | 94 ++++++++++++----------------- spec/PostgresStorageAdapter.spec.js | 11 +++- src/Controllers/index.js | 1 + 3 files changed, 50 insertions(+), 56 deletions(-) diff --git a/spec/PostgresInitOptions.spec.js b/spec/PostgresInitOptions.spec.js index 069d5a64..76024073 100644 --- a/spec/PostgresInitOptions.spec.js +++ b/spec/PostgresInitOptions.spec.js @@ -4,8 +4,7 @@ const PostgresStorageAdapter = require('../lib/Adapters/Storage/Postgres/Postgre const postgresURI = process.env.PARSE_SERVER_TEST_DATABASE_URI || 'postgres://localhost:5432/parse_server_postgres_adapter_test_database'; -const ParseServer = require('../lib/index'); -const express = require('express'); + //public schema const databaseOptions1 = { initOptions: { @@ -24,72 +23,57 @@ const GameScore = Parse.Object.extend({ className: 'GameScore', }); -function createParseServer(options) { - return new Promise((resolve, reject) => { - const parseServer = new ParseServer.default( - Object.assign({}, defaultConfiguration, options, { - serverURL: 'http://localhost:12668/parse', - serverStartComplete: error => { - if (error) { - reject(error); - } else { - expect(Parse.applicationId).toEqual('test'); - const app = express(); - app.use('/parse', parseServer.app); - - const server = app.listen(12668); - Parse.serverURL = 'http://localhost:12668/parse'; - resolve(server); - } - }, - }) - ); - }); -} - describe_only_db('postgres')('Postgres database init options', () => { - let server; - afterAll(done => { - if (server) { - Parse.serverURL = 'http://localhost:8378/1'; - server.close(done); - } - }); - - it('should create server with public schema databaseOptions', done => { + it('should create server with public schema databaseOptions', async () => { const adapter = new PostgresStorageAdapter({ uri: postgresURI, collectionPrefix: 'test_', databaseOptions: databaseOptions1, }); - - createParseServer({ databaseAdapter: adapter }) - .then(newServer => { - server = newServer; - const score = new GameScore({ - score: 1337, - playerName: 'Sean Plott', - cheatMode: false, - }); - return score.save(); - }) - .then(async () => { - await reconfigureServer(); - done(); - }, done.fail); + await reconfigureServer({ + databaseAdapter: adapter, + }); + const score = new GameScore({ + score: 1337, + playerName: 'Sean Plott', + cheatMode: false, + }); + await score.save(); }); - it('should fail to create server if schema databaseOptions does not exist', done => { + it('should create server using postgresql uri with public schema databaseOptions', async () => { + const postgresURI2 = new URL(postgresURI); + postgresURI2.protocol = 'postgresql:'; + const adapter = new PostgresStorageAdapter({ + uri: postgresURI2.toString(), + collectionPrefix: 'test_', + databaseOptions: databaseOptions1, + }); + await reconfigureServer({ + databaseAdapter: adapter, + }); + const score = new GameScore({ + score: 1337, + playerName: 'Sean Plott', + cheatMode: false, + }); + await score.save(); + }); + + it('should fail to create server if schema databaseOptions does not exist', async () => { const adapter = new PostgresStorageAdapter({ uri: postgresURI, collectionPrefix: 'test_', databaseOptions: databaseOptions2, }); - - createParseServer({ databaseAdapter: adapter }).then(done.fail, async () => { - await reconfigureServer(); - done(); - }); + try { + await reconfigureServer({ + databaseAdapter: adapter, + }); + fail("Should have thrown error"); + } catch(error) { + expect(error).toBeDefined(); + } }); }); diff --git a/spec/PostgresStorageAdapter.spec.js b/spec/PostgresStorageAdapter.spec.js index dfb6bf41..769aad74 100644 --- a/spec/PostgresStorageAdapter.spec.js +++ b/spec/PostgresStorageAdapter.spec.js @@ -555,7 +555,7 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => { }, classLevelPermissions: undefined, }); - await new Promise(resolve => setTimeout(resolve, 500)); + await new Promise(resolve => setTimeout(resolve, 2000)); expect(adapter._onchange).toHaveBeenCalled(); }); }); @@ -567,4 +567,13 @@ describe_only_db('postgres')('PostgresStorageAdapter shutdown', () => { adapter.handleShutdown(); expect(adapter._client.$pool.ending).toEqual(true); }); + + it('handleShutdown, close connection of postgresql uri', () => { + const databaseURI2 = new URL(databaseURI); + databaseURI2.protocol = 'postgresql:'; + const adapter = new PostgresStorageAdapter({ uri: databaseURI2.toString() }); + expect(adapter._client.$pool.ending).toEqual(false); + adapter.handleShutdown(); + expect(adapter._client.$pool.ending).toEqual(true); + }); }); diff --git a/src/Controllers/index.js b/src/Controllers/index.js index 89dc79c2..67f90a8e 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -227,6 +227,7 @@ export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOption } switch (protocol) { case 'postgres:': + case 'postgresql:': return new PostgresStorageAdapter({ uri: databaseURI, collectionPrefix, From 75b9a56e0a4f2fd9e438eaaf99f5d2d94fb580a8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 2 Jan 2022 14:26:36 +0000 Subject: [PATCH 39/89] chore(release): 5.0.0-alpha.15 [skip ci] # [5.0.0-alpha.15](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.14...5.0.0-alpha.15) (2022-01-02) ### Features * support `postgresql` protocol in database URI ([#7757](https://github.com/parse-community/parse-server/issues/7757)) ([caf4a23](https://github.com/parse-community/parse-server/commit/caf4a2341f554b28e3918c53e7e897a3ca47bf8b)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index ebeefd38..15ee6254 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.15](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.14...5.0.0-alpha.15) (2022-01-02) + + +### Features + +* support `postgresql` protocol in database URI ([#7757](https://github.com/parse-community/parse-server/issues/7757)) ([caf4a23](https://github.com/parse-community/parse-server/commit/caf4a2341f554b28e3918c53e7e897a3ca47bf8b)) + # [5.0.0-alpha.14](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.13...5.0.0-alpha.14) (2022-01-02) diff --git a/package-lock.json b/package-lock.json index 5f1beddb..ca59098e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.14", + "version": "5.0.0-alpha.15", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 52d6caf5..30389b67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.14", + "version": "5.0.0-alpha.15", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 7af5de4b987ce7a7f665d7aa889f2939f755599e Mon Sep 17 00:00:00 2001 From: Corey Date: Sun, 2 Jan 2022 09:51:49 -0500 Subject: [PATCH 40/89] test: improve PushController tests (#7760) --- spec/PushController.spec.js | 74 ++++++++++++------------------------- 1 file changed, 24 insertions(+), 50 deletions(-) diff --git a/spec/PushController.spec.js b/spec/PushController.spec.js index 4626b5e0..49613214 100644 --- a/spec/PushController.spec.js +++ b/spec/PushController.spec.js @@ -562,11 +562,7 @@ describe('PushController', () => { }); const pushStatusId = await sendPush(payload, {}, config, auth); // it is enqueued so it can take time - await new Promise(resolve => { - setTimeout(() => { - resolve(); - }, 1000); - }); + await sleep(1000); Parse.serverURL = 'http://localhost:8378/1'; // GOOD url const result = await Parse.Push.getPushStatus(pushStatusId); expect(result).toBeDefined(); @@ -767,7 +763,7 @@ describe('PushController', () => { }); }); - it('should not schedule push when not configured', done => { + it('should not schedule push when not configured', async () => { const config = Config.get(Parse.applicationId); const auth = { isMaster: true, @@ -800,33 +796,20 @@ describe('PushController', () => { installations.push(installation); } - reconfigureServer({ + await reconfigureServer({ push: { adapter: pushAdapter }, - }) - .then(() => { - return Parse.Object.saveAll(installations) - .then(() => { - return pushController.sendPush(payload, {}, config, auth); - }) - .then(() => new Promise(resolve => setTimeout(resolve, 300))); - }) - .then(() => { - const query = new Parse.Query('_PushStatus'); - return query.find({ useMasterKey: true }).then(results => { - expect(results.length).toBe(1); - const pushStatus = results[0]; - expect(pushStatus.get('status')).not.toBe('scheduled'); - done(); - }); - }) - .catch(err => { - console.error(err); - fail('should not fail'); - done(); - }); + }); + await Parse.Object.saveAll(installations); + await pushController.sendPush(payload, {}, config, auth); + await sleep(1000); + const query = new Parse.Query('_PushStatus'); + const results = await query.find({ useMasterKey: true }); + expect(results.length).toBe(1); + const pushStatus = results[0]; + expect(pushStatus.get('status')).not.toBe('scheduled'); }); - it('should schedule push when configured', done => { + it('should schedule push when configured', async () => { const auth = { isMaster: true, }; @@ -866,28 +849,19 @@ describe('PushController', () => { installation.set('deviceType', 'ios'); installations.push(installation); } - reconfigureServer({ + await reconfigureServer({ push: { adapter: pushAdapter }, scheduledPush: true, - }) - .then(() => { - const config = Config.get(Parse.applicationId); - return Parse.Object.saveAll(installations) - .then(() => { - return pushController.sendPush(payload, {}, config, auth); - }) - .then(() => new Promise(resolve => setTimeout(resolve, 300))); - }) - .then(() => { - const query = new Parse.Query('_PushStatus'); - return query.find({ useMasterKey: true }).then(results => { - expect(results.length).toBe(1); - const pushStatus = results[0]; - expect(pushStatus.get('status')).toBe('scheduled'); - }); - }) - .then(done) - .catch(done.err); + }); + const config = Config.get(Parse.applicationId); + await Parse.Object.saveAll(installations); + await pushController.sendPush(payload, {}, config, auth); + await sleep(1000); + const query = new Parse.Query('_PushStatus'); + const results = await query.find({ useMasterKey: true }); + expect(results.length).toBe(1); + const pushStatus = results[0]; + expect(pushStatus.get('status')).toBe('scheduled'); }); it('should not enqueue push when device token is not set', async () => { From 5e363eae443f32444ba510113432ce4e32b9d718 Mon Sep 17 00:00:00 2001 From: Corey Date: Sun, 2 Jan 2022 12:43:12 -0500 Subject: [PATCH 41/89] refactor: remove unnecessary error checking in PostgresAdapter (#7761) --- .../Postgres/PostgresStorageAdapter.js | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index de5712b7..f789952e 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -15,7 +15,6 @@ const PostgresRelationDoesNotExistError = '42P01'; const PostgresDuplicateRelationError = '42P07'; const PostgresDuplicateColumnError = '42701'; const PostgresMissingColumnError = '42703'; -const PostgresDuplicateObjectError = '42710'; const PostgresUniqueIndexViolationError = '23505'; const logger = require('../../../logger'); @@ -906,15 +905,7 @@ export class PostgresStorageAdapter implements StorageAdapter { 'CREATE TABLE IF NOT EXISTS "_SCHEMA" ( "className" varChar(120), "schema" jsonb, "isParseClass" bool, PRIMARY KEY ("className") )' ) .catch(error => { - if ( - error.code === PostgresDuplicateRelationError || - error.code === PostgresUniqueIndexViolationError || - error.code === PostgresDuplicateObjectError - ) { - // Table already exists, must have been created by a different request. Ignore error. - } else { - throw error; - } + throw error; }); } @@ -2450,23 +2441,7 @@ export class PostgresStorageAdapter implements StorageAdapter { : fieldNames.map((fieldName, index) => `$${index + 3}:name`); const qs = `CREATE INDEX IF NOT EXISTS $1:name ON $2:name (${constraintPatterns.join()})`; await conn.none(qs, [indexNameOptions.name, className, ...fieldNames]).catch(error => { - if ( - error.code === PostgresDuplicateRelationError && - error.message.includes(indexNameOptions.name) - ) { - // Index already exists. Ignore error. - } else if ( - error.code === PostgresUniqueIndexViolationError && - error.message.includes(indexNameOptions.name) - ) { - // Cast the error into the proper parse error - throw new Parse.Error( - Parse.Error.DUPLICATE_VALUE, - 'A duplicate value for a field with unique values was provided' - ); - } else { - throw error; - } + throw error; }); } } From 0c3feaaa1751964c0db89f25674935c3354b1538 Mon Sep 17 00:00:00 2001 From: Corey Date: Sun, 2 Jan 2022 13:25:53 -0500 Subject: [PATCH 42/89] feat: add Idempotency to Postgres (#7750) --- README.md | 21 +++++++- spec/Idempotency.spec.js | 35 +++++++++++-- spec/PostgresStorageAdapter.spec.js | 11 ++++ .../Postgres/PostgresStorageAdapter.js | 52 +++++++++++++++++-- src/Controllers/DatabaseController.js | 39 +++++++++----- src/Controllers/index.js | 4 +- src/middlewares.js | 3 +- 7 files changed, 139 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 86d1247b..7b507e9c 100644 --- a/README.md +++ b/README.md @@ -525,9 +525,26 @@ let api = new ParseServer({ | `idempotencyOptions.paths` | yes | `Array` | `[]` | `.*` (all paths, includes the examples below),
`functions/.*` (all functions),
`jobs/.*` (all jobs),
`classes/.*` (all classes),
`functions/.*` (all functions),
`users` (user creation / update),
`installations` (installation creation / update) | PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_PATHS | An array of path patterns that have to match the request path for request deduplication to be enabled. The mount path must not be included, for example to match the request path `/parse/functions/myFunction` specify the path pattern `functions/myFunction`. A trailing slash of the request path is ignored, for example the path pattern `functions/myFunction` matches both `/parse/functions/myFunction` and `/parse/functions/myFunction/`. | | `idempotencyOptions.ttl` | yes | `Integer` | `300` | `60` (60 seconds) | PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_TTL | The duration in seconds after which a request record is discarded from the database. Duplicate requests due to network issues can be expected to arrive within milliseconds up to several seconds. This value must be greater than `0`. | -### Notes +### Postgres -- This feature is currently only available for MongoDB and not for Postgres. +To use this feature in Postgres, you will need to create a cron job using [pgAdmin](https://www.pgadmin.org/docs/pgadmin4/development/pgagent_jobs.html) or similar to call the Postgres function `idempotency_delete_expired_records()` that deletes expired idempotency records. You can find an example script below. Make sure the script has the same privileges to log into Postgres as Parse Server. + +```bash +#!/bin/bash + +set -e +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + SELECT idempotency_delete_expired_records(); +EOSQL + +exec "$@" +``` + +Assuming the script above is named, `parse_idempotency_delete_expired_records.sh`, a cron job that runs the script every 2 minutes may look like: + +```bash +2 * * * * /root/parse_idempotency_delete_expired_records.sh >/dev/null 2>&1 +``` ## Localization diff --git a/spec/Idempotency.spec.js b/spec/Idempotency.spec.js index c2ef8665..85fa8a65 100644 --- a/spec/Idempotency.spec.js +++ b/spec/Idempotency.spec.js @@ -6,11 +6,14 @@ const rest = require('../lib/rest'); const auth = require('../lib/Auth'); const uuid = require('uuid'); -describe_only_db('mongo')('Idempotency', () => { +describe('Idempotency', () => { // Parameters /** Enable TTL expiration simulated by removing entry instead of waiting for MongoDB TTL monitor which runs only every 60s, so it can take up to 119s until entry removal - ain't nobody got time for that */ const SIMULATE_TTL = true; + const ttl = 2; + const maxTimeOut = 4000; + // Helpers async function deleteRequestEntry(reqId) { const config = Config.get(Parse.applicationId); @@ -38,9 +41,10 @@ describe_only_db('mongo')('Idempotency', () => { } await setup({ paths: ['functions/.*', 'jobs/.*', 'classes/.*', 'users', 'installations'], - ttl: 30, + ttl: ttl, }); }); + // Tests it('should enforce idempotency for cloud code function', async () => { let counter = 0; @@ -56,7 +60,7 @@ describe_only_db('mongo')('Idempotency', () => { 'X-Parse-Request-Id': 'abc-123', }, }; - expect(Config.get(Parse.applicationId).idempotencyOptions.ttl).toBe(30); + expect(Config.get(Parse.applicationId).idempotencyOptions.ttl).toBe(ttl); await request(params); await request(params).then(fail, e => { expect(e.status).toEqual(400); @@ -83,12 +87,35 @@ describe_only_db('mongo')('Idempotency', () => { if (SIMULATE_TTL) { await deleteRequestEntry('abc-123'); } else { - await new Promise(resolve => setTimeout(resolve, 130000)); + await new Promise(resolve => setTimeout(resolve, maxTimeOut)); } await expectAsync(request(params)).toBeResolved(); expect(counter).toBe(2); }); + it_only_db('postgres')('should delete request entry when postgress ttl function is called', async () => { + const client = Config.get(Parse.applicationId).database.adapter._client; + let counter = 0; + Parse.Cloud.define('myFunction', () => { + counter++; + }); + const params = { + method: 'POST', + url: 'http://localhost:8378/1/functions/myFunction', + headers: { + 'X-Parse-Application-Id': Parse.applicationId, + 'X-Parse-Master-Key': Parse.masterKey, + 'X-Parse-Request-Id': 'abc-123', + }, + }; + await expectAsync(request(params)).toBeResolved(); + await expectAsync(request(params)).toBeRejected(); + await new Promise(resolve => setTimeout(resolve, maxTimeOut)); + await client.one('SELECT idempotency_delete_expired_records()'); + await expectAsync(request(params)).toBeResolved(); + expect(counter).toBe(2); + }); + it('should enforce idempotency for cloud code jobs', async () => { let counter = 0; Parse.Cloud.job('myJob', () => { diff --git a/spec/PostgresStorageAdapter.spec.js b/spec/PostgresStorageAdapter.spec.js index 769aad74..5673d6bc 100644 --- a/spec/PostgresStorageAdapter.spec.js +++ b/spec/PostgresStorageAdapter.spec.js @@ -558,6 +558,17 @@ describe_only_db('postgres')('PostgresStorageAdapter', () => { await new Promise(resolve => setTimeout(resolve, 2000)); expect(adapter._onchange).toHaveBeenCalled(); }); + + it('Idempotency class should have function', async () => { + await reconfigureServer(); + const adapter = Config.get('test').database.adapter; + const client = adapter._client; + const qs = "SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid) WHERE p.proname = 'idempotency_delete_expired_records'"; + const foundFunction = await client.one(qs); + expect(foundFunction.format).toBe("public.idempotency_delete_expired_records()"); + await adapter.deleteIdempotencyFunction(); + await client.none(qs); + }); }); describe_only_db('postgres')('PostgresStorageAdapter shutdown', () => { diff --git a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js index f789952e..7477270a 100644 --- a/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js +++ b/src/Adapters/Storage/Postgres/PostgresStorageAdapter.js @@ -2440,9 +2440,55 @@ export class PostgresStorageAdapter implements StorageAdapter { ? fieldNames.map((fieldName, index) => `lower($${index + 3}:name) varchar_pattern_ops`) : fieldNames.map((fieldName, index) => `$${index + 3}:name`); const qs = `CREATE INDEX IF NOT EXISTS $1:name ON $2:name (${constraintPatterns.join()})`; - await conn.none(qs, [indexNameOptions.name, className, ...fieldNames]).catch(error => { - throw error; - }); + const setIdempotencyFunction = options.setIdempotencyFunction !== undefined ? options.setIdempotencyFunction : false; + if (setIdempotencyFunction) { + await this.ensureIdempotencyFunctionExists(options); + } + await conn.none(qs, [indexNameOptions.name, className, ...fieldNames]) + .catch(error => { + if ( + error.code === PostgresDuplicateRelationError && + error.message.includes(indexNameOptions.name) + ) { + // Index already exists. Ignore error. + } else if ( + error.code === PostgresUniqueIndexViolationError && + error.message.includes(indexNameOptions.name) + ) { + // Cast the error into the proper parse error + throw new Parse.Error( + Parse.Error.DUPLICATE_VALUE, + 'A duplicate value for a field with unique values was provided' + ); + } else { + throw error; + } + }); + } + + async deleteIdempotencyFunction( + options?: Object = {} + ): Promise { + const conn = options.conn !== undefined ? options.conn : this._client; + const qs = 'DROP FUNCTION IF EXISTS idempotency_delete_expired_records()'; + return conn + .none(qs) + .catch(error => { + throw error; + }); + } + + async ensureIdempotencyFunctionExists( + options?: Object = {} + ): Promise { + const conn = options.conn !== undefined ? options.conn : this._client; + const ttlOptions = options.ttl !== undefined ? `${options.ttl} seconds` : '60 seconds'; + const qs = 'CREATE OR REPLACE FUNCTION idempotency_delete_expired_records() RETURNS void LANGUAGE plpgsql AS $$ BEGIN DELETE FROM "_Idempotency" WHERE expire < NOW() - INTERVAL $1; END; $$;'; + return conn + .none(qs, [ttlOptions]) + .catch(error => { + throw error; + }); } } diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 42273b69..2c313f83 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -14,6 +14,7 @@ import logger from '../logger'; import * as SchemaController from './SchemaController'; import { StorageAdapter } from '../Adapters/Storage/StorageAdapter'; import MongoStorageAdapter from '../Adapters/Storage/Mongo/MongoStorageAdapter'; +import PostgresStorageAdapter from '../Adapters/Storage/Postgres/PostgresStorageAdapter'; import SchemaCache from '../Adapters/Cache/SchemaCache'; import type { LoadSchemaOptions } from './types'; import type { QueryOptions, FullQueryOptions } from '../Adapters/Storage/StorageAdapter'; @@ -394,12 +395,14 @@ const relationSchema = { class DatabaseController { adapter: StorageAdapter; + idempotencyOptions: any; schemaCache: any; schemaPromise: ?Promise; _transactionalSession: ?any; - constructor(adapter: StorageAdapter) { + constructor(adapter: StorageAdapter, idempotencyOptions?: Object = {}) { this.adapter = adapter; + this.idempotencyOptions = idempotencyOptions; // We don't want a mutable this.schema, because then you could have // one request that uses different schemas for different parts of // it. Instead, use loadSchema to get a schema. @@ -1713,9 +1716,7 @@ class DatabaseController { }; await this.loadSchema().then(schema => schema.enforceClassExists('_User')); await this.loadSchema().then(schema => schema.enforceClassExists('_Role')); - if (this.adapter instanceof MongoStorageAdapter) { - await this.loadSchema().then(schema => schema.enforceClassExists('_Idempotency')); - } + await this.loadSchema().then(schema => schema.enforceClassExists('_Idempotency')); await this.adapter.ensureUniqueness('_User', requiredUserFields, ['username']).catch(error => { logger.warn('Unable to ensure uniqueness for usernames: ', error); @@ -1751,18 +1752,28 @@ class DatabaseController { logger.warn('Unable to ensure uniqueness for role name: ', error); throw error; }); - if (this.adapter instanceof MongoStorageAdapter) { - await this.adapter - .ensureUniqueness('_Idempotency', requiredIdempotencyFields, ['reqId']) - .catch(error => { - logger.warn('Unable to ensure uniqueness for idempotency request ID: ', error); - throw error; - }); - await this.adapter - .ensureIndex('_Idempotency', requiredIdempotencyFields, ['expire'], 'ttl', false, { + await this.adapter + .ensureUniqueness('_Idempotency', requiredIdempotencyFields, ['reqId']) + .catch(error => { + logger.warn('Unable to ensure uniqueness for idempotency request ID: ', error); + throw error; + }); + + const isMongoAdapter = this.adapter instanceof MongoStorageAdapter; + const isPostgresAdapter = this.adapter instanceof PostgresStorageAdapter; + if (isMongoAdapter || isPostgresAdapter) { + let options = {}; + if (isMongoAdapter) { + options = { ttl: 0, - }) + }; + } else if (isPostgresAdapter) { + options = this.idempotencyOptions; + options.setIdempotencyFunction = true; + } + await this.adapter + .ensureIndex('_Idempotency', requiredIdempotencyFields, ['expire'], 'ttl', false, options) .catch(error => { logger.warn('Unable to create TTL index for idempotency expire date: ', error); throw error; diff --git a/src/Controllers/index.js b/src/Controllers/index.js index 67f90a8e..71ab5ef4 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -143,7 +143,7 @@ export function getLiveQueryController(options: ParseServerOptions): LiveQueryCo } export function getDatabaseController(options: ParseServerOptions): DatabaseController { - const { databaseURI, collectionPrefix, databaseOptions } = options; + const { databaseURI, collectionPrefix, databaseOptions, idempotencyOptions } = options; let { databaseAdapter } = options; if ( (databaseOptions || @@ -157,7 +157,7 @@ export function getDatabaseController(options: ParseServerOptions): DatabaseCont } else { databaseAdapter = loadAdapter(databaseAdapter); } - return new DatabaseController(databaseAdapter); + return new DatabaseController(databaseAdapter, idempotencyOptions); } export function getHooksController( diff --git a/src/middlewares.js b/src/middlewares.js index 88de1072..e749d050 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -6,6 +6,7 @@ import ClientSDK from './ClientSDK'; import defaultLogger from './logger'; import rest from './rest'; import MongoStorageAdapter from './Adapters/Storage/Mongo/MongoStorageAdapter'; +import PostgresStorageAdapter from './Adapters/Storage/Postgres/PostgresStorageAdapter'; export const DEFAULT_ALLOWED_HEADERS = 'X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, X-Parse-Request-Id, Content-Type, Pragma, Cache-Control'; @@ -431,7 +432,7 @@ export function promiseEnforceMasterKeyAccess(request) { */ export function promiseEnsureIdempotency(req) { // Enable feature only for MongoDB - if (!(req.config.database.adapter instanceof MongoStorageAdapter)) { + if (!((req.config.database.adapter instanceof MongoStorageAdapter) || (req.config.database.adapter instanceof PostgresStorageAdapter))) { return Promise.resolve(); } // Get parameters From 410a1c74fbc2d3c17c7ced8008ca3de8a5358b0e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 2 Jan 2022 18:26:55 +0000 Subject: [PATCH 43/89] chore(release): 5.0.0-alpha.16 [skip ci] # [5.0.0-alpha.16](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.15...5.0.0-alpha.16) (2022-01-02) ### Features * add Idempotency to Postgres ([#7750](https://github.com/parse-community/parse-server/issues/7750)) ([0c3feaa](https://github.com/parse-community/parse-server/commit/0c3feaaa1751964c0db89f25674935c3354b1538)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 15ee6254..a3b6cd12 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.16](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.15...5.0.0-alpha.16) (2022-01-02) + + +### Features + +* add Idempotency to Postgres ([#7750](https://github.com/parse-community/parse-server/issues/7750)) ([0c3feaa](https://github.com/parse-community/parse-server/commit/0c3feaaa1751964c0db89f25674935c3354b1538)) + # [5.0.0-alpha.15](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.14...5.0.0-alpha.15) (2022-01-02) diff --git a/package-lock.json b/package-lock.json index ca59098e..fb3b9402 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.15", + "version": "5.0.0-alpha.16", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 30389b67..40e47acc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.15", + "version": "5.0.0-alpha.16", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From d05fb9f2fab431c4880c51b5d8e997a924c752df Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 3 Jan 2022 14:56:55 +0000 Subject: [PATCH 44/89] refactor: upgrade graphql from 15.7.0 to 15.7.1 (#7706) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index fb3b9402..2bfd0ece 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7448,9 +7448,9 @@ "dev": true }, "graphql": { - "version": "15.7.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.7.0.tgz", - "integrity": "sha512-1jvUsS5mSzcgXLTQNQyrP7eKkBZW+HUnmx2LYSnfvkyseVpij8wwO/sFBGgxbkZ+zzFwYQxrHsOana5oMXmMxg==" + "version": "15.7.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.7.1.tgz", + "integrity": "sha512-x34S6gC0/peBZnlK60zCJox/d45A7p6At9oN9EPA3qhoIAlR4LNZmXRLkICBckwwTMJzVdA8cx3QIQZMOl606A==" }, "graphql-extensions": { "version": "0.15.0", diff --git a/package.json b/package.json index 40e47acc..514f0be0 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "deepcopy": "2.1.0", "express": "4.17.1", "follow-redirects": "1.14.6", - "graphql": "15.7.0", + "graphql": "15.7.1", "graphql-list-fields": "2.0.2", "graphql-relay": "0.7.0", "graphql-tag": "2.12.6", From a43638f3003f12793f72b7aa633c219fc061adc5 Mon Sep 17 00:00:00 2001 From: Corey Date: Mon, 3 Jan 2022 18:49:43 -0500 Subject: [PATCH 45/89] test: improve transaction tests to use async/await (#7759) --- spec/ParseServerRESTController.spec.js | 327 +++++++++---------------- spec/batch.spec.js | 175 ++++++------- 2 files changed, 203 insertions(+), 299 deletions(-) diff --git a/spec/ParseServerRESTController.spec.js b/spec/ParseServerRESTController.spec.js index 90fe3832..1b136808 100644 --- a/spec/ParseServerRESTController.spec.js +++ b/spec/ParseServerRESTController.spec.js @@ -15,35 +15,18 @@ describe('ParseServerRESTController', () => { ); }); - it('should handle a get request', done => { - RESTController.request('GET', '/classes/MyObject').then( - res => { - expect(res.results.length).toBe(0); - done(); - }, - err => { - console.log(err); - jfail(err); - done(); - } - ); + it('should handle a get request', async () => { + const res = await RESTController.request('GET', '/classes/MyObject'); + expect(res.results.length).toBe(0); }); - it('should handle a get request with full serverURL mount path', done => { - RESTController.request('GET', '/1/classes/MyObject').then( - res => { - expect(res.results.length).toBe(0); - done(); - }, - err => { - jfail(err); - done(); - } - ); + it('should handle a get request with full serverURL mount path', async () => { + const res = await RESTController.request('GET', '/1/classes/MyObject'); + expect(res.results.length).toBe(0); }); - it('should handle a POST batch without transaction', done => { - RESTController.request('POST', 'batch', { + it('should handle a POST batch without transaction', async () => { + const res = await RESTController.request('POST', 'batch', { requests: [ { method: 'GET', @@ -59,20 +42,12 @@ describe('ParseServerRESTController', () => { path: '/classes/MyObject', }, ], - }).then( - res => { - expect(res.length).toBe(3); - done(); - }, - err => { - jfail(err); - done(); - } - ); + }); + expect(res.length).toBe(3); }); - it('should handle a POST batch with transaction=false', done => { - RESTController.request('POST', 'batch', { + it('should handle a POST batch with transaction=false', async () => { + const res = await RESTController.request('POST', 'batch', { requests: [ { method: 'GET', @@ -89,16 +64,8 @@ describe('ParseServerRESTController', () => { }, ], transaction: false, - }).then( - res => { - expect(res.length).toBe(3); - done(); - }, - err => { - jfail(err); - done(); - } - ); + }); + expect(res.length).toBe(3); }); it('should handle response status', async () => { @@ -186,54 +153,43 @@ describe('ParseServerRESTController', () => { } }); - it('should handle a batch request with transaction = true', async done => { - await reconfigureServer(); + it('should handle a batch request with transaction = true', async () => { const myObject = new Parse.Object('MyObject'); // This is important because transaction only works on pre-existing collections - myObject - .save() - .then(() => { - return myObject.destroy(); - }) - .then(() => { - spyOn(databaseAdapter, 'createObject').and.callThrough(); - - return RESTController.request('POST', 'batch', { - requests: [ - { - method: 'POST', - path: '/1/classes/MyObject', - body: { key: 'value1' }, - }, - { - method: 'POST', - path: '/1/classes/MyObject', - body: { key: 'value2' }, - }, - ], - transaction: true, - }).then(response => { - expect(response.length).toEqual(2); - expect(response[0].success.objectId).toBeDefined(); - expect(response[0].success.createdAt).toBeDefined(); - expect(response[1].success.objectId).toBeDefined(); - expect(response[1].success.createdAt).toBeDefined(); - const query = new Parse.Query('MyObject'); - return query.find().then(results => { - expect(databaseAdapter.createObject.calls.count() % 2).toBe(0); - for (let i = 0; i + 1 < databaseAdapter.createObject.calls.length; i = i + 2) { - expect(databaseAdapter.createObject.calls.argsFor(i)[3]).toBe( - databaseAdapter.createObject.calls.argsFor(i + 1)[3] - ); - } - expect(results.map(result => result.get('key')).sort()).toEqual([ - 'value1', - 'value2', - ]); - done(); - }); - }); - }) - .catch(done.fail); + await myObject.save(); + await myObject.destroy(); + spyOn(databaseAdapter, 'createObject').and.callThrough(); + const response = await RESTController.request('POST', 'batch', { + requests: [ + { + method: 'POST', + path: '/1/classes/MyObject', + body: { key: 'value1' }, + }, + { + method: 'POST', + path: '/1/classes/MyObject', + body: { key: 'value2' }, + }, + ], + transaction: true, + }); + expect(response.length).toEqual(2); + expect(response[0].success.objectId).toBeDefined(); + expect(response[0].success.createdAt).toBeDefined(); + expect(response[1].success.objectId).toBeDefined(); + expect(response[1].success.createdAt).toBeDefined(); + const query = new Parse.Query('MyObject'); + const results = await query.find(); + expect(databaseAdapter.createObject.calls.count() % 2).toBe(0); + for (let i = 0; i + 1 < databaseAdapter.createObject.calls.length; i = i + 2) { + expect(databaseAdapter.createObject.calls.argsFor(i)[3]).toBe( + databaseAdapter.createObject.calls.argsFor(i + 1)[3] + ); + } + expect(results.map(result => result.get('key')).sort()).toEqual([ + 'value1', + 'value2', + ]); }); it('should not save anything when one operation fails in a transaction', async () => { @@ -560,21 +516,11 @@ describe('ParseServerRESTController', () => { }); } - it('should handle a POST request', done => { - RESTController.request('POST', '/classes/MyObject', { key: 'value' }) - .then(() => { - return RESTController.request('GET', '/classes/MyObject'); - }) - .then(res => { - expect(res.results.length).toBe(1); - expect(res.results[0].key).toEqual('value'); - done(); - }) - .catch(err => { - console.log(err); - jfail(err); - done(); - }); + it('should handle a POST request', async () => { + await RESTController.request('POST', '/classes/MyObject', { key: 'value' }); + const res = await RESTController.request('GET', '/classes/MyObject'); + expect(res.results.length).toBe(1); + expect(res.results[0].key).toEqual('value'); }); it('should handle a POST request with context', async () => { @@ -593,125 +539,76 @@ describe('ParseServerRESTController', () => { ); }); - it('ensures sessionTokens are properly handled', done => { - let userId; - Parse.User.signUp('user', 'pass') - .then(user => { - userId = user.id; - const sessionToken = user.getSessionToken(); - return RESTController.request('GET', '/users/me', undefined, { - sessionToken, - }); - }) - .then(res => { - // Result is in JSON format - expect(res.objectId).toEqual(userId); - done(); - }) - .catch(err => { - console.log(err); - jfail(err); - done(); + it('ensures sessionTokens are properly handled', async () => { + const user = await Parse.User.signUp('user', 'pass'); + const sessionToken = user.getSessionToken(); + const res = await RESTController.request('GET', '/users/me', undefined, { + sessionToken, + }); + // Result is in JSON format + expect(res.objectId).toEqual(user.id); + }); + + it('ensures masterKey is properly handled', async () => { + const user = await Parse.User.signUp('user', 'pass'); + const userId = user.id; + await Parse.User.logOut(); + const res = await RESTController.request('GET', '/classes/_User', undefined, { + useMasterKey: true, + }); + expect(res.results.length).toBe(1); + expect(res.results[0].objectId).toEqual(userId); + }); + + it('ensures no user is created when passing an empty username', async () => { + try { + await RESTController.request('POST', '/classes/_User', { + username: '', + password: 'world', }); + fail('Success callback should not be called when passing an empty username.'); + } catch (err) { + expect(err.code).toBe(Parse.Error.USERNAME_MISSING); + expect(err.message).toBe('bad or missing username'); + } }); - it('ensures masterKey is properly handled', done => { - let userId; - Parse.User.signUp('user', 'pass') - .then(user => { - userId = user.id; - return Parse.User.logOut().then(() => { - return RESTController.request('GET', '/classes/_User', undefined, { - useMasterKey: true, - }); - }); - }) - .then( - res => { - expect(res.results.length).toBe(1); - expect(res.results[0].objectId).toEqual(userId); - done(); - }, - err => { - jfail(err); - done(); - } - ); + it('ensures no user is created when passing an empty password', async () => { + try { + await RESTController.request('POST', '/classes/_User', { + username: 'hello', + password: '', + }); + fail('Success callback should not be called when passing an empty password.'); + } catch (err) { + expect(err.code).toBe(Parse.Error.PASSWORD_MISSING); + expect(err.message).toBe('password is required'); + } }); - it('ensures no user is created when passing an empty username', done => { - RESTController.request('POST', '/classes/_User', { - username: '', - password: 'world', - }).then( - () => { - jfail(new Error('Success callback should not be called when passing an empty username.')); - done(); - }, - err => { - expect(err.code).toBe(Parse.Error.USERNAME_MISSING); - expect(err.message).toBe('bad or missing username'); - done(); - } - ); - }); - - it('ensures no user is created when passing an empty password', done => { - RESTController.request('POST', '/classes/_User', { - username: 'hello', - password: '', - }).then( - () => { - jfail(new Error('Success callback should not be called when passing an empty password.')); - done(); - }, - err => { - expect(err.code).toBe(Parse.Error.PASSWORD_MISSING); - expect(err.message).toBe('password is required'); - done(); - } - ); - }); - - it('ensures no session token is created on creating users', done => { - RESTController.request('POST', '/classes/_User', { + it('ensures no session token is created on creating users', async () => { + const user = await RESTController.request('POST', '/classes/_User', { username: 'hello', password: 'world', - }) - .then(user => { - expect(user.sessionToken).toBeUndefined(); - const query = new Parse.Query('_Session'); - return query.find({ useMasterKey: true }); - }) - .then(sessions => { - expect(sessions.length).toBe(0); - done(); - }, done.fail); + }); + expect(user.sessionToken).toBeUndefined(); + const query = new Parse.Query('_Session'); + const sessions = await query.find({ useMasterKey: true }); + expect(sessions.length).toBe(0); }); - it('ensures a session token is created when passing installationId != cloud', done => { - RESTController.request( + it('ensures a session token is created when passing installationId != cloud', async () => { + const user = await RESTController.request( 'POST', '/classes/_User', { username: 'hello', password: 'world' }, { installationId: 'my-installation' } - ) - .then(user => { - expect(user.sessionToken).not.toBeUndefined(); - const query = new Parse.Query('_Session'); - return query.find({ useMasterKey: true }); - }) - .then( - sessions => { - expect(sessions.length).toBe(1); - expect(sessions[0].get('installationId')).toBe('my-installation'); - done(); - }, - err => { - jfail(err); - done(); - } - ); + ); + expect(user.sessionToken).not.toBeUndefined(); + const query = new Parse.Query('_Session'); + const sessions = await query.find({ useMasterKey: true }); + expect(sessions.length).toBe(1); + expect(sessions[0].get('installationId')).toBe('my-installation'); }); it('ensures logIn is saved with installationId', async () => { diff --git a/spec/batch.spec.js b/spec/batch.spec.js index 98050254..b9e079ca 100644 --- a/spec/batch.spec.js +++ b/spec/batch.spec.js @@ -89,10 +89,32 @@ describe('batch', () => { expect(internalURL).toEqual('/classes/Object'); }); - it('should handle a batch request without transaction', async done => { + it('should return the proper url with no url provided', () => { + const originalURL = '/parse/batch'; + const internalURL = batch.makeBatchRoutingPathFunction( + originalURL, + undefined, + publicServerURL + )('/parse/classes/Object'); + + expect(internalURL).toEqual('/classes/Object'); + }); + + it('should return the proper url with no public url provided', () => { + const originalURL = '/parse/batch'; + const internalURL = batch.makeBatchRoutingPathFunction( + originalURL, + serverURLNaked, + undefined + )('/parse/classes/Object'); + + expect(internalURL).toEqual('/classes/Object'); + }); + + it('should handle a batch request without transaction', async () => { spyOn(databaseAdapter, 'createObject').and.callThrough(); - request({ + const response = await request({ method: 'POST', headers: headers, url: 'http://localhost:8378/1/batch', @@ -110,28 +132,25 @@ describe('batch', () => { }, ], }), - }).then(response => { - expect(response.data.length).toEqual(2); - expect(response.data[0].success.objectId).toBeDefined(); - expect(response.data[0].success.createdAt).toBeDefined(); - expect(response.data[1].success.objectId).toBeDefined(); - expect(response.data[1].success.createdAt).toBeDefined(); - const query = new Parse.Query('MyObject'); - query.find().then(results => { - expect(databaseAdapter.createObject.calls.count()).toBe(2); - expect(databaseAdapter.createObject.calls.argsFor(0)[3]).toEqual(null); - expect(databaseAdapter.createObject.calls.argsFor(1)[3]).toEqual(null); - expect(results.map(result => result.get('key')).sort()).toEqual(['value1', 'value2']); - done(); - }); }); + + expect(response.data.length).toEqual(2); + expect(response.data[0].success.objectId).toBeDefined(); + expect(response.data[0].success.createdAt).toBeDefined(); + expect(response.data[1].success.objectId).toBeDefined(); + expect(response.data[1].success.createdAt).toBeDefined(); + const query = new Parse.Query('MyObject'); + const results = await query.find(); + expect(databaseAdapter.createObject.calls.count()).toBe(2); + expect(databaseAdapter.createObject.calls.argsFor(0)[3]).toEqual(null); + expect(databaseAdapter.createObject.calls.argsFor(1)[3]).toEqual(null); + expect(results.map(result => result.get('key')).sort()).toEqual(['value1', 'value2']); }); - it('should handle a batch request with transaction = false', async done => { - await reconfigureServer(); + it('should handle a batch request with transaction = false', async () => { spyOn(databaseAdapter, 'createObject').and.callThrough(); - request({ + const response = await request({ method: 'POST', headers: headers, url: 'http://localhost:8378/1/batch', @@ -150,21 +169,18 @@ describe('batch', () => { ], transaction: false, }), - }).then(response => { - expect(response.data.length).toEqual(2); - expect(response.data[0].success.objectId).toBeDefined(); - expect(response.data[0].success.createdAt).toBeDefined(); - expect(response.data[1].success.objectId).toBeDefined(); - expect(response.data[1].success.createdAt).toBeDefined(); - const query = new Parse.Query('MyObject'); - query.find().then(results => { - expect(databaseAdapter.createObject.calls.count()).toBe(2); - expect(databaseAdapter.createObject.calls.argsFor(0)[3]).toEqual(null); - expect(databaseAdapter.createObject.calls.argsFor(1)[3]).toEqual(null); - expect(results.map(result => result.get('key')).sort()).toEqual(['value1', 'value2']); - done(); - }); }); + expect(response.data.length).toEqual(2); + expect(response.data[0].success.objectId).toBeDefined(); + expect(response.data[0].success.createdAt).toBeDefined(); + expect(response.data[1].success.objectId).toBeDefined(); + expect(response.data[1].success.createdAt).toBeDefined(); + const query = new Parse.Query('MyObject'); + const results = await query.find(); + expect(databaseAdapter.createObject.calls.count()).toBe(2); + expect(databaseAdapter.createObject.calls.argsFor(0)[3]).toEqual(null); + expect(databaseAdapter.createObject.calls.argsFor(1)[3]).toEqual(null); + expect(results.map(result => result.get('key')).sort()).toEqual(['value1', 'value2']); }); if ( @@ -191,58 +207,48 @@ describe('batch', () => { } }); - it('should handle a batch request with transaction = true', async done => { - await reconfigureServer(); + it('should handle a batch request with transaction = true', async () => { const myObject = new Parse.Object('MyObject'); // This is important because transaction only works on pre-existing collections - myObject - .save() - .then(() => { - return myObject.destroy(); - }) - .then(() => { - spyOn(databaseAdapter, 'createObject').and.callThrough(); - - request({ - method: 'POST', - headers: headers, - url: 'http://localhost:8378/1/batch', - body: JSON.stringify({ - requests: [ - { - method: 'POST', - path: '/1/classes/MyObject', - body: { key: 'value1' }, - }, - { - method: 'POST', - path: '/1/classes/MyObject', - body: { key: 'value2' }, - }, - ], - transaction: true, - }), - }).then(response => { - expect(response.data.length).toEqual(2); - expect(response.data[0].success.objectId).toBeDefined(); - expect(response.data[0].success.createdAt).toBeDefined(); - expect(response.data[1].success.objectId).toBeDefined(); - expect(response.data[1].success.createdAt).toBeDefined(); - const query = new Parse.Query('MyObject'); - query.find().then(results => { - expect(databaseAdapter.createObject.calls.count() % 2).toBe(0); - for (let i = 0; i + 1 < databaseAdapter.createObject.calls.length; i = i + 2) { - expect(databaseAdapter.createObject.calls.argsFor(i)[3]).toBe( - databaseAdapter.createObject.calls.argsFor(i + 1)[3] - ); - } - expect(results.map(result => result.get('key')).sort()).toEqual([ - 'value1', - 'value2', - ]); - done(); - }); - }); - }); + await myObject.save(); + await myObject.destroy(); + spyOn(databaseAdapter, 'createObject').and.callThrough(); + const response = await request({ + method: 'POST', + headers: headers, + url: 'http://localhost:8378/1/batch', + body: JSON.stringify({ + requests: [ + { + method: 'POST', + path: '/1/classes/MyObject', + body: { key: 'value1' }, + }, + { + method: 'POST', + path: '/1/classes/MyObject', + body: { key: 'value2' }, + }, + ], + transaction: true, + }), + }); + expect(response.data.length).toEqual(2); + expect(response.data[0].success.objectId).toBeDefined(); + expect(response.data[0].success.createdAt).toBeDefined(); + expect(response.data[1].success.objectId).toBeDefined(); + expect(response.data[1].success.createdAt).toBeDefined(); + const query = new Parse.Query('MyObject'); + const results = await query.find(); + expect(databaseAdapter.createObject.calls.count() % 2).toBe(0); + for (let i = 0; i + 1 < databaseAdapter.createObject.calls.length; i = i + 2) { + expect(databaseAdapter.createObject.calls.argsFor(i)[3]).toBe( + databaseAdapter.createObject.calls.argsFor(i + 1)[3] + ); + } + expect(results.map(result => result.get('key')).sort()).toEqual([ + 'value1', + 'value2', + ]); }); it('should not save anything when one operation fails in a transaction', async () => { @@ -350,6 +356,7 @@ describe('batch', () => { transaction: true, }), }); + fail(); } catch (error) { expect(error).toBeDefined(); const query = new Parse.Query('MyObject'); From a5ffb9502232c03fe87692724e9d6449ac66ad00 Mon Sep 17 00:00:00 2001 From: Corey Date: Thu, 6 Jan 2022 09:26:00 -0500 Subject: [PATCH 46/89] refactor: remove deprecated `url.parse()` method (#7751) --- spec/AuthenticationAdapters.spec.js | 18 +++++++++++++++ spec/batch.spec.js | 22 +++++++++++++++++++ src/Adapters/Auth/gcenter.js | 19 +++++++++------- src/Adapters/Auth/oauth2.js | 3 +-- .../Storage/Postgres/PostgresConfigParser.js | 10 ++++----- src/Controllers/LoggerController.js | 12 +++++----- src/Controllers/index.js | 3 +-- src/ParseServerRESTController.js | 7 +++--- src/batch.js | 16 +++++++------- 9 files changed, 74 insertions(+), 36 deletions(-) diff --git a/spec/AuthenticationAdapters.spec.js b/spec/AuthenticationAdapters.spec.js index d32eba04..89eeb512 100644 --- a/spec/AuthenticationAdapters.spec.js +++ b/spec/AuthenticationAdapters.spec.js @@ -1707,6 +1707,24 @@ describe('Apple Game Center Auth adapter', () => { expect(e.message).toBe('Apple Game Center - invalid publicKeyUrl: invalid.com'); } }); + + it('validateAuthData invalid public key http url', async () => { + const authData = { + id: 'G:1965586982', + publicKeyUrl: 'http://static.gc.apple.com/public-key/gc-prod-4.cer', + timestamp: 1565257031287, + signature: '1234', + salt: 'DzqqrQ==', + bundleId: 'cloud.xtralife.gamecenterauth', + }; + + try { + await gcenter.validateAuthData(authData); + fail(); + } catch (e) { + expect(e.message).toBe('Apple Game Center - invalid publicKeyUrl: http://static.gc.apple.com/public-key/gc-prod-4.cer'); + } + }); }); describe('phant auth adapter', () => { diff --git a/spec/batch.spec.js b/spec/batch.spec.js index b9e079ca..f91f91a0 100644 --- a/spec/batch.spec.js +++ b/spec/batch.spec.js @@ -111,6 +111,28 @@ describe('batch', () => { expect(internalURL).toEqual('/classes/Object'); }); + it('should return the proper url with bad url provided', () => { + const originalURL = '/parse/batch'; + const internalURL = batch.makeBatchRoutingPathFunction( + originalURL, + 'badurl.com', + publicServerURL + )('/parse/classes/Object'); + + expect(internalURL).toEqual('/classes/Object'); + }); + + it('should return the proper url with bad public url provided', () => { + const originalURL = '/parse/batch'; + const internalURL = batch.makeBatchRoutingPathFunction( + originalURL, + serverURLNaked, + 'badurl.com' + )('/parse/classes/Object'); + + expect(internalURL).toEqual('/classes/Object'); + }); + it('should handle a batch request without transaction', async () => { spyOn(databaseAdapter, 'createObject').and.callThrough(); diff --git a/src/Adapters/Auth/gcenter.js b/src/Adapters/Auth/gcenter.js index 090b9fab..322c2430 100644 --- a/src/Adapters/Auth/gcenter.js +++ b/src/Adapters/Auth/gcenter.js @@ -14,20 +14,23 @@ const authData = { const { Parse } = require('parse/node'); const crypto = require('crypto'); const https = require('https'); -const url = require('url'); const cache = {}; // (publicKey -> cert) cache function verifyPublicKeyUrl(publicKeyUrl) { - const parsedUrl = url.parse(publicKeyUrl); - if (parsedUrl.protocol !== 'https:') { + try { + const parsedUrl = new URL(publicKeyUrl); + if (parsedUrl.protocol !== 'https:') { + return false; + } + const hostnameParts = parsedUrl.hostname.split('.'); + const length = hostnameParts.length; + const domainParts = hostnameParts.slice(length - 2, length); + const domain = domainParts.join('.'); + return domain === 'apple.com'; + } catch(error) { return false; } - const hostnameParts = parsedUrl.hostname.split('.'); - const length = hostnameParts.length; - const domainParts = hostnameParts.slice(length - 2, length); - const domain = domainParts.join('.'); - return domain === 'apple.com'; } function convertX509CertToPEM(X509Cert) { diff --git a/src/Adapters/Auth/oauth2.js b/src/Adapters/Auth/oauth2.js index cefe7bdf..ba1fe7bc 100644 --- a/src/Adapters/Auth/oauth2.js +++ b/src/Adapters/Auth/oauth2.js @@ -54,7 +54,6 @@ */ const Parse = require('parse/node').Parse; -const url = require('url'); const querystring = require('querystring'); const httpsRequest = require('./httpsRequest'); @@ -112,7 +111,7 @@ function requestTokenInfo(options, access_token) { if (!options || !options.tokenIntrospectionEndpointUrl) { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, MISSING_URL); } - const parsedUrl = url.parse(options.tokenIntrospectionEndpointUrl); + const parsedUrl = new URL(options.tokenIntrospectionEndpointUrl); const postData = querystring.stringify({ token: access_token, }); diff --git a/src/Adapters/Storage/Postgres/PostgresConfigParser.js b/src/Adapters/Storage/Postgres/PostgresConfigParser.js index 170e7628..d86778cf 100644 --- a/src/Adapters/Storage/Postgres/PostgresConfigParser.js +++ b/src/Adapters/Storage/Postgres/PostgresConfigParser.js @@ -1,18 +1,16 @@ -const url = require('url'); const fs = require('fs'); function getDatabaseOptionsFromURI(uri) { const databaseOptions = {}; - const parsedURI = url.parse(uri); - const queryParams = parseQueryParams(parsedURI.query); - const authParts = parsedURI.auth ? parsedURI.auth.split(':') : []; + const parsedURI = new URL(uri); + const queryParams = parseQueryParams(parsedURI.searchParams.toString()); databaseOptions.host = parsedURI.hostname || 'localhost'; databaseOptions.port = parsedURI.port ? parseInt(parsedURI.port) : 5432; databaseOptions.database = parsedURI.pathname ? parsedURI.pathname.substr(1) : undefined; - databaseOptions.user = authParts.length > 0 ? authParts[0] : ''; - databaseOptions.password = authParts.length > 1 ? authParts[1] : ''; + databaseOptions.user = parsedURI.username; + databaseOptions.password = parsedURI.password; if (queryParams.ssl && queryParams.ssl.toLowerCase() === 'true') { databaseOptions.ssl = true; diff --git a/src/Controllers/LoggerController.js b/src/Controllers/LoggerController.js index 04d3a6d7..8ee492cf 100644 --- a/src/Controllers/LoggerController.js +++ b/src/Controllers/LoggerController.js @@ -1,7 +1,6 @@ import { Parse } from 'parse/node'; import AdaptableController from './AdaptableController'; import { LoggerAdapter } from '../Adapters/Logger/LoggerAdapter'; -import url from 'url'; const MILLISECONDS_IN_A_DAY = 24 * 60 * 60 * 1000; const LOG_STRING_TRUNCATE_LENGTH = 1000; @@ -38,15 +37,16 @@ export class LoggerController extends AdaptableController { }); } - maskSensitiveUrl(urlString) { - const urlObj = url.parse(urlString, true); - const query = urlObj.query; + maskSensitiveUrl(path) { + const urlString = 'http://localhost' + path; // prepend dummy string to make a real URL + const urlObj = new URL(urlString); + const query = urlObj.searchParams; let sanitizedQuery = '?'; - for (const key in query) { + for (const [key, value] of query) { if (key !== 'password') { // normal value - sanitizedQuery += key + '=' + query[key] + '&'; + sanitizedQuery += key + '=' + value + '&'; } else { // password value, redact it sanitizedQuery += key + '=' + '********' + '&'; diff --git a/src/Controllers/index.js b/src/Controllers/index.js index 71ab5ef4..152de684 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -2,7 +2,6 @@ import authDataManager from '../Adapters/Auth'; import { ParseServerOptions } from '../Options'; import { loadAdapter } from '../Adapters/AdapterLoader'; import defaults from '../defaults'; -import url from 'url'; // Controllers import { LoggerController } from './LoggerController'; import { FilesController } from './FilesController'; @@ -220,7 +219,7 @@ export function getAuthDataManager(options: ParseServerOptions) { export function getDatabaseAdapter(databaseURI, collectionPrefix, databaseOptions) { let protocol; try { - const parsedURI = url.parse(databaseURI); + const parsedURI = new URL(databaseURI); protocol = parsedURI.protocol ? parsedURI.protocol.toLowerCase() : null; } catch (e) { /* */ diff --git a/src/ParseServerRESTController.js b/src/ParseServerRESTController.js index 9e765ff3..12ee0a67 100644 --- a/src/ParseServerRESTController.js +++ b/src/ParseServerRESTController.js @@ -1,7 +1,6 @@ const Config = require('./Config'); const Auth = require('./Auth'); const RESTController = require('parse/lib/node/RESTController'); -const URL = require('url'); const Parse = require('parse/node'); function getSessionToken(options) { @@ -38,9 +37,9 @@ function ParseServerRESTController(applicationId, router) { if (!config) { config = Config.get(applicationId); } - const serverURL = URL.parse(config.serverURL); - if (path.indexOf(serverURL.path) === 0) { - path = path.slice(serverURL.path.length, path.length); + const serverURL = new URL(config.serverURL); + if (path.indexOf(serverURL.pathname) === 0) { + path = path.slice(serverURL.pathname.length, path.length); } if (path[0] !== '/') { diff --git a/src/batch.js b/src/batch.js index 58c23cca..0625ef0e 100644 --- a/src/batch.js +++ b/src/batch.js @@ -1,5 +1,4 @@ const Parse = require('parse/node').Parse; -const url = require('url'); const path = require('path'); // These methods handle batch requests. const batchPath = '/batch'; @@ -11,11 +10,12 @@ function mountOnto(router) { }); } -function parseURL(URL) { - if (typeof URL === 'string') { - return url.parse(URL); +function parseURL(urlString) { + try { + return new URL(urlString); + } catch(error) { + return undefined; } - return undefined; } function makeBatchRoutingPathFunction(originalUrl, serverURL, publicServerURL) { @@ -33,9 +33,9 @@ function makeBatchRoutingPathFunction(originalUrl, serverURL, publicServerURL) { return path.posix.join('/', requestPath.slice(apiPrefix.length)); }; - if (serverURL && publicServerURL && serverURL.path != publicServerURL.path) { - const localPath = serverURL.path; - const publicPath = publicServerURL.path; + if (serverURL && publicServerURL && serverURL.pathname != publicServerURL.pathname) { + const localPath = serverURL.pathname; + const publicPath = publicServerURL.pathname; // Override the api prefix apiPrefix = localPath; From 5af6e5dfaa129b1a350afcba4fb381b21c4cc35d Mon Sep 17 00:00:00 2001 From: ThornWu Date: Thu, 13 Jan 2022 09:03:33 +0800 Subject: [PATCH 47/89] fix: schema cache not cleared in some cases (#7678) --- spec/schemas.spec.js | 87 ++++++++++++++++++++++++++++++++++++ src/Routers/SchemasRouter.js | 2 +- 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index e8dcc41e..9557dd79 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -5,6 +5,7 @@ const dd = require('deep-diff'); const Config = require('../lib/Config'); const request = require('../lib/request'); const TestUtils = require('../lib/TestUtils'); +const SchemaController = require('../lib/Controllers/SchemaController').SchemaController; let config; @@ -239,6 +240,52 @@ describe('schemas', () => { }); }); + it('ensure refresh cache after creating a class', async done => { + spyOn(SchemaController.prototype, 'reloadData').and.callFake(() => Promise.resolve()); + await request({ + url: 'http://localhost:8378/1/schemas', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'A', + }, + }); + const response = await request({ + url: 'http://localhost:8378/1/schemas', + method: 'GET', + headers: masterKeyHeaders, + json: true, + }); + const expected = { + results: [ + userSchema, + roleSchema, + { + className: 'A', + fields: { + //Default fields + ACL: { type: 'ACL' }, + createdAt: { type: 'Date' }, + updatedAt: { type: 'Date' }, + objectId: { type: 'String' }, + }, + classLevelPermissions: defaultClassLevelPermissions, + }, + ], + }; + expect( + response.data.results + .sort((s1, s2) => s1.className.localeCompare(s2.className)) + .map(s => { + const withoutIndexes = Object.assign({}, s); + delete withoutIndexes.indexes; + return withoutIndexes; + }) + ).toEqual(expected.results.sort((s1, s2) => s1.className.localeCompare(s2.className))); + done(); + }); + it('responds with a single schema', done => { const obj = hasAllPODobject(); obj.save().then(() => { @@ -1507,6 +1554,46 @@ describe('schemas', () => { }); }); + it('ensure refresh cache after deleting a class', async done => { + config = Config.get('test'); + spyOn(config.schemaCache, 'del').and.callFake(() => {}); + spyOn(SchemaController.prototype, 'reloadData').and.callFake(() => Promise.resolve()); + await request({ + url: 'http://localhost:8378/1/schemas', + method: 'POST', + headers: masterKeyHeaders, + json: true, + body: { + className: 'A', + }, + }); + await request({ + method: 'DELETE', + url: 'http://localhost:8378/1/schemas/A', + headers: masterKeyHeaders, + json: true, + }); + const response = await request({ + url: 'http://localhost:8378/1/schemas', + method: 'GET', + headers: masterKeyHeaders, + json: true, + }); + const expected = { + results: [userSchema, roleSchema], + }; + expect( + response.data.results + .sort((s1, s2) => s1.className.localeCompare(s2.className)) + .map(s => { + const withoutIndexes = Object.assign({}, s); + delete withoutIndexes.indexes; + return withoutIndexes; + }) + ).toEqual(expected.results.sort((s1, s2) => s1.className.localeCompare(s2.className))); + done(); + }); + it('deletes collections including join tables', done => { const obj = new Parse.Object('MyClass'); obj.set('data', 'data'); diff --git a/src/Routers/SchemasRouter.js b/src/Routers/SchemasRouter.js index 54f73cea..1b72b93a 100644 --- a/src/Routers/SchemasRouter.js +++ b/src/Routers/SchemasRouter.js @@ -16,7 +16,7 @@ function classNameMismatchResponse(bodyClass, pathClass) { function getAllSchemas(req) { return req.config.database .loadSchema({ clearCache: true }) - .then(schemaController => schemaController.getAllClasses(true)) + .then(schemaController => schemaController.getAllClasses({ clearCache: true })) .then(schemas => ({ response: { results: schemas } })); } From 98abd7112c633f38ac108c64dc2f1d0ba89f5237 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 13 Jan 2022 01:04:40 +0000 Subject: [PATCH 48/89] chore(release): 5.0.0-alpha.17 [skip ci] # [5.0.0-alpha.17](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.16...5.0.0-alpha.17) (2022-01-13) ### Bug Fixes * schema cache not cleared in some cases ([#7678](https://github.com/parse-community/parse-server/issues/7678)) ([5af6e5d](https://github.com/parse-community/parse-server/commit/5af6e5dfaa129b1a350afcba4fb381b21c4cc35d)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index a3b6cd12..2f2681be 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.17](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.16...5.0.0-alpha.17) (2022-01-13) + + +### Bug Fixes + +* schema cache not cleared in some cases ([#7678](https://github.com/parse-community/parse-server/issues/7678)) ([5af6e5d](https://github.com/parse-community/parse-server/commit/5af6e5dfaa129b1a350afcba4fb381b21c4cc35d)) + # [5.0.0-alpha.16](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.15...5.0.0-alpha.16) (2022-01-02) diff --git a/package-lock.json b/package-lock.json index 2bfd0ece..66dd1eae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.16", + "version": "5.0.0-alpha.17", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 514f0be0..fdf01da5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.16", + "version": "5.0.0-alpha.17", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 8f5a8618cfa7ed9a2a239a095abffa8f3fd8d31a Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 13 Jan 2022 02:05:15 +0000 Subject: [PATCH 49/89] fix: security upgrade follow-redirects from 1.14.6 to 1.14.7 (#7769) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 66dd1eae..2977b1ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7041,9 +7041,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.14.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz", - "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==" + "version": "1.14.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", + "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" }, "for-each": { "version": "0.3.3", diff --git a/package.json b/package.json index fdf01da5..88829596 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "cors": "2.8.5", "deepcopy": "2.1.0", "express": "4.17.1", - "follow-redirects": "1.14.6", + "follow-redirects": "1.14.7", "graphql": "15.7.1", "graphql-list-fields": "2.0.2", "graphql-relay": "0.7.0", From c720fbba5a70d0497087851192d37502055e9c46 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 13 Jan 2022 02:14:07 +0000 Subject: [PATCH 50/89] chore(release): 5.0.0-alpha.18 [skip ci] # [5.0.0-alpha.18](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.17...5.0.0-alpha.18) (2022-01-13) ### Bug Fixes * security upgrade follow-redirects from 1.14.6 to 1.14.7 ([#7769](https://github.com/parse-community/parse-server/issues/7769)) ([8f5a861](https://github.com/parse-community/parse-server/commit/8f5a8618cfa7ed9a2a239a095abffa8f3fd8d31a)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 2f2681be..ea3b0f5d 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.18](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.17...5.0.0-alpha.18) (2022-01-13) + + +### Bug Fixes + +* security upgrade follow-redirects from 1.14.6 to 1.14.7 ([#7769](https://github.com/parse-community/parse-server/issues/7769)) ([8f5a861](https://github.com/parse-community/parse-server/commit/8f5a8618cfa7ed9a2a239a095abffa8f3fd8d31a)) + # [5.0.0-alpha.17](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.16...5.0.0-alpha.17) (2022-01-13) diff --git a/package-lock.json b/package-lock.json index 2977b1ce..08e7e931 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.17", + "version": "5.0.0-alpha.18", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 88829596..2807e5c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.17", + "version": "5.0.0-alpha.18", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 826aa79b9fb1c7c65ae8e72726c97a9d7acb40c4 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Fri, 14 Jan 2022 13:22:30 +0000 Subject: [PATCH 51/89] refactor: upgrade express from 4.17.1 to 4.17.2 (#7776) --- package-lock.json | 144 +++++++++++++++------------------------------- package.json | 2 +- 2 files changed, 48 insertions(+), 98 deletions(-) diff --git a/package-lock.json b/package-lock.json index 08e7e931..d537918d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4601,6 +4601,7 @@ "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, "requires": { "safe-buffer": "5.1.2" }, @@ -4608,7 +4609,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true } } }, @@ -4737,9 +4739,9 @@ } }, "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" }, "cookie-signature": { "version": "1.0.6", @@ -6357,16 +6359,16 @@ } }, "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.2.tgz", + "integrity": "sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg==", "requires": { "accepts": "~1.3.7", "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", + "body-parser": "1.19.1", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.0", + "cookie": "0.4.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "~1.1.2", @@ -6380,41 +6382,27 @@ "on-finished": "~2.3.0", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", + "proxy-addr": "~2.0.7", + "qs": "6.9.6", "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", "statuses": "~1.5.0", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" }, "dependencies": { - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" + "safe-buffer": "5.2.1" } }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -6423,48 +6411,10 @@ "ms": "2.0.0" } }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" } } }, @@ -15039,9 +14989,9 @@ "dev": true }, "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", "requires": { "debug": "2.6.9", "depd": "~1.1.2", @@ -15050,9 +15000,9 @@ "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "~1.7.2", + "http-errors": "1.8.1", "mime": "1.6.0", - "ms": "2.1.1", + "ms": "2.1.3", "on-finished": "~2.3.0", "range-parser": "~1.2.1", "statuses": "~1.5.0" @@ -15074,15 +15024,15 @@ } }, "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", "inherits": "2.0.4", - "setprototypeof": "1.1.1", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" } }, "mime": { @@ -15091,26 +15041,26 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.1" + "send": "0.17.2" } }, "set-blocking": { diff --git a/package.json b/package.json index 2807e5c9..8fc64dc6 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "commander": "5.1.0", "cors": "2.8.5", "deepcopy": "2.1.0", - "express": "4.17.1", + "express": "4.17.2", "follow-redirects": "1.14.7", "graphql": "15.7.1", "graphql-list-fields": "2.0.2", From f5f63bfc64d3481ed944ceb5e9f50b33dccd1ce9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Jan 2022 13:54:53 +0100 Subject: [PATCH 52/89] fix: bump nanoid from 3.1.25 to 3.2.0 (#7781) --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d537918d..060a5f44 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10628,9 +10628,9 @@ "optional": true }, "nanoid": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", - "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", "dev": true }, "nanomatch": { From f105d7aef1f964e95d7e5e3fa0df1c5a24bd9750 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 22 Jan 2022 12:59:57 +0000 Subject: [PATCH 53/89] chore(release): 5.0.0-alpha.19 [skip ci] # [5.0.0-alpha.19](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.18...5.0.0-alpha.19) (2022-01-22) ### Bug Fixes * bump nanoid from 3.1.25 to 3.2.0 ([#7781](https://github.com/parse-community/parse-server/issues/7781)) ([f5f63bf](https://github.com/parse-community/parse-server/commit/f5f63bfc64d3481ed944ceb5e9f50b33dccd1ce9)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index ea3b0f5d..de391202 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.19](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.18...5.0.0-alpha.19) (2022-01-22) + + +### Bug Fixes + +* bump nanoid from 3.1.25 to 3.2.0 ([#7781](https://github.com/parse-community/parse-server/issues/7781)) ([f5f63bf](https://github.com/parse-community/parse-server/commit/f5f63bfc64d3481ed944ceb5e9f50b33dccd1ce9)) + # [5.0.0-alpha.18](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.17...5.0.0-alpha.18) (2022-01-13) diff --git a/package-lock.json b/package-lock.json index 060a5f44..3f2e035c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.18", + "version": "5.0.0-alpha.19", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8fc64dc6..9394d06c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.18", + "version": "5.0.0-alpha.19", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 90823514113a1a085ebc818f7109b3fd7591346f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Jan 2022 14:31:45 +0100 Subject: [PATCH 54/89] fix: bump node-fetch from 2.6.1 to 3.1.1 (#7782) --- package-lock.json | 103 +++++++++++++++++++++++++++++++- package.json | 2 +- spec/ParseGraphQLServer.spec.js | 20 ++++--- 3 files changed, 113 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3f2e035c..e8622c96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1782,6 +1782,15 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } } } }, @@ -3153,6 +3162,16 @@ "requires": { "node-fetch": "^2.6.1", "util.promisify": "^1.0.0" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + } } }, "apollo-server-errors": { @@ -4820,6 +4839,13 @@ "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", "requires": { "node-fetch": "2.6.1" + }, + "dependencies": { + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + } } }, "cross-spawn": { @@ -4885,6 +4911,12 @@ "assert-plus": "^1.0.0" } }, + "data-uri-to-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", + "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "dev": true + }, "dataloader": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.0.0.tgz", @@ -6683,6 +6715,16 @@ "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" }, + "fetch-blob": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.1.4.tgz", + "integrity": "sha512-Eq5Xv5+VlSrYWEqKrusxY1C3Hm/hjeAsCGVG3ft7pZahlUAChpGZT/Ms1WmSLnEAisEXszjzu/s+ce6HZB2VHA==", + "dev": true, + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "fetch-node-website": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/fetch-node-website/-/fetch-node-website-5.0.3.tgz", @@ -7036,6 +7078,15 @@ "mime-types": "^2.1.12" } }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dev": true, + "requires": { + "fetch-blob": "^3.1.2" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -10426,6 +10477,15 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } } } }, @@ -10696,6 +10756,12 @@ "tslib": "^2.0.3" } }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true + }, "node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", @@ -10706,9 +10772,15 @@ } }, "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.1.1.tgz", + "integrity": "sha512-SMk+vKgU77PYotRdWzqZGTZeuFKlsJ0hu4KPviQKkfY+N3vn2MIzr0rvpnYpR8MtB3IEuhlEcuOLbGvLRlA+yg==", + "dev": true, + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.3", + "formdata-polyfill": "^4.0.10" + } }, "node-forge": { "version": "0.10.0", @@ -16114,6 +16186,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "traverse": { "version": "0.6.6", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", @@ -16556,6 +16633,26 @@ "defaults": "^1.0.3" } }, + "web-streams-polyfill": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz", + "integrity": "sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 9394d06c..2ad6ec34 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "mock-mail-adapter": "file:spec/dependencies/mock-mail-adapter", "mongodb-runner": "4.8.1", "mongodb-version-list": "1.0.0", - "node-fetch": "2.6.1", + "node-fetch": "3.1.1", "nyc": "15.1.0", "prettier": "2.0.5", "semantic-release": "17.4.6", diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index d204886f..6541092b 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -1,7 +1,7 @@ const http = require('http'); const express = require('express'); const req = require('../lib/request'); -const fetch = require('node-fetch'); +const fetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); const FormData = require('form-data'); const ws = require('ws'); require('./helper'); @@ -2600,18 +2600,22 @@ describe('ParseGraphQLServer', () => { // "SecondaryObject:bBRgmzIRRM" < "SecondaryObject:nTMcuVbATY" true // base64("SecondaryObject:bBRgmzIRRM"") < base64(""SecondaryObject:nTMcuVbATY"") false // "U2Vjb25kYXJ5T2JqZWN0OmJCUmdteklSUk0=" < "U2Vjb25kYXJ5T2JqZWN0Om5UTWN1VmJBVFk=" false - const originalIds = [getSecondaryObjectsResult.data.secondaryObject2.objectId, - getSecondaryObjectsResult.data.secondaryObject4.objectId]; + const originalIds = [ + getSecondaryObjectsResult.data.secondaryObject2.objectId, + getSecondaryObjectsResult.data.secondaryObject4.objectId, + ]; expect( findSecondaryObjectsResult.data.secondaryObjects.edges[0].node.objectId - ).not.toBe( - findSecondaryObjectsResult.data.secondaryObjects.edges[1].node.objectId - ); + ).not.toBe(findSecondaryObjectsResult.data.secondaryObjects.edges[1].node.objectId); expect( - originalIds.includes(findSecondaryObjectsResult.data.secondaryObjects.edges[0].node.objectId) + originalIds.includes( + findSecondaryObjectsResult.data.secondaryObjects.edges[0].node.objectId + ) ).toBeTrue(); expect( - originalIds.includes(findSecondaryObjectsResult.data.secondaryObjects.edges[1].node.objectId) + originalIds.includes( + findSecondaryObjectsResult.data.secondaryObjects.edges[1].node.objectId + ) ).toBeTrue(); const createPrimaryObjectResult = await apolloClient.mutate({ From 350b59ac5f936329e494bb2caab63fbdbba7d90f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 22 Jan 2022 13:32:51 +0000 Subject: [PATCH 55/89] chore(release): 5.0.0-alpha.20 [skip ci] # [5.0.0-alpha.20](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.19...5.0.0-alpha.20) (2022-01-22) ### Bug Fixes * bump node-fetch from 2.6.1 to 3.1.1 ([#7782](https://github.com/parse-community/parse-server/issues/7782)) ([9082351](https://github.com/parse-community/parse-server/commit/90823514113a1a085ebc818f7109b3fd7591346f)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index de391202..7433ea0d 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.20](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.19...5.0.0-alpha.20) (2022-01-22) + + +### Bug Fixes + +* bump node-fetch from 2.6.1 to 3.1.1 ([#7782](https://github.com/parse-community/parse-server/issues/7782)) ([9082351](https://github.com/parse-community/parse-server/commit/90823514113a1a085ebc818f7109b3fd7591346f)) + # [5.0.0-alpha.19](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.18...5.0.0-alpha.19) (2022-01-22) diff --git a/package-lock.json b/package-lock.json index e8622c96..a13b5cba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.19", + "version": "5.0.0-alpha.20", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2ad6ec34..6203c6f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.19", + "version": "5.0.0-alpha.20", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 433e82f1df627f3905ba69be99da6402710b5366 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Tue, 25 Jan 2022 00:42:55 +0000 Subject: [PATCH 56/89] refactor: upgrade parse from 3.4.0 to 3.4.1 (#7783) --- package-lock.json | 21 +++++++++++++++++---- package.json | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index a13b5cba..9641878c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13509,14 +13509,14 @@ } }, "parse": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.0.tgz", - "integrity": "sha512-FMZLxPW6PvrBgxkXc9AmnYsFKvPwiS4G2n9OI4mdfiSoNzIVLc+bXzlUdJ+I7hiqHsBTP0BrdQczw2/cnVkJ6w==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/parse/-/parse-3.4.1.tgz", + "integrity": "sha512-XTMaHfcOwAOiWLraNtPbCzR8o94ZWjOfaZDMM2jZ1ZDB5twtK1B82lPa+N197efZhcQ+QFbW/eDJsBybD48aSQ==", "requires": { "@babel/runtime": "7.15.4", "@babel/runtime-corejs3": "7.14.7", "crypto-js": "4.1.1", - "idb-keyval": "5.0.6", + "idb-keyval": "6.0.3", "react-native-crypto-js": "1.0.0", "uuid": "3.4.0", "ws": "7.5.1", @@ -13540,6 +13540,14 @@ "regenerator-runtime": "^0.13.4" } }, + "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==", + "requires": { + "safari-14-idb-fix": "^3.0.0" + } + }, "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", @@ -14680,6 +14688,11 @@ } } }, + "safari-14-idb-fix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz", + "integrity": "sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog==" + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", diff --git a/package.json b/package.json index 6203c6f2..58bde7f0 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "mime": "3.0.0", "mongodb": "3.6.11", "mustache": "4.2.0", - "parse": "3.4.0", + "parse": "3.4.1", "pg-monitor": "1.4.1", "pg-promise": "10.11.1", "pluralize": "8.0.0", From 315290d16110110938f80a6b779cc2d1db58c552 Mon Sep 17 00:00:00 2001 From: yog27ray Date: Tue, 25 Jan 2022 17:10:22 +0530 Subject: [PATCH 57/89] feat: add Cloud Code context to `ParseObject.fetch` (#7779) --- spec/CloudCode.spec.js | 15 +++++++++++++++ src/Routers/ClassesRouter.js | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index c185eac5..4b8df9f9 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -3224,6 +3224,21 @@ describe('afterLogin hook', () => { const query = new Parse.Query(TestObject); await query.find({ context: { a: 'a' } }); }); + + it('beforeFind and afterFind should have access to context while making fetch call', async () => { + Parse.Cloud.beforeFind('TestObject', req => { + expect(req.context.a).toEqual('a'); + expect(req.context.b).toBeUndefined(); + req.context.b = 'b'; + }); + Parse.Cloud.afterFind('TestObject', req => { + expect(req.context.a).toEqual('a'); + expect(req.context.b).toEqual('b'); + }); + const obj = new TestObject(); + await obj.save(); + await obj.fetch({ context: { a: 'a' } }); + }); }); describe('saveFile hooks', () => { diff --git a/src/Routers/ClassesRouter.js b/src/Routers/ClassesRouter.js index 6788d93e..7f3e0a84 100644 --- a/src/Routers/ClassesRouter.js +++ b/src/Routers/ClassesRouter.js @@ -83,7 +83,8 @@ export class ClassesRouter extends PromiseRouter { this.className(req), req.params.objectId, options, - req.info.clientSDK + req.info.clientSDK, + req.info.context ) .then(response => { if (!response.results || response.results.length == 0) { From 1299f0697c48b57aa2294b936ae53ff129f8c844 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 25 Jan 2022 11:41:15 +0000 Subject: [PATCH 58/89] chore(release): 5.0.0-alpha.21 [skip ci] # [5.0.0-alpha.21](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.20...5.0.0-alpha.21) (2022-01-25) ### Features * add Cloud Code context to `ParseObject.fetch` ([#7779](https://github.com/parse-community/parse-server/issues/7779)) ([315290d](https://github.com/parse-community/parse-server/commit/315290d16110110938f80a6b779cc2d1db58c552)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 7433ea0d..a78e3f06 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.21](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.20...5.0.0-alpha.21) (2022-01-25) + + +### Features + +* add Cloud Code context to `ParseObject.fetch` ([#7779](https://github.com/parse-community/parse-server/issues/7779)) ([315290d](https://github.com/parse-community/parse-server/commit/315290d16110110938f80a6b779cc2d1db58c552)) + # [5.0.0-alpha.20](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.19...5.0.0-alpha.20) (2022-01-22) diff --git a/package-lock.json b/package-lock.json index 9641878c..17701ad3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.20", + "version": "5.0.0-alpha.21", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 58bde7f0..5067906b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.20", + "version": "5.0.0-alpha.21", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From f88aa2a62a533e5344d1c13dd38c5a0b283a480a Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Sun, 6 Feb 2022 18:30:36 +0100 Subject: [PATCH 59/89] feat: upgrade to MongoDB Node.js driver 4.x for MongoDB 5.0 support (#7794) BREAKING CHANGE: The MongoDB GridStore adapter has been removed. By default, Parse Server already uses GridFS, so if you do not manually use the GridStore adapter, you can ignore this change. --- package-lock.json | 133 ++++++- package.json | 11 +- spec/AudienceRouter.spec.js | 29 +- spec/FilesController.spec.js | 43 +- spec/GridFSBucketStorageAdapter.spec.js | 19 +- spec/GridStoreAdapter.spec.js | 111 ------ spec/MongoStorageAdapter.spec.js | 55 ++- spec/ParseGraphQLServer.spec.js | 93 ++--- spec/ReadPreferenceOption.spec.js | 372 ++++++++---------- src/Adapters/Files/GridFSBucketAdapter.js | 2 +- src/Adapters/Files/GridStoreAdapter.js | 185 +-------- .../Storage/Mongo/MongoSchemaCollection.js | 2 +- .../Storage/Mongo/MongoStorageAdapter.js | 5 +- 13 files changed, 392 insertions(+), 668 deletions(-) delete mode 100644 spec/GridStoreAdapter.spec.js diff --git a/package-lock.json b/package-lock.json index 17701ad3..045195ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2650,6 +2650,20 @@ "@types/node": "*" } }, + "@types/webidl-conversions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", + "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==" + }, + "@types/whatwg-url": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz", + "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, "@types/ws": { "version": "7.4.7", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", @@ -3603,8 +3617,7 @@ "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bcrypt-nodejs": { "version": "0.0.3", @@ -3652,6 +3665,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "dev": true, "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" @@ -3788,13 +3802,13 @@ "bson": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", - "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", + "dev": true }, "buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, "requires": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" @@ -7940,8 +7954,7 @@ "ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { "version": "4.0.6", @@ -8153,6 +8166,11 @@ "loose-envify": "^1.0.0" } }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -10388,16 +10406,63 @@ "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, "mongodb": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.11.tgz", - "integrity": "sha512-4Y4lTFHDHZZdgMaHmojtNAlqkvddX2QQBEN0K//GzxhGwlI9tZ9R0vhbjr1Decw+TF7qK0ZLjQT292XgHRRQgw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz", + "integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==", "requires": { - "bl": "^2.2.1", - "bson": "^1.1.4", - "denque": "^1.4.1", - "optional-require": "^1.0.3", - "safe-buffer": "^5.1.2", - "saslprep": "^1.0.0" + "bson": "^4.6.1", + "denque": "^2.0.1", + "mongodb-connection-string-url": "^2.4.1", + "saslprep": "^1.0.3", + "socks": "^2.6.1" + }, + "dependencies": { + "bson": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz", + "integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==", + "requires": { + "buffer": "^5.6.0" + } + }, + "denque": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", + "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==" + } + } + }, + "mongodb-connection-string-url": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.4.1.tgz", + "integrity": "sha512-d5Kd2bVsKcSA7YI/yo57fSTtMwRQdFkvc5IZwod1RRxJtECeWPPSo7zqcUGJELifRA//Igs4spVtYAmvFCatug==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + }, + "dependencies": { + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } } }, "mongodb-core": { @@ -10520,6 +10585,20 @@ "ms": "2.1.2" } }, + "mongodb": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", + "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", + "dev": true, + "requires": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "optional-require": "^1.1.8", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -13233,9 +13312,10 @@ } }, "optional-require": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.7.tgz", - "integrity": "sha512-cIeRZocXsZnZYn+SevbtSqNlLbeoS4mLzuNn4fvXRMDRNhTGg0sxuKXl0FnZCtnew85LorNxIbZp5OeliILhMw==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", + "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", + "dev": true, "requires": { "require-at": "^1.0.6" } @@ -14518,7 +14598,8 @@ "require-at": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", - "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" + "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", + "dev": true }, "require-directory": { "version": "2.1.1", @@ -15277,6 +15358,11 @@ } } }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -15411,6 +15497,15 @@ } } }, + "socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, "sort-keys": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", diff --git a/package.json b/package.json index 5067906b..8129cb2f 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "lodash": "4.17.21", "lru-cache": "5.1.1", "mime": "3.0.0", - "mongodb": "3.6.11", + "mongodb": "4.3.1", "mustache": "4.2.0", "parse": "3.4.1", "pg-monitor": "1.4.1", @@ -118,12 +118,13 @@ "test:mongodb:4.0.27": "npm run test:mongodb --dbversion=4.0.27", "test:mongodb:4.2.17": "npm run test:mongodb --dbversion=4.2.17", "test:mongodb:4.4.10": "npm run test:mongodb --dbversion=4.4.10", + "test:mongodb:5.0.5": "npm run test:mongodb --dbversion=5.0.5", "posttest:mongodb": "mongodb-runner stop", - "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", - "testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine", + "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", + "testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine", "test": "npm run testonly", - "posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop", - "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=4.4.10} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine", + "posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop", + "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.0.5} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine", "start": "node ./bin/parse-server", "prettier": "prettier --write {src,spec}/{**/*,*}.js", "prepare": "npm run build", diff --git a/spec/AudienceRouter.spec.js b/spec/AudienceRouter.spec.js index 208e7834..9f0f7789 100644 --- a/spec/AudienceRouter.spec.js +++ b/spec/AudienceRouter.spec.js @@ -326,22 +326,24 @@ describe('AudiencesRouter', () => { { name: 'My Audience', query: JSON.stringify({ deviceType: 'ios' }) }, { useMasterKey: true } ).then(audience => { - database.collection('test__Audience').updateOne( - { _id: audience.objectId }, - { - $set: { - times_used: 1, - _last_used: now, - }, - }, - {}, - error => { - expect(error).toEqual(null); + database + .collection('test__Audience') + .updateOne( + { _id: audience.objectId }, + { + $set: { + times_used: 1, + _last_used: now, + }, + } + ) + .then(result => { + expect(result).toBeTruthy(); database .collection('test__Audience') .find({ _id: audience.objectId }) .toArray((error, rows) => { - expect(error).toEqual(null); + expect(error).toEqual(undefined); expect(rows[0]['times_used']).toEqual(1); expect(rows[0]['_last_used']).toEqual(now); Parse._request( @@ -361,8 +363,7 @@ describe('AudiencesRouter', () => { done.fail(error); }); }); - } - ); + }); }); }); diff --git a/spec/FilesController.spec.js b/spec/FilesController.spec.js index 996e4c39..9ea66da6 100644 --- a/spec/FilesController.spec.js +++ b/spec/FilesController.spec.js @@ -3,7 +3,6 @@ const WinstonLoggerAdapter = require('../lib/Adapters/Logger/WinstonLoggerAdapte .WinstonLoggerAdapter; const GridFSBucketAdapter = require('../lib/Adapters/Files/GridFSBucketAdapter') .GridFSBucketAdapter; -const GridStoreAdapter = require('../lib/Adapters/Files/GridStoreAdapter').GridStoreAdapter; const Config = require('../lib/Config'); const FilesController = require('../lib/Controllers/FilesController').default; const databaseURI = 'mongodb://localhost:27017/parse'; @@ -24,8 +23,8 @@ const mockAdapter = { describe('FilesController', () => { it('should properly expand objects', done => { const config = Config.get(Parse.applicationId); - const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); - const filesController = new FilesController(gridStoreAdapter); + const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); + const filesController = new FilesController(gridFSAdapter); const result = filesController.expandFilesInObject(config, function () {}); expect(result).toBeUndefined(); @@ -88,19 +87,19 @@ describe('FilesController', () => { it('should add a unique hash to the file name when the preserveFileName option is false', done => { const config = Config.get(Parse.applicationId); - const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); - spyOn(gridStoreAdapter, 'createFile'); - gridStoreAdapter.createFile.and.returnValue(Promise.resolve()); + const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); + spyOn(gridFSAdapter, 'createFile'); + gridFSAdapter.createFile.and.returnValue(Promise.resolve()); const fileName = 'randomFileName.pdf'; const regexEscapedFileName = fileName.replace(/\./g, '\\$&'); - const filesController = new FilesController(gridStoreAdapter, null, { + const filesController = new FilesController(gridFSAdapter, null, { preserveFileName: false, }); filesController.createFile(config, fileName); - expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1); - expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toMatch( + expect(gridFSAdapter.createFile).toHaveBeenCalledTimes(1); + expect(gridFSAdapter.createFile.calls.mostRecent().args[0]).toMatch( `^.{32}_${regexEscapedFileName}$` ); @@ -109,42 +108,42 @@ describe('FilesController', () => { it('should not add a unique hash to the file name when the preserveFileName option is true', done => { const config = Config.get(Parse.applicationId); - const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); - spyOn(gridStoreAdapter, 'createFile'); - gridStoreAdapter.createFile.and.returnValue(Promise.resolve()); + const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); + spyOn(gridFSAdapter, 'createFile'); + gridFSAdapter.createFile.and.returnValue(Promise.resolve()); const fileName = 'randomFileName.pdf'; - const filesController = new FilesController(gridStoreAdapter, null, { + const filesController = new FilesController(gridFSAdapter, null, { preserveFileName: true, }); filesController.createFile(config, fileName); - expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1); - expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toEqual(fileName); + expect(gridFSAdapter.createFile).toHaveBeenCalledTimes(1); + expect(gridFSAdapter.createFile.calls.mostRecent().args[0]).toEqual(fileName); done(); }); it('should handle adapter without getMetadata', async () => { - const gridStoreAdapter = new GridFSBucketAdapter(databaseURI); - gridStoreAdapter.getMetadata = null; - const filesController = new FilesController(gridStoreAdapter); + const gridFSAdapter = new GridFSBucketAdapter(databaseURI); + gridFSAdapter.getMetadata = null; + const filesController = new FilesController(gridFSAdapter); const result = await filesController.getMetadata(); expect(result).toEqual({}); }); it('should reject slashes in file names', done => { - const gridStoreAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); + const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); const fileName = 'foo/randomFileName.pdf'; - expect(gridStoreAdapter.validateFilename(fileName)).not.toBe(null); + expect(gridFSAdapter.validateFilename(fileName)).not.toBe(null); done(); }); it('should also reject slashes in file names', done => { - const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse'); + const gridFSAdapter = new GridFSBucketAdapter('mongodb://localhost:27017/parse'); const fileName = 'foo/randomFileName.pdf'; - expect(gridStoreAdapter.validateFilename(fileName)).not.toBe(null); + expect(gridFSAdapter.validateFilename(fileName)).not.toBe(null); done(); }); }); diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js index 8431d6d7..7ffdced2 100644 --- a/spec/GridFSBucketStorageAdapter.spec.js +++ b/spec/GridFSBucketStorageAdapter.spec.js @@ -1,4 +1,3 @@ -const GridStoreAdapter = require('../lib/Adapters/Files/GridStoreAdapter').GridStoreAdapter; const GridFSBucketAdapter = require('../lib/Adapters/Files/GridFSBucketAdapter') .GridFSBucketAdapter; const { randomString } = require('../lib/cryptoUtils'); @@ -14,25 +13,13 @@ async function expectMissingFile(gfsAdapter, name) { } } -describe_only_db('mongo')('GridFSBucket and GridStore interop', () => { +describe_only_db('mongo')('GridFSBucket', () => { beforeEach(async () => { - const gsAdapter = new GridStoreAdapter(databaseURI); + const gsAdapter = new GridFSBucketAdapter(databaseURI); const db = await gsAdapter._connect(); await db.dropDatabase(); }); - it('a file created in GridStore should be available in GridFS', async () => { - const gsAdapter = new GridStoreAdapter(databaseURI); - const gfsAdapter = new GridFSBucketAdapter(databaseURI); - await expectMissingFile(gfsAdapter, 'myFileName'); - const originalString = 'abcdefghi'; - await gsAdapter.createFile('myFileName', originalString); - const gsResult = await gsAdapter.getFileData('myFileName'); - expect(gsResult.toString('utf8')).toBe(originalString); - const gfsResult = await gfsAdapter.getFileData('myFileName'); - expect(gfsResult.toString('utf8')).toBe(originalString); - }); - 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( @@ -451,7 +438,7 @@ describe_only_db('mongo')('GridFSBucket and GridStore interop', () => { await db.admin().serverStatus(); expect(false).toBe(true); } catch (e) { - expect(e.message).toEqual('topology was destroyed'); + expect(e.message).toEqual('MongoClient must be connected to perform this operation'); } }); }); diff --git a/spec/GridStoreAdapter.spec.js b/spec/GridStoreAdapter.spec.js deleted file mode 100644 index 145b8e0e..00000000 --- a/spec/GridStoreAdapter.spec.js +++ /dev/null @@ -1,111 +0,0 @@ -const MongoClient = require('mongodb').MongoClient; -const GridStore = require('mongodb').GridStore; - -const GridStoreAdapter = require('../lib/Adapters/Files/GridStoreAdapter').GridStoreAdapter; -const Config = require('../lib/Config'); -const FilesController = require('../lib/Controllers/FilesController').default; - -// Small additional tests to improve overall coverage -describe_only_db('mongo')('GridStoreAdapter', () => { - it('should properly instanciate the GridStore when deleting a file', async done => { - const databaseURI = 'mongodb://localhost:27017/parse'; - const config = Config.get(Parse.applicationId); - const gridStoreAdapter = new GridStoreAdapter(databaseURI); - const db = await gridStoreAdapter._connect(); - await db.dropDatabase(); - const filesController = new FilesController(gridStoreAdapter, Parse.applicationId, {}); - - // save original unlink before redefinition - const originalUnlink = GridStore.prototype.unlink; - - let gridStoreMode; - - // new unlink method that will capture the mode in which GridStore was opened - GridStore.prototype.unlink = function () { - // restore original unlink during first call - GridStore.prototype.unlink = originalUnlink; - - gridStoreMode = this.mode; - - return originalUnlink.call(this); - }; - - filesController - .createFile(config, 'myFilename.txt', 'my file content', 'text/plain') - .then(myFile => { - return MongoClient.connect(databaseURI) - .then(client => { - const database = client.db(client.s.options.dbName); - // Verify the existance of the fs.files document - return database - .collection('fs.files') - .count() - .then(count => { - expect(count).toEqual(1); - return { database, client }; - }); - }) - .then(({ database, client }) => { - // Verify the existance of the fs.files document - return database - .collection('fs.chunks') - .count() - .then(count => { - expect(count).toEqual(1); - return client.close(); - }); - }) - .then(() => { - return filesController.deleteFile(config, myFile.name); - }); - }) - .then(() => { - return MongoClient.connect(databaseURI) - .then(client => { - const database = client.db(client.s.options.dbName); - // Verify the existance of the fs.files document - return database - .collection('fs.files') - .count() - .then(count => { - expect(count).toEqual(0); - return { database, client }; - }); - }) - .then(({ database, client }) => { - // Verify the existance of the fs.files document - return database - .collection('fs.chunks') - .count() - .then(count => { - expect(count).toEqual(0); - return client.close(); - }); - }); - }) - .then(() => { - // Verify that gridStore was opened in read only mode - expect(gridStoreMode).toEqual('r'); - - done(); - }) - .catch(fail); - }); - - it('handleShutdown, close connection', async () => { - const databaseURI = 'mongodb://localhost:27017/parse'; - const gridStoreAdapter = new GridStoreAdapter(databaseURI); - - const db = await gridStoreAdapter._connect(); - const status = await db.admin().serverStatus(); - expect(status.connections.current > 0).toEqual(true); - - await gridStoreAdapter.handleShutdown(); - try { - await db.admin().serverStatus(); - expect(false).toBe(true); - } catch (e) { - expect(e.message).toEqual('topology was destroyed'); - } - }); -}); diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index f6d28664..a31a6134 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -1,7 +1,7 @@ 'use strict'; const MongoStorageAdapter = require('../lib/Adapters/Storage/Mongo/MongoStorageAdapter').default; -const { MongoClient } = require('mongodb'); +const { MongoClient, Collection } = require('mongodb'); const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase'; const request = require('../lib/request'); const Config = require('../lib/Config'); @@ -101,7 +101,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { done.fail('Find succeeded despite taking too long!'); }, err => { - expect(err.name).toEqual('MongoError'); + expect(err.name).toEqual('MongoServerError'); expect(err.code).toEqual(50); expect(err.message).toMatch('operation exceeded time limit'); done(); @@ -283,7 +283,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { await adapter.database.admin().serverStatus(); expect(false).toBe(true); } catch (e) { - expect(e.message).toEqual('topology was destroyed'); + expect(e.message).toEqual('MongoClient must be connected to perform this operation'); } }); @@ -392,8 +392,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { const myObject = new Parse.Object('MyObject'); await myObject.save(); - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough(); + spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough(); await request({ method: 'POST', @@ -412,9 +411,9 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }); let found = false; - databaseAdapter.database.serverConfig.command.calls.all().forEach(call => { + Collection.prototype.findOneAndUpdate.calls.all().forEach(call => { found = true; - expect(call.args[2].session.transaction.state).not.toBe('NO_TRANSACTION'); + expect(call.args[2].session.transaction.state).toBe('TRANSACTION_COMMITTED'); }); expect(found).toBe(true); }); @@ -423,8 +422,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { const myObject = new Parse.Object('MyObject'); await myObject.save(); - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough(); + spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough(); await request({ method: 'POST', @@ -443,9 +441,9 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }); let found = false; - databaseAdapter.database.serverConfig.command.calls.all().forEach(call => { + Collection.prototype.findOneAndUpdate.calls.all().forEach(call => { found = true; - expect(call.args[2].session).toBe(undefined); + expect(call.args[2].session).toBeFalsy(); }); expect(found).toBe(true); }); @@ -454,8 +452,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { const myObject = new Parse.Object('MyObject'); await myObject.save(); - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough(); + spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough(); await request({ method: 'POST', @@ -473,9 +470,9 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }); let found = false; - databaseAdapter.database.serverConfig.command.calls.all().forEach(call => { + Collection.prototype.findOneAndUpdate.calls.all().forEach(call => { found = true; - expect(call.args[2].session).toBe(undefined); + expect(call.args[2].session).toBeFalsy(); }); expect(found).toBe(true); }); @@ -484,8 +481,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { const myObject = new Parse.Object('MyObject'); await myObject.save(); - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'command').and.callThrough(); + spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough(); await request({ method: 'PUT', @@ -495,30 +491,28 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }); let found = false; - databaseAdapter.database.serverConfig.command.calls.all().forEach(call => { + Collection.prototype.findOneAndUpdate.calls.all().forEach(call => { found = true; - expect(call.args[2].session).toBe(undefined); + expect(call.args[2].session).toBeFalsy(); }); expect(found).toBe(true); }); it('should not use transactions when using SDK insert', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'insert').and.callThrough(); + spyOn(Collection.prototype, 'insertOne').and.callThrough(); const myObject = new Parse.Object('MyObject'); await myObject.save(); - const calls = databaseAdapter.database.serverConfig.insert.calls.all(); + const calls = Collection.prototype.insertOne.calls.all(); expect(calls.length).toBeGreaterThan(0); calls.forEach(call => { - expect(call.args[2].session.transaction.state).toBe('NO_TRANSACTION'); + expect(call.args[1].session).toBeFalsy(); }); }); it('should not use transactions when using SDK update', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'update').and.callThrough(); + spyOn(Collection.prototype, 'findOneAndUpdate').and.callThrough(); const myObject = new Parse.Object('MyObject'); await myObject.save(); @@ -526,26 +520,25 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { myObject.set('myAttribute', 'myValue'); await myObject.save(); - const calls = databaseAdapter.database.serverConfig.update.calls.all(); + const calls = Collection.prototype.findOneAndUpdate.calls.all(); expect(calls.length).toBeGreaterThan(0); calls.forEach(call => { - expect(call.args[2].session.transaction.state).toBe('NO_TRANSACTION'); + expect(call.args[2].session).toBeFalsy(); }); }); it('should not use transactions when using SDK delete', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'remove').and.callThrough(); + spyOn(Collection.prototype, 'deleteMany').and.callThrough(); const myObject = new Parse.Object('MyObject'); await myObject.save(); await myObject.destroy(); - const calls = databaseAdapter.database.serverConfig.remove.calls.all(); + const calls = Collection.prototype.deleteMany.calls.all(); expect(calls.length).toBeGreaterThan(0); calls.forEach(call => { - expect(call.args[2].session.transaction.state).toBe('NO_TRANSACTION'); + expect(call.args[1].session).toBeFalsy(); }); }); }); diff --git a/spec/ParseGraphQLServer.spec.js b/spec/ParseGraphQLServer.spec.js index 6541092b..32a52613 100644 --- a/spec/ParseGraphQLServer.spec.js +++ b/spec/ParseGraphQLServer.spec.js @@ -32,7 +32,7 @@ const { } = require('graphql'); const { ParseServer } = require('../'); const { ParseGraphQLServer } = require('../lib/GraphQL/ParseGraphQLServer'); -const ReadPreference = require('mongodb').ReadPreference; +const { ReadPreference, Collection } = require('mongodb'); const { v4: uuidv4 } = require('uuid'); function handleError(e) { @@ -4473,8 +4473,7 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); - const databaseAdapter = parseServer.config.databaseController.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await apolloClient.query({ query: gql` @@ -4498,13 +4497,13 @@ describe('ParseGraphQLServer', () => { let foundGraphQLClassReadPreference = false; let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) { foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { + expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY); + } else if (call.object.s.namespace.collection.indexOf('_User') >= 0) { foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY); + expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY); } }); @@ -4520,8 +4519,7 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); - const databaseAdapter = parseServer.config.databaseController.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await apolloClient.query({ query: gql` @@ -4545,13 +4543,13 @@ describe('ParseGraphQLServer', () => { let foundGraphQLClassReadPreference = false; let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) { foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { + expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY); + } else if (call.object.s.namespace.collection.indexOf('_User') >= 0) { foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY); + expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY); } }); @@ -4564,8 +4562,7 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); - const databaseAdapter = parseServer.config.databaseController.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await apolloClient.query({ query: gql` @@ -4592,13 +4589,13 @@ describe('ParseGraphQLServer', () => { let foundGraphQLClassReadPreference = false; let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) { foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { + expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY); + } else if (call.object.s.namespace.collection.indexOf('_User') >= 0) { foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST); + expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST); } }); @@ -5456,8 +5453,7 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); - const databaseAdapter = parseServer.config.databaseController.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await apolloClient.query({ query: gql` @@ -5482,13 +5478,13 @@ describe('ParseGraphQLServer', () => { let foundGraphQLClassReadPreference = false; let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) { foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { + expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY); + } else if (call.object.s.namespace.collection.indexOf('_User') >= 0) { foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY); + expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY); } }); @@ -5501,8 +5497,7 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); - const databaseAdapter = parseServer.config.databaseController.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await apolloClient.query({ query: gql` @@ -5527,13 +5522,13 @@ describe('ParseGraphQLServer', () => { let foundGraphQLClassReadPreference = false; let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) { foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { + expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY); + } else if (call.object.s.namespace.collection.indexOf('_User') >= 0) { foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY); + expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY); } }); @@ -5546,8 +5541,7 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); - const databaseAdapter = parseServer.config.databaseController.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await apolloClient.query({ query: gql` @@ -5574,13 +5568,13 @@ describe('ParseGraphQLServer', () => { let foundGraphQLClassReadPreference = false; let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) { foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { + expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY); + } else if (call.object.s.namespace.collection.indexOf('_User') >= 0) { foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST); + expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST); } }); @@ -5594,8 +5588,7 @@ describe('ParseGraphQLServer', () => { await parseGraphQLServer.parseGraphQLSchema.schemaCache.clear(); - const databaseAdapter = parseServer.config.databaseController.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await apolloClient.query({ query: gql` @@ -5632,13 +5625,13 @@ describe('ParseGraphQLServer', () => { let foundGraphQLClassReadPreference = false; let foundUserClassReadPreference = false; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('GraphQLClass') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('GraphQLClass') >= 0) { foundGraphQLClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.SECONDARY); - } else if (call.args[0].ns.collection.indexOf('_User') >= 0) { + expect(call.args[1].readPreference).toBe(ReadPreference.SECONDARY); + } else if (call.object.s.namespace.collection.indexOf('_User') >= 0) { foundUserClassReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST); + expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST); } }); diff --git a/spec/ReadPreferenceOption.spec.js b/spec/ReadPreferenceOption.spec.js index f2bc328d..535c35c8 100644 --- a/spec/ReadPreferenceOption.spec.js +++ b/spec/ReadPreferenceOption.spec.js @@ -1,9 +1,8 @@ 'use strict'; const Parse = require('parse/node'); -const ReadPreference = require('mongodb').ReadPreference; +const { ReadPreference, Collection } = require('mongodb'); const request = require('../lib/request'); -const Config = require('../lib/Config'); function waitForReplication() { return new Promise(function (resolve) { @@ -13,8 +12,6 @@ function waitForReplication() { describe_only_db('mongo')('Read preference option', () => { it('should find in primary by default', done => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); @@ -22,7 +19,7 @@ describe_only_db('mongo')('Read preference option', () => { Parse.Object.saveAll([obj0, obj1]) .then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); const query = new Parse.Query('MyObject'); query.equalTo('boolKey', false); @@ -31,10 +28,10 @@ describe_only_db('mongo')('Read preference option', () => { expect(results.length).toBe(1); expect(results[0].get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { myObjectReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.PRIMARY); + expect(call.object.s.readPreference.mode).toBe(ReadPreference.PRIMARY); } }); @@ -58,15 +55,13 @@ describe_only_db('mongo')('Read preference option', () => { databaseAdapter: new MongoStorageAdapter(adapterOptions), }); - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); const query = new Parse.Query('MyObject'); query.equalTo('boolKey', false); @@ -76,10 +71,10 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { myObjectReadPreference = true; - expect(call.args[0].options.readPreference.mode).toBe(ReadPreference.NEAREST); + expect(call.args[1].readPreference).toBe(ReadPreference.NEAREST); } }); @@ -87,15 +82,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference in the beforeFind trigger', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; @@ -110,9 +103,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -120,15 +113,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should check read preference as case insensitive', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'sEcOnDarY'; @@ -144,9 +135,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -154,15 +145,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference in the beforeFind trigger even changing query', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.query.equalTo('boolKey', true); @@ -178,9 +167,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(true); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -188,15 +177,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference in the beforeFind trigger even returning query', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; @@ -216,9 +203,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(true); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -226,15 +213,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference in the beforeFind trigger even returning promise', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; @@ -253,9 +238,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(true); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -263,15 +248,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference to PRIMARY_PREFERRED', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'PRIMARY_PREFERRED'; @@ -286,9 +269,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -296,15 +279,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference to SECONDARY_PREFERRED', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY_PREFERRED'; @@ -319,9 +300,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -329,15 +310,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference to NEAREST', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'NEAREST'; @@ -352,9 +331,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(results[0].get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -362,15 +341,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference for GET', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; @@ -383,9 +360,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(result.get('boolKey')).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -393,15 +370,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference for GET using API', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; @@ -421,9 +396,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(body.boolKey).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -431,15 +406,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference for GET directly from API', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await waitForReplication(); const response = await request({ @@ -454,9 +427,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(response.data.boolKey).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -464,15 +437,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference for GET using API through the beforeFind overriding API option', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY_PREFERRED'; @@ -491,9 +462,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(response.data.boolKey).toBe(false); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -501,15 +472,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference for FIND using API through beforeFind trigger', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; @@ -528,9 +497,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(response.data.results.length).toEqual(2); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -538,15 +507,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference for FIND directly from API', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await waitForReplication(); const response = await request({ @@ -561,9 +528,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(response.data.results.length).toEqual(2); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -571,15 +538,13 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change read preference for FIND using API through the beforeFind overriding API option', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); await Parse.Object.saveAll([obj0, obj1]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY_PREFERRED'; @@ -598,9 +563,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(response.data.results.length).toEqual(2); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -608,15 +573,13 @@ describe_only_db('mongo')('Read preference option', () => { }); xit('should change read preference for count', done => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject'); obj1.set('boolKey', true); Parse.Object.saveAll([obj0, obj1]).then(() => { - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject', req => { req.readPreference = 'SECONDARY'; @@ -631,9 +594,9 @@ describe_only_db('mongo')('Read preference option', () => { expect(result).toBe(1); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); @@ -659,17 +622,16 @@ describe_only_db('mongo')('Read preference option', () => { await waitForReplication(); // Spy on DB adapter - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'startSession').and.callThrough(); + spyOn(Collection.prototype, 'aggregate').and.callThrough(); // Query const query = new Parse.Query('MyObject'); const results = await query.aggregate([{ match: { boolKey: false } }]); // Validate expect(results.length).toBe(1); let readPreference = null; - databaseAdapter.database.serverConfig.startSession.calls.all().forEach(call => { - if (call.args[0].owner.ns.indexOf('MyObject') > -1) { - readPreference = call.args[0].owner.operation.readPreference.mode; + Collection.prototype.aggregate.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') > -1) { + readPreference = call.args[1].readPreference; } }); expect(readPreference).toEqual(ReadPreference.SECONDARY); @@ -685,8 +647,7 @@ describe_only_db('mongo')('Read preference option', () => { await waitForReplication(); // Spy on DB adapter - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); // Query const query = new Parse.Query('MyObject'); query.equalTo('boolKey', false); @@ -695,9 +656,9 @@ describe_only_db('mongo')('Read preference option', () => { // Validate expect(results.length).toBe(1); let myObjectReadPreference = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject') >= 0) { - myObjectReadPreference = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') >= 0) { + myObjectReadPreference = call.args[1].readPreference; } }); expect(myObjectReadPreference).toEqual(ReadPreference.SECONDARY); @@ -713,8 +674,7 @@ describe_only_db('mongo')('Read preference option', () => { await waitForReplication(); // Spy on DB adapter - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - spyOn(databaseAdapter.database.serverConfig, 'startSession').and.callThrough(); + spyOn(Collection.prototype, 'aggregate').and.callThrough(); // Query const query = new Parse.Query('MyObject'); query.readPreference('SECONDARY'); @@ -722,17 +682,15 @@ describe_only_db('mongo')('Read preference option', () => { // Validate expect(results.length).toBe(1); let readPreference = null; - databaseAdapter.database.serverConfig.startSession.calls.all().forEach(call => { - if (call.args[0].owner.ns.indexOf('MyObject') > -1) { - readPreference = call.args[0].owner.operation.readPreference.mode; + Collection.prototype.aggregate.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject') > -1) { + readPreference = call.args[1].readPreference; } }); expect(readPreference).toEqual(ReadPreference.SECONDARY); }); it('should find includes in same replica of readPreference by default', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -743,7 +701,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject2', req => { req.readPreference = 'SECONDARY'; @@ -765,15 +723,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -783,8 +741,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change includes read preference', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -795,7 +751,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject2', req => { req.readPreference = 'SECONDARY_PREFERRED'; @@ -818,15 +774,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -836,8 +792,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change includes read preference when finding through API', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -848,7 +802,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await waitForReplication(); const response = await request({ @@ -873,15 +827,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -891,8 +845,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change includes read preference when getting through API', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -903,7 +855,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await waitForReplication(); const response = await request({ @@ -929,15 +881,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -947,8 +899,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should find subqueries in same replica of readPreference by default', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -959,7 +909,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject2', req => { req.readPreference = 'SECONDARY'; @@ -982,15 +932,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -1000,8 +950,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change subqueries read preference when using matchesQuery', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -1012,7 +960,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject2', req => { req.readPreference = 'SECONDARY_PREFERRED'; @@ -1036,15 +984,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -1054,8 +1002,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change subqueries read preference when using doesNotMatchQuery', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -1066,7 +1012,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject2', req => { req.readPreference = 'SECONDARY_PREFERRED'; @@ -1090,15 +1036,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -1108,8 +1054,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -1120,7 +1064,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); Parse.Cloud.beforeFind('MyObject2', req => { req.readPreference = 'SECONDARY_PREFERRED'; @@ -1145,15 +1089,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); @@ -1163,8 +1107,6 @@ describe_only_db('mongo')('Read preference option', () => { }); it('should change subqueries read preference when using matchesKeyInQuery and doesNotMatchKeyInQuery to find through API', async () => { - const databaseAdapter = Config.get(Parse.applicationId).database.adapter; - const obj0 = new Parse.Object('MyObject0'); obj0.set('boolKey', false); const obj1 = new Parse.Object('MyObject1'); @@ -1175,7 +1117,7 @@ describe_only_db('mongo')('Read preference option', () => { obj2.set('myObject1', obj1); await Parse.Object.saveAll([obj0, obj1, obj2]); - spyOn(databaseAdapter.database.serverConfig, 'cursor').and.callThrough(); + spyOn(Collection.prototype, 'find').and.callThrough(); await waitForReplication(); const whereString = JSON.stringify({ @@ -1215,15 +1157,15 @@ describe_only_db('mongo')('Read preference option', () => { let myObjectReadPreference0 = null; let myObjectReadPreference1 = null; let myObjectReadPreference2 = null; - databaseAdapter.database.serverConfig.cursor.calls.all().forEach(call => { - if (call.args[0].ns.collection.indexOf('MyObject0') >= 0) { - myObjectReadPreference0 = call.args[0].options.readPreference.mode; + Collection.prototype.find.calls.all().forEach(call => { + if (call.object.s.namespace.collection.indexOf('MyObject0') >= 0) { + myObjectReadPreference0 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject1') >= 0) { - myObjectReadPreference1 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject1') >= 0) { + myObjectReadPreference1 = call.args[1].readPreference; } - if (call.args[0].ns.collection.indexOf('MyObject2') >= 0) { - myObjectReadPreference2 = call.args[0].options.readPreference.mode; + if (call.object.s.namespace.collection.indexOf('MyObject2') >= 0) { + myObjectReadPreference2 = call.args[1].readPreference; } }); diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js index 84876fad..06896e73 100644 --- a/src/Adapters/Files/GridFSBucketAdapter.js +++ b/src/Adapters/Files/GridFSBucketAdapter.js @@ -1,6 +1,6 @@ /** GridFSBucketAdapter - Stores files in Mongo using GridStore + Stores files in Mongo using GridFS Requires the database adapter to be based on mongoclient @flow weak diff --git a/src/Adapters/Files/GridStoreAdapter.js b/src/Adapters/Files/GridStoreAdapter.js index ca3166af..39d1ca41 100644 --- a/src/Adapters/Files/GridStoreAdapter.js +++ b/src/Adapters/Files/GridStoreAdapter.js @@ -1,181 +1,4 @@ -/** - GridStoreAdapter - Stores files in Mongo using GridStore - Requires the database adapter to be based on mongoclient - (GridStore is deprecated, Please use GridFSBucket instead) - - @flow weak - */ - -// @flow-disable-next -import { MongoClient, GridStore, Db } from 'mongodb'; -import { FilesAdapter, validateFilename } from './FilesAdapter'; -import defaults from '../../defaults'; - -export class GridStoreAdapter extends FilesAdapter { - _databaseURI: string; - _connectionPromise: Promise; - _mongoOptions: Object; - - constructor(mongoDatabaseURI = defaults.DefaultMongoURI, mongoOptions = {}) { - super(); - this._databaseURI = mongoDatabaseURI; - - const defaultMongoOptions = { - useNewUrlParser: true, - useUnifiedTopology: true, - }; - this._mongoOptions = Object.assign(defaultMongoOptions, mongoOptions); - } - - _connect() { - if (!this._connectionPromise) { - this._connectionPromise = MongoClient.connect(this._databaseURI, this._mongoOptions).then( - client => { - this._client = client; - return client.db(client.s.options.dbName); - } - ); - } - return this._connectionPromise; - } - - // For a given config object, filename, and data, store a file - // Returns a promise - createFile(filename: string, data) { - return this._connect() - .then(database => { - const gridStore = new GridStore(database, filename, 'w'); - return gridStore.open(); - }) - .then(gridStore => { - return gridStore.write(data); - }) - .then(gridStore => { - return gridStore.close(); - }); - } - - deleteFile(filename: string) { - return this._connect() - .then(database => { - const gridStore = new GridStore(database, filename, 'r'); - return gridStore.open(); - }) - .then(gridStore => { - return gridStore.unlink(); - }) - .then(gridStore => { - return gridStore.close(); - }); - } - - getFileData(filename: string) { - return this._connect() - .then(database => { - return GridStore.exist(database, filename).then(() => { - const gridStore = new GridStore(database, filename, 'r'); - return gridStore.open(); - }); - }) - .then(gridStore => { - return gridStore.read(); - }); - } - - getFileLocation(config, filename) { - return config.mount + '/files/' + config.applicationId + '/' + encodeURIComponent(filename); - } - - async handleFileStream(filename: string, req, res, contentType) { - const stream = await this._connect().then(database => { - return GridStore.exist(database, filename).then(() => { - const gridStore = new GridStore(database, filename, 'r'); - return gridStore.open(); - }); - }); - handleRangeRequest(stream, req, res, contentType); - } - - handleShutdown() { - if (!this._client) { - return Promise.resolve(); - } - return this._client.close(false); - } - - validateFilename(filename) { - return validateFilename(filename); - } -} - -// handleRangeRequest is licensed under Creative Commons Attribution 4.0 International License (https://creativecommons.org/licenses/by/4.0/). -// Author: LEROIB at weightingformypizza (https://weightingformypizza.wordpress.com/2015/06/24/stream-html5-media-content-like-video-audio-from-mongodb-using-express-and-gridstore/). -function handleRangeRequest(stream, req, res, contentType) { - const buffer_size = 1024 * 1024; //1024Kb - // Range request, partial stream the file - const parts = req - .get('Range') - .replace(/bytes=/, '') - .split('-'); - let [start, end] = parts; - const notEnded = !end && end !== 0; - const notStarted = !start && start !== 0; - // No end provided, we want all bytes - if (notEnded) { - end = stream.length - 1; - } - // No start provided, we're reading backwards - if (notStarted) { - start = stream.length - end; - end = start + end - 1; - } - - // Data exceeds the buffer_size, cap - if (end - start >= buffer_size) { - end = start + buffer_size - 1; - } - - const contentLength = end - start + 1; - - res.writeHead(206, { - 'Content-Range': 'bytes ' + start + '-' + end + '/' + stream.length, - 'Accept-Ranges': 'bytes', - 'Content-Length': contentLength, - 'Content-Type': contentType, - }); - - stream.seek(start, function () { - // Get gridFile stream - const gridFileStream = stream.stream(true); - let bufferAvail = 0; - let remainingBytesToWrite = contentLength; - let totalBytesWritten = 0; - // Write to response - gridFileStream.on('data', function (data) { - bufferAvail += data.length; - if (bufferAvail > 0) { - // slice returns the same buffer if overflowing - // safe to call in any case - const buffer = data.slice(0, remainingBytesToWrite); - // Write the buffer - res.write(buffer); - // Increment total - totalBytesWritten += buffer.length; - // Decrement remaining - remainingBytesToWrite -= data.length; - // Decrement the available buffer - bufferAvail -= buffer.length; - } - // In case of small slices, all values will be good at that point - // we've written enough, end... - if (totalBytesWritten >= contentLength) { - stream.close(); - res.end(); - this.destroy(); - } - }); - }); -} - -export default GridStoreAdapter; +// Note: GridStore was replaced by GridFSBucketAdapter by default in 2018 by @flovilmart +throw new Error( + 'GridStoreAdapter: GridStore is no longer supported by parse server and mongodb, use GridFSBucketAdapter instead.' +); diff --git a/src/Adapters/Storage/Mongo/MongoSchemaCollection.js b/src/Adapters/Storage/Mongo/MongoSchemaCollection.js index 78284503..20e3eec3 100644 --- a/src/Adapters/Storage/Mongo/MongoSchemaCollection.js +++ b/src/Adapters/Storage/Mongo/MongoSchemaCollection.js @@ -177,7 +177,7 @@ class MongoSchemaCollection { insertSchema(schema: any) { return this._collection .insertOne(schema) - .then(result => mongoSchemaToParseSchema(result.ops[0])) + .then(() => mongoSchemaToParseSchema(schema)) .catch(error => { if (error.code === 11000) { //Mongo's duplicate key error diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index c1fe63ba..93e23b91 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -479,6 +479,7 @@ export class MongoStorageAdapter implements StorageAdapter { const mongoObject = parseObjectToMongoObjectForCreate(className, object, schema); return this._adaptiveCollection(className) .then(collection => collection.insertOne(mongoObject, transactionalSession)) + .then(() => ({ ops: [mongoObject] })) .catch(error => { if (error.code === 11000) { // Duplicate value @@ -517,8 +518,8 @@ export class MongoStorageAdapter implements StorageAdapter { }) .catch(err => this.handleError(err)) .then( - ({ result }) => { - if (result.n === 0) { + ({ deletedCount }) => { + if (deletedCount === 0) { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.'); } return Promise.resolve(); From 1e05309e7900cdeb945b39d42538a04423389dde Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 6 Feb 2022 17:31:41 +0000 Subject: [PATCH 60/89] chore(release): 5.0.0-alpha.22 [skip ci] # [5.0.0-alpha.22](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.21...5.0.0-alpha.22) (2022-02-06) ### Features * upgrade to MongoDB Node.js driver 4.x for MongoDB 5.0 support ([#7794](https://github.com/parse-community/parse-server/issues/7794)) ([f88aa2a](https://github.com/parse-community/parse-server/commit/f88aa2a62a533e5344d1c13dd38c5a0b283a480a)) ### BREAKING CHANGES * The MongoDB GridStore adapter has been removed. By default, Parse Server already uses GridFS, so if you do not manually use the GridStore adapter, you can ignore this change. ([f88aa2a](f88aa2a)) --- changelogs/CHANGELOG_alpha.md | 12 ++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index a78e3f06..524c2cb9 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,15 @@ +# [5.0.0-alpha.22](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.21...5.0.0-alpha.22) (2022-02-06) + + +### Features + +* upgrade to MongoDB Node.js driver 4.x for MongoDB 5.0 support ([#7794](https://github.com/parse-community/parse-server/issues/7794)) ([f88aa2a](https://github.com/parse-community/parse-server/commit/f88aa2a62a533e5344d1c13dd38c5a0b283a480a)) + + +### BREAKING CHANGES + +* The MongoDB GridStore adapter has been removed. By default, Parse Server already uses GridFS, so if you do not manually use the GridStore adapter, you can ignore this change. ([f88aa2a](f88aa2a)) + # [5.0.0-alpha.21](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.20...5.0.0-alpha.21) (2022-01-25) diff --git a/package-lock.json b/package-lock.json index 045195ff..ccc18f48 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.21", + "version": "5.0.0-alpha.22", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8129cb2f..0abd1e1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.21", + "version": "5.0.0-alpha.22", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 08089d6fcbb215412448ce7d92b21b9fe6c929f2 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 7 Feb 2022 00:09:41 +0100 Subject: [PATCH 61/89] fix: server crash using GraphQL due to missing @apollo/client peer dependency (#7787) --- package-lock.json | 34 ++++++++-------------------------- package.json | 2 +- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccc18f48..0ae5227c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,6 @@ "version": "3.4.17", "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.4.17.tgz", "integrity": "sha512-MDt2rwMX1GqodiVEKJqmDmAz8xr0qJmq5PdWeIt0yDaT4GOkKYWZiWkyfhfv3raTk8PyJvbsNG9q2CqmUrlGfg==", - "dev": true, "requires": { "@graphql-typed-document-node/core": "^3.0.0", "@wry/context": "^0.6.0", @@ -34,7 +33,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.2.tgz", "integrity": "sha512-oVMxbUXL48EV/C0/M7gLVsoK6qRHPS85x8zECofEZOVvxGmIPLA9o5Z27cc2PoAyZz1S2VoM2A7FLAnpfGlneA==", - "dev": true, "requires": { "tslib": "^2.3.0" } @@ -43,7 +41,6 @@ "version": "0.9.3", "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.9.3.tgz", "integrity": "sha512-HinBlTbFslQI0OHP07JLsSXPibSegec6r9ai5xxq/qHYCsIQbzpymLpDhAUsnXcSrDEcd0L62L8vsOEdzM0qlA==", - "dev": true, "requires": { "tslib": "^2.1.0" } @@ -51,14 +48,12 @@ "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "zen-observable-ts": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", - "dev": true, "requires": { "@types/zen-observable": "0.8.3", "zen-observable": "0.8.15" @@ -1467,8 +1462,7 @@ "@graphql-typed-document-node/core": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.1.1.tgz", - "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==", - "dev": true + "integrity": "sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==" }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -2690,8 +2684,7 @@ "@types/zen-observable": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", - "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==", - "dev": true + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" }, "@typescript-eslint/types": { "version": "4.31.0", @@ -2771,7 +2764,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.6.1.tgz", "integrity": "sha512-LOmVnY1iTU2D8tv4Xf6MVMZZ+juIJ87Kt/plMijjN20NMAXGmH4u8bS1t0uT74cZ5gwpocYueV58YwyI8y+GKw==", - "dev": true, "requires": { "tslib": "^2.3.0" }, @@ -2779,8 +2771,7 @@ "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -2803,7 +2794,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.3.1.tgz", "integrity": "sha512-WwB53ikYudh9pIorgxrkHKrQZcCqNM/Q/bDzZBffEaGUKGuHrRb3zZUT9Sh2qw9yogC7SsdRmQ1ER0pqvd3bfw==", - "dev": true, "requires": { "tslib": "^2.3.0" }, @@ -2811,8 +2801,7 @@ "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" } } }, @@ -7716,7 +7705,6 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dev": true, "requires": { "react-is": "^16.7.0" } @@ -8884,8 +8872,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.14.1", @@ -9819,7 +9806,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -13305,7 +13291,6 @@ "version": "0.16.1", "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.1.tgz", "integrity": "sha512-64i+Uw3otrndfq5kaoGNoY7pvOhSsjFEN4bdEFh80MWVk/dbgJfMv7VFDeCT8LxNAlEVhQmdVEbfE7X2nWNIIg==", - "dev": true, "requires": { "@wry/context": "^0.6.0", "@wry/trie": "^0.3.0" @@ -14129,7 +14114,6 @@ "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -14277,8 +14261,7 @@ "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "react-native-crypto-js": { "version": "1.0.0", @@ -15973,8 +15956,7 @@ "symbol-observable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==" }, "table": { "version": "5.4.6", diff --git a/package.json b/package.json index 0abd1e1b..b544d4ea 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "dependencies": { "@apollographql/graphql-playground-html": "1.6.29", "@graphql-tools/links": "8.2.1", + "@apollo/client": "3.4.17", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", @@ -62,7 +63,6 @@ }, "devDependencies": { "@actions/core": "1.2.6", - "@apollo/client": "3.4.17", "@babel/cli": "7.10.0", "@babel/core": "7.10.0", "@babel/plugin-proposal-object-rest-spread": "7.10.0", From 43cc97d99fa7346739f9e376a22afe3d95439b4c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 6 Feb 2022 23:10:52 +0000 Subject: [PATCH 62/89] chore(release): 5.0.0-alpha.23 [skip ci] # [5.0.0-alpha.23](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.22...5.0.0-alpha.23) (2022-02-06) ### Bug Fixes * server crash using GraphQL due to missing @apollo/client peer dependency ([#7787](https://github.com/parse-community/parse-server/issues/7787)) ([08089d6](https://github.com/parse-community/parse-server/commit/08089d6fcbb215412448ce7d92b21b9fe6c929f2)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 524c2cb9..531ed30b 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.23](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.22...5.0.0-alpha.23) (2022-02-06) + + +### Bug Fixes + +* server crash using GraphQL due to missing @apollo/client peer dependency ([#7787](https://github.com/parse-community/parse-server/issues/7787)) ([08089d6](https://github.com/parse-community/parse-server/commit/08089d6fcbb215412448ce7d92b21b9fe6c929f2)) + # [5.0.0-alpha.22](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.21...5.0.0-alpha.22) (2022-02-06) diff --git a/package-lock.json b/package-lock.json index 0ae5227c..19b210fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.22", + "version": "5.0.0-alpha.23", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b544d4ea..3f7832f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.22", + "version": "5.0.0-alpha.23", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From c6b20320399f6467f09195c3c839493dc72fd603 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Tue, 8 Feb 2022 12:02:45 +0200 Subject: [PATCH 63/89] refactor: upgrade @apollo/client from 3.4.17 to 3.5.7 (#7797) --- package-lock.json | 36 +++++++++++++++--------------------- package.json | 2 +- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19b210fc..f75a7ed4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,9 @@ "dev": true }, "@apollo/client": { - "version": "3.4.17", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.4.17.tgz", - "integrity": "sha512-MDt2rwMX1GqodiVEKJqmDmAz8xr0qJmq5PdWeIt0yDaT4GOkKYWZiWkyfhfv3raTk8PyJvbsNG9q2CqmUrlGfg==", + "version": "3.5.7", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.7.tgz", + "integrity": "sha512-HSLqTGp3sp/PVIWYLLr5v3fjQSr6Fxg6Z5RQj5Q9ALyseIVudD8GZk1jHplaUblTFMBueXGw3Z6DXObuVAr3tw==", "requires": { "@graphql-typed-document-node/core": "^3.0.0", "@wry/context": "^0.6.0", @@ -24,9 +24,9 @@ "optimism": "^0.16.1", "prop-types": "^15.7.2", "symbol-observable": "^4.0.0", - "ts-invariant": "^0.9.0", + "ts-invariant": "^0.9.4", "tslib": "^2.3.0", - "zen-observable-ts": "~1.1.0" + "zen-observable-ts": "^1.2.0" }, "dependencies": { "@wry/equality": { @@ -38,9 +38,9 @@ } }, "ts-invariant": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.9.3.tgz", - "integrity": "sha512-HinBlTbFslQI0OHP07JLsSXPibSegec6r9ai5xxq/qHYCsIQbzpymLpDhAUsnXcSrDEcd0L62L8vsOEdzM0qlA==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.9.4.tgz", + "integrity": "sha512-63jtX/ZSwnUNi/WhXjnK8kz4cHHpYS60AnmA6ixz17l7E12a5puCWFlNpkne5Rl0J8TBPVHpGjsj4fxs8ObVLQ==", "requires": { "tslib": "^2.1.0" } @@ -51,11 +51,10 @@ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, "zen-observable-ts": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", - "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.3.tgz", + "integrity": "sha512-hc/TGiPkAWpByykMwDcem3SdUgA4We+0Qb36bItSuJC9xD0XVBZoFHYoadAomDSNf64CG8Ydj0Qb8Od8BUWz5g==", "requires": { - "@types/zen-observable": "0.8.3", "zen-observable": "0.8.15" } } @@ -2681,11 +2680,6 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, - "@types/zen-observable": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", - "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" - }, "@typescript-eslint/types": { "version": "4.31.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.0.tgz", @@ -14111,13 +14105,13 @@ "dev": true }, "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "react-is": "^16.13.1" } }, "proto-list": { diff --git a/package.json b/package.json index 3f7832f7..41a19834 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@apollographql/graphql-playground-html": "1.6.29", "@graphql-tools/links": "8.2.1", - "@apollo/client": "3.4.17", + "@apollo/client": "3.5.7", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", From fc9d77f1d45c9c81c40faf14c4e33db9b685cc9d Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 9 Feb 2022 20:07:53 +0200 Subject: [PATCH 64/89] refactor: upgrade jwks-rsa from 1.12.3 to 2.0.5 (#7800) --- package-lock.json | 80 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index f75a7ed4..aff87885 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1819,6 +1819,11 @@ "@octokit/openapi-types": "^11.2.0" } }, + "@panva/asn1.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@panva/asn1.js/-/asn1.js-1.0.0.tgz", + "integrity": "sha512-UdkG3mLEqXgnlKsWanWcgb6dOjUzJ+XC5f+aWw30qrtjxeNUSfKX1cd5FBzOaXQumoe9nIqeZUvrRJS03HCCtw==" + }, "@parse/fs-files-adapter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.1.tgz", @@ -2392,7 +2397,8 @@ "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true }, "@types/accepts": { "version": "1.3.5", @@ -2839,6 +2845,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "requires": { "debug": "4" }, @@ -2847,6 +2854,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -2854,7 +2862,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -3480,14 +3489,6 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "requires": { - "follow-redirects": "^1.14.0" - } - }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -7784,6 +7785,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, "requires": { "@tootallnate/once": "1", "agent-base": "6", @@ -7794,6 +7796,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -7801,7 +7804,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -7819,6 +7823,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, "requires": { "agent-base": "6", "debug": "4" @@ -7828,6 +7833,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -7835,7 +7841,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -8863,6 +8870,14 @@ } } }, + "jose": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz", + "integrity": "sha512-BAiDNeDKTMgk4tvD0BbxJ8xHEHBZgpeRZ1zGPPsitSyMgjoMWiLGYAE7H7NpP5h0lPppQajQs871E8NHUrzVPA==", + "requires": { + "@panva/asn1.js": "^1.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -9065,41 +9080,29 @@ } }, "jwks-rsa": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-1.12.3.tgz", - "integrity": "sha512-cFipFDeYYaO9FhhYJcZWX/IyZgc0+g316rcHnDpT2dNRNIE/lMOmWKKqp09TkJoYlNFzrEVODsR4GgXJMgWhnA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jwks-rsa/-/jwks-rsa-2.0.5.tgz", + "integrity": "sha512-fliHfsiBRzEU0nXzSvwnh0hynzGB0WihF+CinKbSRlaqRxbqqKf2xbBPgwc8mzf18/WgwlG8e5eTpfSTBcU4DQ==", "requires": { "@types/express-jwt": "0.0.42", - "axios": "^0.21.1", - "debug": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "jsonwebtoken": "^8.5.1", + "debug": "^4.3.2", + "jose": "^2.0.5", "limiter": "^1.1.5", - "lru-memoizer": "^2.1.2", - "ms": "^2.1.2", - "proxy-from-env": "^1.1.0" + "lru-memoizer": "^2.1.4" }, "dependencies": { "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, @@ -14129,11 +14132,6 @@ "ipaddr.js": "1.9.1" } }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "ps-node": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ps-node/-/ps-node-0.1.6.tgz", diff --git a/package.json b/package.json index 41a19834..7309a607 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "graphql-upload": "11.0.0", "intersect": "1.0.1", "jsonwebtoken": "8.5.1", - "jwks-rsa": "1.12.3", + "jwks-rsa": "2.0.5", "ldapjs": "2.3.1", "lodash": "4.17.21", "lru-cache": "5.1.1", From 70088a95a78393da2a4ac68be81e63107747626a Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 10 Feb 2022 13:10:14 +0200 Subject: [PATCH 65/89] fix: security upgrade follow-redirects from 1.14.7 to 1.14.8 (#7801) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index aff87885..d32b3e3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7031,9 +7031,9 @@ "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" }, "follow-redirects": { - "version": "1.14.7", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", - "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==" }, "for-each": { "version": "0.3.3", diff --git a/package.json b/package.json index 7309a607..362b4b5b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "cors": "2.8.5", "deepcopy": "2.1.0", "express": "4.17.2", - "follow-redirects": "1.14.7", + "follow-redirects": "1.14.8", "graphql": "15.7.1", "graphql-list-fields": "2.0.2", "graphql-relay": "0.7.0", From d678a43696bd4c59fbc625097dcfbeb8d619f564 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 10 Feb 2022 11:11:17 +0000 Subject: [PATCH 66/89] chore(release): 5.0.0-alpha.24 [skip ci] # [5.0.0-alpha.24](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.23...5.0.0-alpha.24) (2022-02-10) ### Bug Fixes * security upgrade follow-redirects from 1.14.7 to 1.14.8 ([#7801](https://github.com/parse-community/parse-server/issues/7801)) ([70088a9](https://github.com/parse-community/parse-server/commit/70088a95a78393da2a4ac68be81e63107747626a)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 531ed30b..802392c5 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.24](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.23...5.0.0-alpha.24) (2022-02-10) + + +### Bug Fixes + +* security upgrade follow-redirects from 1.14.7 to 1.14.8 ([#7801](https://github.com/parse-community/parse-server/issues/7801)) ([70088a9](https://github.com/parse-community/parse-server/commit/70088a95a78393da2a4ac68be81e63107747626a)) + # [5.0.0-alpha.23](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.22...5.0.0-alpha.23) (2022-02-06) diff --git a/package-lock.json b/package-lock.json index d32b3e3f..64ef8634 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.23", + "version": "5.0.0-alpha.24", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 362b4b5b..d2eb1c3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.23", + "version": "5.0.0-alpha.24", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 82c3015dc09071d555b85e1c08b7eecb68fea1c9 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 13 Feb 2022 12:14:57 +0200 Subject: [PATCH 67/89] refactor: upgrade @parse/push-adapter from 3.4.1 to 4.1.0 (#7810) --- package-lock.json | 22 +++++++++++----------- package.json | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 64ef8634..e65b0502 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1836,9 +1836,9 @@ "dev": true }, "@parse/node-apn": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-4.1.1.tgz", - "integrity": "sha512-stWlQE95w5T0vkVYscoq/S3eXPQ1qzdQbKKQ8GAdw4CSNxRWLWgOH50byUR30thnQ93RshLCH5ROkvXMqzzLtw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.0.tgz", + "integrity": "sha512-WT3iVwr1Y/Jf4nq4RGNwBdLwm3gTodsb+g3IY98MPSJ7LCNf+R81Nj/nQO5r/twJfN1v5B8cAgfvPGs2rPelvg==", "requires": { "debug": "4.3.2", "jsonwebtoken": "8.5.1", @@ -1872,11 +1872,11 @@ } }, "@parse/push-adapter": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-3.4.1.tgz", - "integrity": "sha512-iev69kbwhXbez5nfEwB2GkCWBLUmRlImQTmHPpLnHBJfATYKyXf/H41WQhBPuwwScZBVp9ABsIsjjKy8iKg3fw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.0.tgz", + "integrity": "sha512-8SOU4zgIr3+wn6Hbge4X/zAYAcJR7puJ3aY2ri+8fqMARgBria4JkIeAyKaTG/mUMHw6Qy5DpYYRe0LjImjZNw==", "requires": { - "@parse/node-apn": "4.1.1", + "@parse/node-apn": "5.1.0", "@parse/node-gcm": "1.0.2", "npmlog": "4.1.2", "parse": "3.3.0" @@ -16769,11 +16769,11 @@ "dev": true }, "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", "requires": { - "string-width": "^1.0.2 || 2" + "string-width": "^1.0.2 || 2 || 3 || 4" } }, "winston": { diff --git a/package.json b/package.json index d2eb1c3a..8c7868f6 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", - "@parse/push-adapter": "3.4.1", + "@parse/push-adapter": "4.1.0", "apollo-server-express": "2.25.2", "bcryptjs": "2.4.3", "body-parser": "1.19.1", From b6a20d9e9f0b87655a397cf089c13867ff472d57 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 14 Feb 2022 11:13:35 +0200 Subject: [PATCH 68/89] refactor: upgrade winston from 3.3.3 to 3.4.0 (#7812) --- package-lock.json | 88 +++++++++++++++++++++++++++++------------------ package.json | 2 +- 2 files changed, 56 insertions(+), 34 deletions(-) diff --git a/package-lock.json b/package-lock.json index e65b0502..63389fdc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1172,10 +1172,15 @@ "to-fast-properties": "^2.0.0" } }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" + }, "@dabh/diagnostics": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", - "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "requires": { "colorspace": "1.1.x", "enabled": "2.0.x", @@ -3444,7 +3449,8 @@ "async": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", - "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==" + "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==", + "dev": true }, "async-each": { "version": "1.0.3", @@ -4495,12 +4501,12 @@ } }, "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" + "color-convert": "^1.9.3", + "color-string": "^1.6.0" } }, "color-convert": { @@ -4517,9 +4523,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", + "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -4534,14 +4540,15 @@ "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true }, "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", "requires": { - "color": "3.0.x", + "color": "^3.1.3", "text-hex": "1.0.x" } }, @@ -6685,11 +6692,6 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fast-safe-stringify": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", - "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==" - }, "fastq": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", @@ -9771,14 +9773,14 @@ } }, "logform": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", - "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz", + "integrity": "sha512-CPSJw4ftjf517EhXZGGvTHHkYobo7ZCc0kvwUoOYcjfR2UVrI66RHj8MCrfAdEitdmFqbu2BYdYs8FHHZSb6iw==", "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", + "@colors/colors": "1.5.0", "fecha": "^4.2.0", "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" }, "dependencies": { @@ -14764,6 +14766,11 @@ "ret": "~0.1.10" } }, + "safe-stable-stringify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz", + "integrity": "sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==" + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -16777,21 +16784,26 @@ } }, "winston": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", - "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.4.0.tgz", + "integrity": "sha512-FqilVj+5HKwCfIHQzMxrrd5tBIH10JTS3koFGbLVWBODjiIYq7zir08rFyBT4rrTYG/eaTqDcfSIbcjSM78YSw==", "requires": { "@dabh/diagnostics": "^2.0.2", - "async": "^3.1.0", + "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.2.0", + "logform": "^2.3.2", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.4.0" + "winston-transport": "^4.4.2" }, "dependencies": { + "async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -16801,6 +16813,16 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } + }, + "winston-transport": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", + "requires": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + } } } }, diff --git a/package.json b/package.json index 8c7868f6..dc845d04 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "subscriptions-transport-ws": "0.11.0", "tv4": "1.3.0", "uuid": "8.3.2", - "winston": "3.3.3", + "winston": "3.4.0", "winston-daily-rotate-file": "4.5.5", "ws": "8.2.3" }, From 7a30d7c885975768663f674bc0245c21f7391aa7 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Tue, 15 Feb 2022 13:42:13 +0200 Subject: [PATCH 69/89] refactor: upgrade lru-cache from 5.1.1 to 6.0.0 (#7813) --- package-lock.json | 15 ++++----------- package.json | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 63389fdc..7dde7b8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9824,18 +9824,11 @@ "dev": true }, "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "requires": { - "yallist": "^3.0.2" - }, - "dependencies": { - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - } + "yallist": "^4.0.0" } }, "lru-memoizer": { diff --git a/package.json b/package.json index dc845d04..e248eb63 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "jwks-rsa": "2.0.5", "ldapjs": "2.3.1", "lodash": "4.17.21", - "lru-cache": "5.1.1", + "lru-cache": "6.0.0", "mime": "3.0.0", "mongodb": "4.3.1", "mustache": "4.2.0", From 8cece4a2a8daf1f5b4b2d8be456d3051cf6317c3 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Thu, 17 Feb 2022 00:48:05 +0200 Subject: [PATCH 70/89] refactor: upgrade @apollo/client from 3.5.7 to 3.5.8 (#7814) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7dde7b8a..ae36a9f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,9 @@ "dev": true }, "@apollo/client": { - "version": "3.5.7", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.7.tgz", - "integrity": "sha512-HSLqTGp3sp/PVIWYLLr5v3fjQSr6Fxg6Z5RQj5Q9ALyseIVudD8GZk1jHplaUblTFMBueXGw3Z6DXObuVAr3tw==", + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.8.tgz", + "integrity": "sha512-MAm05+I1ullr64VLpZwon/ISnkMuNLf6vDqgo9wiMhHYBGT4yOAbAIseRdjCHZwfSx/7AUuBgaTNOssZPIr6FQ==", "requires": { "@graphql-typed-document-node/core": "^3.0.0", "@wry/context": "^0.6.0", diff --git a/package.json b/package.json index e248eb63..e6013636 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@apollographql/graphql-playground-html": "1.6.29", "@graphql-tools/links": "8.2.1", - "@apollo/client": "3.5.7", + "@apollo/client": "3.5.8", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", From c7012012aa2f2db78795e9ddd4a5386cd9474f1f Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Fri, 18 Feb 2022 22:44:52 +0200 Subject: [PATCH 71/89] refactor: upgrade winston-daily-rotate-file from 4.5.5 to 4.6.0 (#7816) --- package-lock.json | 39 ++++++++++++++++++++++++++------------- package.json | 2 +- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index ae36a9f1..75e974b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6809,11 +6809,11 @@ } }, "file-stream-rotator": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.5.7.tgz", - "integrity": "sha512-VYb3HZ/GiAGUCrfeakO8Mp54YGswNUHvL7P09WQcXAJNSj3iQ5QraYSp3cIn1MUyw6uzfgN/EFOarCNa4JvUHQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", + "integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==", "requires": { - "moment": "^2.11.2" + "moment": "^2.29.1" } }, "file-type": { @@ -16820,23 +16820,36 @@ } }, "winston-daily-rotate-file": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.5.5.tgz", - "integrity": "sha512-ds0WahIjiDhKCiMXmY799pDBW+58ByqIBtUcsqr4oDoXrAI3Zn+hbgFdUxzMfqA93OG0mPLYVMiotqTgE/WeWQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.6.0.tgz", + "integrity": "sha512-mvpFb1LYmTvh/vz0dIS/aDCwEm0cvDa8D/tE4xWwdUYolD250wf+n0y1PZ2xr7fbvTLF/PQYqXtFIFrmog03Ow==", "requires": { - "file-stream-rotator": "^0.5.7", + "file-stream-rotator": "^0.6.1", "object-hash": "^2.0.1", "triple-beam": "^1.3.0", "winston-transport": "^4.4.0" } }, "winston-transport": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", - "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", "requires": { - "readable-stream": "^2.3.7", - "triple-beam": "^1.2.0" + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, "word-wrap": { diff --git a/package.json b/package.json index e6013636..af422488 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "tv4": "1.3.0", "uuid": "8.3.2", "winston": "3.4.0", - "winston-daily-rotate-file": "4.5.5", + "winston-daily-rotate-file": "4.6.0", "ws": "8.2.3" }, "devDependencies": { From 2a6cec173ed68c8c0d4a9f22b3940db98aa07664 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 20 Feb 2022 19:26:13 +0200 Subject: [PATCH 72/89] refactor: upgrade winston from 3.4.0 to 3.5.0 (#7817) --- package-lock.json | 17 ++++------------- package.json | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 75e974b7..cea8f637 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16777,9 +16777,9 @@ } }, "winston": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.4.0.tgz", - "integrity": "sha512-FqilVj+5HKwCfIHQzMxrrd5tBIH10JTS3koFGbLVWBODjiIYq7zir08rFyBT4rrTYG/eaTqDcfSIbcjSM78YSw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.5.0.tgz", + "integrity": "sha512-OQMbmLsIdVHvm2hSurrYZs+iZNIImXneYJ6pX7LseSMEq20HdTETXiNnNX3FDwN4LB/xDRZLF6JYOY+AI112Kw==", "requires": { "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", @@ -16787,6 +16787,7 @@ "logform": "^2.3.2", "one-time": "^1.0.0", "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.4.2" @@ -16806,16 +16807,6 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } - }, - "winston-transport": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", - "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", - "requires": { - "logform": "^2.3.2", - "readable-stream": "^3.6.0", - "triple-beam": "^1.3.0" - } } } }, diff --git a/package.json b/package.json index af422488..9ef5f517 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "subscriptions-transport-ws": "0.11.0", "tv4": "1.3.0", "uuid": "8.3.2", - "winston": "3.4.0", + "winston": "3.5.0", "winston-daily-rotate-file": "4.6.0", "ws": "8.2.3" }, From 4af253d1f8654a6f57b5137ad310cdacadc922cc Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Wed, 23 Feb 2022 02:55:33 +0200 Subject: [PATCH 73/89] fix: upgrade winston from 3.5.0 to 3.5.1 (#7820) --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index cea8f637..6cdd789d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16777,9 +16777,9 @@ } }, "winston": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.5.0.tgz", - "integrity": "sha512-OQMbmLsIdVHvm2hSurrYZs+iZNIImXneYJ6pX7LseSMEq20HdTETXiNnNX3FDwN4LB/xDRZLF6JYOY+AI112Kw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.5.1.tgz", + "integrity": "sha512-tbRtVy+vsSSCLcZq/8nXZaOie/S2tPXPFt4be/Q3vI/WtYwm7rrwidxVw2GRa38FIXcJ1kUM6MOZ9Jmnk3F3UA==", "requires": { "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", diff --git a/package.json b/package.json index 9ef5f517..98b67ea4 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "subscriptions-transport-ws": "0.11.0", "tv4": "1.3.0", "uuid": "8.3.2", - "winston": "3.5.0", + "winston": "3.5.1", "winston-daily-rotate-file": "4.6.0", "ws": "8.2.3" }, From 9806912045ae651fce66db38b3b6f5e798e14139 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 23 Feb 2022 00:56:33 +0000 Subject: [PATCH 74/89] chore(release): 5.0.0-alpha.25 [skip ci] # [5.0.0-alpha.25](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.24...5.0.0-alpha.25) (2022-02-23) ### Bug Fixes * upgrade winston from 3.5.0 to 3.5.1 ([#7820](https://github.com/parse-community/parse-server/issues/7820)) ([4af253d](https://github.com/parse-community/parse-server/commit/4af253d1f8654a6f57b5137ad310cdacadc922cc)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 802392c5..5c684b36 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.25](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.24...5.0.0-alpha.25) (2022-02-23) + + +### Bug Fixes + +* upgrade winston from 3.5.0 to 3.5.1 ([#7820](https://github.com/parse-community/parse-server/issues/7820)) ([4af253d](https://github.com/parse-community/parse-server/commit/4af253d1f8654a6f57b5137ad310cdacadc922cc)) + # [5.0.0-alpha.24](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.23...5.0.0-alpha.24) (2022-02-10) diff --git a/package-lock.json b/package-lock.json index 6cdd789d..34c0c9e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.24", + "version": "5.0.0-alpha.25", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 98b67ea4..38809766 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.24", + "version": "5.0.0-alpha.25", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 5ca228882332b65f3ac05407e6e4da1ee3ef3749 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Fri, 25 Feb 2022 18:56:29 +0200 Subject: [PATCH 75/89] fix: package.json & package-lock.json to reduce vulnerabilities (#7823) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-NODEFETCH-2342118 --- package-lock.json | 101 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 51 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 34c0c9e2..abce4b42 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1198,20 +1198,20 @@ } }, "@graphql-tools/batch-execute": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.3.1.tgz", - "integrity": "sha512-63kHY8ZdoO5FoeDXYHnAak1R3ysMViMPwWC2XUblFckuVLMUPmB2ONje8rjr2CvzWBHAW8c1Zsex+U3xhKtGIA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.3.2.tgz", + "integrity": "sha512-ICWqM+MvEkIPHm18Q0cmkvm134zeQMomBKmTRxyxMNhL/ouz6Nqld52/brSlaHnzA3fczupeRJzZ0YatruGBcQ==", "requires": { - "@graphql-tools/utils": "^8.5.1", + "@graphql-tools/utils": "^8.6.2", "dataloader": "2.0.0", "tslib": "~2.3.0", "value-or-promise": "1.0.11" }, "dependencies": { "@graphql-tools/utils": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.3.tgz", - "integrity": "sha512-HDNGWFVa8QQkoQB0H1lftvaO1X5xUaUDk1zr1qDe0xN1NL0E/CrQdJ5UKLqOvH4hkqVUPxQsyOoAZFkaH6rLHg==", + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.2.tgz", + "integrity": "sha512-x1DG0cJgpJtImUlNE780B/dfp8pxvVxOD6UeykFH5rHes26S4kGokbgU8F1IgrJ1vAPm/OVBHtd2kicTsPfwdA==", "requires": { "tslib": "~2.3.0" } @@ -1242,63 +1242,64 @@ } }, "@graphql-tools/links": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.1.tgz", - "integrity": "sha512-J0igz42eKh/RQxDZPdEE4YiztY3zWTBcsn/bUtJp52XKNj0EIO0fR6WLEocT6uxgWCNnWYPOQUaf7bEgeW44Vg==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.2.tgz", + "integrity": "sha512-lWyRvG4KqVj/3dpuQzZN34TXs9+5ETaT1MxhPHe6LIF/DdNQk4Q4Y7VeET/fZ8ZhbzgweMy0AA+ZkrS2HxBcgw==", "requires": { - "@graphql-tools/delegate": "^8.4.1", - "@graphql-tools/utils": "^8.5.1", - "apollo-upload-client": "16.0.0", - "cross-fetch": "3.1.4", - "form-data": "4.0.0", + "@graphql-tools/delegate": "^8.5.1", + "@graphql-tools/utils": "^8.6.2", + "apollo-upload-client": "17.0.0", + "form-data": "^4.0.0", + "node-fetch": "^2.6.5", "tslib": "~2.3.0" }, "dependencies": { "@graphql-tools/delegate": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.4.2.tgz", - "integrity": "sha512-CjggOhiL4WtyG2I3kux+1/p8lQxSFHBj0gwa0NxnQ6Vsnpw7Ig5VP1ovPnitFuBv2k4QdC37Nj2xv2n7DRn8fw==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.5.1.tgz", + "integrity": "sha512-/YPmVxitt57F8sH50pnfXASzOOjEfaUDkX48eF5q6f16+JBncej2zeu+Zm2c68q8MbIxhPlEGfpd0QZeqTvAxw==", "requires": { - "@graphql-tools/batch-execute": "^8.3.1", - "@graphql-tools/schema": "^8.3.1", - "@graphql-tools/utils": "^8.5.3", + "@graphql-tools/batch-execute": "^8.3.2", + "@graphql-tools/schema": "^8.3.2", + "@graphql-tools/utils": "^8.6.2", "dataloader": "2.0.0", + "graphql-executor": "0.0.18", "tslib": "~2.3.0", "value-or-promise": "1.0.11" } }, "@graphql-tools/merge": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.1.tgz", - "integrity": "sha512-Q240kcUszhXiAYudjuJgNuLgy9CryDP3wp83NOZQezfA6h3ByYKU7xI6DiKrdjyVaGpYN3ppUmdj0uf5GaXzMA==", + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.3.tgz", + "integrity": "sha512-XCSmL6/Xg8259OTWNp69B57CPWiVL69kB7pposFrufG/zaAlI9BS68dgzrxmmSqZV5ZHU4r/6Tbf6fwnEJGiSw==", "requires": { - "@graphql-tools/utils": "^8.5.1", + "@graphql-tools/utils": "^8.6.2", "tslib": "~2.3.0" } }, "@graphql-tools/schema": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.1.tgz", - "integrity": "sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.2.tgz", + "integrity": "sha512-77feSmIuHdoxMXRbRyxE8rEziKesd/AcqKV6fmxe7Zt+PgIQITxNDew2XJJg7qFTMNM43W77Ia6njUSBxNOkwg==", "requires": { - "@graphql-tools/merge": "^8.2.1", - "@graphql-tools/utils": "^8.5.1", + "@graphql-tools/merge": "^8.2.3", + "@graphql-tools/utils": "^8.6.2", "tslib": "~2.3.0", "value-or-promise": "1.0.11" } }, "@graphql-tools/utils": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.5.3.tgz", - "integrity": "sha512-HDNGWFVa8QQkoQB0H1lftvaO1X5xUaUDk1zr1qDe0xN1NL0E/CrQdJ5UKLqOvH4hkqVUPxQsyOoAZFkaH6rLHg==", + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.2.tgz", + "integrity": "sha512-x1DG0cJgpJtImUlNE780B/dfp8pxvVxOD6UeykFH5rHes26S4kGokbgU8F1IgrJ1vAPm/OVBHtd2kicTsPfwdA==", "requires": { "tslib": "~2.3.0" } }, "apollo-upload-client": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-16.0.0.tgz", - "integrity": "sha512-aLhYucyA0T8aBEQ5g+p13qnR9RUyL8xqb8FSZ7e/Kw2KUOsotLUlFluLobqaE7JSUFwc6sKfXIcwB7y4yEjbZg==", + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/apollo-upload-client/-/apollo-upload-client-17.0.0.tgz", + "integrity": "sha512-pue33bWVbdlXAGFPkgz53TTmxVMrKeQr0mdRcftNY+PoHIdbGZD0hoaXHvO6OePJAkFz7OiCFUf98p1G/9+Ykw==", "requires": { "extract-files": "^11.0.0" } @@ -1313,6 +1314,14 @@ "mime-types": "^2.1.12" } }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", @@ -4838,21 +4847,6 @@ "cross-spawn": "^7.0.1" } }, - "cross-fetch": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz", - "integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==", - "requires": { - "node-fetch": "2.6.1" - }, - "dependencies": { - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" - } - } - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -7453,6 +7447,11 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.7.1.tgz", "integrity": "sha512-x34S6gC0/peBZnlK60zCJox/d45A7p6At9oN9EPA3qhoIAlR4LNZmXRLkICBckwwTMJzVdA8cx3QIQZMOl606A==" }, + "graphql-executor": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.18.tgz", + "integrity": "sha512-upUSl7tfZCZ5dWG1XkOvpG70Yk3duZKcCoi/uJso4WxJVT6KIrcK4nZ4+2X/hzx46pL8wAukgYHY6iNmocRN+g==" + }, "graphql-extensions": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.15.0.tgz", diff --git a/package.json b/package.json index 38809766..daf95b9d 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "license": "BSD-3-Clause", "dependencies": { "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/links": "8.2.1", + "@graphql-tools/links": "8.2.2", "@apollo/client": "3.5.8", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", From ad5d17953ba0e8378bdc421ef3769bb3469d60ad Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 25 Feb 2022 16:57:59 +0000 Subject: [PATCH 76/89] chore(release): 5.0.0-alpha.26 [skip ci] # [5.0.0-alpha.26](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.25...5.0.0-alpha.26) (2022-02-25) ### Bug Fixes * package.json & package-lock.json to reduce vulnerabilities ([#7823](https://github.com/parse-community/parse-server/issues/7823)) ([5ca2288](https://github.com/parse-community/parse-server/commit/5ca228882332b65f3ac05407e6e4da1ee3ef3749)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 5c684b36..b9f98314 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.26](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.25...5.0.0-alpha.26) (2022-02-25) + + +### Bug Fixes + +* package.json & package-lock.json to reduce vulnerabilities ([#7823](https://github.com/parse-community/parse-server/issues/7823)) ([5ca2288](https://github.com/parse-community/parse-server/commit/5ca228882332b65f3ac05407e6e4da1ee3ef3749)) + # [5.0.0-alpha.25](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.24...5.0.0-alpha.25) (2022-02-23) diff --git a/package-lock.json b/package-lock.json index abce4b42..eb1d5995 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.25", + "version": "5.0.0-alpha.26", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index daf95b9d..8def2836 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.25", + "version": "5.0.0-alpha.26", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 8a126fc1a23e8534c884cab0a846335754b4d6d6 Mon Sep 17 00:00:00 2001 From: Antonio Davi Macedo Coelho de Castro Date: Fri, 25 Feb 2022 15:01:15 -0800 Subject: [PATCH 77/89] Update node engine to 2.22.0 (#7827) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8def2836..bae61c61 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "madge:circular": "node_modules/.bin/madge ./src --circular" }, "engines": { - "node": ">=12.20.0 <17" + "node": ">=12.22.0 <17" }, "bin": { "parse-server": "bin/parse-server" From f235412c1b6c2b173b7531f285429ea7214b56a2 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sat, 12 Mar 2022 14:13:38 +0100 Subject: [PATCH 78/89] revert: update node engine to 2.22.0 (#7827) This reverts commit 8a126fc1a23e8534c884cab0a846335754b4d6d6. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bae61c61..8def2836 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "madge:circular": "node_modules/.bin/madge ./src --circular" }, "engines": { - "node": ">=12.22.0 <17" + "node": ">=12.20.0 <17" }, "bin": { "parse-server": "bin/parse-server" From 6bc021ee1430b843deb9b8429b8b51fd697fc3d6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 12 Mar 2022 13:14:36 +0000 Subject: [PATCH 79/89] chore(release): 5.0.0-alpha.27 [skip ci] # [5.0.0-alpha.27](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.26...5.0.0-alpha.27) (2022-03-12) ### Reverts * update node engine to 2.22.0 ([#7827](https://github.com/parse-community/parse-server/issues/7827)) ([f235412](https://github.com/parse-community/parse-server/commit/f235412c1b6c2b173b7531f285429ea7214b56a2)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index b9f98314..9aca837b 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.27](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.26...5.0.0-alpha.27) (2022-03-12) + + +### Reverts + +* update node engine to 2.22.0 ([#7827](https://github.com/parse-community/parse-server/issues/7827)) ([f235412](https://github.com/parse-community/parse-server/commit/f235412c1b6c2b173b7531f285429ea7214b56a2)) + # [5.0.0-alpha.26](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.25...5.0.0-alpha.26) (2022-02-25) diff --git a/package-lock.json b/package-lock.json index eb1d5995..702b206a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.26", + "version": "5.0.0-alpha.27", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8def2836..10739ee6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.26", + "version": "5.0.0-alpha.27", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 972b800ae4d8dc3eda81bc62789da4eb97ba8c23 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sat, 12 Mar 2022 14:30:59 +0100 Subject: [PATCH 80/89] docs: add revert commit instructions to CONTRIBUTING guide (#7845) --- CONTRIBUTING.md | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1605c47e..ddc99a81 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,6 +22,8 @@ - [Pull Request](#pull-request) - [Breaking Change](#breaking-change) - [Merging](#merging) + - [Breaking Change](#breaking-change-1) + - [Reverting](#reverting) - [Versioning](#versioning) - [Code of Conduct](#code-of-conduct) @@ -335,8 +337,13 @@ If a pull request contains a braking change, the description of the pull request The following guide is for anyone who merges a contributor pull request into the working branch, the working branch into a release branch, a release branch into another release branch, or any other direct commits such as hotfixes into release branches or the working branch. -- For changelog generation, only the commit message set when merging the pull request is relevant. The title and description of the GitHub pull request as authored by the contributor have no influence on the changelog generation. However, the title of the GitHub pull request should be used as the commit message. -- If the pull request contains a breaking change, the commit message must contain the phrase `BREAKING CHANGE`, capitalized and without any formatting, followed by a short description of the breaking change and ideally how the developer should address it, all in a single line. This line should contain more details focusing on the "breaking” aspect of the change and is intended to assist the developer in adapting. Keep it concise, as it will become part of the changelog entry, for example: +- A contributor pull request must be merged into the working branch using `Squash and Merge`, to create a single commit message that describes the change. +- A release branch or the default branch must be merged into another release branch using `Merge Commit`, to preserve each individual commit message that describes its respective change. +- For changelog generation, only the commit message set when merging the pull request is relevant. The title and description of the GitHub pull request as authored by the contributor have no influence on the changelog generation. However, the title of the GitHub pull request should be used as the commit message. See the following chapters for considerations in special scenarios, e.g. merging a breaking change or reverting a commit. + +### Breaking Change + +If the pull request contains a breaking change, the commit message must contain the phrase `BREAKING CHANGE`, capitalized and without any formatting, followed by a short description of the breaking change and ideally how the developer should address it, all in a single line. This line should contain more details focusing on the "breaking” aspect of the change and is intended to assist the developer in adapting. Keep it concise, as it will become part of the changelog entry, for example: ``` fix: remove handle from door @@ -344,8 +351,16 @@ The following guide is for anyone who merges a contributor pull request into the BREAKING CHANGE: You cannot open the door anymore by using a handle. See the [#migration guide](http://example.com) for more details. ``` Keep in mind that in a repository with release automation, merging such a commit message will trigger a release with a major version increment. -- A contributor pull request must be merged into the working branch using `Squash and Merge`, to create a single commit message that describes the change. -- A release branch or the default branch must be merged into another release branch using `Merge Commit`, to preserve each individual commit message that describes its respective change. + +### Reverting + +If the commit reverts a previous commit, use the prefix `revert:`, followed by the header of the reverted commit. In the body of the commit message add `This reverts commit .`, where the hash is the SHA of the commit being reverted. For example: + + ``` + revert: fix: remove handle from door + + This reverts commit 1234567890abcdef. + ``` ## Versioning From e569f402b1fd8648fb0d1523b71b2a03273902a5 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sat, 12 Mar 2022 14:47:23 +0100 Subject: [PATCH 81/89] fix: security vulnerability that allows remote code execution (GHSA-p6h4-93qp-jhcm) (#7844) --- .madgerc | 10 + resources/buildConfigDefinitions.js | 14 ++ spec/vulnerabilities.spec.js | 283 ++++++++++++++++++++++++++ src/Config.js | 12 +- src/Controllers/DatabaseController.js | 107 ++++++---- src/Controllers/index.js | 4 +- src/Options/Definitions.js | 18 ++ src/Options/docs.js | 1 + src/Options/index.js | 7 + src/RestWrite.js | 14 ++ src/Utils.js | 26 +++ 11 files changed, 450 insertions(+), 46 deletions(-) create mode 100644 .madgerc create mode 100644 spec/vulnerabilities.spec.js diff --git a/.madgerc b/.madgerc new file mode 100644 index 00000000..4b9aa24b --- /dev/null +++ b/.madgerc @@ -0,0 +1,10 @@ +{ + "detectiveOptions": { + "ts": { + "skipTypeImports": true + }, + "es6": { + "skipTypeImports": true + } + } +} diff --git a/resources/buildConfigDefinitions.js b/resources/buildConfigDefinitions.js index 52ff3ac7..670aafad 100644 --- a/resources/buildConfigDefinitions.js +++ b/resources/buildConfigDefinitions.js @@ -172,6 +172,20 @@ function parseDefaultValue(elt, value, t) { literalValue = t.arrayExpression(array.map((value) => { if (typeof value == 'string') { return t.stringLiteral(value); + } else if (typeof value == 'number') { + return t.numericLiteral(value); + } else if (typeof value == 'object') { + const object = parsers.objectParser(value); + const props = Object.entries(object).map(([k, v]) => { + if (typeof v == 'string') { + return t.objectProperty(t.identifier(k), t.stringLiteral(v)); + } else if (typeof v == 'number') { + return t.objectProperty(t.identifier(k), t.numericLiteral(v)); + } else if (typeof v == 'boolean') { + return t.objectProperty(t.identifier(k), t.booleanLiteral(v)); + } + }); + return t.objectExpression(props); } else { throw new Error('Unable to parse array'); } diff --git a/spec/vulnerabilities.spec.js b/spec/vulnerabilities.spec.js new file mode 100644 index 00000000..1255d643 --- /dev/null +++ b/spec/vulnerabilities.spec.js @@ -0,0 +1,283 @@ +const request = require('../lib/request'); + +describe('Vulnerabilities', () => { + describe('Object prototype pollution', () => { + it('denies object prototype to be polluted with keyword "constructor"', async () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const response = await request({ + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/PP', + body: JSON.stringify({ + obj: { + constructor: { + prototype: { + dummy: 0, + }, + }, + }, + }), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe('Prohibited keyword in request data: {"key":"constructor"}.'); + expect(Object.prototype.dummy).toBeUndefined(); + }); + + it('denies object prototype to be polluted with keypath string "constructor"', async () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const objResponse = await request({ + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/PP', + body: JSON.stringify({ + obj: {}, + }), + }).catch(e => e); + const pollResponse = await request({ + headers: headers, + method: 'PUT', + url: `http://localhost:8378/1/classes/PP/${objResponse.data.objectId}`, + body: JSON.stringify({ + 'obj.constructor.prototype.dummy': { + __op: 'Increment', + amount: 1, + }, + }), + }).catch(e => e); + expect(Object.prototype.dummy).toBeUndefined(); + expect(pollResponse.status).toBe(400); + const text = JSON.parse(pollResponse.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe('Prohibited keyword in request data: {"key":"constructor"}.'); + expect(Object.prototype.dummy).toBeUndefined(); + }); + + it('denies object prototype to be polluted with keyword "__proto__"', async () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const response = await request({ + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/PP', + body: JSON.stringify({ 'obj.__proto__.dummy': 0 }), + }).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe('Prohibited keyword in request data: {"key":"__proto__"}.'); + expect(Object.prototype.dummy).toBeUndefined(); + }); + }); + + describe('Request denylist', () => { + it('denies BSON type code data in write request by default', async () => { + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const params = { + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/RCE', + body: JSON.stringify({ + obj: { + _bsontype: 'Code', + code: 'delete Object.prototype.evalFunctions', + }, + }), + }; + const response = await request(params).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe( + 'Prohibited keyword in request data: {"key":"_bsontype","value":"Code"}.' + ); + }); + + it('allows BSON type code data in write request with custom denylist', async () => { + await reconfigureServer({ + requestKeywordDenylist: [], + }); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const params = { + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/RCE', + body: JSON.stringify({ + obj: { + _bsontype: 'Code', + code: 'delete Object.prototype.evalFunctions', + }, + }), + }; + const response = await request(params).catch(e => e); + expect(response.status).toBe(201); + const text = JSON.parse(response.text); + expect(text.objectId).toBeDefined(); + }); + + it('denies write request with custom denylist of key/value', async () => { + await reconfigureServer({ + requestKeywordDenylist: [{ key: 'a[K]ey', value: 'aValue[123]*' }], + }); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const params = { + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/RCE', + body: JSON.stringify({ + obj: { + aKey: 'aValue321', + code: 'delete Object.prototype.evalFunctions', + }, + }), + }; + const response = await request(params).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe( + 'Prohibited keyword in request data: {"key":"a[K]ey","value":"aValue[123]*"}.' + ); + }); + + it('denies write request with custom denylist of nested key/value', async () => { + await reconfigureServer({ + requestKeywordDenylist: [{ key: 'a[K]ey', value: 'aValue[123]*' }], + }); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const params = { + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/RCE', + body: JSON.stringify({ + obj: { + nested: { + aKey: 'aValue321', + code: 'delete Object.prototype.evalFunctions', + }, + }, + }), + }; + const response = await request(params).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe( + 'Prohibited keyword in request data: {"key":"a[K]ey","value":"aValue[123]*"}.' + ); + }); + + it('denies write request with custom denylist of key/value in array', async () => { + await reconfigureServer({ + requestKeywordDenylist: [{ key: 'a[K]ey', value: 'aValue[123]*' }], + }); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const params = { + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/RCE', + body: JSON.stringify({ + obj: [ + { + aKey: 'aValue321', + code: 'delete Object.prototype.evalFunctions', + }, + ], + }), + }; + const response = await request(params).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe( + 'Prohibited keyword in request data: {"key":"a[K]ey","value":"aValue[123]*"}.' + ); + }); + + it('denies write request with custom denylist of key', async () => { + await reconfigureServer({ + requestKeywordDenylist: [{ key: 'a[K]ey' }], + }); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const params = { + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/RCE', + body: JSON.stringify({ + obj: { + aKey: 'aValue321', + code: 'delete Object.prototype.evalFunctions', + }, + }), + }; + const response = await request(params).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe('Prohibited keyword in request data: {"key":"a[K]ey"}.'); + }); + + it('denies write request with custom denylist of value', async () => { + await reconfigureServer({ + requestKeywordDenylist: [{ value: 'aValue[123]*' }], + }); + const headers = { + 'Content-Type': 'application/json', + 'X-Parse-Application-Id': 'test', + 'X-Parse-REST-API-Key': 'rest', + }; + const params = { + headers: headers, + method: 'POST', + url: 'http://localhost:8378/1/classes/RCE', + body: JSON.stringify({ + obj: { + aKey: 'aValue321', + code: 'delete Object.prototype.evalFunctions', + }, + }), + }; + const response = await request(params).catch(e => e); + expect(response.status).toBe(400); + const text = JSON.parse(response.text); + expect(text.code).toBe(Parse.Error.INVALID_KEY_NAME); + expect(text.error).toBe('Prohibited keyword in request data: {"value":"aValue[123]*"}.'); + }); + }); +}); diff --git a/src/Config.js b/src/Config.js index 069b7e2a..04834d32 100644 --- a/src/Config.js +++ b/src/Config.js @@ -35,7 +35,7 @@ export class Config { config.applicationId = applicationId; Object.keys(cacheInfo).forEach(key => { if (key == 'databaseController') { - config.database = new DatabaseController(cacheInfo.databaseController.adapter); + config.database = new DatabaseController(cacheInfo.databaseController.adapter, config); } else { config[key] = cacheInfo[key]; } @@ -78,6 +78,7 @@ export class Config { security, enforcePrivateUsers, schema, + requestKeywordDenylist, }) { if (masterKey === readOnlyMasterKey) { throw new Error('masterKey and readOnlyMasterKey should be different'); @@ -116,6 +117,15 @@ export class Config { this.validateSecurityOptions(security); this.validateSchemaOptions(schema); this.validateEnforcePrivateUsers(enforcePrivateUsers); + this.validateRequestKeywordDenylist(requestKeywordDenylist); + } + + static validateRequestKeywordDenylist(requestKeywordDenylist) { + if (requestKeywordDenylist === undefined) { + requestKeywordDenylist = requestKeywordDenylist.default; + } else if (!Array.isArray(requestKeywordDenylist)) { + throw 'Parse Server option requestKeywordDenylist must be an array.'; + } } static validateEnforcePrivateUsers(enforcePrivateUsers) { diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index 2c313f83..f7322fc5 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -17,6 +17,7 @@ import MongoStorageAdapter from '../Adapters/Storage/Mongo/MongoStorageAdapter'; import PostgresStorageAdapter from '../Adapters/Storage/Postgres/PostgresStorageAdapter'; import SchemaCache from '../Adapters/Cache/SchemaCache'; import type { LoadSchemaOptions } from './types'; +import type { ParseServerOptions } from '../Options'; import type { QueryOptions, FullQueryOptions } from '../Adapters/Storage/StorageAdapter'; function addWriteACL(query, acl) { @@ -258,41 +259,6 @@ const isSpecialUpdateKey = key => { return specialKeysForUpdate.indexOf(key) >= 0; }; -function expandResultOnKeyPath(object, key, value) { - if (key.indexOf('.') < 0) { - object[key] = value[key]; - return object; - } - const path = key.split('.'); - const firstKey = path[0]; - const nextPath = path.slice(1).join('.'); - object[firstKey] = expandResultOnKeyPath(object[firstKey] || {}, nextPath, value[firstKey]); - delete object[key]; - return object; -} - -function sanitizeDatabaseResult(originalObject, result): Promise { - const response = {}; - if (!result) { - return Promise.resolve(response); - } - Object.keys(originalObject).forEach(key => { - const keyUpdate = originalObject[key]; - // determine if that was an op - if ( - keyUpdate && - typeof keyUpdate === 'object' && - keyUpdate.__op && - ['Add', 'AddUnique', 'Remove', 'Increment'].indexOf(keyUpdate.__op) > -1 - ) { - // only valid ops that produce an actionable result - // the op may have happend on a keypath - expandResultOnKeyPath(response, key, result); - } - }); - return Promise.resolve(response); -} - function joinTableName(className, key) { return `_Join:${key}:${className}`; } @@ -395,17 +361,18 @@ const relationSchema = { class DatabaseController { adapter: StorageAdapter; - idempotencyOptions: any; schemaCache: any; schemaPromise: ?Promise; _transactionalSession: ?any; + options: ParseServerOptions; + idempotencyOptions: any; - constructor(adapter: StorageAdapter, idempotencyOptions?: Object = {}) { + constructor(adapter: StorageAdapter, options: ParseServerOptions) { this.adapter = adapter; - this.idempotencyOptions = idempotencyOptions; - // We don't want a mutable this.schema, because then you could have - // one request that uses different schemas for different parts of - // it. Instead, use loadSchema to get a schema. + this.options = options || {}; + this.idempotencyOptions = this.options.idempotencyOptions || {}; + // Prevent mutable this.schema, otherwise one request could use + // multiple schemas, so instead use loadSchema to get a schema. this.schemaPromise = null; this._transactionalSession = null; } @@ -646,7 +613,7 @@ class DatabaseController { if (skipSanitization) { return Promise.resolve(result); } - return sanitizeDatabaseResult(originalUpdate, result); + return this._sanitizeDatabaseResult(originalUpdate, result); }); }); } @@ -873,7 +840,7 @@ class DatabaseController { object, relationUpdates ).then(() => { - return sanitizeDatabaseResult(originalObject, result.ops[0]); + return this._sanitizeDatabaseResult(originalObject, result.ops[0]); }); }); }); @@ -1782,6 +1749,60 @@ class DatabaseController { await this.adapter.updateSchemaWithIndexes(); } + _expandResultOnKeyPath(object: any, key: string, value: any): any { + if (key.indexOf('.') < 0) { + object[key] = value[key]; + return object; + } + const path = key.split('.'); + const firstKey = path[0]; + const nextPath = path.slice(1).join('.'); + + // Scan request data for denied keywords + if (this.options && this.options.requestKeywordDenylist) { + // Scan request data for denied keywords + for (const keyword of this.options.requestKeywordDenylist) { + const isMatch = (a, b) => (typeof a === 'string' && new RegExp(a).test(b)) || a === b; + if (isMatch(firstKey, keyword.key)) { + throw new Parse.Error( + Parse.Error.INVALID_KEY_NAME, + `Prohibited keyword in request data: ${JSON.stringify(keyword)}.` + ); + } + } + } + + object[firstKey] = this._expandResultOnKeyPath( + object[firstKey] || {}, + nextPath, + value[firstKey] + ); + delete object[key]; + return object; + } + + _sanitizeDatabaseResult(originalObject: any, result: any): Promise { + const response = {}; + if (!result) { + return Promise.resolve(response); + } + Object.keys(originalObject).forEach(key => { + const keyUpdate = originalObject[key]; + // determine if that was an op + if ( + keyUpdate && + typeof keyUpdate === 'object' && + keyUpdate.__op && + ['Add', 'AddUnique', 'Remove', 'Increment'].indexOf(keyUpdate.__op) > -1 + ) { + // only valid ops that produce an actionable result + // the op may have happened on a keypath + this._expandResultOnKeyPath(response, key, result); + } + }); + return Promise.resolve(response); + } + static _validateQuery: any => void; } diff --git a/src/Controllers/index.js b/src/Controllers/index.js index 152de684..b2feff0f 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -142,7 +142,7 @@ export function getLiveQueryController(options: ParseServerOptions): LiveQueryCo } export function getDatabaseController(options: ParseServerOptions): DatabaseController { - const { databaseURI, collectionPrefix, databaseOptions, idempotencyOptions } = options; + const { databaseURI, collectionPrefix, databaseOptions } = options; let { databaseAdapter } = options; if ( (databaseOptions || @@ -156,7 +156,7 @@ export function getDatabaseController(options: ParseServerOptions): DatabaseCont } else { databaseAdapter = loadAdapter(databaseAdapter); } - return new DatabaseController(databaseAdapter, idempotencyOptions); + return new DatabaseController(databaseAdapter, options); } export function getHooksController( diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index e2cbd179..1edd704b 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -350,6 +350,24 @@ module.exports.ParseServerOptions = { env: 'PARSE_SERVER_READ_ONLY_MASTER_KEY', help: 'Read-only key, which has the same capabilities as MasterKey without writes', }, + requestKeywordDenylist: { + env: 'PARSE_SERVER_REQUEST_KEYWORD_DENYLIST', + help: + 'An array of keys and values that are prohibited in database read and write requests to prevent potential security vulnerabilities. It is possible to specify only a key (`{"key":"..."}`), only a value (`{"value":"..."}`) or a key-value pair (`{"key":"...","value":"..."}`). The specification can use the following types: `boolean`, `numeric` or `string`, where `string` will be interpreted as a regex notation. Request data is deep-scanned for matching definitions to detect also any nested occurrences. Defaults are patterns that are likely to be used in malicious requests. Setting this option will override the default patterns.', + action: parsers.arrayParser, + default: [ + { + key: '_bsontype', + value: 'Code', + }, + { + key: 'constructor', + }, + { + key: '__proto__', + }, + ], + }, restAPIKey: { env: 'PARSE_SERVER_REST_API_KEY', help: 'Key for REST calls', diff --git a/src/Options/docs.js b/src/Options/docs.js index c6b2e1ab..fc0ff3b7 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -64,6 +64,7 @@ * @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 * @property {String} readOnlyMasterKey Read-only key, which has the same capabilities as MasterKey without writes + * @property {RequestKeywordDenylist[]} requestKeywordDenylist An array of keys and values that are prohibited in database read and write requests to prevent potential security vulnerabilities. It is possible to specify only a key (`{"key":"..."}`), only a value (`{"value":"..."}`) or a key-value pair (`{"key":"...","value":"..."}`). The specification can use the following types: `boolean`, `numeric` or `string`, where `string` will be interpreted as a regex notation. Request data is deep-scanned for matching definitions to detect also any nested occurrences. Defaults are patterns that are likely to be used in malicious requests. Setting this option will override the default patterns. * @property {String} restAPIKey Key for REST calls * @property {Boolean} revokeSessionOnPasswordReset When a user changes their password, either through the reset password email or while logged in, all sessions are revoked if this is true. Set to false if you don't want to revoke sessions. * @property {Boolean} scheduledPush Configuration for push scheduling, defaults to false. diff --git a/src/Options/index.js b/src/Options/index.js index 31b9e10d..3482d88c 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -14,6 +14,10 @@ type Adapter = string | any | T; type NumberOrBoolean = number | boolean; type NumberOrString = number | string; type ProtectedFields = any; +type RequestKeywordDenylist = { + key: string | any, + value: any, +}; export interface ParseServerOptions { /* Your Parse Application ID @@ -252,6 +256,9 @@ export interface ParseServerOptions { /* Set to true if new users should be created without public read and write access. :DEFAULT: false */ enforcePrivateUsers: ?boolean; + /* An array of keys and values that are prohibited in database read and write requests to prevent potential security vulnerabilities. It is possible to specify only a key (`{"key":"..."}`), only a value (`{"value":"..."}`) or a key-value pair (`{"key":"...","value":"..."}`). The specification can use the following types: `boolean`, `numeric` or `string`, where `string` will be interpreted as a regex notation. Request data is deep-scanned for matching definitions to detect also any nested occurrences. Defaults are patterns that are likely to be used in malicious requests. Setting this option will override the default patterns. + :DEFAULT: [{"key":"_bsontype","value":"Code"},{"key":"constructor"},{"key":"__proto__"}] */ + requestKeywordDenylist: ?(RequestKeywordDenylist[]); } export interface SecurityOptions { diff --git a/src/RestWrite.js b/src/RestWrite.js index a651cf9c..8b728731 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -6,6 +6,7 @@ var SchemaController = require('./Controllers/SchemaController'); var deepcopy = require('deepcopy'); const Auth = require('./Auth'); +const Utils = require('./Utils'); var cryptoUtils = require('./cryptoUtils'); var passwordCrypto = require('./password'); var Parse = require('parse/node'); @@ -61,6 +62,19 @@ function RestWrite(config, auth, className, query, data, originalData, clientSDK } } + if (this.config.requestKeywordDenylist) { + // Scan request data for denied keywords + for (const keyword of this.config.requestKeywordDenylist) { + const match = Utils.objectContainsKeyValue(data, keyword.key, keyword.value); + if (match) { + throw new Parse.Error( + Parse.Error.INVALID_KEY_NAME, + `Prohibited keyword in request data: ${JSON.stringify(keyword)}.` + ); + } + } + } + // When the operation is complete, this.response may have several // fields. // response: the actual data to be returned diff --git a/src/Utils.js b/src/Utils.js index c96be084..399939a1 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -332,6 +332,32 @@ class Utils { }; } } + + /** + * Deep-scans an object for a matching key/value definition. + * @param {Object} obj The object to scan. + * @param {String | undefined} key The key to match, or undefined if only the value should be matched. + * @param {any | undefined} value The value to match, or undefined if only the key should be matched. + * @returns {Boolean} True if a match was found, false otherwise. + */ + static objectContainsKeyValue(obj, key, value) { + const isMatch = (a, b) => (typeof a === 'string' && new RegExp(a).test(b)) || a === b; + const isKeyMatch = k => isMatch(key, k); + const isValueMatch = v => isMatch(value, v); + for (const [k, v] of Object.entries(obj)) { + if (key !== undefined && value === undefined && isKeyMatch(k)) { + return true; + } else if (key === undefined && value !== undefined && isValueMatch(v)) { + return true; + } else if (key !== undefined && value !== undefined && isKeyMatch(k) && isValueMatch(v)) { + return true; + } + if (['[object Object]', '[object Array]'].includes(Object.prototype.toString.call(v))) { + return Utils.objectContainsKeyValue(v, key, value); + } + } + return false; + } } module.exports = Utils; From 9b344da9d08a18417d379111f1ac4cbfc3e46149 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 12 Mar 2022 13:48:37 +0000 Subject: [PATCH 82/89] chore(release): 5.0.0-alpha.28 [skip ci] # [5.0.0-alpha.28](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.27...5.0.0-alpha.28) (2022-03-12) ### Bug Fixes * security vulnerability that allows remote code execution (GHSA-p6h4-93qp-jhcm) ([#7844](https://github.com/parse-community/parse-server/issues/7844)) ([e569f40](https://github.com/parse-community/parse-server/commit/e569f402b1fd8648fb0d1523b71b2a03273902a5)) --- changelogs/CHANGELOG_alpha.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 9aca837b..21863e35 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.0.0-alpha.28](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.27...5.0.0-alpha.28) (2022-03-12) + + +### Bug Fixes + +* security vulnerability that allows remote code execution (GHSA-p6h4-93qp-jhcm) ([#7844](https://github.com/parse-community/parse-server/issues/7844)) ([e569f40](https://github.com/parse-community/parse-server/commit/e569f402b1fd8648fb0d1523b71b2a03273902a5)) + # [5.0.0-alpha.27](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.26...5.0.0-alpha.27) (2022-03-12) diff --git a/package-lock.json b/package-lock.json index 702b206a..ec5397ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.27", + "version": "5.0.0-alpha.28", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 10739ee6..0cdc1c6f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.27", + "version": "5.0.0-alpha.28", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 5ace99d542a11e422af46d9fd6b1d3d2513b34cf Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sat, 12 Mar 2022 15:10:44 +0100 Subject: [PATCH 83/89] feat: bump required node engine to >=12.22.10 (#7846) BREAKING CHANGE: This requires Node.js version >=12.22.10. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0cdc1c6f..8bbbb172 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "madge:circular": "node_modules/.bin/madge ./src --circular" }, "engines": { - "node": ">=12.20.0 <17" + "node": ">=12.22.10 <17" }, "bin": { "parse-server": "bin/parse-server" From 3e68491df0ade7663e21bd02fbc3567bc56705f6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 12 Mar 2022 14:12:38 +0000 Subject: [PATCH 84/89] chore(release): 5.0.0-alpha.29 [skip ci] # [5.0.0-alpha.29](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.28...5.0.0-alpha.29) (2022-03-12) ### Features * bump required node engine to >=12.22.10 ([#7846](https://github.com/parse-community/parse-server/issues/7846)) ([5ace99d](https://github.com/parse-community/parse-server/commit/5ace99d542a11e422af46d9fd6b1d3d2513b34cf)) ### BREAKING CHANGES * This requires Node.js version >=12.22.10. ([5ace99d](5ace99d)) --- changelogs/CHANGELOG_alpha.md | 12 ++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_alpha.md b/changelogs/CHANGELOG_alpha.md index 21863e35..0f800988 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,15 @@ +# [5.0.0-alpha.29](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.28...5.0.0-alpha.29) (2022-03-12) + + +### Features + +* bump required node engine to >=12.22.10 ([#7846](https://github.com/parse-community/parse-server/issues/7846)) ([5ace99d](https://github.com/parse-community/parse-server/commit/5ace99d542a11e422af46d9fd6b1d3d2513b34cf)) + + +### BREAKING CHANGES + +* This requires Node.js version >=12.22.10. ([5ace99d](5ace99d)) + # [5.0.0-alpha.28](https://github.com/parse-community/parse-server/compare/5.0.0-alpha.27...5.0.0-alpha.28) (2022-03-12) diff --git a/package-lock.json b/package-lock.json index ec5397ac..6e6ccb08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.28", + "version": "5.0.0-alpha.29", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 8bbbb172..f0c2cc9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.28", + "version": "5.0.0-alpha.29", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 2dceec735937d9950f970783b20aa57bd314052c Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sat, 12 Mar 2022 16:23:25 +0100 Subject: [PATCH 85/89] docs: improve explanation for commit type usage in CONTRIBUTING guide (#7849) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ddc99a81..cbcf7e19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -305,7 +305,7 @@ For release automation, the title of pull requests needs to be written in a defi ``` The _type_ is the category of change that is made, possible types are: -- `feat` - add a new feature +- `feat` - add a new feature or improve an existing feature - `fix` - fix a bug - `refactor` - refactor code without impact on features or performance - `docs` - add or edit code comments, documentation, GitHub pages From 1f6e19fccef66ebb5775f8d127bdcd515058cc60 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sun, 13 Mar 2022 13:44:24 +0100 Subject: [PATCH 86/89] docs: add major release instructions to CONTRIBUTING guide (#7854) --- CONTRIBUTING.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cbcf7e19..df5df279 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,6 +24,7 @@ - [Merging](#merging) - [Breaking Change](#breaking-change-1) - [Reverting](#reverting) + - [Major Release / Long-Term-Support](#major-release--long-term-support) - [Versioning](#versioning) - [Code of Conduct](#code-of-conduct) @@ -362,6 +363,23 @@ If the commit reverts a previous commit, use the prefix `revert:`, followed by t This reverts commit 1234567890abcdef. ``` +### Major Release / Long-Term-Support + +Long-Term-Support (LTS) is provided for the previous Parse Server major version. For example, Parse Server 4.x will receive security updates until Parse Server 5.x is superseded by Parse Server 6.x and becomes the new LTS version. While the current major version is published on branch `release`, a LTS version is published on branch `release-#.x.x`, for example `release-4.x.x` for the Parse Server 4.x LTS branch. + +#### Preparing Release + +The following changes are done in the `alpha` branch, before publishing the last `beta` version that will eventually become the major release. This way the changes trickle naturally through all branches and code consistency is ensured among branches. + +- 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 + +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. + ## Versioning > The following versioning system is applied since Parse Server 5.0.0 and does not necessarily apply to previous releases. From 2eebc68f21e2322354a2a45232873721fcd54843 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Mon, 14 Mar 2022 18:20:12 +0100 Subject: [PATCH 87/89] docs: fix release link in CHANGELOG (#7856) --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c12e7cf..51ff85f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,8 +42,7 @@ Details: - Suitable environment: experimental -[log_release]: https://github.com/parse-community/parse-server/blob/release/CHANGELOG.md - +[log_release]: https://github.com/parse-community/parse-server/blob/release/changelogs/CHANGELOG_release.md [log_beta]: https://github.com/parse-community/parse-server/blob/beta/changelogs/CHANGELOG_beta.md [log_alpha]: https://github.com/parse-community/parse-server/blob/alpha/changelogs/CHANGELOG_alpha.md [branch_release]: https://github.com/parse-community/parse-server/tree/release From 9fa80eb4ed0125a3b787b7590cda6158cc9dd857 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 15 Mar 2022 00:13:57 +0000 Subject: [PATCH 89/89] chore(release): 5.0.0-beta.10 [skip ci] # [5.0.0-beta.10](https://github.com/parse-community/parse-server/compare/5.0.0-beta.9...5.0.0-beta.10) (2022-03-15) ### Bug Fixes * adding or modifying a nested property requires addField permissions ([#7679](https://github.com/parse-community/parse-server/issues/7679)) ([6a6248b](https://github.com/parse-community/parse-server/commit/6a6248b6cb2e732d17131e18e659943b894ed2f1)) * bump nanoid from 3.1.25 to 3.2.0 ([#7781](https://github.com/parse-community/parse-server/issues/7781)) ([f5f63bf](https://github.com/parse-community/parse-server/commit/f5f63bfc64d3481ed944ceb5e9f50b33dccd1ce9)) * bump node-fetch from 2.6.1 to 3.1.1 ([#7782](https://github.com/parse-community/parse-server/issues/7782)) ([9082351](https://github.com/parse-community/parse-server/commit/90823514113a1a085ebc818f7109b3fd7591346f)) * node engine compatibility did not include node 16 ([#7739](https://github.com/parse-community/parse-server/issues/7739)) ([ea7c014](https://github.com/parse-community/parse-server/commit/ea7c01400f992a1263543706fe49b6174758a2d6)) * node engine range has no upper limit to exclude incompatible node versions ([#7692](https://github.com/parse-community/parse-server/issues/7692)) ([573558d](https://github.com/parse-community/parse-server/commit/573558d3adcbcc6222c92003829867e1a73eef94)) * package.json & package-lock.json to reduce vulnerabilities ([#7823](https://github.com/parse-community/parse-server/issues/7823)) ([5ca2288](https://github.com/parse-community/parse-server/commit/5ca228882332b65f3ac05407e6e4da1ee3ef3749)) * schema cache not cleared in some cases ([#7678](https://github.com/parse-community/parse-server/issues/7678)) ([5af6e5d](https://github.com/parse-community/parse-server/commit/5af6e5dfaa129b1a350afcba4fb381b21c4cc35d)) * security upgrade follow-redirects from 1.14.6 to 1.14.7 ([#7769](https://github.com/parse-community/parse-server/issues/7769)) ([8f5a861](https://github.com/parse-community/parse-server/commit/8f5a8618cfa7ed9a2a239a095abffa8f3fd8d31a)) * security upgrade follow-redirects from 1.14.7 to 1.14.8 ([#7801](https://github.com/parse-community/parse-server/issues/7801)) ([70088a9](https://github.com/parse-community/parse-server/commit/70088a95a78393da2a4ac68be81e63107747626a)) * security vulnerability that allows remote code execution (GHSA-p6h4-93qp-jhcm) ([#7844](https://github.com/parse-community/parse-server/issues/7844)) ([e569f40](https://github.com/parse-community/parse-server/commit/e569f402b1fd8648fb0d1523b71b2a03273902a5)) * server crash using GraphQL due to missing @apollo/client peer dependency ([#7787](https://github.com/parse-community/parse-server/issues/7787)) ([08089d6](https://github.com/parse-community/parse-server/commit/08089d6fcbb215412448ce7d92b21b9fe6c929f2)) * unable to use objectId size higher than 19 on GraphQL API ([#7627](https://github.com/parse-community/parse-server/issues/7627)) ([ed86c80](https://github.com/parse-community/parse-server/commit/ed86c807721cc52a1a5a9dea0b768717eec269ed)) * upgrade mime from 2.5.2 to 3.0.0 ([#7725](https://github.com/parse-community/parse-server/issues/7725)) ([f5ef98b](https://github.com/parse-community/parse-server/commit/f5ef98bde32083403c0e30a12162fcc1e52cac37)) * upgrade parse from 3.3.1 to 3.4.0 ([#7723](https://github.com/parse-community/parse-server/issues/7723)) ([d4c1f47](https://github.com/parse-community/parse-server/commit/d4c1f473073764cb0570c633fc4a30669c2ce889)) * upgrade winston from 3.5.0 to 3.5.1 ([#7820](https://github.com/parse-community/parse-server/issues/7820)) ([4af253d](https://github.com/parse-community/parse-server/commit/4af253d1f8654a6f57b5137ad310cdacadc922cc)) ### Features * add Cloud Code context to `ParseObject.fetch` ([#7779](https://github.com/parse-community/parse-server/issues/7779)) ([315290d](https://github.com/parse-community/parse-server/commit/315290d16110110938f80a6b779cc2d1db58c552)) * add Idempotency to Postgres ([#7750](https://github.com/parse-community/parse-server/issues/7750)) ([0c3feaa](https://github.com/parse-community/parse-server/commit/0c3feaaa1751964c0db89f25674935c3354b1538)) * add support for Node 16 ([#7707](https://github.com/parse-community/parse-server/issues/7707)) ([45cc58c](https://github.com/parse-community/parse-server/commit/45cc58c7e5e640a46c5d508019a3aa81242964b1)) * bump required node engine to >=12.22.10 ([#7846](https://github.com/parse-community/parse-server/issues/7846)) ([5ace99d](https://github.com/parse-community/parse-server/commit/5ace99d542a11e422af46d9fd6b1d3d2513b34cf)) * support `postgresql` protocol in database URI ([#7757](https://github.com/parse-community/parse-server/issues/7757)) ([caf4a23](https://github.com/parse-community/parse-server/commit/caf4a2341f554b28e3918c53e7e897a3ca47bf8b)) * support relativeTime query constraint on Postgres ([#7747](https://github.com/parse-community/parse-server/issues/7747)) ([16b1b2a](https://github.com/parse-community/parse-server/commit/16b1b2a19714535ca805f2dbb3b561d8f6a519a7)) * upgrade to MongoDB Node.js driver 4.x for MongoDB 5.0 support ([#7794](https://github.com/parse-community/parse-server/issues/7794)) ([f88aa2a](https://github.com/parse-community/parse-server/commit/f88aa2a62a533e5344d1c13dd38c5a0b283a480a)) ### Reverts * refactor: allow ES import for cloud string if package type is module ([b64640c](https://github.com/parse-community/parse-server/commit/b64640c5705f733798783e68d216e957044ef23c)) * update node engine to 2.22.0 ([#7827](https://github.com/parse-community/parse-server/issues/7827)) ([f235412](https://github.com/parse-community/parse-server/commit/f235412c1b6c2b173b7531f285429ea7214b56a2)) ### BREAKING CHANGES * This requires Node.js version >=12.22.10. ([5ace99d](5ace99d)) * The MongoDB GridStore adapter has been removed. By default, Parse Server already uses GridFS, so if you do not manually use the GridStore adapter, you can ignore this change. ([f88aa2a](f88aa2a)) * Removes official Node 15 support which has reached it end-of-life date. ([45cc58c](45cc58c)) --- changelogs/CHANGELOG_beta.md | 43 ++++++++++++++++++++++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/changelogs/CHANGELOG_beta.md b/changelogs/CHANGELOG_beta.md index c49b9a22..4c6b49cc 100644 --- a/changelogs/CHANGELOG_beta.md +++ b/changelogs/CHANGELOG_beta.md @@ -1,3 +1,46 @@ +# [5.0.0-beta.10](https://github.com/parse-community/parse-server/compare/5.0.0-beta.9...5.0.0-beta.10) (2022-03-15) + + +### Bug Fixes + +* adding or modifying a nested property requires addField permissions ([#7679](https://github.com/parse-community/parse-server/issues/7679)) ([6a6248b](https://github.com/parse-community/parse-server/commit/6a6248b6cb2e732d17131e18e659943b894ed2f1)) +* bump nanoid from 3.1.25 to 3.2.0 ([#7781](https://github.com/parse-community/parse-server/issues/7781)) ([f5f63bf](https://github.com/parse-community/parse-server/commit/f5f63bfc64d3481ed944ceb5e9f50b33dccd1ce9)) +* bump node-fetch from 2.6.1 to 3.1.1 ([#7782](https://github.com/parse-community/parse-server/issues/7782)) ([9082351](https://github.com/parse-community/parse-server/commit/90823514113a1a085ebc818f7109b3fd7591346f)) +* node engine compatibility did not include node 16 ([#7739](https://github.com/parse-community/parse-server/issues/7739)) ([ea7c014](https://github.com/parse-community/parse-server/commit/ea7c01400f992a1263543706fe49b6174758a2d6)) +* node engine range has no upper limit to exclude incompatible node versions ([#7692](https://github.com/parse-community/parse-server/issues/7692)) ([573558d](https://github.com/parse-community/parse-server/commit/573558d3adcbcc6222c92003829867e1a73eef94)) +* package.json & package-lock.json to reduce vulnerabilities ([#7823](https://github.com/parse-community/parse-server/issues/7823)) ([5ca2288](https://github.com/parse-community/parse-server/commit/5ca228882332b65f3ac05407e6e4da1ee3ef3749)) +* schema cache not cleared in some cases ([#7678](https://github.com/parse-community/parse-server/issues/7678)) ([5af6e5d](https://github.com/parse-community/parse-server/commit/5af6e5dfaa129b1a350afcba4fb381b21c4cc35d)) +* security upgrade follow-redirects from 1.14.6 to 1.14.7 ([#7769](https://github.com/parse-community/parse-server/issues/7769)) ([8f5a861](https://github.com/parse-community/parse-server/commit/8f5a8618cfa7ed9a2a239a095abffa8f3fd8d31a)) +* security upgrade follow-redirects from 1.14.7 to 1.14.8 ([#7801](https://github.com/parse-community/parse-server/issues/7801)) ([70088a9](https://github.com/parse-community/parse-server/commit/70088a95a78393da2a4ac68be81e63107747626a)) +* security vulnerability that allows remote code execution (GHSA-p6h4-93qp-jhcm) ([#7844](https://github.com/parse-community/parse-server/issues/7844)) ([e569f40](https://github.com/parse-community/parse-server/commit/e569f402b1fd8648fb0d1523b71b2a03273902a5)) +* server crash using GraphQL due to missing @apollo/client peer dependency ([#7787](https://github.com/parse-community/parse-server/issues/7787)) ([08089d6](https://github.com/parse-community/parse-server/commit/08089d6fcbb215412448ce7d92b21b9fe6c929f2)) +* unable to use objectId size higher than 19 on GraphQL API ([#7627](https://github.com/parse-community/parse-server/issues/7627)) ([ed86c80](https://github.com/parse-community/parse-server/commit/ed86c807721cc52a1a5a9dea0b768717eec269ed)) +* upgrade mime from 2.5.2 to 3.0.0 ([#7725](https://github.com/parse-community/parse-server/issues/7725)) ([f5ef98b](https://github.com/parse-community/parse-server/commit/f5ef98bde32083403c0e30a12162fcc1e52cac37)) +* upgrade parse from 3.3.1 to 3.4.0 ([#7723](https://github.com/parse-community/parse-server/issues/7723)) ([d4c1f47](https://github.com/parse-community/parse-server/commit/d4c1f473073764cb0570c633fc4a30669c2ce889)) +* upgrade winston from 3.5.0 to 3.5.1 ([#7820](https://github.com/parse-community/parse-server/issues/7820)) ([4af253d](https://github.com/parse-community/parse-server/commit/4af253d1f8654a6f57b5137ad310cdacadc922cc)) + +### Features + +* add Cloud Code context to `ParseObject.fetch` ([#7779](https://github.com/parse-community/parse-server/issues/7779)) ([315290d](https://github.com/parse-community/parse-server/commit/315290d16110110938f80a6b779cc2d1db58c552)) +* add Idempotency to Postgres ([#7750](https://github.com/parse-community/parse-server/issues/7750)) ([0c3feaa](https://github.com/parse-community/parse-server/commit/0c3feaaa1751964c0db89f25674935c3354b1538)) +* add support for Node 16 ([#7707](https://github.com/parse-community/parse-server/issues/7707)) ([45cc58c](https://github.com/parse-community/parse-server/commit/45cc58c7e5e640a46c5d508019a3aa81242964b1)) +* bump required node engine to >=12.22.10 ([#7846](https://github.com/parse-community/parse-server/issues/7846)) ([5ace99d](https://github.com/parse-community/parse-server/commit/5ace99d542a11e422af46d9fd6b1d3d2513b34cf)) +* support `postgresql` protocol in database URI ([#7757](https://github.com/parse-community/parse-server/issues/7757)) ([caf4a23](https://github.com/parse-community/parse-server/commit/caf4a2341f554b28e3918c53e7e897a3ca47bf8b)) +* support relativeTime query constraint on Postgres ([#7747](https://github.com/parse-community/parse-server/issues/7747)) ([16b1b2a](https://github.com/parse-community/parse-server/commit/16b1b2a19714535ca805f2dbb3b561d8f6a519a7)) +* upgrade to MongoDB Node.js driver 4.x for MongoDB 5.0 support ([#7794](https://github.com/parse-community/parse-server/issues/7794)) ([f88aa2a](https://github.com/parse-community/parse-server/commit/f88aa2a62a533e5344d1c13dd38c5a0b283a480a)) + +### Reverts + +* refactor: allow ES import for cloud string if package type is module ([b64640c](https://github.com/parse-community/parse-server/commit/b64640c5705f733798783e68d216e957044ef23c)) +* update node engine to 2.22.0 ([#7827](https://github.com/parse-community/parse-server/issues/7827)) ([f235412](https://github.com/parse-community/parse-server/commit/f235412c1b6c2b173b7531f285429ea7214b56a2)) + + +### BREAKING CHANGES + +* This requires Node.js version >=12.22.10. ([5ace99d](5ace99d)) +* The MongoDB GridStore adapter has been removed. By default, Parse Server already uses GridFS, so if you do not manually use the GridStore adapter, you can ignore this change. ([f88aa2a](f88aa2a)) +* Removes official Node 15 support which has reached it end-of-life date. ([45cc58c](45cc58c)) + # [5.0.0-beta.9](https://github.com/parse-community/parse-server/compare/5.0.0-beta.8...5.0.0-beta.9) (2022-03-12) diff --git a/package-lock.json b/package-lock.json index 6e6ccb08..0be4c2e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.29", + "version": "5.0.0-beta.10", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f0c2cc9d..567b8a95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.0.0-alpha.29", + "version": "5.0.0-beta.10", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": {