Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/Adapters/Storage/Mongo/MongoStorageAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,22 @@ export class MongoStorageAdapter implements StorageAdapter {
this.enableSchemaHooks = !!mongoOptions.enableSchemaHooks;
this.schemaCacheTtl = mongoOptions.schemaCacheTtl;
this.disableIndexFieldValidation = !!mongoOptions.disableIndexFieldValidation;
for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'maxTimeMS', 'disableIndexFieldValidation']) {
delete mongoOptions[key];
// 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 [
'enableSchemaHooks',
'schemaCacheTtl',
'maxTimeMS',
'disableIndexFieldValidation',
'createIndexUsername',
'createIndexUsernameCaseInsensitive',
'createIndexEmail',
'createIndexEmailCaseInsensitive',
'createIndexEmailVerifyToken',
'createIndexPasswordResetToken',
'createIndexRoleName',
]) {
delete this._mongoOptions[key];
}
}
Expand Down
74 changes: 45 additions & 29 deletions src/Controllers/DatabaseController.js
Original file line number Diff line number Diff line change
Expand Up @@ -1738,50 +1738,66 @@ class DatabaseController {
await this.loadSchema().then(schema => schema.enforceClassExists('_Role'));
await this.loadSchema().then(schema => schema.enforceClassExists('_Idempotency'));

await this.adapter.ensureUniqueness('_User', requiredUserFields, ['username']).catch(error => {
logger.warn('Unable to ensure uniqueness for usernames: ', error);
throw error;
});
const databaseOptions = this.options.databaseOptions || {};

if (databaseOptions.createIndexUsername) {
await this.adapter.ensureUniqueness('_User', requiredUserFields, ['username']).catch(error => {
logger.warn('Unable to ensure uniqueness for usernames: ', error);
throw error;
});
}

if (!this.options.enableCollationCaseComparison) {
if (databaseOptions.createIndexUsernameCaseInsensitive) {
await this.adapter
.ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)
.catch(error => {
logger.warn('Unable to create case insensitive username index: ', error);
throw error;
});
}

if (databaseOptions.createIndexEmailCaseInsensitive) {
await this.adapter
.ensureIndex('_User', requiredUserFields, ['email'], 'case_insensitive_email', true)
.catch(error => {
logger.warn('Unable to create case insensitive email index: ', error);
throw error;
});
}
}

if (databaseOptions.createIndexEmail) {
await this.adapter.ensureUniqueness('_User', requiredUserFields, ['email']).catch(error => {
logger.warn('Unable to ensure uniqueness for user email addresses: ', error);
throw error;
});
}

if (databaseOptions.createIndexEmailVerifyToken) {
await this.adapter
.ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)
.ensureIndex('_User', requiredUserFields, ['_email_verify_token'], '_email_verify_token', false)
.catch(error => {
logger.warn('Unable to create case insensitive username index: ', error);
logger.warn('Unable to create index for email verification token: ', error);
throw error;
});
}

if (databaseOptions.createIndexPasswordResetToken) {
await this.adapter
.ensureIndex('_User', requiredUserFields, ['email'], 'case_insensitive_email', true)
.ensureIndex('_User', requiredUserFields, ['_perishable_token'], '_perishable_token', false)
.catch(error => {
logger.warn('Unable to create case insensitive email index: ', error);
logger.warn('Unable to create index for password reset token: ', error);
throw error;
});
}

await this.adapter.ensureUniqueness('_User', requiredUserFields, ['email']).catch(error => {
logger.warn('Unable to ensure uniqueness for user email addresses: ', error);
throw error;
});

await this.adapter
.ensureIndex('_User', requiredUserFields, ['_email_verify_token'], '_email_verify_token', false)
.catch(error => {
logger.warn('Unable to create index for email verification token: ', error);
throw error;
});

await this.adapter
.ensureIndex('_User', requiredUserFields, ['_perishable_token'], '_perishable_token', false)
.catch(error => {
logger.warn('Unable to create index for password reset token: ', error);
if (databaseOptions.createIndexRoleName) {
await this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name']).catch(error => {
logger.warn('Unable to ensure uniqueness for role name: ', error);
throw error;
});

await this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name']).catch(error => {
logger.warn('Unable to ensure uniqueness for role name: ', error);
throw error;
});
}

await this.adapter
.ensureUniqueness('_Idempotency', requiredIdempotencyFields, ['reqId'])
Expand Down
49 changes: 49 additions & 0 deletions src/Options/Definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,55 @@ module.exports.DatabaseOptions = {
'The MongoDB driver option to specify the amount of time, in milliseconds, to wait to establish a single TCP socket connection to the server before raising an error. Specifying 0 disables the connection timeout.',
action: parsers.numberParser('connectTimeoutMS'),
},
createIndexEmail: {
env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_EMAIL',
help:
'Set to `true` to automatically create indexes on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
action: parsers.booleanParser,
default: true,
},
createIndexEmailCaseInsensitive: {
env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_EMAIL_CASE_INSENSITIVE',
help:
'Set to `true` to automatically create a case-insensitive index on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
action: parsers.booleanParser,
default: true,
},
createIndexEmailVerifyToken: {
env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_EMAIL_VERIFY_TOKEN',
help:
'Set to `true` to automatically create an index on the _email_verify_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
action: parsers.booleanParser,
default: true,
},
createIndexPasswordResetToken: {
env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_PASSWORD_RESET_TOKEN',
help:
'Set to `true` to automatically create an index on the _perishable_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
action: parsers.booleanParser,
default: true,
},
createIndexRoleName: {
env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_ROLE_NAME',
help:
'Set to `true` to automatically create a unique index on the name field of the _Role collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
action: parsers.booleanParser,
default: true,
},
createIndexUsername: {
env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USERNAME',
help:
'Set to `true` to automatically create indexes on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
action: parsers.booleanParser,
default: true,
},
createIndexUsernameCaseInsensitive: {
env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USERNAME_CASE_INSENSITIVE',
help:
'Set to `true` to automatically create a case-insensitive index on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
action: parsers.booleanParser,
default: true,
},
disableIndexFieldValidation: {
env: 'PARSE_SERVER_DATABASE_DISABLE_INDEX_FIELD_VALIDATION',
help:
Expand Down
7 changes: 7 additions & 0 deletions src/Options/docs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions src/Options/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,27 @@ export interface DatabaseOptions {
autoSelectFamily: ?boolean;
/* The MongoDB driver option to specify the amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the autoSelectFamily option. If set to a positive integer less than 10, the value 10 is used instead. */
autoSelectFamilyAttemptTimeout: ?number;
/* Set to `true` to automatically create indexes on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
:DEFAULT: true */
createIndexEmail: ?boolean;
/* Set to `true` to automatically create a case-insensitive index on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
:DEFAULT: true */
createIndexEmailCaseInsensitive: ?boolean;
/* Set to `true` to automatically create an index on the _email_verify_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
:DEFAULT: true */
createIndexEmailVerifyToken: ?boolean;
/* Set to `true` to automatically create an index on the _perishable_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
:DEFAULT: true */
createIndexPasswordResetToken: ?boolean;
/* Set to `true` to automatically create indexes on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
:DEFAULT: true */
createIndexUsername: ?boolean;
/* Set to `true` to automatically create a case-insensitive index on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
:DEFAULT: true */
createIndexUsernameCaseInsensitive: ?boolean;
/* Set to `true` to automatically create a unique index on the name field of the _Role collection on server start. Set to `false` to skip index creation. Default is `true`.<br><br>⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
:DEFAULT: true */
createIndexRoleName: ?boolean;
/* Set to `true` to disable validation of index fields. When disabled, indexes can be created even if the fields do not exist in the schema. This can be useful when creating indexes on fields that will be added later. */
disableIndexFieldValidation: ?boolean;
}
Expand Down
Loading