From 00ba74c71f447a80e0eee93285138cd79820a585 Mon Sep 17 00:00:00 2001 From: Riqwan Thamir Date: Wed, 3 Jul 2024 12:32:30 +0200 Subject: [PATCH] fix: user email is set to a unique index (#7917) --- .../src/migrations/.snapshot-medusa-user.json | 4 ++-- .../src/migrations/Migration20240703095850.ts | 21 +++++++++++++++++++ packages/modules/user/src/models/user.ts | 10 ++++----- 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 packages/modules/user/src/migrations/Migration20240703095850.ts diff --git a/packages/modules/user/src/migrations/.snapshot-medusa-user.json b/packages/modules/user/src/migrations/.snapshot-medusa-user.json index ba5c75981b..bde5888069 100644 --- a/packages/modules/user/src/migrations/.snapshot-medusa-user.json +++ b/packages/modules/user/src/migrations/.snapshot-medusa-user.json @@ -126,7 +126,7 @@ "composite": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_invite_token\" ON \"invite\" (deleted_at) WHERE deleted_at IS NOT NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_invite_deleted_at\" ON \"invite\" (deleted_at) WHERE deleted_at IS NOT NULL" }, { "keyName": "invite_pkey", @@ -241,7 +241,7 @@ "composite": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_user_email\" ON \"user\" (email) WHERE deleted_at IS NULL" + "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_user_email\" ON \"user\" (email) WHERE deleted_at IS NULL" }, { "keyName": "IDX_user_deleted_at", diff --git a/packages/modules/user/src/migrations/Migration20240703095850.ts b/packages/modules/user/src/migrations/Migration20240703095850.ts new file mode 100644 index 0000000000..5df9f59fdb --- /dev/null +++ b/packages/modules/user/src/migrations/Migration20240703095850.ts @@ -0,0 +1,21 @@ +import { Migration } from "@mikro-orm/migrations" + +export class Migration20240703095850 extends Migration { + async up(): Promise { + this.addSql('drop index if exists "IDX_user_email";') + + this.addSql( + 'CREATE UNIQUE INDEX "IDX_user_email" ON "user" (email) WHERE deleted_at IS NULL;' + ) + // Adding this log here as the point of failure is not in this function, but bundled up when running all pending migration + console.warn( + `Note: If the index "IDX_user_email" fails to create, then delete any existing users with duplicate emails before retrying the migration.` + ) + } + + async down(): Promise { + this.addSql( + 'CREATE INDEX IF NOT EXISTS "IDX_user_email" ON "user" (email) WHERE deleted_at IS NULL;' + ) + } +} diff --git a/packages/modules/user/src/models/user.ts b/packages/modules/user/src/models/user.ts index ca1ba27a95..0c454725e8 100644 --- a/packages/modules/user/src/models/user.ts +++ b/packages/modules/user/src/models/user.ts @@ -11,8 +11,8 @@ import { import { DAL } from "@medusajs/types" import { - DALUtils, createPsqlIndexStatementHelper, + DALUtils, generateEntityId, Searchable, } from "@medusajs/utils" @@ -20,10 +20,11 @@ import { const userEmailIndexName = "IDX_user_email" const userEmailIndexStatement = createPsqlIndexStatementHelper({ name: userEmailIndexName, + unique: true, tableName: "user", columns: "email", where: "deleted_at IS NULL", -}).expression +}) const userDeletedAtIndexName = "IDX_user_deleted_at" const userDeletedAtIndexStatement = createPsqlIndexStatementHelper({ @@ -56,10 +57,7 @@ export default class User { @Property({ columnType: "text", nullable: true }) last_name: string | null = null - @Index({ - name: userEmailIndexName, - expression: userEmailIndexStatement, - }) + @userEmailIndexStatement.MikroORMIndex() @Searchable() @Property({ columnType: "text" }) email: string