From 89890c4df79fa85cc969c543a7e7d3445780b19d Mon Sep 17 00:00:00 2001 From: Kay Joosten Date: Tue, 2 Jun 2026 11:46:07 +0200 Subject: [PATCH] feat(db): add unique constraint on user.uuid The uuid column stores collabPersonUuid, which must be unique per user. The existing non-unique idx_user_uuid provided no enforcement. Migration uses ALGORITHM=INPLACE, LOCK=NONE for zero-downtime on large tables. Skips if idx_user_uuid is absent (already migrated manually). Closes #1974 --- .../Version20260602000000.php | 77 +++++++++++++++++++ .../Authentication/Entity/User.php | 2 +- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 migrations/DoctrineMigrations/Version20260602000000.php diff --git a/migrations/DoctrineMigrations/Version20260602000000.php b/migrations/DoctrineMigrations/Version20260602000000.php new file mode 100644 index 0000000000..b619d81390 --- /dev/null +++ b/migrations/DoctrineMigrations/Version20260602000000.php @@ -0,0 +1,77 @@ +connection->createSchemaManager()->introspectTableIndexes( + new OptionallyQualifiedName(Identifier::unquoted('user'), null) + ); + $existingIndex = array_filter( + $indexes, + static fn(Index $index) => $index->getObjectName()->equals( + UnqualifiedName::unquoted('idx_user_uuid'), + UnquotedIdentifierFolding::NONE + ) + ); + + $this->skipIf( + count($existingIndex) === 0, + 'Index idx_user_uuid on user table does not exist. Skipping (already migrated).' + ); + } + + public function up(Schema $schema): void + { + $this->addSql('SET SESSION innodb_sort_buffer_size = 268435456'); + $this->addSql( + 'ALTER TABLE `user` ADD UNIQUE INDEX `uq_user_uuid` (`uuid`), DROP INDEX `idx_user_uuid`, ALGORITHM=INPLACE, LOCK=NONE' + ); + } + + public function down(Schema $schema): void + { + $this->addSql( + 'ALTER TABLE `user` ADD INDEX `idx_user_uuid` (`uuid`), DROP INDEX `uq_user_uuid`' + ); + } + + public function isTransactional(): bool + { + return false; + } +} diff --git a/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php b/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php index 747a5d97d6..d5b6ff76a9 100644 --- a/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php +++ b/src/OpenConext/EngineBlockBundle/Authentication/Entity/User.php @@ -23,7 +23,7 @@ use OpenConext\EngineBlockBundle\Authentication\Repository\UserRepository; #[ORM\Entity(repositoryClass: UserRepository::class)] -#[ORM\Index(name: 'idx_user_uuid', columns: ['uuid'])] +#[ORM\UniqueConstraint(name: 'uq_user_uuid', columns: ['uuid'])] class User { /**