Skip to content

Commit d3d4003

Browse files
authored
fix: GridFSBucketAdapter throws when using some Parse Server specific options in MongoDB database options (#9915)
1 parent 502a512 commit d3d4003

File tree

5 files changed

+53
-28
lines changed

5 files changed

+53
-28
lines changed

spec/GridFSBucketStorageAdapter.spec.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,20 @@ describe_only_db('mongo')('GridFSBucket', () => {
2424
const databaseURI = 'mongodb://localhost:27017/parse';
2525
const gfsAdapter = new GridFSBucketAdapter(databaseURI, {
2626
retryWrites: true,
27-
// these are not supported by the mongo client
27+
// Parse Server-specific options that should be filtered out before passing to MongoDB client
28+
allowPublicExplain: true,
2829
enableSchemaHooks: true,
2930
schemaCacheTtl: 5000,
3031
maxTimeMS: 30000,
32+
disableIndexFieldValidation: true,
33+
logClientEvents: [{ name: 'commandStarted' }],
34+
createIndexUserUsername: true,
35+
createIndexUserUsernameCaseInsensitive: true,
36+
createIndexUserEmail: true,
37+
createIndexUserEmailCaseInsensitive: true,
38+
createIndexUserEmailVerifyToken: true,
39+
createIndexUserPasswordResetToken: true,
40+
createIndexRoleName: true,
3141
});
3242

3343
const db = await gfsAdapter._connect();

src/Adapters/Files/GridFSBucketAdapter.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// @flow-disable-next
1010
import { MongoClient, GridFSBucket, Db } from 'mongodb';
1111
import { FilesAdapter, validateFilename } from './FilesAdapter';
12-
import defaults from '../../defaults';
12+
import defaults, { ParseServerDatabaseOptions } from '../../defaults';
1313
const crypto = require('crypto');
1414

1515
export class GridFSBucketAdapter extends FilesAdapter {
@@ -34,10 +34,10 @@ export class GridFSBucketAdapter extends FilesAdapter {
3434
.digest('base64')
3535
.substring(0, 32)
3636
: null;
37-
const defaultMongoOptions = {
38-
};
37+
const defaultMongoOptions = {};
3938
const _mongoOptions = Object.assign(defaultMongoOptions, mongoOptions);
40-
for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'maxTimeMS', 'disableIndexFieldValidation']) {
39+
// Remove Parse Server-specific options that should not be passed to MongoDB client
40+
for (const key of ParseServerDatabaseOptions) {
4141
delete _mongoOptions[key];
4242
}
4343
this._mongoOptions = _mongoOptions;

src/Adapters/Storage/Mongo/MongoStorageAdapter.js

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
import Parse from 'parse/node';
1717
// @flow-disable-next
1818
import _ from 'lodash';
19-
import defaults from '../../../defaults';
19+
import defaults, { ParseServerDatabaseOptions } from '../../../defaults';
2020
import logger from '../../../logger';
2121
import Utils from '../../../Utils';
2222

@@ -147,7 +147,6 @@ export class MongoStorageAdapter implements StorageAdapter {
147147
constructor({ uri = defaults.DefaultMongoURI, collectionPrefix = '', mongoOptions = {} }: any) {
148148
this._uri = uri;
149149
this._collectionPrefix = collectionPrefix;
150-
this._mongoOptions = { ...mongoOptions };
151150
this._onchange = () => {};
152151

153152
// MaxTimeMS is not a global MongoDB client option, it is applied per operation.
@@ -158,24 +157,12 @@ export class MongoStorageAdapter implements StorageAdapter {
158157
this.disableIndexFieldValidation = !!mongoOptions.disableIndexFieldValidation;
159158
this._logClientEvents = mongoOptions.logClientEvents;
160159

161-
// Remove Parse Server-specific options that should not be passed to MongoDB client
162-
// Note: We only delete from this._mongoOptions, not from the original mongoOptions object,
163-
// because other components (like DatabaseController) need access to these options
164-
for (const key of [
165-
'allowPublicExplain',
166-
'enableSchemaHooks',
167-
'schemaCacheTtl',
168-
'maxTimeMS',
169-
'disableIndexFieldValidation',
170-
'logClientEvents',
171-
'createIndexUserUsername',
172-
'createIndexUserUsernameCaseInsensitive',
173-
'createIndexUserEmail',
174-
'createIndexUserEmailCaseInsensitive',
175-
'createIndexUserEmailVerifyToken',
176-
'createIndexUserPasswordResetToken',
177-
'createIndexRoleName',
178-
]) {
160+
// Create a copy of mongoOptions and remove Parse Server-specific options that should not
161+
// be passed to MongoDB client. Note: We only delete from this._mongoOptions, not from the
162+
// original mongoOptions object, because other components (like DatabaseController) need
163+
// access to these options.
164+
this._mongoOptions = { ...mongoOptions };
165+
for (const key of ParseServerDatabaseOptions) {
179166
delete this._mongoOptions[key];
180167
}
181168
}

src/defaults.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,21 @@ const computedDefaults = {
3333

3434
export default Object.assign({}, DefinitionDefaults, computedDefaults);
3535
export const DefaultMongoURI = DefinitionDefaults.databaseURI;
36+
37+
// Parse Server-specific database options that should be filtered out
38+
// before passing to MongoDB client
39+
export const ParseServerDatabaseOptions = [
40+
'allowPublicExplain',
41+
'createIndexRoleName',
42+
'createIndexUserEmail',
43+
'createIndexUserEmailCaseInsensitive',
44+
'createIndexUserEmailVerifyToken',
45+
'createIndexUserPasswordResetToken',
46+
'createIndexUserUsername',
47+
'createIndexUserUsernameCaseInsensitive',
48+
'disableIndexFieldValidation',
49+
'enableSchemaHooks',
50+
'logClientEvents',
51+
'maxTimeMS',
52+
'schemaCacheTtl',
53+
];

types/Options/index.d.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,17 +228,28 @@ export interface FileUploadOptions {
228228
}
229229
export interface DatabaseOptions {
230230
// Parse Server custom options
231+
allowPublicExplain?: boolean;
232+
createIndexRoleName?: boolean;
233+
createIndexUserEmail?: boolean;
234+
createIndexUserEmailCaseInsensitive?: boolean;
235+
createIndexUserEmailVerifyToken?: boolean;
236+
createIndexUserPasswordResetToken?: boolean;
237+
createIndexUserUsername?: boolean;
238+
createIndexUserUsernameCaseInsensitive?: boolean;
239+
disableIndexFieldValidation?: boolean;
231240
enableSchemaHooks?: boolean;
241+
logClientEvents?: any[];
242+
// maxTimeMS is a MongoDB option but Parse Server applies it per-operation, not as a global client option
243+
maxTimeMS?: number;
232244
schemaCacheTtl?: number;
233-
245+
234246
// MongoDB driver options
235247
appName?: string;
236248
authMechanism?: string;
237249
authMechanismProperties?: any;
238250
authSource?: string;
239251
autoSelectFamily?: boolean;
240252
autoSelectFamilyAttemptTimeout?: number;
241-
allowPublicExplain?: boolean;
242253
compressors?: string[] | string;
243254
connectTimeoutMS?: number;
244255
directConnection?: boolean;
@@ -250,7 +261,6 @@ export interface DatabaseOptions {
250261
maxIdleTimeMS?: number;
251262
maxPoolSize?: number;
252263
maxStalenessSeconds?: number;
253-
maxTimeMS?: number;
254264
minPoolSize?: number;
255265
proxyHost?: string;
256266
proxyPassword?: string;

0 commit comments

Comments
 (0)