diff --git a/.changeset/fifty-lizards-jump.md b/.changeset/fifty-lizards-jump.md new file mode 100644 index 000000000000..9e25adc86072 --- /dev/null +++ b/.changeset/fifty-lizards-jump.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fix: Performance issue when using api to create users diff --git a/.changeset/quick-spies-count.md b/.changeset/quick-spies-count.md new file mode 100644 index 000000000000..a845151cc840 --- /dev/null +++ b/.changeset/quick-spies-count.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/apps/meteor/app/lib/server/functions/checkEmailAvailability.ts b/apps/meteor/app/lib/server/functions/checkEmailAvailability.ts index 21a5fc36de85..900f299bafe5 100644 --- a/apps/meteor/app/lib/server/functions/checkEmailAvailability.ts +++ b/apps/meteor/app/lib/server/functions/checkEmailAvailability.ts @@ -1,8 +1,5 @@ -import { escapeRegExp } from '@rocket.chat/string-helpers'; import { Users } from '@rocket.chat/models'; export const checkEmailAvailability = async function (email: string): Promise { - return !(await Users.findOne({ - 'emails.address': { $regex: new RegExp(`^${escapeRegExp(email).trim()}$`, 'i') }, - })); + return !(await Users.findOneByEmailAddress(email)); }; diff --git a/apps/meteor/server/models/raw/Users.js b/apps/meteor/server/models/raw/Users.js index d9195da6a437..390ef81b7bd9 100644 --- a/apps/meteor/server/models/raw/Users.js +++ b/apps/meteor/server/models/raw/Users.js @@ -66,6 +66,18 @@ export class UsersRaw extends BaseRaw { { key: { language: 1 }, sparse: true }, { key: { 'active': 1, 'services.email2fa.enabled': 1 }, sparse: true }, // used by statistics { key: { 'active': 1, 'services.totp.enabled': 1 }, sparse: true }, // used by statistics + // Used for case insensitive queries + // @deprecated + // Should be converted to unique index later within a migration to prevent errors of duplicated + // records. Those errors does not helps to identify the duplicated value so we need to find a + // way to help the migration in case it happens. + { + key: { 'emails.address': 1 }, + unique: false, + sparse: true, + name: 'emails.address_insensitive', + collation: { locale: 'en', strength: 2, caseLevel: false }, + }, ]; } @@ -1910,17 +1922,23 @@ export class UsersRaw extends BaseRaw { findOneByEmailAddressAndServiceNameIgnoringCase(emailAddress, userId, serviceName, options) { const query = { - 'emails.address': new RegExp(`^${escapeRegExp(String(emailAddress).trim())}$`, 'i'), + 'emails.address': String(emailAddress).trim(), [`services.${serviceName}.id`]: userId, }; - return this.findOne(query, options); + return this.findOne(query, { + collation: { locale: 'en', strength: 2 }, // Case insensitive + ...options, + }); } findOneByEmailAddress(emailAddress, options) { - const query = { 'emails.address': String(emailAddress).trim().toLowerCase() }; + const query = { 'emails.address': String(emailAddress).trim() }; - return this.findOne(query, options); + return this.findOne(query, { + collation: { locale: 'en', strength: 2 }, // Case insensitive + ...options, + }); } findOneWithoutLDAPByEmailAddress(emailAddress, options) {