diff --git a/README.md b/README.md
index e73f9b90..b935b83e 100644
--- a/README.md
+++ b/README.md
@@ -18,8 +18,6 @@
-
-
@@ -80,7 +78,7 @@ The fastest and easiest way to get started is to run MongoDB and Parse Server lo
Before you start make sure you have installed:
-- [NodeJS](https://www.npmjs.com/) that includes `npm`
+- [NodeJS](https://www.npmjs.com/) that includes `npm`
- [MongoDB](https://www.mongodb.com/) or [PostgreSQL](https://www.postgresql.org/)
- Optionally [Docker](https://www.docker.com/)
@@ -337,7 +335,7 @@ It’s possible to change the default pages of the app and redirect the user to
```js
var server = ParseServer({
...otherOptions,
-
+
customPages: {
passwordResetSuccess: "http://yourapp.com/passwordResetSuccess",
verifyEmailSuccess: "http://yourapp.com/verifyEmailSuccess",
diff --git a/package-lock.json b/package-lock.json
index f2d3f036..03b47a94 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9032,9 +9032,9 @@
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"mongodb": {
- "version": "3.5.3",
- "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.3.tgz",
- "integrity": "sha512-II7P7A3XUdPiXRgcN96qIoRa1oesM6qLNZkzfPluNZjVkgQk3jnQwOT6/uDk4USRDTTLjNFw2vwfmbRGTA7msg==",
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.4.tgz",
+ "integrity": "sha512-xGH41Ig4dkSH5ROGezkgDbsgt/v5zbNUwE3TcFsSbDc6Qn3Qil17dhLsESSDDPTiyFDCPJRpfd4887dtsPgKtA==",
"requires": {
"bl": "^2.2.0",
"bson": "^1.1.1",
diff --git a/package.json b/package.json
index f6bb772d..d84b71e8 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"lodash": "4.17.15",
"lru-cache": "5.1.1",
"mime": "2.4.4",
- "mongodb": "3.5.3",
+ "mongodb": "3.5.4",
"node-rsa": "1.0.7",
"parse": "2.11.0",
"pg-promise": "10.4.4",
diff --git a/spec/DatabaseController.spec.js b/spec/DatabaseController.spec.js
index 70b554f8..af373e64 100644
--- a/spec/DatabaseController.spec.js
+++ b/spec/DatabaseController.spec.js
@@ -3,118 +3,56 @@ const validateQuery = DatabaseController._validateQuery;
describe('DatabaseController', function() {
describe('validateQuery', function() {
- describe('with skipMongoDBServer13732Workaround disabled (the default)', function() {
- it('should restructure simple cases of SERVER-13732', done => {
- const query = {
- $or: [{ a: 1 }, { a: 2 }],
- _rperm: { $in: ['a', 'b'] },
- foo: 3,
- };
- validateQuery(query, false);
- expect(query).toEqual({
- $or: [
- { a: 1, _rperm: { $in: ['a', 'b'] }, foo: 3 },
- { a: 2, _rperm: { $in: ['a', 'b'] }, foo: 3 },
- ],
- });
- done();
- });
-
- it('should not restructure SERVER-13732 queries with $nears', done => {
- let query = { $or: [{ a: 1 }, { b: 1 }], c: { $nearSphere: {} } };
- validateQuery(query, false);
- expect(query).toEqual({
- $or: [{ a: 1 }, { b: 1 }],
- c: { $nearSphere: {} },
- });
- query = { $or: [{ a: 1 }, { b: 1 }], c: { $near: {} } };
- validateQuery(query, false);
- expect(query).toEqual({ $or: [{ a: 1 }, { b: 1 }], c: { $near: {} } });
- done();
- });
-
- it('should push refactored keys down a tree for SERVER-13732', done => {
- const query = {
- a: 1,
- $or: [{ $or: [{ b: 1 }, { b: 2 }] }, { $or: [{ c: 1 }, { c: 2 }] }],
- };
- validateQuery(query, false);
- expect(query).toEqual({
- $or: [
- { $or: [{ b: 1, a: 1 }, { b: 2, a: 1 }] },
- { $or: [{ c: 1, a: 1 }, { c: 2, a: 1 }] },
- ],
- });
- done();
- });
-
- it('should reject invalid queries', done => {
- expect(() => validateQuery({ $or: { a: 1 } }, false)).toThrow();
- done();
- });
-
- it('should accept valid queries', done => {
- expect(() =>
- validateQuery({ $or: [{ a: 1 }, { b: 2 }] }, false)
- ).not.toThrow();
- done();
+ it('should not restructure simple cases of SERVER-13732', done => {
+ const query = {
+ $or: [{ a: 1 }, { a: 2 }],
+ _rperm: { $in: ['a', 'b'] },
+ foo: 3,
+ };
+ validateQuery(query);
+ expect(query).toEqual({
+ $or: [{ a: 1 }, { a: 2 }],
+ _rperm: { $in: ['a', 'b'] },
+ foo: 3,
});
+ done();
});
- describe('with skipMongoDBServer13732Workaround enabled', function() {
- it('should not restructure simple cases of SERVER-13732', done => {
- const query = {
- $or: [{ a: 1 }, { a: 2 }],
- _rperm: { $in: ['a', 'b'] },
- foo: 3,
- };
- validateQuery(query, true);
- expect(query).toEqual({
- $or: [{ a: 1 }, { a: 2 }],
- _rperm: { $in: ['a', 'b'] },
- foo: 3,
- });
- done();
+ it('should not restructure SERVER-13732 queries with $nears', done => {
+ let query = { $or: [{ a: 1 }, { b: 1 }], c: { $nearSphere: {} } };
+ validateQuery(query);
+ expect(query).toEqual({
+ $or: [{ a: 1 }, { b: 1 }],
+ c: { $nearSphere: {} },
+ });
+ query = { $or: [{ a: 1 }, { b: 1 }], c: { $near: {} } };
+ validateQuery(query);
+ expect(query).toEqual({ $or: [{ a: 1 }, { b: 1 }], c: { $near: {} } });
+ done();
+ });
+
+ it('should not push refactored keys down a tree for SERVER-13732', done => {
+ const query = {
+ a: 1,
+ $or: [{ $or: [{ b: 1 }, { b: 2 }] }, { $or: [{ c: 1 }, { c: 2 }] }],
+ };
+ validateQuery(query);
+ expect(query).toEqual({
+ a: 1,
+ $or: [{ $or: [{ b: 1 }, { b: 2 }] }, { $or: [{ c: 1 }, { c: 2 }] }],
});
- it('should not restructure SERVER-13732 queries with $nears', done => {
- let query = { $or: [{ a: 1 }, { b: 1 }], c: { $nearSphere: {} } };
- validateQuery(query, true);
- expect(query).toEqual({
- $or: [{ a: 1 }, { b: 1 }],
- c: { $nearSphere: {} },
- });
- query = { $or: [{ a: 1 }, { b: 1 }], c: { $near: {} } };
- validateQuery(query, true);
- expect(query).toEqual({ $or: [{ a: 1 }, { b: 1 }], c: { $near: {} } });
- done();
- });
+ done();
+ });
- it('should not push refactored keys down a tree for SERVER-13732', done => {
- const query = {
- a: 1,
- $or: [{ $or: [{ b: 1 }, { b: 2 }] }, { $or: [{ c: 1 }, { c: 2 }] }],
- };
- validateQuery(query, true);
- expect(query).toEqual({
- a: 1,
- $or: [{ $or: [{ b: 1 }, { b: 2 }] }, { $or: [{ c: 1 }, { c: 2 }] }],
- });
+ it('should reject invalid queries', done => {
+ expect(() => validateQuery({ $or: { a: 1 } })).toThrow();
+ done();
+ });
- done();
- });
-
- it('should reject invalid queries', done => {
- expect(() => validateQuery({ $or: { a: 1 } }, true)).toThrow();
- done();
- });
-
- it('should accept valid queries', done => {
- expect(() =>
- validateQuery({ $or: [{ a: 1 }, { b: 2 }] }, true)
- ).not.toThrow();
- done();
- });
+ it('should accept valid queries', done => {
+ expect(() => validateQuery({ $or: [{ a: 1 }, { b: 2 }] })).not.toThrow();
+ done();
});
});
});
diff --git a/src/Config.js b/src/Config.js
index 8d31d3d9..2077626f 100644
--- a/src/Config.js
+++ b/src/Config.js
@@ -34,8 +34,7 @@ export class Config {
);
config.database = new DatabaseController(
cacheInfo.databaseController.adapter,
- schemaCache,
- cacheInfo.skipMongoDBServer13732Workaround
+ schemaCache
);
} else {
config[key] = cacheInfo[key];
diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js
index 650781b5..5c3b8ab3 100644
--- a/src/Controllers/DatabaseController.js
+++ b/src/Controllers/DatabaseController.js
@@ -69,73 +69,14 @@ const isSpecialQueryKey = key => {
return specialQuerykeys.indexOf(key) >= 0;
};
-const validateQuery = (
- query: any,
- skipMongoDBServer13732Workaround: boolean
-): void => {
+const validateQuery = (query: any): void => {
if (query.ACL) {
throw new Parse.Error(Parse.Error.INVALID_QUERY, 'Cannot query on ACL.');
}
if (query.$or) {
if (query.$or instanceof Array) {
- query.$or.forEach(el =>
- validateQuery(el, skipMongoDBServer13732Workaround)
- );
-
- if (!skipMongoDBServer13732Workaround) {
- /* In MongoDB 3.2 & 3.4, $or queries which are not alone at the top
- * level of the query can not make efficient use of indexes due to a
- * long standing bug known as SERVER-13732.
- *
- * This bug was fixed in MongoDB version 3.6.
- *
- * For versions pre-3.6, the below logic produces a substantial
- * performance improvement inside the database by avoiding the bug.
- *
- * For versions 3.6 and above, there is no performance improvement and
- * the logic is unnecessary. Some query patterns are even slowed by
- * the below logic, due to the bug having been fixed and better
- * query plans being chosen.
- *
- * When versions before 3.4 are no longer supported by this project,
- * this logic, and the accompanying `skipMongoDBServer13732Workaround`
- * flag, can be removed.
- *
- * This block restructures queries in which $or is not the sole top
- * level element by moving all other top-level predicates inside every
- * subdocument of the $or predicate, allowing MongoDB's query planner
- * to make full use of the most relevant indexes.
- *
- * EG: {$or: [{a: 1}, {a: 2}], b: 2}
- * Becomes: {$or: [{a: 1, b: 2}, {a: 2, b: 2}]}
- *
- * The only exceptions are $near and $nearSphere operators, which are
- * constrained to only 1 operator per query. As a result, these ops
- * remain at the top level
- *
- * https://jira.mongodb.org/browse/SERVER-13732
- * https://github.com/parse-community/parse-server/issues/3767
- */
- Object.keys(query).forEach(key => {
- const noCollisions = !query.$or.some(subq =>
- Object.prototype.hasOwnProperty.call(subq, key)
- );
- let hasNears = false;
- if (query[key] != null && typeof query[key] == 'object') {
- hasNears = '$near' in query[key] || '$nearSphere' in query[key];
- }
- if (key != '$or' && noCollisions && !hasNears) {
- query.$or.forEach(subquery => {
- subquery[key] = query[key];
- });
- delete query[key];
- }
- });
- query.$or.forEach(el =>
- validateQuery(el, skipMongoDBServer13732Workaround)
- );
- }
+ query.$or.forEach(validateQuery);
} else {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
@@ -146,9 +87,7 @@ const validateQuery = (
if (query.$and) {
if (query.$and instanceof Array) {
- query.$and.forEach(el =>
- validateQuery(el, skipMongoDBServer13732Workaround)
- );
+ query.$and.forEach(validateQuery);
} else {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
@@ -159,9 +98,7 @@ const validateQuery = (
if (query.$nor) {
if (query.$nor instanceof Array && query.$nor.length > 0) {
- query.$nor.forEach(el =>
- validateQuery(el, skipMongoDBServer13732Workaround)
- );
+ query.$nor.forEach(validateQuery);
} else {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
@@ -487,21 +424,15 @@ class DatabaseController {
adapter: StorageAdapter;
schemaCache: any;
schemaPromise: ?Promise;
- skipMongoDBServer13732Workaround: boolean;
_transactionalSession: ?any;
- constructor(
- adapter: StorageAdapter,
- schemaCache: any,
- skipMongoDBServer13732Workaround: boolean
- ) {
+ constructor(adapter: StorageAdapter, schemaCache: any) {
this.adapter = adapter;
this.schemaCache = schemaCache;
// We don't want a mutable this.schema, because then you could have
// one request that uses different schemas for different parts of
// it. Instead, use loadSchema to get a schema.
this.schemaPromise = null;
- this.skipMongoDBServer13732Workaround = skipMongoDBServer13732Workaround;
this._transactionalSession = null;
}
@@ -660,7 +591,7 @@ class DatabaseController {
if (acl) {
query = addWriteACL(query, acl);
}
- validateQuery(query, this.skipMongoDBServer13732Workaround);
+ validateQuery(query);
return schemaController
.getOneSchema(className, true)
.catch(error => {
@@ -939,7 +870,7 @@ class DatabaseController {
if (acl) {
query = addWriteACL(query, acl);
}
- validateQuery(query, this.skipMongoDBServer13732Workaround);
+ validateQuery(query);
return schemaController
.getOneSchema(className)
.catch(error => {
@@ -1460,7 +1391,7 @@ class DatabaseController {
query = addReadACL(query, aclGroup);
}
}
- validateQuery(query, this.skipMongoDBServer13732Workaround);
+ validateQuery(query);
if (count) {
if (!classExists) {
return 0;
@@ -1893,7 +1824,7 @@ class DatabaseController {
]);
}
- static _validateQuery: (any, boolean) => void;
+ static _validateQuery: any => void;
}
module.exports = DatabaseController;
diff --git a/src/Controllers/index.js b/src/Controllers/index.js
index 8ef76793..d10ad800 100644
--- a/src/Controllers/index.js
+++ b/src/Controllers/index.js
@@ -171,7 +171,6 @@ export function getDatabaseController(
const {
databaseURI,
databaseOptions,
- skipMongoDBServer13732Workaround,
collectionPrefix,
schemaCacheTTL,
enableSingleSchemaCache,
@@ -195,8 +194,7 @@ export function getDatabaseController(
}
return new DatabaseController(
databaseAdapter,
- new SchemaCache(cacheController, schemaCacheTTL, enableSingleSchemaCache),
- skipMongoDBServer13732Workaround
+ new SchemaCache(cacheController, schemaCacheTTL, enableSingleSchemaCache)
);
}
diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js
index 4bded75a..72500203 100644
--- a/src/Options/Definitions.js
+++ b/src/Options/Definitions.js
@@ -371,12 +371,6 @@ module.exports.ParseServerOptions = {
help: 'Disables console output',
action: parsers.booleanParser,
},
- skipMongoDBServer13732Workaround: {
- env: 'PARSE_SKIP_MONGODB_SERVER_13732_WORKAROUND',
- help: 'Circumvent Parse workaround for historical MongoDB bug SERVER-13732',
- action: parsers.booleanParser,
- default: false,
- },
startLiveQueryServer: {
env: 'PARSE_SERVER_START_LIVE_QUERY_SERVER',
help: 'Starts the liveQuery server',
diff --git a/src/Options/docs.js b/src/Options/docs.js
index 098fefb5..9e5b6ac8 100644
--- a/src/Options/docs.js
+++ b/src/Options/docs.js
@@ -67,7 +67,6 @@
* @property {String} serverURL URL to your parse server with http:// or https://.
* @property {Number} sessionLength Session duration, in seconds, defaults to 1 year
* @property {Boolean} silent Disables console output
- * @property {Boolean} skipMongoDBServer13732Workaround Circumvent Parse workaround for historical MongoDB bug SERVER-13732
* @property {Boolean} startLiveQueryServer Starts the liveQuery server
* @property {String[]} userSensitiveFields Personally identifiable information fields in the user table the should be removed for non-authorized users. Deprecated @see protectedFields
* @property {Boolean} verbose Set the logging to verbose
diff --git a/src/Options/index.js b/src/Options/index.js
index 43922ed3..3aa5b7fc 100644
--- a/src/Options/index.js
+++ b/src/Options/index.js
@@ -64,10 +64,6 @@ export interface ParseServerOptions {
databaseOptions: ?any;
/* Adapter module for the database */
databaseAdapter: ?Adapter;
- /* Circumvent Parse workaround for historical MongoDB bug SERVER-13732
- :ENV: PARSE_SKIP_MONGODB_SERVER_13732_WORKAROUND
- :DEFAULT: false */
- skipMongoDBServer13732Workaround: ?boolean;
/* Full path to your cloud code main.js */
cloud: ?string;
/* A collection prefix for the classes