From 8cf756b3a3e1fcb70552f7084ede3852034d2fd5 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:10:16 +0100 Subject: [PATCH 1/6] refactor --- types/Options/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/Options/index.d.ts b/types/Options/index.d.ts index 3332d0693c..7f48bbe350 100644 --- a/types/Options/index.d.ts +++ b/types/Options/index.d.ts @@ -230,7 +230,8 @@ export interface DatabaseOptions { // Parse Server custom options enableSchemaHooks?: boolean; schemaCacheTtl?: number; - + allowPublicExplain?: boolean; + // MongoDB driver options appName?: string; authMechanism?: string; @@ -238,7 +239,6 @@ export interface DatabaseOptions { authSource?: string; autoSelectFamily?: boolean; autoSelectFamilyAttemptTimeout?: number; - allowPublicExplain?: boolean; compressors?: string[] | string; connectTimeoutMS?: number; directConnection?: boolean; From 44e0013b529ae1de645d64dd8e025d58c77ea920 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:10:22 +0100 Subject: [PATCH 2/6] fix --- src/Adapters/Files/GridFSBucketAdapter.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js index 45a585ecc2..0ea554e2af 100644 --- a/src/Adapters/Files/GridFSBucketAdapter.js +++ b/src/Adapters/Files/GridFSBucketAdapter.js @@ -37,7 +37,21 @@ export class GridFSBucketAdapter extends FilesAdapter { const defaultMongoOptions = { }; const _mongoOptions = Object.assign(defaultMongoOptions, mongoOptions); - for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'maxTimeMS', 'disableIndexFieldValidation']) { + for (const key of [ + 'allowPublicExplain', + 'enableSchemaHooks', + 'schemaCacheTtl', + 'maxTimeMS', + 'disableIndexFieldValidation', + 'logClientEvents', + 'createIndexUserUsername', + 'createIndexUserUsernameCaseInsensitive', + 'createIndexUserEmail', + 'createIndexUserEmailCaseInsensitive', + 'createIndexUserEmailVerifyToken', + 'createIndexUserPasswordResetToken', + 'createIndexRoleName', + ]) { delete _mongoOptions[key]; } this._mongoOptions = _mongoOptions; From b1675317abd6b74da4e1c61fa19de0e3d37b6074 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:12:07 +0100 Subject: [PATCH 3/6] tests --- spec/GridFSBucketStorageAdapter.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js index d30415edf3..99eadef62b 100644 --- a/spec/GridFSBucketStorageAdapter.spec.js +++ b/spec/GridFSBucketStorageAdapter.spec.js @@ -25,9 +25,11 @@ describe_only_db('mongo')('GridFSBucket', () => { const gfsAdapter = new GridFSBucketAdapter(databaseURI, { retryWrites: true, // these are not supported by the mongo client + allowPublicExplain: true, enableSchemaHooks: true, schemaCacheTtl: 5000, maxTimeMS: 30000, + logClientEvents: [{ name: 'commandStarted' }], }); const db = await gfsAdapter._connect(); From e1802e02a927cbd5e37f549fc5515d4556f74906 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:15:26 +0100 Subject: [PATCH 4/6] test --- spec/GridFSBucketStorageAdapter.spec.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/spec/GridFSBucketStorageAdapter.spec.js b/spec/GridFSBucketStorageAdapter.spec.js index 99eadef62b..8e1e4f2900 100644 --- a/spec/GridFSBucketStorageAdapter.spec.js +++ b/spec/GridFSBucketStorageAdapter.spec.js @@ -24,12 +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(); From dc5bf0069161525f421c7b80c84e93c676e2fdd4 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:24:19 +0100 Subject: [PATCH 5/6] centralize --- src/Adapters/Files/GridFSBucketAdapter.js | 22 +++------------ .../Storage/Mongo/MongoStorageAdapter.js | 27 +++++-------------- src/defaults.js | 18 +++++++++++++ 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/Adapters/Files/GridFSBucketAdapter.js b/src/Adapters/Files/GridFSBucketAdapter.js index 0ea554e2af..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,24 +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 [ - 'allowPublicExplain', - 'enableSchemaHooks', - 'schemaCacheTtl', - 'maxTimeMS', - 'disableIndexFieldValidation', - 'logClientEvents', - 'createIndexUserUsername', - 'createIndexUserUsernameCaseInsensitive', - 'createIndexUserEmail', - 'createIndexUserEmailCaseInsensitive', - 'createIndexUserEmailVerifyToken', - 'createIndexUserPasswordResetToken', - 'createIndexRoleName', - ]) { + // 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..ee39f15273 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', + 'enableSchemaHooks', + 'schemaCacheTtl', + 'maxTimeMS', + 'disableIndexFieldValidation', + 'logClientEvents', + 'createIndexUserUsername', + 'createIndexUserUsernameCaseInsensitive', + 'createIndexUserEmail', + 'createIndexUserEmailCaseInsensitive', + 'createIndexUserEmailVerifyToken', + 'createIndexUserPasswordResetToken', + 'createIndexRoleName', +]; From 99aa1f8ca29792c072ea39323b8ea8b5e53409a9 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sat, 8 Nov 2025 18:30:25 +0100 Subject: [PATCH 6/6] fix --- src/defaults.js | 16 ++++++++-------- types/Options/index.d.ts | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/defaults.js b/src/defaults.js index ee39f15273..07eeb51360 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -38,16 +38,16 @@ export const DefaultMongoURI = DefinitionDefaults.databaseURI; // before passing to MongoDB client export const ParseServerDatabaseOptions = [ 'allowPublicExplain', - 'enableSchemaHooks', - 'schemaCacheTtl', - 'maxTimeMS', - 'disableIndexFieldValidation', - 'logClientEvents', - 'createIndexUserUsername', - 'createIndexUserUsernameCaseInsensitive', + 'createIndexRoleName', 'createIndexUserEmail', 'createIndexUserEmailCaseInsensitive', 'createIndexUserEmailVerifyToken', 'createIndexUserPasswordResetToken', - 'createIndexRoleName', + 'createIndexUserUsername', + 'createIndexUserUsernameCaseInsensitive', + 'disableIndexFieldValidation', + 'enableSchemaHooks', + 'logClientEvents', + 'maxTimeMS', + 'schemaCacheTtl', ]; diff --git a/types/Options/index.d.ts b/types/Options/index.d.ts index 7f48bbe350..ad11050648 100644 --- a/types/Options/index.d.ts +++ b/types/Options/index.d.ts @@ -228,9 +228,20 @@ 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; - allowPublicExplain?: boolean; // MongoDB driver options appName?: string; @@ -250,7 +261,6 @@ export interface DatabaseOptions { maxIdleTimeMS?: number; maxPoolSize?: number; maxStalenessSeconds?: number; - maxTimeMS?: number; minPoolSize?: number; proxyHost?: string; proxyPassword?: string;