diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js index d30415edf3..8e1e4f2900 100644 --- a/spec/GridFSBucketStorageAdapter.spec.js +++ b/spec/GridFSBucketStorageAdapter.spec.js @@ -24,10 +24,20 @@ describe_only_db('mongo')('GridFSBucket', () => { const databaseURI = 'mongodb://localhost:27017/parse'; const gfsAdapter = new GridFSBucketAdapter(databaseURI, { retryWrites: true, - // these are not supported by the mongo client + // Parse Server-specific options that should be filtered out before passing to MongoDB client + allowPublicExplain: true, enableSchemaHooks: true, schemaCacheTtl: 5000, maxTimeMS: 30000, + disableIndexFieldValidation: true, + logClientEvents: [{ name: 'commandStarted' }], + createIndexUserUsername: true, + createIndexUserUsernameCaseInsensitive: true, + createIndexUserEmail: true, + createIndexUserEmailCaseInsensitive: true, + createIndexUserEmailVerifyToken: true, + createIndexUserPasswordResetToken: true, + createIndexRoleName: true, }); const db = await gfsAdapter._connect(); diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js index 45a585ecc2..b301d1c0c1 100644 --- a/src/Adapters/Files/GridFSBucketAdapter.js +++ b/src/Adapters/Files/GridFSBucketAdapter.js @@ -9,7 +9,7 @@ // @flow-disable-next import { MongoClient, GridFSBucket, Db } from 'mongodb'; import { FilesAdapter, validateFilename } from './FilesAdapter'; -import defaults from '../../defaults'; +import defaults, { ParseServerDatabaseOptions } from '../../defaults'; const crypto = require('crypto'); export class GridFSBucketAdapter extends FilesAdapter { @@ -34,10 +34,10 @@ export class GridFSBucketAdapter extends FilesAdapter { .digest('base64') .substring(0, 32) : null; - const defaultMongoOptions = { - }; + const defaultMongoOptions = {}; const _mongoOptions = Object.assign(defaultMongoOptions, mongoOptions); - for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'maxTimeMS', 'disableIndexFieldValidation']) { + // Remove Parse Server-specific options that should not be passed to MongoDB client + for (const key of ParseServerDatabaseOptions) { delete _mongoOptions[key]; } this._mongoOptions = _mongoOptions; diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index afe9f39282..50fd348861 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -16,7 +16,7 @@ import { import Parse from 'parse/node'; // @flow-disable-next import _ from 'lodash'; -import defaults from '../../../defaults'; +import defaults, { ParseServerDatabaseOptions } from '../../../defaults'; import logger from '../../../logger'; import Utils from '../../../Utils'; @@ -147,7 +147,6 @@ export class MongoStorageAdapter implements StorageAdapter { constructor({ uri = defaults.DefaultMongoURI, collectionPrefix = '', mongoOptions = {} }: any) { this._uri = uri; this._collectionPrefix = collectionPrefix; - this._mongoOptions = { ...mongoOptions }; this._onchange = () => {}; // MaxTimeMS is not a global MongoDB client option, it is applied per operation. @@ -158,24 +157,12 @@ export class MongoStorageAdapter implements StorageAdapter { this.disableIndexFieldValidation = !!mongoOptions.disableIndexFieldValidation; this._logClientEvents = mongoOptions.logClientEvents; - // Remove Parse Server-specific options that should not be passed to MongoDB client - // Note: We only delete from this._mongoOptions, not from the original mongoOptions object, - // because other components (like DatabaseController) need access to these options - for (const key of [ - 'allowPublicExplain', - 'enableSchemaHooks', - 'schemaCacheTtl', - 'maxTimeMS', - 'disableIndexFieldValidation', - 'logClientEvents', - 'createIndexUserUsername', - 'createIndexUserUsernameCaseInsensitive', - 'createIndexUserEmail', - 'createIndexUserEmailCaseInsensitive', - 'createIndexUserEmailVerifyToken', - 'createIndexUserPasswordResetToken', - 'createIndexRoleName', - ]) { + // Create a copy of mongoOptions and remove Parse Server-specific options that should not + // be passed to MongoDB client. Note: We only delete from this._mongoOptions, not from the + // original mongoOptions object, because other components (like DatabaseController) need + // access to these options. + this._mongoOptions = { ...mongoOptions }; + for (const key of ParseServerDatabaseOptions) { delete this._mongoOptions[key]; } } diff --git a/src/defaults.js b/src/defaults.js index a2b105d8db..07eeb51360 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -33,3 +33,21 @@ const computedDefaults = { export default Object.assign({}, DefinitionDefaults, computedDefaults); export const DefaultMongoURI = DefinitionDefaults.databaseURI; + +// Parse Server-specific database options that should be filtered out +// before passing to MongoDB client +export const ParseServerDatabaseOptions = [ + 'allowPublicExplain', + 'createIndexRoleName', + 'createIndexUserEmail', + 'createIndexUserEmailCaseInsensitive', + 'createIndexUserEmailVerifyToken', + 'createIndexUserPasswordResetToken', + 'createIndexUserUsername', + 'createIndexUserUsernameCaseInsensitive', + 'disableIndexFieldValidation', + 'enableSchemaHooks', + 'logClientEvents', + 'maxTimeMS', + 'schemaCacheTtl', +]; diff --git a/types/Options/index.d.ts b/types/Options/index.d.ts index 3332d0693c..ad11050648 100644 --- a/types/Options/index.d.ts +++ b/types/Options/index.d.ts @@ -228,9 +228,21 @@ export interface FileUploadOptions { } export interface DatabaseOptions { // Parse Server custom options + allowPublicExplain?: boolean; + createIndexRoleName?: boolean; + createIndexUserEmail?: boolean; + createIndexUserEmailCaseInsensitive?: boolean; + createIndexUserEmailVerifyToken?: boolean; + createIndexUserPasswordResetToken?: boolean; + createIndexUserUsername?: boolean; + createIndexUserUsernameCaseInsensitive?: boolean; + disableIndexFieldValidation?: boolean; enableSchemaHooks?: boolean; + logClientEvents?: any[]; + // maxTimeMS is a MongoDB option but Parse Server applies it per-operation, not as a global client option + maxTimeMS?: number; schemaCacheTtl?: number; - + // MongoDB driver options appName?: string; authMechanism?: string; @@ -238,7 +250,6 @@ export interface DatabaseOptions { authSource?: string; autoSelectFamily?: boolean; autoSelectFamilyAttemptTimeout?: number; - allowPublicExplain?: boolean; compressors?: string[] | string; connectTimeoutMS?: number; directConnection?: boolean; @@ -250,7 +261,6 @@ export interface DatabaseOptions { maxIdleTimeMS?: number; maxPoolSize?: number; maxStalenessSeconds?: number; - maxTimeMS?: number; minPoolSize?: number; proxyHost?: string; proxyPassword?: string;