diff --git a/packages/backend/src/db/migrations/20231013094544_convert_user_emails_to_lowercase.ts b/packages/backend/src/db/migrations/20231013094544_convert_user_emails_to_lowercase.ts new file mode 100644 index 00000000..623bfc75 --- /dev/null +++ b/packages/backend/src/db/migrations/20231013094544_convert_user_emails_to_lowercase.ts @@ -0,0 +1,13 @@ +import { Knex } from 'knex'; + +export async function up(knex: Knex): Promise { + await knex('users') + .whereRaw('email != LOWER(email)') + .update({ + email: knex.raw('LOWER(email)'), + }); +} + +export async function down(): Promise { + // void +} diff --git a/packages/backend/src/graphql/mutations/create-user.ee.ts b/packages/backend/src/graphql/mutations/create-user.ee.ts index 887bdc89..956be348 100644 --- a/packages/backend/src/graphql/mutations/create-user.ee.ts +++ b/packages/backend/src/graphql/mutations/create-user.ee.ts @@ -13,12 +13,18 @@ type Params = { }; }; -const createUser = async (_parent: unknown, params: Params, context: Context) => { +const createUser = async ( + _parent: unknown, + params: Params, + context: Context +) => { context.currentUser.can('create', 'User'); const { fullName, email, password } = params.input; - const existingUser = await User.query().findOne({ email }); + const existingUser = await User.query().findOne({ + email: email.toLowerCase(), + }); if (existingUser) { throw new Error('User already exists!'); diff --git a/packages/backend/src/graphql/mutations/forgot-password.ee.ts b/packages/backend/src/graphql/mutations/forgot-password.ee.ts index 5e28a429..e40a32d9 100644 --- a/packages/backend/src/graphql/mutations/forgot-password.ee.ts +++ b/packages/backend/src/graphql/mutations/forgot-password.ee.ts @@ -15,7 +15,7 @@ type Params = { const forgotPassword = async (_parent: unknown, params: Params) => { const { email } = params.input; - const user = await User.query().findOne({ email }); + const user = await User.query().findOne({ email: email.toLowerCase() }); if (!user) { throw new Error('Email address not found!'); diff --git a/packages/backend/src/graphql/mutations/register-user.ee.ts b/packages/backend/src/graphql/mutations/register-user.ee.ts index 0a7ede07..ba0651b4 100644 --- a/packages/backend/src/graphql/mutations/register-user.ee.ts +++ b/packages/backend/src/graphql/mutations/register-user.ee.ts @@ -12,7 +12,9 @@ type Params = { const registerUser = async (_parent: unknown, params: Params) => { const { fullName, email, password } = params.input; - const existingUser = await User.query().findOne({ email }); + const existingUser = await User.query().findOne({ + email: email.toLowerCase(), + }); if (existingUser) { throw new Error('User already exists!'); diff --git a/packages/backend/src/models/user.ts b/packages/backend/src/models/user.ts index fe58670c..20060458 100644 --- a/packages/backend/src/models/user.ts +++ b/packages/backend/src/models/user.ts @@ -263,6 +263,8 @@ class User extends Base { async $beforeInsert(queryContext: QueryContext) { await super.$beforeInsert(queryContext); + + this.email = this.email.toLowerCase(); await this.generateHash(); if (appConfig.isCloud) { @@ -273,6 +275,7 @@ class User extends Base { async $beforeUpdate(opt: ModelOptions, queryContext: QueryContext) { await super.$beforeUpdate(opt, queryContext); + this.email = this.email.toLowerCase(); await this.generateHash(); }