From 17324e1e94f0f3d0d34fd6fd87a8a4d011b620db Mon Sep 17 00:00:00 2001 From: Johann150 Date: Fri, 3 Feb 2023 00:27:33 +0100 Subject: [PATCH] server: add unique constraint for registry items fixes https://akkoma.dev/FoundKeyGang/FoundKey/issues/335 --- .../1675375940759-registry-remove-domain.js | 19 +++++++++++++++++++ .../src/models/entities/registry-item.ts | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 packages/backend/migration/1675375940759-registry-remove-domain.js diff --git a/packages/backend/migration/1675375940759-registry-remove-domain.js b/packages/backend/migration/1675375940759-registry-remove-domain.js new file mode 100644 index 000000000..50a6f6b8b --- /dev/null +++ b/packages/backend/migration/1675375940759-registry-remove-domain.js @@ -0,0 +1,19 @@ +export class registryRemoveDomain1675375940759 { + name = 'registryRemoveDomain1675375940759' + + async up(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_0a72bdfcdb97c0eca11fe7ecad"`); + await queryRunner.query(`ALTER TABLE "registry_item" DROP COLUMN "domain"`); + await queryRunner.query(`ALTER TABLE "registry_item" ALTER COLUMN "key" TYPE text USING "key"::text`); + // delete existing duplicated entries, keeping the latest updated one + await queryRunner.query(`DELETE FROM "registry_item" AS "a" WHERE "updatedAt" != (SELECT MAX("updatedAt") OVER (PARTITION BY "userId", "key", "scope") FROM "registry_item" AS "b" WHERE "a"."userId" = "b"."userId" AND "a"."key" = "b"."key" AND "a"."scope" = "b"."scope")`); + await queryRunner.query(`ALTER TABLE "registry_item" ADD CONSTRAINT "UQ_b8d6509f847331273ab99daccc7" UNIQUE ("userId", "key", "scope")`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "registry_item" DROP CONSTRAINT "UQ_b8d6509f847331273ab99daccc7"`); + await queryRunner.query(`ALTER TABLE "registry_item" ALTER COLUMN "key" TYPE character varying(1024) USING "key"::varchar(1024)`); + await queryRunner.query(`ALTER TABLE "registry_item" ADD "domain" character varying(512)`); + await queryRunner.query(`CREATE INDEX "IDX_0a72bdfcdb97c0eca11fe7ecad" ON "registry_item" ("domain") `); + } +} diff --git a/packages/backend/src/models/entities/registry-item.ts b/packages/backend/src/models/entities/registry-item.ts index e82acb0e4..9ed2af720 100644 --- a/packages/backend/src/models/entities/registry-item.ts +++ b/packages/backend/src/models/entities/registry-item.ts @@ -1,9 +1,9 @@ -import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; +import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne, Unique } from 'typeorm'; import { id } from '../id.js'; import { User } from './user.js'; -// TODO: 同じdomain、同じscope、同じkeyのレコードは二つ以上存在しないように制約付けたい @Entity() +@Unique(['userId', 'key', 'scope']) export class RegistryItem { @PrimaryColumn(id()) public id: string; @@ -31,8 +31,7 @@ export class RegistryItem { @JoinColumn() public user: User | null; - @Column('varchar', { - length: 1024, + @Column('text', { comment: 'The key of the RegistryItem.', }) public key: string;