From 7af33a5c9f29b7e0d8157bccaca3e262a97b3206 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 28 Feb 2022 01:57:21 +0100 Subject: [PATCH 1/5] migration to convert all emails to lowercase --- database/migrations/0025-emails_to_lower.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 database/migrations/0025-emails_to_lower.ts diff --git a/database/migrations/0025-emails_to_lower.ts b/database/migrations/0025-emails_to_lower.ts new file mode 100644 index 000000000..14ba35261 --- /dev/null +++ b/database/migrations/0025-emails_to_lower.ts @@ -0,0 +1,16 @@ +/* MIGRATION TO MAKE ALL EMAILS LOWERCASE + * + * Make all `email` values in `users` lowercase. + * This allows safe queries without any modificators + */ + +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +export async function upgrade(queryFn: (query: string, values?: any[]) => Promise>) { + await queryFn('UPDATE `users` SET `email` = LOWER(`email`);') +} + +export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { + // This migration cannot be revered +} From fcb6b1c2d3c87d90dbbcc039264ee8d189b2ba7c Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 28 Feb 2022 02:04:42 +0100 Subject: [PATCH 2/5] update database version --- backend/src/config/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 8961fc358..580dd1a0c 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -4,7 +4,7 @@ import dotenv from 'dotenv' dotenv.config() const constants = { - DB_VERSION: '0024-combine_transaction_tables', + DB_VERSION: '0025-emails_to_lower', DECAY_START_TIME: new Date('2021-05-13 17:46:31'), // GMT+0 } From ca3d4b87ebb9eff15f1d92eae077fe8e63ac125b Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 28 Feb 2022 02:05:05 +0100 Subject: [PATCH 3/5] trim and lower email to ensure future login will work --- backend/src/graphql/resolver/UserResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index dfa685ed0..fb9c18563 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -335,7 +335,7 @@ export class UserResolver { } // Validate email unique - // TODO: i can register an email in upper/lower case twice + email = email.trim().toLowerCase() // TODO we cannot use repository.count(), since it does not allow to specify if you want to include the soft deletes const userFound = await DbUser.findOne({ email }, { withDeleted: true }) if (userFound) { From 7358524168c13df713915085a74c832ddfa59d29 Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 28 Feb 2022 02:20:17 +0100 Subject: [PATCH 4/5] database lint fixes --- database/migrations/0025-emails_to_lower.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/database/migrations/0025-emails_to_lower.ts b/database/migrations/0025-emails_to_lower.ts index 14ba35261..33f085e69 100644 --- a/database/migrations/0025-emails_to_lower.ts +++ b/database/migrations/0025-emails_to_lower.ts @@ -11,6 +11,7 @@ export async function upgrade(queryFn: (query: string, values?: any[]) => Promis await queryFn('UPDATE `users` SET `email` = LOWER(`email`);') } +// eslint-disable-next-line @typescript-eslint/no-unused-vars export async function downgrade(queryFn: (query: string, values?: any[]) => Promise>) { // This migration cannot be revered } From 396907ce89d574f30193cfd0229b725b7fdf1f1b Mon Sep 17 00:00:00 2001 From: Ulf Gebhardt Date: Mon, 28 Feb 2022 11:55:24 +0100 Subject: [PATCH 5/5] also make email lowercase on email functions --- backend/src/graphql/resolver/UserResolver.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index fb9c18563..2612407bf 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -408,6 +408,7 @@ export class UserResolver { @Authorized([RIGHTS.SEND_ACTIVATION_EMAIL]) @Mutation(() => Boolean) async sendActivationEmail(@Arg('email') email: string): Promise { + email = email.trim().toLowerCase() const user = await DbUser.findOneOrFail({ email: email }) const queryRunner = getConnection().createQueryRunner() @@ -448,7 +449,7 @@ export class UserResolver { @Query(() => Boolean) async sendResetPasswordEmail(@Arg('email') email: string): Promise { // TODO: this has duplicate code with createUser - + email = email.trim().toLowerCase() const user = await DbUser.findOneOrFail({ email }) const optInCode = await getOptInCode(user.id)