From 9ef19687ba0f26ee4a8c566d9d0049bb9e61736e Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Fri, 25 Mar 2022 19:47:05 +0100 Subject: [PATCH 01/46] ci: fix node engine check (#7891) --- ci/nodeEngineCheck.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/ci/nodeEngineCheck.js b/ci/nodeEngineCheck.js index da68f314b1..a68f2c593c 100644 --- a/ci/nodeEngineCheck.js +++ b/ci/nodeEngineCheck.js @@ -75,17 +75,21 @@ class NodeEngineCheck { // For each file for (const file of files) { - // Get node version const contentString = await fs.readFile(file, 'utf-8'); - const contentJson = JSON.parse(contentString); - const version = ((contentJson || {}).engines || {}).node; - - // Add response - response.push({ - file: file, - nodeVersion: version - }); + try { + const contentJson = JSON.parse(contentString); + const version = ((contentJson || {}).engines || {}).node; + + // Add response + response.push({ + file: file, + nodeVersion: version + }); + } catch(e) { + console.log(`Ignoring file because it is not valid JSON: ${file}`); + core.warning(`Ignoring file because it is not valid JSON: ${file}`); + } } // If results should be cleaned by removing undefined node versions From f63fb2b338c908f0e7a648d338c26b9daa50c8f2 Mon Sep 17 00:00:00 2001 From: dblythy Date: Sat, 26 Mar 2022 13:39:16 +1100 Subject: [PATCH 02/46] fix: return correct response when revert is used in beforeSave (#7839) --- spec/CloudCode.spec.js | 134 +++++++++++++++++++++++++++++++++++++++++ src/RestWrite.js | 59 +++++++++--------- 2 files changed, 165 insertions(+), 28 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 4b8df9f9c9..faaa6b826a 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1494,6 +1494,110 @@ describe('Cloud Code', () => { }); }); + it('before save can revert fields', async () => { + Parse.Cloud.beforeSave('TestObject', ({ object }) => { + object.revert('foo'); + return object; + }); + + Parse.Cloud.afterSave('TestObject', ({ object }) => { + expect(object.get('foo')).toBeUndefined(); + return object; + }); + + const obj = new TestObject(); + obj.set('foo', 'bar'); + await obj.save(); + + expect(obj.get('foo')).toBeUndefined(); + await obj.fetch(); + + expect(obj.get('foo')).toBeUndefined(); + }); + + it('before save can revert fields with existing object', async () => { + Parse.Cloud.beforeSave( + 'TestObject', + ({ object }) => { + object.revert('foo'); + return object; + }, + { + skipWithMasterKey: true, + } + ); + + Parse.Cloud.afterSave( + 'TestObject', + ({ object }) => { + expect(object.get('foo')).toBe('bar'); + return object; + }, + { + skipWithMasterKey: true, + } + ); + + const obj = new TestObject(); + obj.set('foo', 'bar'); + await obj.save(null, { useMasterKey: true }); + + expect(obj.get('foo')).toBe('bar'); + obj.set('foo', 'yolo'); + await obj.save(); + expect(obj.get('foo')).toBe('bar'); + }); + + it('can unset in afterSave', async () => { + Parse.Cloud.beforeSave('TestObject', ({ object }) => { + if (!object.existed()) { + object.set('secret', true); + return object; + } + object.revert('secret'); + }); + + Parse.Cloud.afterSave('TestObject', ({ object }) => { + object.unset('secret'); + }); + + Parse.Cloud.beforeFind( + 'TestObject', + ({ query }) => { + query.exclude('secret'); + }, + { + skipWithMasterKey: true, + } + ); + + const obj = new TestObject(); + await obj.save(); + expect(obj.get('secret')).toBeUndefined(); + await obj.fetch(); + expect(obj.get('secret')).toBeUndefined(); + await obj.fetch({ useMasterKey: true }); + expect(obj.get('secret')).toBe(true); + }); + + it('should revert in beforeSave', async () => { + Parse.Cloud.beforeSave('MyObject', ({ object }) => { + if (!object.existed()) { + object.set('count', 0); + return object; + } + object.revert('count'); + return object; + }); + const obj = await new Parse.Object('MyObject').save(); + expect(obj.get('count')).toBe(0); + obj.set('count', 10); + await obj.save(); + expect(obj.get('count')).toBe(0); + await obj.fetch(); + expect(obj.get('count')).toBe(0); + }); + it('beforeSave should not sanitize database', async done => { const { adapter } = Config.get(Parse.applicationId).database; const spy = spyOn(adapter, 'findOneAndUpdate').and.callThrough(); @@ -1860,6 +1964,36 @@ describe('afterSave hooks', () => { const myObject = new MyObject(); myObject.save().then(() => done()); }); + + it('should unset in afterSave', async () => { + Parse.Cloud.afterSave( + 'MyObject', + ({ object }) => { + object.unset('secret'); + }, + { + skipWithMasterKey: true, + } + ); + const obj = new Parse.Object('MyObject'); + obj.set('secret', 'bar'); + await obj.save(); + expect(obj.get('secret')).toBeUndefined(); + await obj.fetch(); + expect(obj.get('secret')).toBe('bar'); + }); + + it('should unset', async () => { + Parse.Cloud.beforeSave('MyObject', ({ object }) => { + object.set('secret', 'hidden'); + }); + + Parse.Cloud.afterSave('MyObject', ({ object }) => { + object.unset('secret'); + }); + const obj = await new Parse.Object('MyObject').save(); + expect(obj.get('secret')).toBeUndefined(); + }); }); describe('beforeDelete hooks', () => { diff --git a/src/RestWrite.js b/src/RestWrite.js index 8b728731da..3e20328a9a 100644 --- a/src/RestWrite.js +++ b/src/RestWrite.js @@ -95,6 +95,7 @@ function RestWrite(config, auth, className, query, data, originalData, clientSDK // Shared SchemaController to be reused to reduce the number of loadSchema() calls per request // Once set the schemaData should be immutable this.validSchemaController = null; + this.pendingOps = {}; } // A convenient method to perform all the steps of processing the @@ -225,18 +226,11 @@ RestWrite.prototype.runBeforeSaveTrigger = function () { return Promise.resolve(); } - // Cloud code gets a bit of extra data for its objects - var extraData = { className: this.className }; - if (this.query && this.query.objectId) { - extraData.objectId = this.query.objectId; - } + const { originalObject, updatedObject } = this.buildParseObjects(); - let originalObject = null; - const updatedObject = this.buildUpdatedObject(extraData); - if (this.query && this.query.objectId) { - // This is an update for existing object. - originalObject = triggers.inflate(extraData, this.originalData); - } + const stateController = Parse.CoreManager.getObjectStateController(); + const [pending] = stateController.getPendingOps(updatedObject._getStateIdentifier()); + this.pendingOps = { ...pending }; return Promise.resolve() .then(() => { @@ -1531,20 +1525,7 @@ RestWrite.prototype.runAfterSaveTrigger = function () { return Promise.resolve(); } - var extraData = { className: this.className }; - if (this.query && this.query.objectId) { - extraData.objectId = this.query.objectId; - } - - // Build the original object, we only do this for a update write. - let originalObject; - if (this.query && this.query.objectId) { - originalObject = triggers.inflate(extraData, this.originalData); - } - - // Build the inflated object, different from beforeSave, originalData is not empty - // since developers can change data in the beforeSave. - const updatedObject = this.buildUpdatedObject(extraData); + const { originalObject, updatedObject } = this.buildParseObjects(); updatedObject._handleSaveResponse(this.response.response, this.response.status || 200); this.config.database.loadSchema().then(schemaController => { @@ -1569,8 +1550,15 @@ RestWrite.prototype.runAfterSaveTrigger = function () { this.context ) .then(result => { - if (result && typeof result === 'object') { + const jsonReturned = result && !result._toFullJSON; + if (jsonReturned) { + this.pendingOps = {}; this.response.response = result; + } else { + this.response.response = this._updateResponseWithData( + (result || updatedObject)._toFullJSON(), + this.data + ); } }) .catch(function (err) { @@ -1604,7 +1592,13 @@ RestWrite.prototype.sanitizedData = function () { }; // Returns an updated copy of the object -RestWrite.prototype.buildUpdatedObject = function (extraData) { +RestWrite.prototype.buildParseObjects = function () { + const extraData = { className: this.className, objectId: this.query?.objectId }; + let originalObject; + if (this.query && this.query.objectId) { + originalObject = triggers.inflate(extraData, this.originalData); + } + const className = Parse.Object.fromJSON(extraData); const readOnlyAttributes = className.constructor.readOnlyAttributes ? className.constructor.readOnlyAttributes() @@ -1642,7 +1636,7 @@ RestWrite.prototype.buildUpdatedObject = function (extraData) { delete sanitized[attribute]; } updatedObject.set(sanitized); - return updatedObject; + return { updatedObject, originalObject }; }; RestWrite.prototype.cleanUserAuthData = function () { @@ -1662,6 +1656,15 @@ RestWrite.prototype.cleanUserAuthData = function () { }; RestWrite.prototype._updateResponseWithData = function (response, data) { + const { updatedObject } = this.buildParseObjects(); + const stateController = Parse.CoreManager.getObjectStateController(); + const [pending] = stateController.getPendingOps(updatedObject._getStateIdentifier()); + for (const key in this.pendingOps) { + if (!pending[key]) { + data[key] = this.originalData ? this.originalData[key] : { __op: 'Delete' }; + this.storage.fieldsChangedByTrigger.push(key); + } + } if (_.isEmpty(this.storage.fieldsChangedByTrigger)) { return response; } From b3199d739775dd1ecb2e000b1734f71120e18e3d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 26 Mar 2022 02:40:21 +0000 Subject: [PATCH 03/46] chore(release): 5.2.1-alpha.1 [skip ci] ## [5.2.1-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.0...5.2.1-alpha.1) (2022-03-26) ### Bug Fixes * return correct response when revert is used in beforeSave ([#7839](https://github.com/parse-community/parse-server/issues/7839)) ([f63fb2b](https://github.com/parse-community/parse-server/commit/f63fb2b338c908f0e7a648d338c26b9daa50c8f2)) --- 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 6938ec3c74..511c994d0e 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +## [5.2.1-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.0...5.2.1-alpha.1) (2022-03-26) + + +### Bug Fixes + +* return correct response when revert is used in beforeSave ([#7839](https://github.com/parse-community/parse-server/issues/7839)) ([f63fb2b](https://github.com/parse-community/parse-server/commit/f63fb2b338c908f0e7a648d338c26b9daa50c8f2)) + # [5.2.0-alpha.3](https://github.com/parse-community/parse-server/compare/5.2.0-alpha.2...5.2.0-alpha.3) (2022-03-24) diff --git a/package-lock.json b/package-lock.json index 32800119bb..5468d2c4f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.0", + "version": "5.2.1-alpha.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 2bc25fba02..a5ab014590 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.0", + "version": "5.2.1-alpha.1", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 48bd512eeb47666967dff8c5e723ddc5b7801daa Mon Sep 17 00:00:00 2001 From: dblythy Date: Sun, 27 Mar 2022 01:29:39 +1100 Subject: [PATCH 04/46] perf: reduce database operations when using the constant parameter in Cloud Function validation (#7892) --- src/triggers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/triggers.js b/src/triggers.js index 8320b5fb74..360166d0aa 100644 --- a/src/triggers.js +++ b/src/triggers.js @@ -738,7 +738,7 @@ async function builtInTriggerValidator(options, request, auth) { } if (opt.constant && request.object) { if (request.original) { - request.object.set(key, request.original.get(key)); + request.object.revert(key); } else if (opt.default != null) { request.object.set(key, opt.default); } From e0cca580e7105b4a9a6ac0c73b02c8e7fa54839c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 26 Mar 2022 14:30:48 +0000 Subject: [PATCH 05/46] chore(release): 5.2.1-alpha.2 [skip ci] ## [5.2.1-alpha.2](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.1...5.2.1-alpha.2) (2022-03-26) ### Performance Improvements * reduce database operations when using the constant parameter in Cloud Function validation ([#7892](https://github.com/parse-community/parse-server/issues/7892)) ([48bd512](https://github.com/parse-community/parse-server/commit/48bd512eeb47666967dff8c5e723ddc5b7801daa)) --- 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 511c994d0e..dcbe2dd4ed 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +## [5.2.1-alpha.2](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.1...5.2.1-alpha.2) (2022-03-26) + + +### Performance Improvements + +* reduce database operations when using the constant parameter in Cloud Function validation ([#7892](https://github.com/parse-community/parse-server/issues/7892)) ([48bd512](https://github.com/parse-community/parse-server/commit/48bd512eeb47666967dff8c5e723ddc5b7801daa)) + ## [5.2.1-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.0...5.2.1-alpha.1) (2022-03-26) diff --git a/package-lock.json b/package-lock.json index 5468d2c4f4..d37e18d2dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.1-alpha.1", + "version": "5.2.1-alpha.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a5ab014590..a2395fafe0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.1-alpha.1", + "version": "5.2.1-alpha.2", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 90155cf1680e5e0499b0000e071c6cb0ce3aef96 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 27 Mar 2022 03:59:16 +0200 Subject: [PATCH 06/46] feat: add MongoDB 5.1 compatibility (#7682) --- .github/workflows/ci.yml | 5 ++ README.md | 23 ++--- package.json | 9 +- spec/MongoStorageAdapter.spec.js | 36 +++++++- spec/ParseQuery.hint.spec.js | 144 +++++++++++++++++++++++++++++-- 5 files changed, 195 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2463901a91..f8584ff9cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,6 +101,11 @@ jobs: strategy: matrix: include: + - name: MongoDB 5.1, ReplicaSet, WiredTiger + MONGODB_VERSION: 5.1.0 + MONGODB_TOPOLOGY: replicaset + MONGODB_STORAGE_ENGINE: wiredTiger + NODE_VERSION: 14.18.1 - name: MongoDB 5.0, ReplicaSet, WiredTiger MONGODB_VERSION: 5.0.3 MONGODB_TOPOLOGY: replicaset diff --git a/README.md b/README.md index 7b507e9c80..5a5d88c3d6 100644 --- a/README.md +++ b/README.md @@ -112,8 +112,8 @@ Before you start make sure you have installed: #### Node.js Parse Server is continuously tested with the most recent releases of Node.js to ensure compatibility. We follow the [Node.js Long Term Support plan](https://github.com/nodejs/Release) and only test against versions that are officially supported and have not reached their end-of-life date. -| Version | Latest Version | End-of-Life | Compatible | -|------------|----------------|-------------|---------------| +| Version | Latest Version | End-of-Life | Compatible | +|------------|----------------|-------------|--------------| | 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 | @@ -124,20 +124,21 @@ Parse Server is continuously tested with the most recent releases of MongoDB to | Version | Latest Version | End-of-Life | Compatible | |-------------|----------------|--------------|------------| -| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes | -| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes | -| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes | -| MongoDB 5.0 | 5.0.3 | January 2024 | ✅ Yes | - +| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes | +| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes | +| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes | +| MongoDB 5.0 | 5.0.3 | January 2024 | ✅ Yes | +| MongoDB 5.1 | 5.1.0 | January 2024 | ✅ Yes | + #### PostgreSQL Parse Server is continuously tested with the most recent releases of PostgreSQL and PostGIS to ensure compatibility, using [PostGIS docker images](https://registry.hub.docker.com/r/postgis/postgis/tags?page=1&ordering=last_updated). We follow the [PostgreSQL support schedule](https://www.postgresql.org/support/versioning) and [PostGIS support schedule](https://www.postgis.net/eol_policy/) and only test against versions that are officially supported and have not reached their end-of-life date. Due to the extensive PostgreSQL support duration of 5 years, Parse Server drops support if a version is older than 3.5 years and a newer version has been available for at least 2.5 years. | Version | PostGIS Version | End-of-Life | Parse Server Support End | Compatible | |-------------|-----------------|---------------|--------------------------|------------| -| 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 | +| 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 diff --git a/package.json b/package.json index a2395fafe0..d8d229ab38 100644 --- a/package.json +++ b/package.json @@ -120,12 +120,13 @@ "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", + "test:mongodb:5.1.0": "npm run test:mongodb --dbversion=5.1.0", "posttest:mongodb": "mongodb-runner stop", - "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", + "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", + "testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} 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:=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", + "posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop", + "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} 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/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index a31a6134f7..130971a535 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -308,7 +308,7 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { await expectAsync(adapter.getClass('UnknownClass')).toBeRejectedWith(undefined); }); - it('should use index for caseInsensitive query', async () => { + it_only_mongodb_version('<5.1')('should use index for caseInsensitive query', async () => { const user = new Parse.User(); user.set('username', 'Bugs'); user.set('password', 'Bunny'); @@ -342,6 +342,40 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { expect(postIndexPlan.executionStats.executionStages.stage).toBe('FETCH'); }); + it_only_mongodb_version('>=5.1')('should use index for caseInsensitive query', async () => { + const user = new Parse.User(); + user.set('username', 'Bugs'); + user.set('password', 'Bunny'); + await user.signUp(); + + const database = Config.get(Parse.applicationId).database; + await database.adapter.dropAllIndexes('_User'); + + const preIndexPlan = await database.find( + '_User', + { username: 'bugs' }, + { caseInsensitive: true, explain: true } + ); + + const schema = await new Parse.Schema('_User').get(); + + await database.adapter.ensureIndex( + '_User', + schema, + ['username'], + 'case_insensitive_username', + true + ); + + const postIndexPlan = await database.find( + '_User', + { username: 'bugs' }, + { caseInsensitive: true, explain: true } + ); + expect(preIndexPlan.queryPlanner.winningPlan.queryPlan.stage).toBe('COLLSCAN'); + expect(postIndexPlan.queryPlanner.winningPlan.queryPlan.stage).toBe('FETCH'); + }); + it('should delete field without index', async () => { const database = Config.get(Parse.applicationId).database; const obj = new Parse.Object('MyObject'); diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index 2685137801..8ceb441d5b 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -27,7 +27,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { await TestUtils.destroyAllDataPermanently(false); }); - it('query find with hint string', async () => { + it_only_mongodb_version('<5.1')('query find with hint string', async () => { const object = new TestObject(); await object.save(); @@ -39,7 +39,18 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(explain.queryPlanner.winningPlan.inputStage.indexName).toBe('_id_'); }); - it('query find with hint object', async () => { + it_only_mongodb_version('>=5.1')('query find with hint string', async () => { + const object = new TestObject(); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + const explain = await collection._rawFind({ _id: object.id }, { hint: '_id_', explain: true }); + expect(explain.queryPlanner.winningPlan.queryPlan.stage).toBe('FETCH'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('IXSCAN'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.indexName).toBe('_id_'); + }); + + it_only_mongodb_version('<5.1')('query find with hint object', async () => { const object = new TestObject(); await object.save(); @@ -53,6 +64,20 @@ describe_only_db('mongo')('Parse.Query hint', () => { }); }); + it_only_mongodb_version('>=5.1')('query find with hint object', async () => { + const object = new TestObject(); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + const explain = await collection._rawFind( + { _id: object.id }, + { hint: { _id: 1 }, explain: true } + ); + expect(explain.queryPlanner.winningPlan.queryPlan.stage).toBe('FETCH'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('IXSCAN'); + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.keyPattern).toEqual({ _id: 1 }); + }); + it_only_mongodb_version('<4.4')('query aggregate with hint string', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -73,7 +98,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.indexName).toBe('_id_'); }); - it_only_mongodb_version('>=4.4')('query aggregate with hint string', async () => { + it_only_mongodb_version('>=4.4<5.1')('query aggregate with hint string', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -97,6 +122,30 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); }); + it_only_mongodb_version('>=5.1')('query aggregate with hint string', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let { queryPlanner } = result[0].stages[0].$cursor; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: '_id_', + explain: true, + }); + queryPlanner = result[0].stages[0].$cursor.queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + }); + it_only_mongodb_version('<4.4')('query aggregate with hint object', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -117,7 +166,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it_only_mongodb_version('>=4.4')('query aggregate with hint object', async () => { + it_only_mongodb_version('>=4.4<5.1')('query aggregate with hint object', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -142,7 +191,32 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it('query find with hint (rest)', async () => { + it_only_mongodb_version('>=5.1')('query aggregate with hint object', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let { queryPlanner } = result[0].stages[0].$cursor; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: { _id: 1 }, + explain: true, + }); + queryPlanner = result[0].stages[0].$cursor.queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); + + it_only_mongodb_version('<5.1')('query find with hint (rest)', async () => { const object = new TestObject(); await object.save(); let options = Object.assign({}, masterKeyOptions, { @@ -167,6 +241,31 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(explain.queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); }); + it_only_mongodb_version('>=5.1')('query find with hint (rest)', async () => { + const object = new TestObject(); + await object.save(); + let options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/classes/TestObject', + qs: { + explain: true, + }, + }); + let response = await request(options); + let explain = response.data.results; + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + + options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/classes/TestObject', + qs: { + explain: true, + hint: '_id_', + }, + }); + response = await request(options); + explain = response.data.results; + expect(explain.queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + }); + it_only_mongodb_version('<4.4')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -194,7 +293,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it_only_mongodb_version('>=4.4')('query aggregate with hint (rest)', async () => { + it_only_mongodb_version('>=4.4<5.1')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); let options = Object.assign({}, masterKeyOptions, { @@ -226,4 +325,37 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); + + it_only_mongodb_version('>=5.1')('query aggregate with hint (rest)', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + let options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + let response = await request(options); + let { queryPlanner } = response.data.results[0].stages[0].$cursor; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + hint: '_id_', + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + response = await request(options); + queryPlanner = response.data.results[0].stages[0].$cursor.queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('PROJECTION_SIMPLE'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); }); From 499cead1de6751c88442a7da4a24096017b231cb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 27 Mar 2022 02:00:17 +0000 Subject: [PATCH 07/46] chore(release): 5.3.0-alpha.1 [skip ci] # [5.3.0-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.2...5.3.0-alpha.1) (2022-03-27) ### Features * add MongoDB 5.1 compatibility ([#7682](https://github.com/parse-community/parse-server/issues/7682)) ([90155cf](https://github.com/parse-community/parse-server/commit/90155cf1680e5e0499b0000e071c6cb0ce3aef96)) --- 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 dcbe2dd4ed..a61aef3404 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.3.0-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.2...5.3.0-alpha.1) (2022-03-27) + + +### Features + +* add MongoDB 5.1 compatibility ([#7682](https://github.com/parse-community/parse-server/issues/7682)) ([90155cf](https://github.com/parse-community/parse-server/commit/90155cf1680e5e0499b0000e071c6cb0ce3aef96)) + ## [5.2.1-alpha.2](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.1...5.2.1-alpha.2) (2022-03-26) diff --git a/package-lock.json b/package-lock.json index d37e18d2dd..dacb8759d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.1-alpha.2", + "version": "5.3.0-alpha.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d8d229ab38..35ac12f220 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.2.1-alpha.2", + "version": "5.3.0-alpha.1", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From ef56e98ef65041b4d3b7b82cce3473269c27f6fd Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sun, 27 Mar 2022 15:17:48 +0200 Subject: [PATCH 08/46] fix: security upgrade parse push adapter from 4.1.0 to 4.1.2 (#7893) --- package-lock.json | 84 +++++++++++++++++++++++++---------------------- package.json | 4 +-- 2 files changed, 46 insertions(+), 42 deletions(-) diff --git a/package-lock.json b/package-lock.json index dacb8759d8..47bdc1593d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1109,11 +1109,11 @@ } }, "@babel/runtime-corejs3": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.6.tgz", - "integrity": "sha512-Xl8SPYtdjcMoCsIM4teyVRg7jIcgl8F2kRtoCcXuHzXswt9UxZCS6BzRo8fcnCuP6u2XtPgvyonmEPF57Kxo9Q==", + "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.14.0", + "core-js-pure": "^3.15.0", "regenerator-runtime": "^0.13.4" } }, @@ -1850,20 +1850,20 @@ "dev": true }, "@parse/node-apn": { - "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==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@parse/node-apn/-/node-apn-5.1.3.tgz", + "integrity": "sha512-Bwhmbm895lEIF2772PJ8dSvBjrtOG9/q/TDMxmX40IgZxQFoXS73+JUIKTq3CA7SUB/Szu5roJINQ0L2U/1MJw==", "requires": { - "debug": "4.3.2", + "debug": "4.3.3", "jsonwebtoken": "8.5.1", - "node-forge": "0.10.0", - "verror": "1.10.0" + "node-forge": "1.3.0", + "verror": "1.10.1" }, "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" } @@ -1872,6 +1872,16 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } } } }, @@ -1886,42 +1896,36 @@ } }, "@parse/push-adapter": { - "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==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@parse/push-adapter/-/push-adapter-4.1.2.tgz", + "integrity": "sha512-034vZTlAzgdfefIY4+Q4j8DHS/VwUAIVoh1JeRkHNfyQmUQ++uKbQbUQdJ/nf11HHS69kwLENs13BmhlHMpyHQ==", "requires": { - "@parse/node-apn": "5.1.0", + "@parse/node-apn": "5.1.3", "@parse/node-gcm": "1.0.2", "npmlog": "4.1.2", - "parse": "3.3.0" + "parse": "3.4.0" }, "dependencies": { "@babel/runtime": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", - "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "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" } }, - "crypto-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", - "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==", - "optional": true - }, "parse": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/parse/-/parse-3.3.0.tgz", - "integrity": "sha512-SQkTDupU7JQBJpYFIpO8TlQjUtjboUdkXaak57pjoC1ZVbhaiNyLsdYbrlM0B+sNYhlvcMh7zwZW48u10+zm0A==", + "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.6", - "@babel/runtime-corejs3": "7.14.6", - "crypto-js": "4.0.0", + "@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" } }, @@ -1931,9 +1935,9 @@ "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==" } } }, @@ -10899,9 +10903,9 @@ } }, "node-forge": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", - "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.0.tgz", + "integrity": "sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==" }, "node-netstat": { "version": "1.8.0", diff --git a/package.json b/package.json index 35ac12f220..147ac79f56 100644 --- a/package.json +++ b/package.json @@ -19,13 +19,13 @@ ], "license": "BSD-3-Clause", "dependencies": { + "@apollo/client": "3.5.8", "@apollographql/graphql-playground-html": "1.6.29", "@graphql-tools/links": "8.2.2", - "@apollo/client": "3.5.8", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", - "@parse/push-adapter": "4.1.0", + "@parse/push-adapter": "4.1.2", "apollo-server-express": "2.25.2", "bcryptjs": "2.4.3", "body-parser": "1.19.1", From 119dbe0cd5c68b435736948553eba68e974a3334 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 27 Mar 2022 13:18:57 +0000 Subject: [PATCH 09/46] chore(release): 5.3.0-alpha.2 [skip ci] # [5.3.0-alpha.2](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.1...5.3.0-alpha.2) (2022-03-27) ### Bug Fixes * security upgrade parse push adapter from 4.1.0 to 4.1.2 ([#7893](https://github.com/parse-community/parse-server/issues/7893)) ([ef56e98](https://github.com/parse-community/parse-server/commit/ef56e98ef65041b4d3b7b82cce3473269c27f6fd)) --- 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 a61aef3404..c3e5136322 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.3.0-alpha.2](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.1...5.3.0-alpha.2) (2022-03-27) + + +### Bug Fixes + +* security upgrade parse push adapter from 4.1.0 to 4.1.2 ([#7893](https://github.com/parse-community/parse-server/issues/7893)) ([ef56e98](https://github.com/parse-community/parse-server/commit/ef56e98ef65041b4d3b7b82cce3473269c27f6fd)) + # [5.3.0-alpha.1](https://github.com/parse-community/parse-server/compare/5.2.1-alpha.2...5.3.0-alpha.1) (2022-03-27) diff --git a/package-lock.json b/package-lock.json index 47bdc1593d..f1ebbfdc0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.1", + "version": "5.3.0-alpha.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 147ac79f56..a89abb4821 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.1", + "version": "5.3.0-alpha.2", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 6b4b358f0842ae920e45652f5e8b2afebc6caf3a Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Sun, 27 Mar 2022 22:44:02 +0200 Subject: [PATCH 10/46] feat: add MongoDB 5.2 support (#7894) --- .github/workflows/ci.yml | 9 +++- README.md | 15 +++--- package.json | 13 +++--- spec/ParseQuery.hint.spec.js | 88 ++++++++++++++++++++++++++++++++++-- 4 files changed, 107 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8584ff9cb..924139b944 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -101,13 +101,18 @@ jobs: strategy: matrix: include: + - name: MongoDB 5.2, ReplicaSet, WiredTiger + MONGODB_VERSION: 5.2.1 + MONGODB_TOPOLOGY: replicaset + MONGODB_STORAGE_ENGINE: wiredTiger + NODE_VERSION: 14.18.1 - name: MongoDB 5.1, ReplicaSet, WiredTiger - MONGODB_VERSION: 5.1.0 + MONGODB_VERSION: 5.1.1 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger NODE_VERSION: 14.18.1 - name: MongoDB 5.0, ReplicaSet, WiredTiger - MONGODB_VERSION: 5.0.3 + MONGODB_VERSION: 5.0.6 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger NODE_VERSION: 16.13.0 diff --git a/README.md b/README.md index 5a5d88c3d6..dc14dd7f1a 100644 --- a/README.md +++ b/README.md @@ -122,13 +122,14 @@ Parse Server is continuously tested with the most recent releases of Node.js to #### 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. -| Version | Latest Version | End-of-Life | Compatible | -|-------------|----------------|--------------|------------| -| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes | -| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes | -| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes | -| MongoDB 5.0 | 5.0.3 | January 2024 | ✅ Yes | -| MongoDB 5.1 | 5.1.0 | January 2024 | ✅ Yes | +| Version | Latest Version | End-of-Life | Compatible | +|-------------|----------------|-------------|------------| +| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes | +| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes | +| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes | +| MongoDB 5.0 | 5.0.6 | TBD | ✅ Yes | +| MongoDB 5.1 | 5.1.1 | TBD | ✅ Yes | +| MongoDB 5.2 | 5.2.1 | TBD | ✅ Yes | #### PostgreSQL Parse Server is continuously tested with the most recent releases of PostgreSQL and PostGIS to ensure compatibility, using [PostGIS docker images](https://registry.hub.docker.com/r/postgis/postgis/tags?page=1&ordering=last_updated). We follow the [PostgreSQL support schedule](https://www.postgresql.org/support/versioning) and [PostGIS support schedule](https://www.postgis.net/eol_policy/) and only test against versions that are officially supported and have not reached their end-of-life date. Due to the extensive PostgreSQL support duration of 5 years, Parse Server drops support if a version is older than 3.5 years and a newer version has been available for at least 2.5 years. diff --git a/package.json b/package.json index a89abb4821..01cac39632 100644 --- a/package.json +++ b/package.json @@ -119,14 +119,15 @@ "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", - "test:mongodb:5.1.0": "npm run test:mongodb --dbversion=5.1.0", + "test:mongodb:5.0.6": "npm run test:mongodb --dbversion=5.0.6", + "test:mongodb:5.1.1": "npm run test:mongodb --dbversion=5.1.1", + "test:mongodb:5.2.1": "npm run test:mongodb --dbversion=5.2.1", "posttest:mongodb": "mongodb-runner stop", - "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", - "testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine", + "pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", + "testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} 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:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop", - "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine", + "posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop", + "coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} 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/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index 8ceb441d5b..db45106359 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -122,7 +122,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); }); - it_only_mongodb_version('>=5.1')('query aggregate with hint string', async () => { + it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint string', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -146,6 +146,30 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); }); + it_only_mongodb_version('>=5.2')('query aggregate with hint string', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: '_id_', + explain: true, + }); + queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + }); + it_only_mongodb_version('<4.4')('query aggregate with hint object', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -191,7 +215,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it_only_mongodb_version('>=5.1')('query aggregate with hint object', async () => { + it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint object', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -216,6 +240,31 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); + it_only_mongodb_version('>=5.2')('query aggregate with hint object', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + + const collection = await config.database.adapter._adaptiveCollection('TestObject'); + let result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + explain: true, + }); + let queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + result = await collection.aggregate([{ $group: { _id: '$foo' } }], { + hint: { _id: 1 }, + explain: true, + }); + queryPlanner = result[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); + it_only_mongodb_version('<5.1')('query find with hint (rest)', async () => { const object = new TestObject(); await object.save(); @@ -326,7 +375,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it_only_mongodb_version('>=5.1')('query aggregate with hint (rest)', async () => { + it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); let options = Object.assign({}, masterKeyOptions, { @@ -358,4 +407,37 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); + + it_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { + const object = new TestObject({ foo: 'bar' }); + await object.save(); + let options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + let response = await request(options); + let queryPlanner = response.data.results[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined(); + + options = Object.assign({}, masterKeyOptions, { + url: Parse.serverURL + '/aggregate/TestObject', + qs: { + explain: true, + hint: '_id_', + group: JSON.stringify({ objectId: '$foo' }), + }, + }); + response = await request(options); + queryPlanner = response.data.results[0].queryPlanner; + expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); + expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + }); }); From 75eca2d52fee63b21f4ce0e75a3043f533c046bb Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 27 Mar 2022 20:46:31 +0000 Subject: [PATCH 11/46] chore(release): 5.3.0-alpha.3 [skip ci] # [5.3.0-alpha.3](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.2...5.3.0-alpha.3) (2022-03-27) ### Features * add MongoDB 5.2 support ([#7894](https://github.com/parse-community/parse-server/issues/7894)) ([6b4b358](https://github.com/parse-community/parse-server/commit/6b4b358f0842ae920e45652f5e8b2afebc6caf3a)) --- 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 c3e5136322..888add258c 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.3.0-alpha.3](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.2...5.3.0-alpha.3) (2022-03-27) + + +### Features + +* add MongoDB 5.2 support ([#7894](https://github.com/parse-community/parse-server/issues/7894)) ([6b4b358](https://github.com/parse-community/parse-server/commit/6b4b358f0842ae920e45652f5e8b2afebc6caf3a)) + # [5.3.0-alpha.2](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.1...5.3.0-alpha.2) (2022-03-27) diff --git a/package-lock.json b/package-lock.json index f1ebbfdc0a..46e7dab718 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.2", + "version": "5.3.0-alpha.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 01cac39632..5cd91c0978 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.2", + "version": "5.3.0-alpha.3", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 0cec09f870c9db336a659a0a25c15451d7de4cee Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 31 Mar 2022 18:20:14 +1100 Subject: [PATCH 12/46] fix: allow ES import for cloud string if package type is module --- .babelrc | 3 +- spec/CloudCode.spec.js | 22 +++++++++++ spec/cloud/cloudCodeModuleFile.js | 3 ++ spec/helper.js | 66 ++++++++++++------------------- src/ParseServer.js | 59 +++++++++++++++++++-------- src/index.js | 1 + 6 files changed, 96 insertions(+), 58 deletions(-) create mode 100644 spec/cloud/cloudCodeModuleFile.js diff --git a/.babelrc b/.babelrc index 9151969bde..a199154b82 100644 --- a/.babelrc +++ b/.babelrc @@ -7,7 +7,8 @@ ["@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 faaa6b826a..b77a5926f1 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -39,6 +39,28 @@ describe('Cloud Code', () => { }); }); + it('should wait for cloud code to load', async () => { + await reconfigureServer({ + async cloud() { + await new Promise(resolve => setTimeout(resolve, 1000)); + Parse.Cloud.beforeSave('Test', () => { + throw 'Cannot save.'; + }); + }, + }); + await expectAsync(new Parse.Object('Test').save()).toBeRejectedWith( + new Parse.Error(141, 'Cannot save.') + ); + }); + + 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 new file mode 100644 index 0000000000..a62b4fcc24 --- /dev/null +++ b/spec/cloud/cloudCodeModuleFile.js @@ -0,0 +1,3 @@ +Parse.Cloud.define('cloudCodeInFile', () => { + return 'It is possible to define cloud code in a file.'; +}); diff --git a/spec/helper.js b/spec/helper.js index 612c716202..eb84fd1dca 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -142,46 +142,32 @@ let server; let didChangeConfiguration = false; // Allows testing specific configurations of Parse Server -const reconfigureServer = (changedConfiguration = {}) => { - return new Promise((resolve, reject) => { - if (server) { - return server.close(() => { - server = undefined; - reconfigureServer(changedConfiguration).then(resolve, reject); - }); - } - try { - let parseServer = undefined; - didChangeConfiguration = Object.keys(changedConfiguration).length !== 0; - const newConfiguration = Object.assign({}, defaultConfiguration, changedConfiguration, { - serverStartComplete: error => { - if (error) { - reject(error); - } else { - Parse.CoreManager.setRESTController(RESTController); - resolve(parseServer); - } - }, - mountPath: '/1', - port, - }); - cache.clear(); - parseServer = ParseServer.start(newConfiguration); - parseServer.expressApp.use('/1', err => { - console.error(err); - fail('should not call next'); - }); - server = parseServer.server; - server.on('connection', connection => { - const key = `${connection.remoteAddress}:${connection.remotePort}`; - openConnections[key] = connection; - connection.on('close', () => { - delete openConnections[key]; - }); - }); - } catch (error) { - reject(error); - } +const reconfigureServer = async (changedConfiguration = {}) => { + if (server) { + await new Promise(resolve => server.close(resolve)); + server = undefined; + } + let parseServer = undefined; + didChangeConfiguration = Object.keys(changedConfiguration).length !== 0; + const newConfiguration = Object.assign({}, defaultConfiguration, changedConfiguration, { + mountPath: '/1', + port, + }); + cache.clear(); + parseServer = await ParseServer.createAsync(newConfiguration); + parseServer.start(); + Parse.CoreManager.setRESTController(RESTController); + parseServer.expressApp.use('/1', err => { + console.error(err); + fail('should not call next'); + }); + server = parseServer.server; + server.on('connection', connection => { + const key = `${connection.remoteAddress}:${connection.remotePort}`; + openConnections[key] = connection; + connection.on('close', () => { + delete openConnections[key]; + }); }); }; diff --git a/src/ParseServer.js b/src/ParseServer.js index e6b30d1918..2a61f14c68 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -83,36 +83,39 @@ class ParseServer { logging.setLogger(loggerController); // Note: Tests will start to fail if any validation happens after this is called. - databaseController - .performInitialization() - .then(() => hooksController.load()) - .then(async () => { + (async () => { + try { + await databaseController.performInitialization(); + await hooksController.load(); if (schema) { await new DefinedSchemas(schema, this.config).execute(); } + if (cloud) { + addParseCloud(); + if (typeof cloud === 'function') { + await cloud(Parse); + } else if (typeof cloud === 'string') { + if (process.env.npm_package_type === 'module') { + await import(path.resolve(process.cwd(), cloud)); + } else { + require(path.resolve(process.cwd(), cloud)); + } + } else { + throw "argument 'cloud' must either be a string or a function"; + } + } if (serverStartComplete) { serverStartComplete(); } - }) - .catch(error => { + } catch (error) { if (serverStartComplete) { serverStartComplete(error); } else { console.error(error); process.exit(1); } - }); - - if (cloud) { - addParseCloud(); - if (typeof cloud === 'function') { - cloud(Parse); - } else if (typeof cloud === 'string') { - require(path.resolve(process.cwd(), cloud)); - } else { - throw "argument 'cloud' must either be a string or a function"; } - } + })(); if (security && security.enableCheck && security.enableCheckLog) { new CheckRunner(options.security).run(); @@ -255,6 +258,9 @@ class ParseServer { * @returns {ParseServer} the parse server instance */ start(options: ParseServerOptions, callback: ?() => void) { + if (!options) { + options = this.config; + } const app = express(); if (options.middleware) { let middleware; @@ -323,6 +329,25 @@ class ParseServer { return parseServer.start(options, callback); } + /** + * @static + * Create an async parse server + * @param {ParseServerOptions} options the parse server initialization options */ + static createAsync(options) { + return new Promise((resolve, reject) => { + const parseServer = new ParseServer({ + ...options, + serverStartComplete(error) { + if (error) { + reject(error); + } else { + resolve(parseServer); + } + }, + }); + }); + } + /** * Helper method to create a liveQuery server * @static diff --git a/src/index.js b/src/index.js index bbbdaf545f..ba854a1c2f 100644 --- a/src/index.js +++ b/src/index.js @@ -21,6 +21,7 @@ const _ParseServer = function (options: ParseServerOptions) { // Mount the create liveQueryServer _ParseServer.createLiveQueryServer = ParseServer.createLiveQueryServer; _ParseServer.start = ParseServer.start; +_ParseServer.createAsync = ParseServer.createAsync; const S3Adapter = useExternal('S3Adapter', '@parse/s3-files-adapter'); const GCSAdapter = useExternal('GCSAdapter', '@parse/gcs-files-adapter'); From 4e14aa26e924492df32cd3f98951a330c4f8cd8d Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 31 Mar 2022 19:31:27 +1100 Subject: [PATCH 13/46] revert helper --- spec/CloudCode.spec.js | 9 +++++- spec/helper.js | 66 +++++++++++++++++++++++++----------------- 2 files changed, 48 insertions(+), 27 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index b77a5926f1..57a8a32c65 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -1,6 +1,7 @@ 'use strict'; const Config = require('../lib/Config'); const Parse = require('parse/node'); +const ParseServer = require('../lib/index').ParseServer; const request = require('../lib/request'); const InMemoryCacheAdapter = require('../lib/Adapters/Cache/InMemoryCacheAdapter') .InMemoryCacheAdapter; @@ -40,7 +41,10 @@ describe('Cloud Code', () => { }); it('should wait for cloud code to load', async () => { - await reconfigureServer({ + const config = Config.get('test'); + const initiated = new Date(); + const parseServer = await ParseServer.createAsync({ + ...config, async cloud() { await new Promise(resolve => setTimeout(resolve, 1000)); Parse.Cloud.beforeSave('Test', () => { @@ -48,6 +52,9 @@ describe('Cloud Code', () => { }); }, }); + const now = new Date(); + expect(now.getTime() - initiated.getTime() > 1000).toBeTrue(); + parseServer.start({ port: 18380, mountPath: '/test2' }); await expectAsync(new Parse.Object('Test').save()).toBeRejectedWith( new Parse.Error(141, 'Cannot save.') ); diff --git a/spec/helper.js b/spec/helper.js index eb84fd1dca..612c716202 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -142,32 +142,46 @@ let server; let didChangeConfiguration = false; // Allows testing specific configurations of Parse Server -const reconfigureServer = async (changedConfiguration = {}) => { - if (server) { - await new Promise(resolve => server.close(resolve)); - server = undefined; - } - let parseServer = undefined; - didChangeConfiguration = Object.keys(changedConfiguration).length !== 0; - const newConfiguration = Object.assign({}, defaultConfiguration, changedConfiguration, { - mountPath: '/1', - port, - }); - cache.clear(); - parseServer = await ParseServer.createAsync(newConfiguration); - parseServer.start(); - Parse.CoreManager.setRESTController(RESTController); - parseServer.expressApp.use('/1', err => { - console.error(err); - fail('should not call next'); - }); - server = parseServer.server; - server.on('connection', connection => { - const key = `${connection.remoteAddress}:${connection.remotePort}`; - openConnections[key] = connection; - connection.on('close', () => { - delete openConnections[key]; - }); +const reconfigureServer = (changedConfiguration = {}) => { + return new Promise((resolve, reject) => { + if (server) { + return server.close(() => { + server = undefined; + reconfigureServer(changedConfiguration).then(resolve, reject); + }); + } + try { + let parseServer = undefined; + didChangeConfiguration = Object.keys(changedConfiguration).length !== 0; + const newConfiguration = Object.assign({}, defaultConfiguration, changedConfiguration, { + serverStartComplete: error => { + if (error) { + reject(error); + } else { + Parse.CoreManager.setRESTController(RESTController); + resolve(parseServer); + } + }, + mountPath: '/1', + port, + }); + cache.clear(); + parseServer = ParseServer.start(newConfiguration); + parseServer.expressApp.use('/1', err => { + console.error(err); + fail('should not call next'); + }); + server = parseServer.server; + server.on('connection', connection => { + const key = `${connection.remoteAddress}:${connection.remotePort}`; + openConnections[key] = connection; + connection.on('close', () => { + delete openConnections[key]; + }); + }); + } catch (error) { + reject(error); + } }); }; From 132a3e081304dc35bc1155d109f40cea00e76e37 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sun, 3 Apr 2022 15:09:04 +0100 Subject: [PATCH 14/46] refactor: upgrade mongodb from 4.3.1 to 4.4.1 (#7906) --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 46e7dab718..8a0335dede 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10447,21 +10447,21 @@ "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" }, "mongodb": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.3.1.tgz", - "integrity": "sha512-sNa8APSIk+r4x31ZwctKjuPSaeKuvUeNb/fu/3B6dRM02HpEgig7hTHM8A/PJQTlxuC/KFWlDlQjhsk/S43tBg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.4.1.tgz", + "integrity": "sha512-IAD3nFtCR4s22vi5qjqkCBnuyDDrOW8WVSSmgHquOvGaP1iTD+XpC5tr8wAUbZ2EeZkaswwBKQFHDvl4qYcKqQ==", "requires": { "bson": "^4.6.1", "denque": "^2.0.1", - "mongodb-connection-string-url": "^2.4.1", + "mongodb-connection-string-url": "^2.5.2", "saslprep": "^1.0.3", - "socks": "^2.6.1" + "socks": "^2.6.2" }, "dependencies": { "bson": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz", - "integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.2.tgz", + "integrity": "sha512-VeJKHShcu1b/ugl0QiujlVuBepab714X9nNyBdA1kfekuDGecxgpTA2Z6nYbagrWFeiIyzSWIOzju3lhj+RNyQ==", "requires": { "buffer": "^5.6.0" } @@ -10474,9 +10474,9 @@ } }, "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==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz", + "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==", "requires": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" @@ -15536,12 +15536,12 @@ } }, "socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", "requires": { "ip": "^1.1.5", - "smart-buffer": "^4.1.0" + "smart-buffer": "^4.2.0" } }, "sort-keys": { diff --git a/package.json b/package.json index 5cd91c0978..7aa9f07f4a 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "lodash": "4.17.21", "lru-cache": "6.0.0", "mime": "3.0.0", - "mongodb": "4.3.1", + "mongodb": "4.4.1", "mustache": "4.2.0", "parse": "3.4.1", "pg-monitor": "1.4.1", From d74b6a3e3bb1d8f5f3c54698f4a1765c88dde759 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 3 Apr 2022 17:30:38 +0200 Subject: [PATCH 15/46] ci: bump environment (#7907) --- .github/workflows/ci.yml | 48 ++++++++++++++++++++-------------------- README.md | 12 +++++----- package.json | 6 ++--- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 924139b944..7c56b7cc38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ on: branches: - '**' env: - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 PARSE_SERVER_TEST_TIMEOUT: 20000 jobs: check-ci: @@ -105,53 +105,53 @@ jobs: MONGODB_VERSION: 5.2.1 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 14.19.1 - name: MongoDB 5.1, ReplicaSet, WiredTiger MONGODB_VERSION: 5.1.1 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 14.19.1 - name: MongoDB 5.0, ReplicaSet, WiredTiger MONGODB_VERSION: 5.0.6 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.4, ReplicaSet, WiredTiger - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.2, ReplicaSet, WiredTiger - MONGODB_VERSION: 4.2.17 + MONGODB_VERSION: 4.2.19 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.0, ReplicaSet, WiredTiger - MONGODB_VERSION: 4.0.27 + MONGODB_VERSION: 4.0.28 MONGODB_TOPOLOGY: replicaset MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: MongoDB 4.0, Standalone, MMAPv1 - MONGODB_VERSION: 4.0.27 + MONGODB_VERSION: 4.0.28 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: mmapv1 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: Redis Cache PARSE_SERVER_TEST_CACHE: redis - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: Node 12 - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 12.22.7 + NODE_VERSION: 12.22.11 - name: Node 14 - MONGODB_VERSION: 4.4.10 + MONGODB_VERSION: 4.4.13 MONGODB_TOPOLOGY: standalone MONGODB_STORAGE_ENGINE: wiredTiger - NODE_VERSION: 14.18.1 + NODE_VERSION: 14.19.1 fail-fast: false name: ${{ matrix.name }} timeout-minutes: 15 @@ -193,22 +193,22 @@ jobs: include: - name: PostgreSQL 11, PostGIS 3.0 POSTGRES_IMAGE: postgis/postgis:11-3.0 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 11, PostGIS 3.1 POSTGRES_IMAGE: postgis/postgis:11-3.1 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 11, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:11-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 12, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:12-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 13, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:13-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 - name: PostgreSQL 14, PostGIS 3.2 POSTGRES_IMAGE: postgis/postgis:14-3.2 - NODE_VERSION: 16.13.0 + NODE_VERSION: 16.14.2 fail-fast: false name: ${{ matrix.name }} timeout-minutes: 15 diff --git a/README.md b/README.md index dc14dd7f1a..b321392fa5 100644 --- a/README.md +++ b/README.md @@ -114,9 +114,9 @@ Parse Server is continuously tested with the most recent releases of Node.js to | Version | Latest Version | End-of-Life | Compatible | |------------|----------------|-------------|--------------| -| 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 12 | 12.22.11 | April 2022 | ✅ Yes | +| Node.js 14 | 14.19.1 | April 2023 | ✅ Yes | +| Node.js 16 | 16.14.2 | April 2024 | ✅ Yes | | Node.js 17 | 17.x | June 2022 | ❌ Not tested | #### MongoDB @@ -124,9 +124,9 @@ Parse Server is continuously tested with the most recent releases of MongoDB to | Version | Latest Version | End-of-Life | Compatible | |-------------|----------------|-------------|------------| -| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes | -| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes | -| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes | +| MongoDB 4.0 | 4.0.28 | April 2022 | ✅ Yes | +| MongoDB 4.2 | 4.2.19 | TBD | ✅ Yes | +| MongoDB 4.4 | 4.4.13 | TBD | ✅ Yes | | MongoDB 5.0 | 5.0.6 | TBD | ✅ Yes | | MongoDB 5.1 | 5.1.1 | TBD | ✅ Yes | | MongoDB 5.2 | 5.2.1 | TBD | ✅ Yes | diff --git a/package.json b/package.json index 7aa9f07f4a..dfbd9b4097 100644 --- a/package.json +++ b/package.json @@ -116,9 +116,9 @@ "test:mongodb:runnerstart": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start", "test:mongodb:testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=$npm_config_dbversion} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine", "test:mongodb": "npm run test:mongodb:runnerstart --dbversion=$npm_config_dbversion && npm run test:mongodb:testonly --dbversion=$npm_config_dbversion", - "test:mongodb:4.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:4.0.28": "npm run test:mongodb --dbversion=4.0.28", + "test:mongodb:4.2.19": "npm run test:mongodb --dbversion=4.2.19", + "test:mongodb:4.4.13": "npm run test:mongodb --dbversion=4.4.13", "test:mongodb:5.0.6": "npm run test:mongodb --dbversion=5.0.6", "test:mongodb:5.1.1": "npm run test:mongodb --dbversion=5.1.1", "test:mongodb:5.2.1": "npm run test:mongodb --dbversion=5.2.1", From 2b0957cb4eb09d068674d949384c3c7e502e57e9 Mon Sep 17 00:00:00 2001 From: Antoine Cormouls Date: Mon, 4 Apr 2022 01:40:29 +0200 Subject: [PATCH 16/46] refactor: add missing schema definitions (#7917) --- resources/buildConfigDefinitions.js | 36 ++++++------ src/Options/Definitions.js | 89 ++++++++++++++++------------- src/Options/docs.js | 12 ++++ src/Options/index.js | 27 ++++++++- src/SchemaMigrations/Migrations.js | 21 ++++--- 5 files changed, 116 insertions(+), 69 deletions(-) diff --git a/resources/buildConfigDefinitions.js b/resources/buildConfigDefinitions.js index 670aafad38..b41c53f07c 100644 --- a/resources/buildConfigDefinitions.js +++ b/resources/buildConfigDefinitions.js @@ -23,23 +23,25 @@ const nestedOptionTypes = [ 'PagesRoute', 'PasswordPolicyOptions', 'SecurityOptions', + 'SchemaOptions', ]; /** The prefix of environment variables for nested options. */ const nestedOptionEnvPrefix = { - 'AccountLockoutOptions' : 'PARSE_SERVER_ACCOUNT_LOCKOUT_', - 'CustomPagesOptions' : 'PARSE_SERVER_CUSTOM_PAGES_', + 'AccountLockoutOptions': 'PARSE_SERVER_ACCOUNT_LOCKOUT_', + 'CustomPagesOptions': 'PARSE_SERVER_CUSTOM_PAGES_', 'DatabaseOptions': 'PARSE_SERVER_DATABASE_', - 'FileUploadOptions' : 'PARSE_SERVER_FILE_UPLOAD_', - 'IdempotencyOptions' : 'PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_', - 'LiveQueryOptions' : 'PARSE_SERVER_LIVEQUERY_', - 'LiveQueryServerOptions' : 'PARSE_LIVE_QUERY_SERVER_', - 'PagesCustomUrlsOptions' : 'PARSE_SERVER_PAGES_CUSTOM_URL_', - 'PagesOptions' : 'PARSE_SERVER_PAGES_', + 'FileUploadOptions': 'PARSE_SERVER_FILE_UPLOAD_', + 'IdempotencyOptions': 'PARSE_SERVER_EXPERIMENTAL_IDEMPOTENCY_', + 'LiveQueryOptions': 'PARSE_SERVER_LIVEQUERY_', + 'LiveQueryServerOptions': 'PARSE_LIVE_QUERY_SERVER_', + 'PagesCustomUrlsOptions': 'PARSE_SERVER_PAGES_CUSTOM_URL_', + 'PagesOptions': 'PARSE_SERVER_PAGES_', 'PagesRoute': 'PARSE_SERVER_PAGES_ROUTE_', - 'ParseServerOptions' : 'PARSE_SERVER_', - 'PasswordPolicyOptions' : 'PARSE_SERVER_PASSWORD_POLICY_', + 'ParseServerOptions': 'PARSE_SERVER_', + 'PasswordPolicyOptions': 'PARSE_SERVER_PASSWORD_POLICY_', 'SecurityOptions': 'PARSE_SERVER_SECURITY_', + 'SchemaOptions': 'PARSE_SERVER_SCHEMA_', }; function last(array) { @@ -50,7 +52,7 @@ const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' function toENV(key) { let str = ''; let previousIsUpper = false; - for(let i = 0; i < key.length; i++) { + for (let i = 0; i < key.length; i++) { const char = key[i]; if (letters.indexOf(char) >= 0) { if (!previousIsUpper) { @@ -273,8 +275,8 @@ function inject(t, list) { return { results, comments }; } -const makeRequire = function(variableName, module, t) { - const decl = t.variableDeclarator(t.identifier(variableName), t.callExpression(t.identifier('require'), [t.stringLiteral(module)])); +const makeRequire = function (variableName, module, t) { + const decl = t.variableDeclarator(t.identifier(variableName), t.callExpression(t.identifier('require'), [t.stringLiteral(module)])); return t.variableDeclaration('var', [decl]) } let docs = ``; @@ -283,14 +285,14 @@ const plugin = function (babel) { const moduleExports = t.memberExpression(t.identifier('module'), t.identifier('exports')); return { visitor: { - ImportDeclaration: function(path) { + ImportDeclaration: function (path) { path.remove(); }, - Program: function(path) { + Program: function (path) { // Inject the parser's loader path.unshiftContainer('body', makeRequire('parsers', './parsers', t)); }, - ExportDeclaration: function(path) { + ExportDeclaration: function (path) { // Export declaration on an interface if (path.node && path.node.declaration && path.node.declaration.type == 'InterfaceDeclaration') { const { results, comments } = inject(t, doInterface(path.node.declaration)); @@ -313,6 +315,6 @@ Do not edit manually, but update Options/index.js ` const babel = require("@babel/core"); -const res = babel.transformFileSync('./src/Options/index.js', { plugins: [ plugin, '@babel/transform-flow-strip-types' ], babelrc: false, auxiliaryCommentBefore, sourceMaps: false }); +const res = babel.transformFileSync('./src/Options/index.js', { plugins: [plugin, '@babel/transform-flow-strip-types'], babelrc: false, auxiliaryCommentBefore, sourceMaps: false }); require('fs').writeFileSync('./src/Options/Definitions.js', res.code + '\n'); require('fs').writeFileSync('./src/Options/docs.js', docs); diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index 1edd704bd6..f8b8eab633 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -5,6 +5,51 @@ Do not edit manually, but update Options/index.js */ var parsers = require('./parsers'); +module.exports.SchemaOptions = { + afterMigration: { + env: 'PARSE_SERVER_SCHEMA_AFTER_MIGRATION', + help: 'Execute a callback after running schema migrations.', + }, + beforeMigration: { + env: 'PARSE_SERVER_SCHEMA_BEFORE_MIGRATION', + help: 'Execute a callback before running schema migrations.', + }, + definitions: { + env: 'PARSE_SERVER_SCHEMA_DEFINITIONS', + help: + 'Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema', + required: true, + action: parsers.objectParser, + default: [], + }, + deleteExtraFields: { + env: 'PARSE_SERVER_SCHEMA_DELETE_EXTRA_FIELDS', + help: + 'Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development.', + action: parsers.booleanParser, + default: false, + }, + lockSchemas: { + env: 'PARSE_SERVER_SCHEMA_LOCK_SCHEMAS', + help: + 'Is true if Parse Server will reject any attempts to modify the schema while the server is running.', + action: parsers.booleanParser, + default: false, + }, + recreateModifiedFields: { + env: 'PARSE_SERVER_SCHEMA_RECREATE_MODIFIED_FIELDS', + help: + 'Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development.', + action: parsers.booleanParser, + default: false, + }, + strict: { + env: 'PARSE_SERVER_SCHEMA_STRICT', + help: 'Is true if Parse Server should exit if schema update fail.', + action: parsers.booleanParser, + default: false, + }, +}; module.exports.ParseServerOptions = { accountLockout: { env: 'PARSE_SERVER_ACCOUNT_LOCKOUT', @@ -385,6 +430,11 @@ module.exports.ParseServerOptions = { action: parsers.booleanParser, default: false, }, + schema: { + env: 'PARSE_SERVER_SCHEMA', + help: 'Defined schema', + action: parsers.objectParser, + }, security: { env: 'PARSE_SERVER_SECURITY', help: 'The security options to identify and report weak security settings.', @@ -464,45 +514,6 @@ module.exports.SecurityOptions = { default: false, }, }; -module.exports.SchemaOptions = { - definitions: { - help: 'The schema definitions.', - default: [], - }, - strict: { - env: 'PARSE_SERVER_SCHEMA_STRICT', - help: 'Is true if Parse Server should exit if schema update fail.', - action: parsers.booleanParser, - default: true, - }, - deleteExtraFields: { - env: 'PARSE_SERVER_SCHEMA_DELETE_EXTRA_FIELDS', - help: - 'Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development.', - action: parsers.booleanParser, - default: false, - }, - recreateModifiedFields: { - env: 'PARSE_SERVER_SCHEMA_RECREATE_MODIFIED_FIELDS', - help: - 'Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development.', - action: parsers.booleanParser, - default: false, - }, - lockSchemas: { - env: 'PARSE_SERVER_SCHEMA_LOCK', - help: - 'Is true if Parse Server will reject any attempts to modify the schema while the server is running.', - action: parsers.booleanParser, - default: false, - }, - beforeMigration: { - help: 'Execute a callback before running schema migrations.', - }, - afterMigration: { - help: 'Execute a callback after running schema migrations.', - }, -}; module.exports.PagesOptions = { customRoutes: { env: 'PARSE_SERVER_PAGES_CUSTOM_ROUTES', diff --git a/src/Options/docs.js b/src/Options/docs.js index fc0ff3b799..24b60c46a9 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -1,3 +1,14 @@ +/** + * @interface SchemaOptions + * @property {Function} afterMigration Execute a callback after running schema migrations. + * @property {Function} beforeMigration Execute a callback before running schema migrations. + * @property {Any} definitions Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema + * @property {Boolean} deleteExtraFields Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development. + * @property {Boolean} lockSchemas Is true if Parse Server will reject any attempts to modify the schema while the server is running. + * @property {Boolean} recreateModifiedFields Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development. + * @property {Boolean} strict Is true if Parse Server should exit if schema update fail. + */ + /** * @interface ParseServerOptions * @property {AccountLockoutOptions} accountLockout The account lockout policy for failed login attempts. @@ -68,6 +79,7 @@ * @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. + * @property {SchemaOptions} schema Defined schema * @property {SecurityOptions} security The security options to identify and report weak security settings. * @property {Function} serverCloseComplete Callback when server has closed * @property {Function} serverStartComplete Callback when server has started diff --git a/src/Options/index.js b/src/Options/index.js index 3482d88c50..8124446f99 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -8,7 +8,28 @@ import { MailAdapter } from '../Adapters/Email/MailAdapter'; import { PubSubAdapter } from '../Adapters/PubSub/PubSubAdapter'; import { WSSAdapter } from '../Adapters/WebSocketServer/WSSAdapter'; import { CheckGroup } from '../Security/CheckGroup'; -import type { SchemaOptions } from '../SchemaMigrations/Migrations'; + +export interface SchemaOptions { + /* Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema + :DEFAULT: [] */ + definitions: any; + /* Is true if Parse Server should exit if schema update fail. + :DEFAULT: false */ + strict: ?boolean; + /* Is true if Parse Server should delete any fields not defined in a schema definition. This should only be used during development. + :DEFAULT: false */ + deleteExtraFields: ?boolean; + /* Is true if Parse Server should recreate any fields that are different between the current database schema and theschema definition. This should only be used during development. + :DEFAULT: false */ + recreateModifiedFields: ?boolean; + /* Is true if Parse Server will reject any attempts to modify the schema while the server is running. + :DEFAULT: false */ + lockSchemas: ?boolean; + /* Execute a callback before running schema migrations. */ + beforeMigration: ?() => void | Promise; + /* Execute a callback after running schema migrations. */ + afterMigration: ?() => void | Promise; +} type Adapter = string | any | T; type NumberOrBoolean = number | boolean; @@ -246,7 +267,9 @@ export interface ParseServerOptions { playgroundPath: ?string; /* Callback when server has started */ serverStartComplete: ?(error: ?Error) => void; - /* Rest representation on Parse.Schema https://docs.parseplatform.org/rest/guide/#adding-a-schema */ + /* Defined schema + :ENV: PARSE_SERVER_SCHEMA + */ schema: ?SchemaOptions; /* Callback when server has closed */ serverCloseComplete: ?() => void; diff --git a/src/SchemaMigrations/Migrations.js b/src/SchemaMigrations/Migrations.js index 9142cdbcde..8768911189 100644 --- a/src/SchemaMigrations/Migrations.js +++ b/src/SchemaMigrations/Migrations.js @@ -1,5 +1,15 @@ // @flow +export interface SchemaOptions { + definitions: JSONSchema[]; + strict: ?boolean; + deleteExtraFields: ?boolean; + recreateModifiedFields: ?boolean; + lockSchemas: ?boolean; + beforeMigration: ?() => void | Promise; + afterMigration: ?() => void | Promise; +} + export type FieldValueType = | 'String' | 'Boolean' @@ -35,17 +45,6 @@ export interface IndexesInterface { [key: string]: IndexInterface; } -export interface SchemaOptions { - definitions: JSONSchema[]; - strict: ?boolean; - deleteExtraFields: ?boolean; - recreateModifiedFields: ?boolean; - lockSchemas: ?boolean; - /* Callback when server has started and before running schemas migration operations if schemas key provided */ - beforeMigration: ?() => void | Promise; - afterMigration: ?() => void | Promise; -} - export type CLPOperation = 'find' | 'count' | 'get' | 'update' | 'create' | 'delete'; // @Typescript 4.1+ // type CLPPermission = 'requiresAuthentication' | '*' | `user:${string}` | `role:${string}` From a72b384f76137a3d83ffb69f65cb25aff1bbab4f Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 4 Apr 2022 10:04:37 +1000 Subject: [PATCH 17/46] fix: custom database options are not passed to MongoDB GridFS (#7911) --- spec/FilesController.spec.js | 14 ++++++++++++++ src/Controllers/index.js | 12 ++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/spec/FilesController.spec.js b/spec/FilesController.spec.js index 9ea66da6ea..8fee5aca2f 100644 --- a/spec/FilesController.spec.js +++ b/spec/FilesController.spec.js @@ -43,6 +43,20 @@ describe('FilesController', () => { done(); }); + it_only_db('mongo')('should pass databaseOptions to GridFSBucketAdapter', async () => { + await reconfigureServer({ + databaseURI: 'mongodb://localhost:27017/parse', + filesAdapter: null, + databaseAdapter: null, + databaseOptions: { + retryWrites: true, + }, + }); + const config = Config.get(Parse.applicationId); + expect(config.database.adapter._mongoOptions.retryWrites).toBeTrue(); + expect(config.filesController.adapter._mongoOptions.retryWrites).toBeTrue(); + }); + it('should create a server log on failure', done => { const logController = new LoggerController(new WinstonLoggerAdapter()); diff --git a/src/Controllers/index.js b/src/Controllers/index.js index b2feff0fc2..0a9b3db57d 100644 --- a/src/Controllers/index.js +++ b/src/Controllers/index.js @@ -91,12 +91,20 @@ export function getLoggerController(options: ParseServerOptions): LoggerControll } export function getFilesController(options: ParseServerOptions): FilesController { - const { appId, databaseURI, filesAdapter, databaseAdapter, preserveFileName, fileKey } = options; + const { + appId, + databaseURI, + databaseOptions = {}, + filesAdapter, + databaseAdapter, + preserveFileName, + fileKey, + } = options; if (!filesAdapter && databaseAdapter) { throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.'; } const filesControllerAdapter = loadAdapter(filesAdapter, () => { - return new GridFSBucketAdapter(databaseURI, {}, fileKey); + return new GridFSBucketAdapter(databaseURI, databaseOptions, fileKey); }); return new FilesController(filesControllerAdapter, appId, { preserveFileName, From 0b929dbeb3b731415163d4c90abc9d938c81a526 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 4 Apr 2022 00:22:45 +0000 Subject: [PATCH 18/46] chore(release): 5.3.0-alpha.4 [skip ci] # [5.3.0-alpha.4](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.3...5.3.0-alpha.4) (2022-04-04) ### Bug Fixes * custom database options are not passed to MongoDB GridFS ([#7911](https://github.com/parse-community/parse-server/issues/7911)) ([a72b384](https://github.com/parse-community/parse-server/commit/a72b384f76137a3d83ffb69f65cb25aff1bbab4f)) --- 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 888add258c..9c61249c0e 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.3.0-alpha.4](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.3...5.3.0-alpha.4) (2022-04-04) + + +### Bug Fixes + +* custom database options are not passed to MongoDB GridFS ([#7911](https://github.com/parse-community/parse-server/issues/7911)) ([a72b384](https://github.com/parse-community/parse-server/commit/a72b384f76137a3d83ffb69f65cb25aff1bbab4f)) + # [5.3.0-alpha.3](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.2...5.3.0-alpha.3) (2022-03-27) diff --git a/package-lock.json b/package-lock.json index 8a0335dede..4a9ebba5fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.3", + "version": "5.3.0-alpha.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index dfbd9b4097..feb577a4b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.3", + "version": "5.3.0-alpha.4", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From cbdf7e81f2f025a8d7fe4a4850f39fa88fa09e2e Mon Sep 17 00:00:00 2001 From: dblythy Date: Wed, 6 Apr 2022 02:27:45 +1000 Subject: [PATCH 19/46] Update ParseServer.js --- src/ParseServer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ParseServer.js b/src/ParseServer.js index 2a61f14c68..8a5db315a8 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -332,7 +332,8 @@ class ParseServer { /** * @static * Create an async parse server - * @param {ParseServerOptions} options the parse server initialization options */ + * @param {ParseServerOptions} options the parse server initialization options + */ static createAsync(options) { return new Promise((resolve, reject) => { const parseServer = new ParseServer({ From ef3680abca3a561e21669a215b73edf099999ac9 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Sat, 9 Apr 2022 21:00:11 +0100 Subject: [PATCH 20/46] refactor: upgrade @apollo/client from 3.5.8 to 3.5.9 (#7921) --- 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 4a9ebba5fc..7f98079965 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,9 @@ "dev": true }, "@apollo/client": { - "version": "3.5.8", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.8.tgz", - "integrity": "sha512-MAm05+I1ullr64VLpZwon/ISnkMuNLf6vDqgo9wiMhHYBGT4yOAbAIseRdjCHZwfSx/7AUuBgaTNOssZPIr6FQ==", + "version": "3.5.9", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.5.9.tgz", + "integrity": "sha512-Qq3OE3GpyPG2fYXBzi1n4QXcKZ11c6jHdrXK2Kkn9SD+vUymSrllXsldqnKUK9tslxKqkKzNrkCXkLv7PxwfSQ==", "requires": { "@graphql-typed-document-node/core": "^3.0.0", "@wry/context": "^0.6.0", diff --git a/package.json b/package.json index feb577a4b3..5ac57aa4ba 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ ], "license": "BSD-3-Clause", "dependencies": { - "@apollo/client": "3.5.8", + "@apollo/client": "3.5.9", "@apollographql/graphql-playground-html": "1.6.29", "@graphql-tools/links": "8.2.2", "@graphql-tools/stitch": "6.2.4", From 6b68593eaec17e8b183899d2b92699c9ede7625b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 9 Apr 2022 22:42:21 +0200 Subject: [PATCH 21/46] fix: security upgrade moment from 2.29.1 to 2.29.2 (#7931) --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7f98079965..a14194094a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10442,9 +10442,9 @@ } }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", + "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==" }, "mongodb": { "version": "4.4.1", From e88fb726dc15d875d5501c33fbc5fc9fd7226216 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 9 Apr 2022 20:44:41 +0000 Subject: [PATCH 22/46] chore(release): 5.3.0-alpha.5 [skip ci] # [5.3.0-alpha.5](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.4...5.3.0-alpha.5) (2022-04-09) ### Bug Fixes * security upgrade moment from 2.29.1 to 2.29.2 ([#7931](https://github.com/parse-community/parse-server/issues/7931)) ([6b68593](https://github.com/parse-community/parse-server/commit/6b68593eaec17e8b183899d2b92699c9ede7625b)) --- 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 9c61249c0e..8813d2f3b2 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.3.0-alpha.5](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.4...5.3.0-alpha.5) (2022-04-09) + + +### Bug Fixes + +* security upgrade moment from 2.29.1 to 2.29.2 ([#7931](https://github.com/parse-community/parse-server/issues/7931)) ([6b68593](https://github.com/parse-community/parse-server/commit/6b68593eaec17e8b183899d2b92699c9ede7625b)) + # [5.3.0-alpha.4](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.3...5.3.0-alpha.4) (2022-04-04) diff --git a/package-lock.json b/package-lock.json index a14194094a..07f4744370 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.4", + "version": "5.3.0-alpha.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 5ac57aa4ba..9ea9975472 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.4", + "version": "5.3.0-alpha.5", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From b7a1d7617b4bcac677cecedfeb6ac4a27447083b Mon Sep 17 00:00:00 2001 From: Marvin ROGER Date: Mon, 11 Apr 2022 15:55:11 +0200 Subject: [PATCH 23/46] fix: peer dependency mismatch for GraphQL dependencies (#7934) --- 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 07f4744370..31cc35f10d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7507,9 +7507,9 @@ "dev": true }, "graphql": { - "version": "15.7.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.7.1.tgz", - "integrity": "sha512-x34S6gC0/peBZnlK60zCJox/d45A7p6At9oN9EPA3qhoIAlR4LNZmXRLkICBckwwTMJzVdA8cx3QIQZMOl606A==" + "version": "15.8.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz", + "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==" }, "graphql-executor": { "version": "0.0.18", diff --git a/package.json b/package.json index 9ea9975472..c4272e1b5e 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "deepcopy": "2.1.0", "express": "4.17.2", "follow-redirects": "1.14.8", - "graphql": "15.7.1", + "graphql": "15.8.0", "graphql-list-fields": "2.0.2", "graphql-relay": "0.7.0", "graphql-tag": "2.12.6", From 34b8110c4b50d383c0c48c780192ffb03132c794 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 11 Apr 2022 13:56:07 +0000 Subject: [PATCH 24/46] chore(release): 5.3.0-alpha.6 [skip ci] # [5.3.0-alpha.6](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.5...5.3.0-alpha.6) (2022-04-11) ### Bug Fixes * peer dependency mismatch for GraphQL dependencies ([#7934](https://github.com/parse-community/parse-server/issues/7934)) ([b7a1d76](https://github.com/parse-community/parse-server/commit/b7a1d7617b4bcac677cecedfeb6ac4a27447083b)) --- 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 8813d2f3b2..dcd26cb178 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.3.0-alpha.6](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.5...5.3.0-alpha.6) (2022-04-11) + + +### Bug Fixes + +* peer dependency mismatch for GraphQL dependencies ([#7934](https://github.com/parse-community/parse-server/issues/7934)) ([b7a1d76](https://github.com/parse-community/parse-server/commit/b7a1d7617b4bcac677cecedfeb6ac4a27447083b)) + # [5.3.0-alpha.5](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.4...5.3.0-alpha.5) (2022-04-09) diff --git a/package-lock.json b/package-lock.json index 31cc35f10d..862b989af0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.5", + "version": "5.3.0-alpha.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c4272e1b5e..e099363bc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.5", + "version": "5.3.0-alpha.6", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From 43ad5b34821813aa29b2deff0ce81ff2815b8708 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 11 Apr 2022 21:16:41 +0100 Subject: [PATCH 25/46] refactor: upgrade @graphql-tools/links from 8.2.2 to 8.2.4 (#7932) --- package-lock.json | 68 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 862b989af0..8a30449748 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1198,20 +1198,20 @@ } }, "@graphql-tools/batch-execute": { - "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==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.3.3.tgz", + "integrity": "sha512-22q/uCMUf+z3EWoM3ZM6DopDBGkni2TsfUb/mJIysunh5u8btAuXeju++De7RFwwUw+awdJXfunFQJG+OoH5Dg==", "requires": { - "@graphql-tools/utils": "^8.6.2", + "@graphql-tools/utils": "8.6.3", "dataloader": "2.0.0", "tslib": "~2.3.0", "value-or-promise": "1.0.11" }, "dependencies": { "@graphql-tools/utils": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.2.tgz", - "integrity": "sha512-x1DG0cJgpJtImUlNE780B/dfp8pxvVxOD6UeykFH5rHes26S4kGokbgU8F1IgrJ1vAPm/OVBHtd2kicTsPfwdA==", + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.3.tgz", + "integrity": "sha512-CNyP7Uu7dlVMQ32IpHWOxz4yic9BYXXVkDhG0UdTKSszvzHdgMilemE9MpUrGzzBPsTe3aYTtNGyPUkyh9yTXA==", "requires": { "tslib": "~2.3.0" } @@ -1242,12 +1242,12 @@ } }, "@graphql-tools/links": { - "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==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.4.tgz", + "integrity": "sha512-110WRC6VORKl+/9olmJva3gEhhK/qB4kJ6rrKVP2l9YfNdPQ50y/NemtixHNSP6d+WQ77sdvDPDXqLaT/v+q1w==", "requires": { - "@graphql-tools/delegate": "^8.5.1", - "@graphql-tools/utils": "^8.6.2", + "@graphql-tools/delegate": "8.5.4", + "@graphql-tools/utils": "8.6.3", "apollo-upload-client": "17.0.0", "form-data": "^4.0.0", "node-fetch": "^2.6.5", @@ -1255,43 +1255,43 @@ }, "dependencies": { "@graphql-tools/delegate": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.5.1.tgz", - "integrity": "sha512-/YPmVxitt57F8sH50pnfXASzOOjEfaUDkX48eF5q6f16+JBncej2zeu+Zm2c68q8MbIxhPlEGfpd0QZeqTvAxw==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.5.4.tgz", + "integrity": "sha512-+3BCgSPCp/HoeOBjhz6X7RY7HMCNBanz/wkxo0/e4rk8TqJ3sjZCH470SHvsxCsBIlMwx4FYwkmxePgX/V+0Cg==", "requires": { - "@graphql-tools/batch-execute": "^8.3.2", - "@graphql-tools/schema": "^8.3.2", - "@graphql-tools/utils": "^8.6.2", + "@graphql-tools/batch-execute": "8.3.3", + "@graphql-tools/schema": "8.3.3", + "@graphql-tools/utils": "8.6.3", "dataloader": "2.0.0", - "graphql-executor": "0.0.18", + "graphql-executor": "0.0.19", "tslib": "~2.3.0", "value-or-promise": "1.0.11" } }, "@graphql-tools/merge": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.3.tgz", - "integrity": "sha512-XCSmL6/Xg8259OTWNp69B57CPWiVL69kB7pposFrufG/zaAlI9BS68dgzrxmmSqZV5ZHU4r/6Tbf6fwnEJGiSw==", + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.4.tgz", + "integrity": "sha512-hiNRTsS948F+BB4Q7CZXLaGFOIHQzmimVq3EEI/+PQZsPb7kYDzg0Ow0GyV4conDdEiooLqHf7I1dWzTYwvs0A==", "requires": { - "@graphql-tools/utils": "^8.6.2", + "@graphql-tools/utils": "8.6.3", "tslib": "~2.3.0" } }, "@graphql-tools/schema": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.2.tgz", - "integrity": "sha512-77feSmIuHdoxMXRbRyxE8rEziKesd/AcqKV6fmxe7Zt+PgIQITxNDew2XJJg7qFTMNM43W77Ia6njUSBxNOkwg==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.3.tgz", + "integrity": "sha512-OrRLU9/7UmkDemeyNUy62uH+FofgV3bpVVZJprc9bhe3gZsY7kQNIdY7H1unINlepjLvGOgk7u7iLo2+EhjyWw==", "requires": { - "@graphql-tools/merge": "^8.2.3", - "@graphql-tools/utils": "^8.6.2", + "@graphql-tools/merge": "8.2.4", + "@graphql-tools/utils": "8.6.3", "tslib": "~2.3.0", "value-or-promise": "1.0.11" } }, "@graphql-tools/utils": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.2.tgz", - "integrity": "sha512-x1DG0cJgpJtImUlNE780B/dfp8pxvVxOD6UeykFH5rHes26S4kGokbgU8F1IgrJ1vAPm/OVBHtd2kicTsPfwdA==", + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.3.tgz", + "integrity": "sha512-CNyP7Uu7dlVMQ32IpHWOxz4yic9BYXXVkDhG0UdTKSszvzHdgMilemE9MpUrGzzBPsTe3aYTtNGyPUkyh9yTXA==", "requires": { "tslib": "~2.3.0" } @@ -7512,9 +7512,9 @@ "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==" }, "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==" + "version": "0.0.19", + "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.19.tgz", + "integrity": "sha512-AFOcsk/yMtl9jcO/f/0Our7unWxJ5m3FS5HjWfsXRHCyjjaubXpSHiOZO/hSYv6brayIrupDoVAzCuJpBc3elg==" }, "graphql-extensions": { "version": "0.15.0", diff --git a/package.json b/package.json index e099363bc2..6236fa9795 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@apollo/client": "3.5.9", "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/links": "8.2.2", + "@graphql-tools/links": "8.2.4", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", From b45d44e666c590cd2e30f54312f8721edc40ee9b Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Fri, 15 Apr 2022 10:47:47 +0100 Subject: [PATCH 26/46] refactor: upgrade @graphql-tools/links from 8.2.4 to 8.2.6 (#7935) --- package-lock.json | 68 +++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8a30449748..7a79dc3c8a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1198,20 +1198,20 @@ } }, "@graphql-tools/batch-execute": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.3.3.tgz", - "integrity": "sha512-22q/uCMUf+z3EWoM3ZM6DopDBGkni2TsfUb/mJIysunh5u8btAuXeju++De7RFwwUw+awdJXfunFQJG+OoH5Dg==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-8.4.1.tgz", + "integrity": "sha512-63+lNWrwXmofjZVa7ML+n9CBviClF3K+RP3Xx3hxGQ8BrhvB1pWS1yzaUZqrkiiKdTu1v3mJGVfmooHwzlyPwQ==", "requires": { - "@graphql-tools/utils": "8.6.3", + "@graphql-tools/utils": "8.6.5", "dataloader": "2.0.0", "tslib": "~2.3.0", "value-or-promise": "1.0.11" }, "dependencies": { "@graphql-tools/utils": { - "version": "8.6.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.3.tgz", - "integrity": "sha512-CNyP7Uu7dlVMQ32IpHWOxz4yic9BYXXVkDhG0UdTKSszvzHdgMilemE9MpUrGzzBPsTe3aYTtNGyPUkyh9yTXA==", + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.5.tgz", + "integrity": "sha512-mjOtaWiS2WIqRz/cq5gaeM3sVrllcu2xbtHROw1su1v3xWa3D3dKgn8Lrl7+tvWs5WUVySsBss/VZ3WdoPkCrA==", "requires": { "tslib": "~2.3.0" } @@ -1242,12 +1242,12 @@ } }, "@graphql-tools/links": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.4.tgz", - "integrity": "sha512-110WRC6VORKl+/9olmJva3gEhhK/qB4kJ6rrKVP2l9YfNdPQ50y/NemtixHNSP6d+WQ77sdvDPDXqLaT/v+q1w==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.6.tgz", + "integrity": "sha512-5+T1xONiedSYKLujk3dou0roiDyIr22MhyHVqQuw29nqy2Hal5IM3+oGPhqRHOLFEkgnASMKf+0VUIK69chc8g==", "requires": { - "@graphql-tools/delegate": "8.5.4", - "@graphql-tools/utils": "8.6.3", + "@graphql-tools/delegate": "8.6.1", + "@graphql-tools/utils": "8.6.5", "apollo-upload-client": "17.0.0", "form-data": "^4.0.0", "node-fetch": "^2.6.5", @@ -1255,43 +1255,43 @@ }, "dependencies": { "@graphql-tools/delegate": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.5.4.tgz", - "integrity": "sha512-+3BCgSPCp/HoeOBjhz6X7RY7HMCNBanz/wkxo0/e4rk8TqJ3sjZCH470SHvsxCsBIlMwx4FYwkmxePgX/V+0Cg==", + "version": "8.6.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.6.1.tgz", + "integrity": "sha512-cah5ZGguJGN+6Ts94guhqWTq+Ymtjc5MLnCNFYOtHoGG82zXUE4ip84samvWUaf/u+kCQEgkA0IFTIvhcjrpGw==", "requires": { - "@graphql-tools/batch-execute": "8.3.3", - "@graphql-tools/schema": "8.3.3", - "@graphql-tools/utils": "8.6.3", + "@graphql-tools/batch-execute": "8.4.1", + "@graphql-tools/schema": "8.3.5", + "@graphql-tools/utils": "8.6.5", "dataloader": "2.0.0", - "graphql-executor": "0.0.19", + "graphql-executor": "0.0.21", "tslib": "~2.3.0", "value-or-promise": "1.0.11" } }, "@graphql-tools/merge": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.4.tgz", - "integrity": "sha512-hiNRTsS948F+BB4Q7CZXLaGFOIHQzmimVq3EEI/+PQZsPb7kYDzg0Ow0GyV4conDdEiooLqHf7I1dWzTYwvs0A==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.2.6.tgz", + "integrity": "sha512-dkwTm4czMISi/Io47IVvq2Fl9q4TIGKpJ0VZjuXYdEFkECyH6A5uwxZfPVandZG+gQs8ocFFoa6RisiUJLZrJw==", "requires": { - "@graphql-tools/utils": "8.6.3", + "@graphql-tools/utils": "8.6.5", "tslib": "~2.3.0" } }, "@graphql-tools/schema": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.3.tgz", - "integrity": "sha512-OrRLU9/7UmkDemeyNUy62uH+FofgV3bpVVZJprc9bhe3gZsY7kQNIdY7H1unINlepjLvGOgk7u7iLo2+EhjyWw==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.5.tgz", + "integrity": "sha512-3mJ/K7TdL+fnEUtCUqF4qkh1fcNMzaxgwKgO9fSYSTS7zyT16hbi5XSulSTshygHgaD2u+MO588iR4ZJcbZcIg==", "requires": { - "@graphql-tools/merge": "8.2.4", - "@graphql-tools/utils": "8.6.3", + "@graphql-tools/merge": "8.2.6", + "@graphql-tools/utils": "8.6.5", "tslib": "~2.3.0", "value-or-promise": "1.0.11" } }, "@graphql-tools/utils": { - "version": "8.6.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.3.tgz", - "integrity": "sha512-CNyP7Uu7dlVMQ32IpHWOxz4yic9BYXXVkDhG0UdTKSszvzHdgMilemE9MpUrGzzBPsTe3aYTtNGyPUkyh9yTXA==", + "version": "8.6.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-8.6.5.tgz", + "integrity": "sha512-mjOtaWiS2WIqRz/cq5gaeM3sVrllcu2xbtHROw1su1v3xWa3D3dKgn8Lrl7+tvWs5WUVySsBss/VZ3WdoPkCrA==", "requires": { "tslib": "~2.3.0" } @@ -7512,9 +7512,9 @@ "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==" }, "graphql-executor": { - "version": "0.0.19", - "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.19.tgz", - "integrity": "sha512-AFOcsk/yMtl9jcO/f/0Our7unWxJ5m3FS5HjWfsXRHCyjjaubXpSHiOZO/hSYv6brayIrupDoVAzCuJpBc3elg==" + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.21.tgz", + "integrity": "sha512-XGq8batWbqptkR4PNm7WlbeDya2YEurwQUUH5v0XNxQ1/XguB9nKfJjzPKCNEM6RiB0L3rZ7wAFt3oh6B+ikrQ==" }, "graphql-extensions": { "version": "0.15.0", diff --git a/package.json b/package.json index 6236fa9795..5df19a9f0b 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@apollo/client": "3.5.9", "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/links": "8.2.4", + "@graphql-tools/links": "8.2.6", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", From 8b919613f0babe1bbf524fb391b0d3853e029e68 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Sun, 17 Apr 2022 16:55:02 -0500 Subject: [PATCH 27/46] refactor: upgrade @graphql-tools/links from 8.2.6 to 8.2.7 (#7941) --- 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 7a79dc3c8a..126246b4cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1242,11 +1242,11 @@ } }, "@graphql-tools/links": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.6.tgz", - "integrity": "sha512-5+T1xONiedSYKLujk3dou0roiDyIr22MhyHVqQuw29nqy2Hal5IM3+oGPhqRHOLFEkgnASMKf+0VUIK69chc8g==", + "version": "8.2.7", + "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.7.tgz", + "integrity": "sha512-XcwAzqeAWs1ShN8/xRL2Zg4nFO27LMxlVn0wMWzKSBkxaGMS80xchmxwL2z0IOkn9kOCxyvYxyHwDSc5WmD//A==", "requires": { - "@graphql-tools/delegate": "8.6.1", + "@graphql-tools/delegate": "8.7.0", "@graphql-tools/utils": "8.6.5", "apollo-upload-client": "17.0.0", "form-data": "^4.0.0", @@ -1255,15 +1255,15 @@ }, "dependencies": { "@graphql-tools/delegate": { - "version": "8.6.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.6.1.tgz", - "integrity": "sha512-cah5ZGguJGN+6Ts94guhqWTq+Ymtjc5MLnCNFYOtHoGG82zXUE4ip84samvWUaf/u+kCQEgkA0IFTIvhcjrpGw==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.7.0.tgz", + "integrity": "sha512-tsmNFV8nVvPY2nApCj69ck32/Jdj44rYbUZx+cpyUWOzfbUT1iu0d1mUwn5UeHuGnB+Bzgn3fuTypg97mDEyEw==", "requires": { "@graphql-tools/batch-execute": "8.4.1", "@graphql-tools/schema": "8.3.5", "@graphql-tools/utils": "8.6.5", "dataloader": "2.0.0", - "graphql-executor": "0.0.21", + "graphql-executor": "0.0.22", "tslib": "~2.3.0", "value-or-promise": "1.0.11" } @@ -7512,9 +7512,9 @@ "integrity": "sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw==" }, "graphql-executor": { - "version": "0.0.21", - "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.21.tgz", - "integrity": "sha512-XGq8batWbqptkR4PNm7WlbeDya2YEurwQUUH5v0XNxQ1/XguB9nKfJjzPKCNEM6RiB0L3rZ7wAFt3oh6B+ikrQ==" + "version": "0.0.22", + "resolved": "https://registry.npmjs.org/graphql-executor/-/graphql-executor-0.0.22.tgz", + "integrity": "sha512-WbKSnSHFn6REKKH4T6UAwDM3mLUnYMQlQLNG0Fw+Lkb3ilCnL3m5lkJ7411LAI9sF7BvPbthovVZhsEUh9Xfag==" }, "graphql-extensions": { "version": "0.15.0", diff --git a/package.json b/package.json index 5df19a9f0b..531aa35b3b 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@apollo/client": "3.5.9", "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/links": "8.2.6", + "@graphql-tools/links": "8.2.7", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", From 122afcf3197b8cecd0e0e298e2d0f0338a07c8eb Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Wed, 20 Apr 2022 09:47:21 -0500 Subject: [PATCH 28/46] refactor: upgrade body-parser from 1.19.1 to 1.19.2 (#7944) --- package-lock.json | 82 ++++++++++++++++++++++++++++++++++++++--------- package.json | 2 +- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/package-lock.json b/package-lock.json index 126246b4cc..0c99ee60c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3741,19 +3741,19 @@ "dev": true }, "body-parser": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz", - "integrity": "sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", "requires": { - "bytes": "3.1.1", + "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", "http-errors": "1.8.1", "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.9.6", - "raw-body": "2.4.2", + "qs": "6.9.7", + "raw-body": "2.4.3", "type-is": "~1.6.18" }, "dependencies": { @@ -3778,9 +3778,9 @@ } }, "qs": { - "version": "6.9.6", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", - "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" }, "toidentifier": { "version": "1.0.1", @@ -3924,9 +3924,9 @@ } }, "bytes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", - "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" }, "cache-base": { "version": "1.0.1", @@ -6490,6 +6490,28 @@ "vary": "~1.1.2" }, "dependencies": { + "body-parser": { + "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.1", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.6", + "raw-body": "2.4.2", + "type-is": "~1.6.18" + } + }, + "bytes": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", + "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -6506,10 +6528,38 @@ "ms": "2.0.0" } }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, "qs": { "version": "6.9.6", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz", "integrity": "sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ==" + }, + "raw-body": { + "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.1", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" } } }, @@ -14259,11 +14309,11 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz", - "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", "requires": { - "bytes": "3.1.1", + "bytes": "3.1.2", "http-errors": "1.8.1", "iconv-lite": "0.4.24", "unpipe": "1.0.0" diff --git a/package.json b/package.json index 531aa35b3b..5547615670 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@parse/push-adapter": "4.1.2", "apollo-server-express": "2.25.2", "bcryptjs": "2.4.3", - "body-parser": "1.19.1", + "body-parser": "1.19.2", "commander": "5.1.0", "cors": "2.8.5", "deepcopy": "2.1.0", From 8868628540dca64a43da2d32c1308c9611975362 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Fri, 22 Apr 2022 12:45:43 -0500 Subject: [PATCH 29/46] refactor: upgrade @graphql-tools/links from 8.2.7 to 8.2.8 (#7945) --- 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 0c99ee60c3..69bb26e4ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1242,11 +1242,11 @@ } }, "@graphql-tools/links": { - "version": "8.2.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.7.tgz", - "integrity": "sha512-XcwAzqeAWs1ShN8/xRL2Zg4nFO27LMxlVn0wMWzKSBkxaGMS80xchmxwL2z0IOkn9kOCxyvYxyHwDSc5WmD//A==", + "version": "8.2.8", + "resolved": "https://registry.npmjs.org/@graphql-tools/links/-/links-8.2.8.tgz", + "integrity": "sha512-++4XkURFEG3VDKZK6yYeRV/+g8lQZ0kvjYQUBEmn6Zxrf0/haF4cOZhwMdc1MIaihfo615cT9BHjs9Rtd8hbmA==", "requires": { - "@graphql-tools/delegate": "8.7.0", + "@graphql-tools/delegate": "8.7.1", "@graphql-tools/utils": "8.6.5", "apollo-upload-client": "17.0.0", "form-data": "^4.0.0", @@ -1255,12 +1255,12 @@ }, "dependencies": { "@graphql-tools/delegate": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.7.0.tgz", - "integrity": "sha512-tsmNFV8nVvPY2nApCj69ck32/Jdj44rYbUZx+cpyUWOzfbUT1iu0d1mUwn5UeHuGnB+Bzgn3fuTypg97mDEyEw==", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-8.7.1.tgz", + "integrity": "sha512-e98/NRaOH5wQy624bRd5i5qUKz5tCs8u4xBmxW89d7t6V6CveXj7pvAgmnR9DbwOkO6IA3P799p/aa/YG/pWTA==", "requires": { "@graphql-tools/batch-execute": "8.4.1", - "@graphql-tools/schema": "8.3.5", + "@graphql-tools/schema": "8.3.6", "@graphql-tools/utils": "8.6.5", "dataloader": "2.0.0", "graphql-executor": "0.0.22", @@ -1278,9 +1278,9 @@ } }, "@graphql-tools/schema": { - "version": "8.3.5", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.5.tgz", - "integrity": "sha512-3mJ/K7TdL+fnEUtCUqF4qkh1fcNMzaxgwKgO9fSYSTS7zyT16hbi5XSulSTshygHgaD2u+MO588iR4ZJcbZcIg==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-8.3.6.tgz", + "integrity": "sha512-7tWYRQ8hB/rv2zAtv2LtnQl4UybyJPtRz/VLKRmgi7+F5t8iYBahmmsxMDAYMWMmWMqEDiKk54TvAes+J069rQ==", "requires": { "@graphql-tools/merge": "8.2.6", "@graphql-tools/utils": "8.6.5", diff --git a/package.json b/package.json index 5547615670..9f8b5d6c93 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "@apollo/client": "3.5.9", "@apollographql/graphql-playground-html": "1.6.29", - "@graphql-tools/links": "8.2.7", + "@graphql-tools/links": "8.2.8", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", "@parse/fs-files-adapter": "1.2.1", From 20fc4e23b53c91aac657f894bd70d049b7525c37 Mon Sep 17 00:00:00 2001 From: Snyk bot Date: Mon, 25 Apr 2022 13:30:35 +0200 Subject: [PATCH 30/46] fix: security upgrade @parse/fs-files-adapter from 1.2.1 to 1.2.2 (#7948) --- 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 69bb26e4ab..036791d7e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1839,9 +1839,9 @@ "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", - "integrity": "sha512-jUbmlvql9+5Mz8Q6KSk1jH823MVerhOYK1svayYpF03v75OtDn3p+mAoFvPS5UpRln1kT6BlBnLfw4Hv08SD5Q==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@parse/fs-files-adapter/-/fs-files-adapter-1.2.2.tgz", + "integrity": "sha512-VUsVZXgt53FULqUd9xqGDW6RXes62qHXTNOeRSlS1MOemiCdtQOUGgLHgjdYQXnZ1hPLkxZKph96AluZUb953g==" }, "@parse/minami": { "version": "1.0.0", diff --git a/package.json b/package.json index 9f8b5d6c93..e6643758c8 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@graphql-tools/links": "8.2.8", "@graphql-tools/stitch": "6.2.4", "@graphql-tools/utils": "6.2.4", - "@parse/fs-files-adapter": "1.2.1", + "@parse/fs-files-adapter": "1.2.2", "@parse/push-adapter": "4.1.2", "apollo-server-express": "2.25.2", "bcryptjs": "2.4.3", From 8cf0b5ede775289661bc5aeccb418e8d9be27bf6 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Apr 2022 11:31:38 +0000 Subject: [PATCH 31/46] chore(release): 5.3.0-alpha.7 [skip ci] # [5.3.0-alpha.7](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.6...5.3.0-alpha.7) (2022-04-25) ### Bug Fixes * security upgrade @parse/fs-files-adapter from 1.2.1 to 1.2.2 ([#7948](https://github.com/parse-community/parse-server/issues/7948)) ([20fc4e2](https://github.com/parse-community/parse-server/commit/20fc4e23b53c91aac657f894bd70d049b7525c37)) --- 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 dcd26cb178..d5004cc012 100644 --- a/changelogs/CHANGELOG_alpha.md +++ b/changelogs/CHANGELOG_alpha.md @@ -1,3 +1,10 @@ +# [5.3.0-alpha.7](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.6...5.3.0-alpha.7) (2022-04-25) + + +### Bug Fixes + +* security upgrade @parse/fs-files-adapter from 1.2.1 to 1.2.2 ([#7948](https://github.com/parse-community/parse-server/issues/7948)) ([20fc4e2](https://github.com/parse-community/parse-server/commit/20fc4e23b53c91aac657f894bd70d049b7525c37)) + # [5.3.0-alpha.6](https://github.com/parse-community/parse-server/compare/5.3.0-alpha.5...5.3.0-alpha.6) (2022-04-11) diff --git a/package-lock.json b/package-lock.json index 036791d7e5..f7b48c41fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.6", + "version": "5.3.0-alpha.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e6643758c8..3eb8c67e17 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "parse-server", - "version": "5.3.0-alpha.6", + "version": "5.3.0-alpha.7", "description": "An express module providing a Parse-compatible API server", "main": "lib/index.js", "repository": { From ac80bddaa5efc51a907db8fa4d9cb6e20ff9ca04 Mon Sep 17 00:00:00 2001 From: Manuel <5673677+mtrezza@users.noreply.github.com> Date: Wed, 27 Apr 2022 14:07:21 +0200 Subject: [PATCH 32/46] refactor: upgrade winston from 3.5.1 to 3.7.2 (#7954) --- package-lock.json | 16 ++++++++-------- package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index f7b48c41fe..51e9eb4335 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4596,9 +4596,9 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz", - "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -16890,20 +16890,20 @@ } }, "winston": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.5.1.tgz", - "integrity": "sha512-tbRtVy+vsSSCLcZq/8nXZaOie/S2tPXPFt4be/Q3vI/WtYwm7rrwidxVw2GRa38FIXcJ1kUM6MOZ9Jmnk3F3UA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz", + "integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==", "requires": { "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", - "logform": "^2.3.2", + "logform": "^2.4.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.4.2" + "winston-transport": "^4.5.0" }, "dependencies": { "async": { diff --git a/package.json b/package.json index 3eb8c67e17..dc66337d8f 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.1", + "winston": "3.7.2", "winston-daily-rotate-file": "4.6.0", "ws": "8.2.3" }, From 901a3ea6586e98a4437555884aaea11391ac0f26 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 20:31:11 +1000 Subject: [PATCH 33/46] rename method to create --- spec/CloudCode.spec.js | 2 +- spec/DefinedSchemas.spec.js | 3 ++- spec/index.spec.js | 27 ++++++++++++++++++++++++++ src/ParseServer.js | 13 ++++++++++--- src/SchemaMigrations/DefinedSchemas.js | 11 ++++++----- src/index.js | 2 +- 6 files changed, 47 insertions(+), 11 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 57a8a32c65..a59447ada2 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -43,7 +43,7 @@ describe('Cloud Code', () => { it('should wait for cloud code to load', async () => { const config = Config.get('test'); const initiated = new Date(); - const parseServer = await ParseServer.createAsync({ + const parseServer = await ParseServer.create({ ...config, async cloud() { await new Promise(resolve => setTimeout(resolve, 1000)); diff --git a/spec/DefinedSchemas.spec.js b/spec/DefinedSchemas.spec.js index 9cc164640c..5b15cb7037 100644 --- a/spec/DefinedSchemas.spec.js +++ b/spec/DefinedSchemas.spec.js @@ -595,7 +595,7 @@ describe('DefinedSchemas', () => { const logger = require('../lib/logger').logger; spyOn(DefinedSchemas.prototype, 'wait').and.resolveTo(); spyOn(logger, 'error').and.callThrough(); - spyOn(Parse.Schema, 'all').and.callFake(() => { + spyOn(DefinedSchemas.prototype, 'createDeleteSession').and.callFake(() => { throw error; }); @@ -606,6 +606,7 @@ describe('DefinedSchemas', () => { expect(logger.error).toHaveBeenCalledWith(`Failed to run migrations: ${error.toString()}`); }); + it('should perform migration in parallel without failing', async () => { const server = await reconfigureServer(); const logger = require('../lib/logger').logger; diff --git a/spec/index.spec.js b/spec/index.spec.js index dd9be1792b..29368a81e2 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -531,6 +531,33 @@ describe('server', () => { .catch(done.fail); }); + it('create should not override server start complete', async () => { + const config = Config.get('test'); + const spy = spyOn(config, 'serverStartComplete').and.callFake(() => {}); + await ParseServer.ParseServer.create(config); + expect(spy).toHaveBeenCalled(); + }); + + it('should wait for schemas to load', async () => { + const parseServer = await ParseServer.ParseServer.create({ + appId: 'aTestApp', + masterKey: 'aTestMasterKey', + serverURL: 'http://localhost:12667/parse', + schema: { + definitions: [ + { className: '_User' }, + { className: 'Test', classLevelPermissions: { addField: { '*': true } } }, + ], + }, + }); + expect(Parse.applicationId).toEqual('aTestApp'); + const app = express(); + app.use('/parse', parseServer.app); + app.listen(12667); + const schema = await Parse.Schema.all(); + expect(schema.length).toBe(3); + }); + it('should not fail when Google signin is introduced without the optional clientId', done => { const jwt = require('jsonwebtoken'); diff --git a/src/ParseServer.js b/src/ParseServer.js index 8a5db315a8..14fd5a1c58 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -331,17 +331,24 @@ class ParseServer { /** * @static - * Create an async parse server - * @param {ParseServerOptions} options the parse server initialization options + * Creates an async parse server + * @param {ParseServerOptions} options the parse server initialization options */ - static createAsync(options) { + static create(options) { + const serverStartCallback = options.serverStartComplete; return new Promise((resolve, reject) => { const parseServer = new ParseServer({ ...options, serverStartComplete(error) { if (error) { reject(error); + if (serverStartCallback) { + serverStartCallback(error); + } } else { + if (serverStartCallback) { + serverStartCallback(); + } resolve(parseServer); } }, diff --git a/src/SchemaMigrations/DefinedSchemas.js b/src/SchemaMigrations/DefinedSchemas.js index 0db3be6358..a585554ba6 100644 --- a/src/SchemaMigrations/DefinedSchemas.js +++ b/src/SchemaMigrations/DefinedSchemas.js @@ -7,6 +7,8 @@ import { internalCreateSchema, internalUpdateSchema } from '../Routers/SchemasRo import { defaultColumns, systemClasses } from '../Controllers/SchemaController'; import { ParseServerOptions } from '../Options'; import * as Migrations from './Migrations'; +import Auth from '../Auth'; +import rest from '../rest'; export class DefinedSchemas { config: ParseServerOptions; @@ -96,9 +98,9 @@ export class DefinedSchemas { }, 20000); } - // Hack to force session schema to be created await this.createDeleteSession(); - this.allCloudSchemas = await Parse.Schema.all(); + const schemaController = await this.config.database.loadSchema(); + this.allCloudSchemas = await schemaController.getAllClasses(); clearTimeout(timeout); await Promise.all(this.localSchemas.map(async localSchema => this.saveOrUpdate(localSchema))); @@ -171,9 +173,8 @@ export class DefinedSchemas { // Create a fake session since Parse do not create the _Session until // a session is created async createDeleteSession() { - const session = new Parse.Session(); - await session.save(null, { useMasterKey: true }); - await session.destroy({ useMasterKey: true }); + const { response } = await rest.create(this.config, Auth.master(this.config), '_Session', {}); + await rest.del(this.config, Auth.master(this.config), '_Session', response.objectId); } async saveOrUpdate(localSchema: Migrations.JSONSchema) { diff --git a/src/index.js b/src/index.js index ba854a1c2f..6f55411cb1 100644 --- a/src/index.js +++ b/src/index.js @@ -21,7 +21,7 @@ const _ParseServer = function (options: ParseServerOptions) { // Mount the create liveQueryServer _ParseServer.createLiveQueryServer = ParseServer.createLiveQueryServer; _ParseServer.start = ParseServer.start; -_ParseServer.createAsync = ParseServer.createAsync; +_ParseServer.create = ParseServer.create; const S3Adapter = useExternal('S3Adapter', '@parse/s3-files-adapter'); const GCSAdapter = useExternal('GCSAdapter', '@parse/gcs-files-adapter'); From 08e6c344a3a477e25dadd65261aad6bd8a0021cd Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 20:38:56 +1000 Subject: [PATCH 34/46] resolve .app --- spec/index.spec.js | 4 ++-- src/ParseServer.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/index.spec.js b/spec/index.spec.js index 29368a81e2..d0eadd7fd7 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -304,7 +304,7 @@ describe('server', () => { serverStartComplete: () => { expect(Parse.applicationId).toEqual('aTestApp'); const app = express(); - app.use('/parse', parseServer.app); + app.use('/parse', parseServer); const server = app.listen(12666); const obj = new Parse.Object('AnObject'); @@ -552,7 +552,7 @@ describe('server', () => { }); expect(Parse.applicationId).toEqual('aTestApp'); const app = express(); - app.use('/parse', parseServer.app); + app.use('/parse', parseServer); app.listen(12667); const schema = await Parse.Schema.all(); expect(schema.length).toBe(3); diff --git a/src/ParseServer.js b/src/ParseServer.js index 14fd5a1c58..4997f37a24 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -349,7 +349,7 @@ class ParseServer { if (serverStartCallback) { serverStartCallback(); } - resolve(parseServer); + resolve(parseServer.app); } }, }); From efe75c2320cb1bc0f8b9a62bc2ebe1b561965751 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 20:42:57 +1000 Subject: [PATCH 35/46] Update index.spec.js --- spec/index.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/index.spec.js b/spec/index.spec.js index d0eadd7fd7..91063c9d50 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -304,7 +304,7 @@ describe('server', () => { serverStartComplete: () => { expect(Parse.applicationId).toEqual('aTestApp'); const app = express(); - app.use('/parse', parseServer); + app.use('/parse', parseServer.app); const server = app.listen(12666); const obj = new Parse.Object('AnObject'); From e6c45f54ad5e6475e19724cd5d3e6ce7ba925cec Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 21:40:57 +1000 Subject: [PATCH 36/46] create startApp function --- spec/CloudCode.spec.js | 15 ++++++++---- spec/index.spec.js | 12 ++++++---- src/ParseServer.js | 54 +++++++++++++++++++----------------------- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index a59447ada2..82788b1ed0 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -41,20 +41,25 @@ describe('Cloud Code', () => { }); it('should wait for cloud code to load', async () => { - const config = Config.get('test'); const initiated = new Date(); - const parseServer = await ParseServer.create({ - ...config, + const server = await new ParseServer({ + appId: 'test2', + masterKey: 'abc', + serverURL: 'http://localhost:12668/parse', async cloud() { await new Promise(resolve => setTimeout(resolve, 1000)); Parse.Cloud.beforeSave('Test', () => { throw 'Cannot save.'; }); }, - }); + }).startApp(); + const express = require('express'); + const app = express(); + app.use('/parse', server); + await new Promise(resolve => app.listen(12668, resolve)); + const now = new Date(); expect(now.getTime() - initiated.getTime() > 1000).toBeTrue(); - parseServer.start({ port: 18380, mountPath: '/test2' }); await expectAsync(new Parse.Object('Test').save()).toBeRejectedWith( new Parse.Error(141, 'Cannot save.') ); diff --git a/spec/index.spec.js b/spec/index.spec.js index 91063c9d50..05e4332013 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -534,12 +534,13 @@ describe('server', () => { it('create should not override server start complete', async () => { const config = Config.get('test'); const spy = spyOn(config, 'serverStartComplete').and.callFake(() => {}); - await ParseServer.ParseServer.create(config); + await new ParseServer.ParseServer(config).startApp(); expect(spy).toHaveBeenCalled(); }); it('should wait for schemas to load', async () => { - const parseServer = await ParseServer.ParseServer.create({ + const spy = spyOn(process.stdout, 'write'); + const parseServer = await new ParseServer.ParseServer({ appId: 'aTestApp', masterKey: 'aTestMasterKey', serverURL: 'http://localhost:12667/parse', @@ -549,13 +550,14 @@ describe('server', () => { { className: 'Test', classLevelPermissions: { addField: { '*': true } } }, ], }, - }); + }).startApp(); expect(Parse.applicationId).toEqual('aTestApp'); + expect(spy).toHaveBeenCalledWith('info: Running Migrations\n'); const app = express(); app.use('/parse', parseServer); - app.listen(12667); + await new Promise(resolve => app.listen(12667, resolve)); const schema = await Parse.Schema.all(); - expect(schema.length).toBe(3); + expect(schema.length).toBeGreaterThan(3); }); it('should not fail when Google signin is introduced without the optional clientId', done => { diff --git a/src/ParseServer.js b/src/ParseServer.js index 4997f37a24..0f8df76d56 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -107,7 +107,14 @@ class ParseServer { if (serverStartComplete) { serverStartComplete(); } + if (this.startCallbackSuccess) { + this.startCallbackSuccess(this.app); + } + this.started = true; } catch (error) { + if (this.startCallbackError) { + this.startCallbackError(error); + } if (serverStartComplete) { serverStartComplete(error); } else { @@ -122,9 +129,26 @@ class ParseServer { } } + /** + * Starts the Parse Server to be served as an express app + * @returns {Promise} express middleware + */ + + startApp() { + return new Promise((resolve, reject) => { + if (this.started) { + reject('startApp has already been called.'); + return; + } + this.startCallbackSuccess = resolve; + this.startCallbackError = reject; + }); + } + get app() { if (!this._app) { this._app = ParseServer.app(this.config); + this._app.startApp = async () => await this.startApp(); } return this._app; } @@ -258,9 +282,6 @@ class ParseServer { * @returns {ParseServer} the parse server instance */ start(options: ParseServerOptions, callback: ?() => void) { - if (!options) { - options = this.config; - } const app = express(); if (options.middleware) { let middleware; @@ -329,33 +350,6 @@ class ParseServer { return parseServer.start(options, callback); } - /** - * @static - * Creates an async parse server - * @param {ParseServerOptions} options the parse server initialization options - */ - static create(options) { - const serverStartCallback = options.serverStartComplete; - return new Promise((resolve, reject) => { - const parseServer = new ParseServer({ - ...options, - serverStartComplete(error) { - if (error) { - reject(error); - if (serverStartCallback) { - serverStartCallback(error); - } - } else { - if (serverStartCallback) { - serverStartCallback(); - } - resolve(parseServer.app); - } - }, - }); - }); - } - /** * Helper method to create a liveQuery server * @static From b23d3465445cd41d1eb134fd92a8b0d9e14acc20 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 21:45:16 +1000 Subject: [PATCH 37/46] Update index.spec.js --- spec/index.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/index.spec.js b/spec/index.spec.js index 05e4332013..fb7c92de3c 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -552,12 +552,12 @@ describe('server', () => { }, }).startApp(); expect(Parse.applicationId).toEqual('aTestApp'); - expect(spy).toHaveBeenCalledWith('info: Running Migrations\n'); + expect(spy).toHaveBeenCalledWith('info: Running Migrations Completed\n'); const app = express(); app.use('/parse', parseServer); await new Promise(resolve => app.listen(12667, resolve)); const schema = await Parse.Schema.all(); - expect(schema.length).toBeGreaterThan(3); + expect(schema.length).toBeGreaterThanOrEqual(3); }); it('should not fail when Google signin is introduced without the optional clientId', done => { From 2ae3980c2b3da70ec409b330fa396f30ddd2c448 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 21:50:51 +1000 Subject: [PATCH 38/46] increase coverage --- spec/CloudCode.spec.js | 21 +++++++++++++++++++++ src/ParseServer.js | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 82788b1ed0..2f35a410be 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -65,6 +65,21 @@ describe('Cloud Code', () => { ); }); + it('can call startApp twice', async () => { + const server = await new ParseServer({ + appId: 'test2', + masterKey: 'abc', + serverURL: 'http://localhost:12668/parse', + async cloud() { + await new Promise(resolve => setTimeout(resolve, 1000)); + Parse.Cloud.beforeSave('Test', () => { + throw 'Cannot save.'; + }); + }, + }).startApp(); + await server.startApp(); + }); + it('can load cloud code as a module', async () => { process.env.npm_package_type = 'module'; await reconfigureServer({ cloud: './spec/cloud/cloudCodeModuleFile.js' }); @@ -73,6 +88,12 @@ describe('Cloud Code', () => { delete process.env.npm_package_type; }); + it('cloud code must be valid type', async () => { + await expectAsync(reconfigureServer({ cloud: true })).toBeRejectedWith( + "argument 'cloud' must either be a string or a function" + ); + }); + it('can create functions', done => { Parse.Cloud.define('hello', () => { return 'Hello world!'; diff --git a/src/ParseServer.js b/src/ParseServer.js index 0f8df76d56..02e5a25ecb 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -137,7 +137,7 @@ class ParseServer { startApp() { return new Promise((resolve, reject) => { if (this.started) { - reject('startApp has already been called.'); + resolve(this.app); return; } this.startCallbackSuccess = resolve; From 81de641075a081f006452fca0e18234dddf53267 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 21:55:17 +1000 Subject: [PATCH 39/46] Update DefinedSchemas.js --- src/SchemaMigrations/DefinedSchemas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SchemaMigrations/DefinedSchemas.js b/src/SchemaMigrations/DefinedSchemas.js index a585554ba6..bca01ec49b 100644 --- a/src/SchemaMigrations/DefinedSchemas.js +++ b/src/SchemaMigrations/DefinedSchemas.js @@ -11,7 +11,7 @@ import Auth from '../Auth'; import rest from '../rest'; export class DefinedSchemas { - config: ParseServerOptions; + config: any; schemaOptions: Migrations.SchemaOptions; localSchemas: Migrations.JSONSchema[]; retries: number; From d7ee11459c060a1c7270f5b151685faacf7b4bb0 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 22:52:21 +1000 Subject: [PATCH 40/46] close servers --- spec/CloudCode.spec.js | 7 ++++--- spec/index.spec.js | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 2f35a410be..03e4449c94 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -42,7 +42,7 @@ describe('Cloud Code', () => { it('should wait for cloud code to load', async () => { const initiated = new Date(); - const server = await new ParseServer({ + const parseServer = await new ParseServer({ appId: 'test2', masterKey: 'abc', serverURL: 'http://localhost:12668/parse', @@ -55,14 +55,15 @@ describe('Cloud Code', () => { }).startApp(); const express = require('express'); const app = express(); - app.use('/parse', server); - await new Promise(resolve => app.listen(12668, resolve)); + app.use('/parse', parseServer); + const server = app.listen(12668); const now = new Date(); expect(now.getTime() - initiated.getTime() > 1000).toBeTrue(); await expectAsync(new Parse.Object('Test').save()).toBeRejectedWith( new Parse.Error(141, 'Cannot save.') ); + await server.close(); }); it('can call startApp twice', async () => { diff --git a/spec/index.spec.js b/spec/index.spec.js index fb7c92de3c..f75fada391 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -543,7 +543,7 @@ describe('server', () => { const parseServer = await new ParseServer.ParseServer({ appId: 'aTestApp', masterKey: 'aTestMasterKey', - serverURL: 'http://localhost:12667/parse', + serverURL: 'http://localhost:12669/parse', schema: { definitions: [ { className: '_User' }, @@ -555,9 +555,10 @@ describe('server', () => { expect(spy).toHaveBeenCalledWith('info: Running Migrations Completed\n'); const app = express(); app.use('/parse', parseServer); - await new Promise(resolve => app.listen(12667, resolve)); + const server = app.listen(12669); const schema = await Parse.Schema.all(); expect(schema.length).toBeGreaterThanOrEqual(3); + await server.close(); }); it('should not fail when Google signin is introduced without the optional clientId', done => { From 1f8a4ee9dd849be9616d017b510cdb545354b2eb Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 22:53:55 +1000 Subject: [PATCH 41/46] Update index.js --- src/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/index.js b/src/index.js index 6f55411cb1..bbbdaf545f 100644 --- a/src/index.js +++ b/src/index.js @@ -21,7 +21,6 @@ const _ParseServer = function (options: ParseServerOptions) { // Mount the create liveQueryServer _ParseServer.createLiveQueryServer = ParseServer.createLiveQueryServer; _ParseServer.start = ParseServer.start; -_ParseServer.create = ParseServer.create; const S3Adapter = useExternal('S3Adapter', '@parse/s3-files-adapter'); const GCSAdapter = useExternal('GCSAdapter', '@parse/gcs-files-adapter'); From 7f9959286c0f7342bd03680dae982570ba769707 Mon Sep 17 00:00:00 2001 From: dblythy Date: Thu, 28 Apr 2022 23:36:50 +1000 Subject: [PATCH 42/46] fix tests --- spec/CloudCode.spec.js | 4 +++- spec/helper.js | 2 ++ spec/index.spec.js | 17 +++++++---------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/spec/CloudCode.spec.js b/spec/CloudCode.spec.js index 03e4449c94..44a754626f 100644 --- a/spec/CloudCode.spec.js +++ b/spec/CloudCode.spec.js @@ -46,6 +46,7 @@ describe('Cloud Code', () => { appId: 'test2', masterKey: 'abc', serverURL: 'http://localhost:12668/parse', + silent: true, async cloud() { await new Promise(resolve => setTimeout(resolve, 1000)); Parse.Cloud.beforeSave('Test', () => { @@ -63,7 +64,7 @@ describe('Cloud Code', () => { await expectAsync(new Parse.Object('Test').save()).toBeRejectedWith( new Parse.Error(141, 'Cannot save.') ); - await server.close(); + await new Promise(resolve => server.close(resolve)); }); it('can call startApp twice', async () => { @@ -71,6 +72,7 @@ describe('Cloud Code', () => { appId: 'test2', masterKey: 'abc', serverURL: 'http://localhost:12668/parse', + silent: true, async cloud() { await new Promise(resolve => setTimeout(resolve, 1000)); Parse.Cloud.beforeSave('Test', () => { diff --git a/spec/helper.js b/spec/helper.js index 612c716202..3dcfa7ec68 100644 --- a/spec/helper.js +++ b/spec/helper.js @@ -198,7 +198,9 @@ beforeAll(async () => { } } await reconfigureServer(); +}); +beforeEach(() => { Parse.initialize('test', 'test', 'test'); Parse.serverURL = 'http://localhost:' + port + '/1'; }); diff --git a/spec/index.spec.js b/spec/index.spec.js index f75fada391..0d81002984 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -531,16 +531,9 @@ describe('server', () => { .catch(done.fail); }); - it('create should not override server start complete', async () => { - const config = Config.get('test'); - const spy = spyOn(config, 'serverStartComplete').and.callFake(() => {}); - await new ParseServer.ParseServer(config).startApp(); - expect(spy).toHaveBeenCalled(); - }); - it('should wait for schemas to load', async () => { const spy = spyOn(process.stdout, 'write'); - const parseServer = await new ParseServer.ParseServer({ + const config = { appId: 'aTestApp', masterKey: 'aTestMasterKey', serverURL: 'http://localhost:12669/parse', @@ -550,7 +543,11 @@ describe('server', () => { { className: 'Test', classLevelPermissions: { addField: { '*': true } } }, ], }, - }).startApp(); + serverStartComplete() {}, + }; + const startSpy = spyOn(config, 'serverStartComplete').and.callFake(() => {}); + const parseServer = await new ParseServer.ParseServer(config).startApp(); + expect(startSpy).toHaveBeenCalled(); expect(Parse.applicationId).toEqual('aTestApp'); expect(spy).toHaveBeenCalledWith('info: Running Migrations Completed\n'); const app = express(); @@ -558,7 +555,7 @@ describe('server', () => { const server = app.listen(12669); const schema = await Parse.Schema.all(); expect(schema.length).toBeGreaterThanOrEqual(3); - await server.close(); + await new Promise(resolve => server.close(resolve)); }); it('should not fail when Google signin is introduced without the optional clientId', done => { From caa75f66f1f728fe98797e13e6ca9bfd856d1f11 Mon Sep 17 00:00:00 2001 From: dblythy Date: Fri, 29 Apr 2022 12:47:50 +1000 Subject: [PATCH 43/46] Update ParseServer.js --- src/ParseServer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ParseServer.js b/src/ParseServer.js index 02e5a25ecb..11b2fcabe4 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -105,7 +105,7 @@ class ParseServer { } } if (serverStartComplete) { - serverStartComplete(); + await Promise.resolve(serverStartComplete()); } if (this.startCallbackSuccess) { this.startCallbackSuccess(this.app); @@ -130,7 +130,7 @@ class ParseServer { } /** - * Starts the Parse Server to be served as an express app + * Starts the Parse Server to be served as an express. Resolves when parse-server is ready to accept external traffic * @returns {Promise} express middleware */ From dec4082c84589476071a29f7110d083f522d0bc0 Mon Sep 17 00:00:00 2001 From: dblythy Date: Fri, 29 Apr 2022 17:02:32 +1000 Subject: [PATCH 44/46] Update ParseServer.js --- src/ParseServer.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ParseServer.js b/src/ParseServer.js index 11b2fcabe4..cd97c9dc45 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -130,7 +130,8 @@ class ParseServer { } /** - * Starts the Parse Server to be served as an express. Resolves when parse-server is ready to accept external traffic + * Starts the Parse Server to be served as an express. Resolves when parse-server is ready to accept external traffic. + * Note: when using `await startApp()`, server JS SDK methods will not be available until expressApp.listen(port) is called. * @returns {Promise} express middleware */ From d65be73ba275b063eb6adf2f1d0ad03a85f01bb1 Mon Sep 17 00:00:00 2001 From: dblythy Date: Tue, 3 May 2022 13:35:41 +1000 Subject: [PATCH 45/46] add holdPublicRoutes --- spec/index.spec.js | 24 ++++++++++++++++++++++++ src/Config.js | 5 +++++ src/Options/Definitions.js | 7 +++++++ src/Options/docs.js | 1 + src/Options/index.js | 3 +++ src/ParseServer.js | 23 ++++++++++++++++++++++- 6 files changed, 62 insertions(+), 1 deletion(-) diff --git a/spec/index.spec.js b/spec/index.spec.js index 0d81002984..06538de90c 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -558,6 +558,30 @@ describe('server', () => { await new Promise(resolve => server.close(resolve)); }); + it('call call startApp with mountPublicRoutes', async () => { + const config = { + appId: 'aTestApp', + masterKey: 'aTestMasterKey', + serverURL: 'http://localhost:12701/parse', + holdPublicRoutes: true, + }; + const parseServer = await new ParseServer.ParseServer(config).startApp(); + expect(Parse.applicationId).toEqual('aTestApp'); + expect(Parse.serverURL).toEqual('http://localhost:12701/parse'); + const app = express(); + app.use('/parse', parseServer); + const server = app.listen(12701); + const testObject = new Parse.Object('TestObject'); + // api usage requires masterKey until mountPublicRoutes is called + await expectAsync(testObject.save(null, { useMasterKey: true })).toBeResolved(); + await expectAsync(testObject.save()).toBeRejectedWith( + new Parse.Error(undefined, 'unauthorized: master key is required') + ); + parseServer.mountPublicRoutes(); + await expectAsync(testObject.save()).toBeResolved(); + await new Promise(resolve => server.close(resolve)); + }); + it('should not fail when Google signin is introduced without the optional clientId', done => { const jwt = require('jsonwebtoken'); diff --git a/src/Config.js b/src/Config.js index 04834d3291..f94da6e15b 100644 --- a/src/Config.js +++ b/src/Config.js @@ -79,6 +79,7 @@ export class Config { enforcePrivateUsers, schema, requestKeywordDenylist, + holdPublicRoutes, }) { if (masterKey === readOnlyMasterKey) { throw new Error('masterKey and readOnlyMasterKey should be different'); @@ -103,6 +104,10 @@ export class Config { throw 'revokeSessionOnPasswordReset must be a boolean value'; } + if (typeof holdPublicRoutes !== 'boolean') { + throw 'holdPublicRoutes must be a boolean value'; + } + if (publicServerURL) { if (!publicServerURL.startsWith('http://') && !publicServerURL.startsWith('https://')) { throw 'publicServerURL should be a valid HTTPS URL starting with https://'; diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index f8b8eab633..bb70286aeb 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -236,6 +236,13 @@ module.exports.ParseServerOptions = { env: 'PARSE_SERVER_GRAPH_QLSCHEMA', help: 'Full path to your GraphQL custom schema.graphql file', }, + holdPublicRoutes: { + env: 'PARSE_SERVER_HOLD_PUBLIC_ROUTES', + help: + 'Set to true if Parse Server should require masterKey access before `mountRoutes()` is called.', + action: parsers.booleanParser, + default: false, + }, host: { env: 'PARSE_SERVER_HOST', help: 'The host to serve ParseServer on, defaults to 0.0.0.0', diff --git a/src/Options/docs.js b/src/Options/docs.js index 24b60c46a9..a54e8dab29 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -46,6 +46,7 @@ * @property {FileUploadOptions} fileUpload Options for file uploads * @property {String} graphQLPath Mount path for the GraphQL endpoint, defaults to /graphql * @property {String} graphQLSchema Full path to your GraphQL custom schema.graphql file + * @property {Boolean} holdPublicRoutes Set to true if Parse Server should require masterKey access before `mountRoutes()` is called. * @property {String} host The host to serve ParseServer on, defaults to 0.0.0.0 * @property {IdempotencyOptions} idempotencyOptions Options for request idempotency to deduplicate identical requests that may be caused by network issues. Caution, this is an experimental feature that may not be appropriate for production. * @property {String} javascriptKey Key for the Javascript SDK diff --git a/src/Options/index.js b/src/Options/index.js index 8124446f99..0b9d0cf5ed 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -282,6 +282,9 @@ export interface ParseServerOptions { /* 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[]); + /* Set to true if Parse Server should require masterKey access before `mountRoutes()` is called. + :DEFAULT: false */ + holdPublicRoutes: ?boolean; } export interface SecurityOptions { diff --git a/src/ParseServer.js b/src/ParseServer.js index cd97c9dc45..1317c20a05 100644 --- a/src/ParseServer.js +++ b/src/ParseServer.js @@ -146,10 +146,20 @@ class ParseServer { }); } + /** + * Method that is called when Parse Server is ready to + * @returns {Promise} express middleware + */ + + mountPublicRoutes() { + this.config.publicRoutesAvailable = true; + } + get app() { if (!this._app) { this._app = ParseServer.app(this.config); this._app.startApp = async () => await this.startApp(); + this._app.mountPublicRoutes = () => this.mountPublicRoutes(); } return this._app; } @@ -180,7 +190,7 @@ class ParseServer { * Create an express app for the parse server * @param {Object} options let you specify the maxUploadSize when creating the express app */ static app(options) { - const { maxUploadSize = '20mb', appId, directAccess, pages } = options; + const { maxUploadSize = '20mb', appId, directAccess, pages, holdPublicRoutes } = options; // This app serves the Parse API directly. // It's the equivalent of https://api.parse.com/1 in the hosted Parse API. var api = express(); @@ -212,6 +222,17 @@ class ParseServer { api.use(middlewares.allowMethodOverride); api.use(middlewares.handleParseHeaders); + if (holdPublicRoutes) { + options.publicRoutesAvailable = false; + api.use((req, res, next) => { + if (options.publicRoutesAvailable) { + next(); + return; + } + middlewares.enforceMasterKeyAccess(req, res, next); + }); + } + const appRouter = ParseServer.promiseRouter({ appId }); api.use(appRouter.expressRouter()); From 7cd5e3801910de3ebd11ff2277abd57c52276aaf Mon Sep 17 00:00:00 2001 From: dblythy Date: Tue, 3 May 2022 13:49:18 +1000 Subject: [PATCH 46/46] definitions --- src/Options/Definitions.js | 2 +- src/Options/docs.js | 2 +- src/Options/index.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js index bb70286aeb..c12524c0e4 100644 --- a/src/Options/Definitions.js +++ b/src/Options/Definitions.js @@ -239,7 +239,7 @@ module.exports.ParseServerOptions = { holdPublicRoutes: { env: 'PARSE_SERVER_HOLD_PUBLIC_ROUTES', help: - 'Set to true if Parse Server should require masterKey access before `mountRoutes()` is called.', + 'Set to true if Parse Server should require masterKey access before `mountPublicRoutes()` is called.', action: parsers.booleanParser, default: false, }, diff --git a/src/Options/docs.js b/src/Options/docs.js index a54e8dab29..8fb9e6b29d 100644 --- a/src/Options/docs.js +++ b/src/Options/docs.js @@ -46,7 +46,7 @@ * @property {FileUploadOptions} fileUpload Options for file uploads * @property {String} graphQLPath Mount path for the GraphQL endpoint, defaults to /graphql * @property {String} graphQLSchema Full path to your GraphQL custom schema.graphql file - * @property {Boolean} holdPublicRoutes Set to true if Parse Server should require masterKey access before `mountRoutes()` is called. + * @property {Boolean} holdPublicRoutes Set to true if Parse Server should require masterKey access before `mountPublicRoutes()` is called. * @property {String} host The host to serve ParseServer on, defaults to 0.0.0.0 * @property {IdempotencyOptions} idempotencyOptions Options for request idempotency to deduplicate identical requests that may be caused by network issues. Caution, this is an experimental feature that may not be appropriate for production. * @property {String} javascriptKey Key for the Javascript SDK diff --git a/src/Options/index.js b/src/Options/index.js index 0b9d0cf5ed..174eaac8f5 100644 --- a/src/Options/index.js +++ b/src/Options/index.js @@ -282,7 +282,7 @@ export interface ParseServerOptions { /* 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[]); - /* Set to true if Parse Server should require masterKey access before `mountRoutes()` is called. + /* Set to true if Parse Server should require masterKey access before `mountPublicRoutes()` is called. :DEFAULT: false */ holdPublicRoutes: ?boolean; }