From d1ea6a897e8a2ed6707b4eceea7bb0d4fe6ab5e5 Mon Sep 17 00:00:00 2001
From: Zack Pollard <zackpollard@ymail.com>
Date: Mon, 20 Feb 2023 01:50:27 +0000
Subject: [PATCH] chore(server): typeorm definitions fix part 3 (#1796)

* chore(server): tidy up exif typeorm entity definition

* chore(server): tidy up shared link typeorm entity definition

* chore(server): tidy up smart info typeorm entity definition

* chore(server): tidy up tag typeorm entity definition

* ci: add job that checks typeorm migrations are correct and up-to-date
---
 .github/workflows/test.yml                    |  45 ++++++++++++++++++
 mobile/openapi/doc/ExifResponseDto.md         | Bin 1263 -> 1229 bytes
 mobile/openapi/doc/SmartInfoResponseDto.md    | Bin 558 -> 521 bytes
 .../openapi/lib/model/exif_response_dto.dart  | Bin 10423 -> 10179 bytes
 .../lib/model/smart_info_response_dto.dart    | Bin 4566 -> 3967 bytes
 .../openapi/test/exif_response_dto_test.dart  | Bin 2495 -> 2409 bytes
 .../test/smart_info_response_dto_test.dart    | Bin 828 -> 739 bytes
 .../metadata-extraction.processor.ts          |   2 +-
 server/immich-openapi-specs.json              |   9 ----
 .../asset/response-dto/exif-response.dto.ts   |   3 --
 .../response-dto/smart-info-response.dto.ts   |   2 -
 .../metadata-extraction.interface.ts          |   2 +-
 server/libs/domain/test/fixtures.ts           |   4 --
 .../libs/infra/src/db/entities/exif.entity.ts |  17 +++----
 .../src/db/entities/shared-link.entity.ts     |  15 ++++--
 .../src/db/entities/smart-info.entity.ts      |  14 ++----
 .../libs/infra/src/db/entities/tag.entity.ts  |   6 +--
 ...1676848629119-ExifEntityDefinitionFixes.ts |  28 +++++++++++
 ...8694786-SharedLinkEntityDefinitionFixes.ts |  14 ++++++
 ...52143506-SmartInfoEntityDefinitionFixes.ts |  24 ++++++++++
 web/src/api/open-api/api.ts                   |  12 -----
 21 files changed, 138 insertions(+), 59 deletions(-)
 create mode 100644 server/libs/infra/src/db/migrations/1676848629119-ExifEntityDefinitionFixes.ts
 create mode 100644 server/libs/infra/src/db/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts
 create mode 100644 server/libs/infra/src/db/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0fb588fc11..8e26546f9b 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -79,6 +79,51 @@ jobs:
           echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
           exit 1
 
+  generated-typeorm-migrations-up-to-date:
+    name: Check generated TypeORM migrations are up-to-date
+    runs-on: ubuntu-latest
+    services:
+      postgres:
+        image: postgres
+        env:
+          POSTGRES_PASSWORD: postgres
+          POSTGRES_USER: postgres
+          POSTGRES_DB: immich
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
+        ports:
+          - 5432:5432
+    steps:
+      - uses: actions/checkout@v3
+      - name: Install server dependencies
+        run: |
+          cd server
+          npm ci
+      - name: Run existing migrations
+        run: |
+          cd server
+          npm run typeorm:migrations:run
+      - name: Generate new migrations
+        continue-on-error: true
+        run: |
+          cd server
+          npm run typeorm:migrations:generate ./libs/infra/src/db/migrations/TestMigration
+      - name: Find file changes
+        uses: tj-actions/verify-changed-files@v13.1
+        id: verify-changed-files
+        with:
+          files: |
+            server/libs/infra/src/db/migrations/
+      - name: Verify files have not changed
+        if: steps.verify-changed-files.outputs.files_changed == 'true'
+        run: |
+          echo "ERROR: Generated files not up to date!"
+          echo "Changed files: ${{ steps.verify-changed-files.outputs.changed_files }}"
+          exit 1
+
   mobile-integration-tests:
     name: Run mobile end-to-end integration tests
     runs-on: macos-latest
diff --git a/mobile/openapi/doc/ExifResponseDto.md b/mobile/openapi/doc/ExifResponseDto.md
index 3cea9375b4cb1c6c21811abeea79cfcfd139c269..5ae1099c0b2101bdac1cb52373e7e4bbad48a11d 100644
GIT binary patch
delta 10
ScmaFQd6sj+t&M*^GXnr0n+4ne

delta 16
YcmX@h`JQvaEvC$ri7ym3-ulc807EkfA^-pY

diff --git a/mobile/openapi/doc/SmartInfoResponseDto.md b/mobile/openapi/doc/SmartInfoResponseDto.md
index 84a273768a127c0dd0eaf78f5b403aa4eae3a0d6..39d162abe4d2522eab1423f6170c37d14e390fc7 100644
GIT binary patch
delta 11
ScmZ3-(#bO6{$>_NEk*ztuLF_*

delta 45
wcmeBVS;sQrzEWn2mX<<|f|gcrNl|8AI+z3GN9PxmWaj53=EN#&yratq09RcPJ^%m!

diff --git a/mobile/openapi/lib/model/exif_response_dto.dart b/mobile/openapi/lib/model/exif_response_dto.dart
index 6c80667d5d454bb18e9f5dd2b5d9140c211ac9b1..1cb298c355b42233284cb1fceacaefa2db2d49c9 100644
GIT binary patch
delta 42
ycmdlUc-VhK8{_85jLnRjm6(4qZZ>9RW!@ae!Oya}l;<Dg=G%Nxyql9{LU;gIEDqNI

delta 150
zcmX@?zddk68zXaOiq7U5#$HCI%#_XlnOK-OGE)?6Z54pLFDxR=KpMo$E6vGKuvaip
zumTDw>SZJrXE^7lq-rW?Z)V~UWdZ83RRJ2LuvwhvAIPN18~G&pGE>xJ6>JqsGBS(x
mfI@}B@*tUoB65@482L6U^ZD?C__fk<tU#5TI-Ap^V|f6Pfh>an

diff --git a/mobile/openapi/lib/model/smart_info_response_dto.dart b/mobile/openapi/lib/model/smart_info_response_dto.dart
index d24c836d5e28a8a0c7f350fcc05557dfc54664e7..f567a82a83f8833aa3afcbe54d56989178d0261b 100644
GIT binary patch
delta 37
vcmV+=0NVf7BmW+-l>w8Y0XLIH1ErGz1b&mH1dfwC1$MI;22}*Jp9(hz7&Z+!

delta 570
zcmZ{h%}(4f6ooZE5@`0_wr7S)Ow@FS^*~4~wv}25)D5DNC%&1uHFgv`Qz3+SfU2vs
ztG+}fo}e$$T^|5m0<IJ23bKgh>vKMzdwu)-@7C|1y@8T(^R4&xaz3Ar0RH2HCgBLi
zdRpM9P!45fORD@CTw!Z1QHV8RNn}`LUYlBLvD7rip)wi47X(*QrgD`DudG3?G~L6c
zB^S_OsjekKKvFL1OYN~1x+Y9(r_8FQOxh#u7nA=Hq8Nq!N^7d(R<a^PmGC6*`OelA
zXUHt0PiyCq3$3vf*%x>lf(N$1LuUB1l4k4;{o}wIrzBMnQg*sW5^(Y-T5NA%KOghZ
z!u$fc8|<O4n3zJz-4PexDd+dP+I|WzR?WZOk4+_!BrIu`{qMYlO$dq<J6LdGJS&7N
z4!E}nubS(Aa3nAJ1<_m#))70#og>0IUlP90&YI(DTgmMcByF%6^M4Ir^m+L+e0Fs+
i_%xg<xxlF?KZXZ*pC9o|9>PrnAVy1w;;VG?&Bh&TBE1>_

diff --git a/mobile/openapi/test/exif_response_dto_test.dart b/mobile/openapi/test/exif_response_dto_test.dart
index 8d38e88e08970adf928e0ec3a76d66817af47a4e..173a37b3a3171ab143967e19d7e12e81675398f5 100644
GIT binary patch
delta 12
Tcmdll{8DJcRmRQQOjFnaBt`_!

delta 26
fcmaDUv|o6`RYs=Fl*xjeiXbY1Rd@46#u@AYf-(sS

diff --git a/mobile/openapi/test/smart_info_response_dto_test.dart b/mobile/openapi/test/smart_info_response_dto_test.dart
index a5e901b7b385d2cea5e18c9fc34877fa2dab9f4b..711e62cc5b883f643a6d9bc3cbb3c81bb929d2c0 100644
GIT binary patch
delta 12
TcmdnP_Lz0U1IEpkOw5b`B0mH!

delta 32
mcmaFNx`%DU14ho^lA_GKbcM{6$=pneOhC$j$!hXj#%}<_u?w#N

diff --git a/server/apps/microservices/src/processors/metadata-extraction.processor.ts b/server/apps/microservices/src/processors/metadata-extraction.processor.ts
index 3216f9592a..6308a42d16 100644
--- a/server/apps/microservices/src/processors/metadata-extraction.processor.ts
+++ b/server/apps/microservices/src/processors/metadata-extraction.processor.ts
@@ -253,7 +253,7 @@ export class MetadataExtractionProcessor {
     if (this.isGeocodeInitialized) {
       const { latitude, longitude } = job.data;
       const { country, state, city } = await this.reverseGeocodeExif(latitude, longitude);
-      await this.exifRepository.update({ id: job.data.exifId }, { city, state, country });
+      await this.exifRepository.update({ assetId: job.data.assetId }, { city, state, country });
     }
   }
 
diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json
index 12b939797b..43c070c843 100644
--- a/server/immich-openapi-specs.json
+++ b/server/immich-openapi-specs.json
@@ -3136,12 +3136,6 @@
       "ExifResponseDto": {
         "type": "object",
         "properties": {
-          "id": {
-            "type": "integer",
-            "nullable": true,
-            "default": null,
-            "format": "int64"
-          },
           "fileSizeInByte": {
             "type": "integer",
             "nullable": true,
@@ -3245,9 +3239,6 @@
       "SmartInfoResponseDto": {
         "type": "object",
         "properties": {
-          "id": {
-            "type": "string"
-          },
           "tags": {
             "nullable": true,
             "type": "array",
diff --git a/server/libs/domain/src/asset/response-dto/exif-response.dto.ts b/server/libs/domain/src/asset/response-dto/exif-response.dto.ts
index 1695157af5..f47b753cfa 100644
--- a/server/libs/domain/src/asset/response-dto/exif-response.dto.ts
+++ b/server/libs/domain/src/asset/response-dto/exif-response.dto.ts
@@ -2,8 +2,6 @@ import { ExifEntity } from '@app/infra/db/entities';
 import { ApiProperty } from '@nestjs/swagger';
 
 export class ExifResponseDto {
-  @ApiProperty({ type: 'integer', format: 'int64' })
-  id?: number | null = null;
   make?: string | null = null;
   model?: string | null = null;
   imageName?: string | null = null;
@@ -29,7 +27,6 @@ export class ExifResponseDto {
 
 export function mapExif(entity: ExifEntity): ExifResponseDto {
   return {
-    id: entity.id,
     make: entity.make,
     model: entity.model,
     imageName: entity.imageName,
diff --git a/server/libs/domain/src/asset/response-dto/smart-info-response.dto.ts b/server/libs/domain/src/asset/response-dto/smart-info-response.dto.ts
index 788bec8d91..5e73cc594a 100644
--- a/server/libs/domain/src/asset/response-dto/smart-info-response.dto.ts
+++ b/server/libs/domain/src/asset/response-dto/smart-info-response.dto.ts
@@ -1,14 +1,12 @@
 import { SmartInfoEntity } from '@app/infra/db/entities';
 
 export class SmartInfoResponseDto {
-  id?: string;
   tags?: string[] | null;
   objects?: string[] | null;
 }
 
 export function mapSmartInfo(entity: SmartInfoEntity): SmartInfoResponseDto {
   return {
-    id: entity.id,
     tags: entity.tags,
     objects: entity.objects,
   };
diff --git a/server/libs/domain/src/job/interfaces/metadata-extraction.interface.ts b/server/libs/domain/src/job/interfaces/metadata-extraction.interface.ts
index bfacdb1e05..c64678a6ab 100644
--- a/server/libs/domain/src/job/interfaces/metadata-extraction.interface.ts
+++ b/server/libs/domain/src/job/interfaces/metadata-extraction.interface.ts
@@ -25,7 +25,7 @@ export interface IVideoLengthExtractionProcessor {
 }
 
 export interface IReverseGeocodingProcessor {
-  exifId: number;
+  assetId: string;
   latitude: number;
   longitude: number;
 }
diff --git a/server/libs/domain/test/fixtures.ts b/server/libs/domain/test/fixtures.ts
index ce07f4eb76..0d6ae37410 100644
--- a/server/libs/domain/test/fixtures.ts
+++ b/server/libs/domain/test/fixtures.ts
@@ -119,7 +119,6 @@ export const assetEntityStub = {
 };
 
 const assetInfo: ExifResponseDto = {
-  id: 1,
   make: 'camera-make',
   model: 'camera-model',
   imageName: 'fancy-image',
@@ -155,7 +154,6 @@ const assetResponse: AssetResponseDto = {
   isFavorite: false,
   mimeType: 'image/jpeg',
   smartInfo: {
-    id: 'should-be-a-number',
     tags: [],
     objects: ['a', 'b', 'c'],
   },
@@ -391,7 +389,6 @@ export const sharedLinkStub = {
           isFavorite: false,
           mimeType: 'image/jpeg',
           smartInfo: {
-            id: 'should-be-a-number',
             assetId: 'id_1',
             tags: [],
             objects: ['a', 'b', 'c'],
@@ -405,7 +402,6 @@ export const sharedLinkStub = {
           livePhotoVideoId: null,
           exifInfo: {
             livePhotoCID: null,
-            id: 1,
             assetId: 'id_1',
             description: 'description',
             exifImageWidth: 500,
diff --git a/server/libs/infra/src/db/entities/exif.entity.ts b/server/libs/infra/src/db/entities/exif.entity.ts
index 612b310daa..8375bdbfca 100644
--- a/server/libs/infra/src/db/entities/exif.entity.ts
+++ b/server/libs/infra/src/db/entities/exif.entity.ts
@@ -1,20 +1,19 @@
-import { Index, JoinColumn, OneToOne } from 'typeorm';
+import { Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
 import { Column } from 'typeorm/decorator/columns/Column';
-import { PrimaryGeneratedColumn } from 'typeorm/decorator/columns/PrimaryGeneratedColumn';
 import { Entity } from 'typeorm/decorator/entity/Entity';
 import { AssetEntity } from './asset.entity';
 
 @Entity('exif')
 export class ExifEntity {
-  @PrimaryGeneratedColumn()
-  id!: number;
+  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
+  @JoinColumn()
+  asset?: AssetEntity;
 
-  @Index({ unique: true })
-  @Column({ type: 'uuid' })
+  @PrimaryColumn()
   assetId!: string;
 
   /* General info */
-  @Column({ type: 'text', nullable: true, default: '' })
+  @Column({ type: 'text', default: '' })
   description!: string; // or caption
 
   @Column({ type: 'integer', nullable: true })
@@ -83,10 +82,6 @@ export class ExifEntity {
   @Column({ type: 'float8', nullable: true })
   fps?: number | null;
 
-  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
-  @JoinColumn({ name: 'assetId', referencedColumnName: 'id' })
-  asset?: AssetEntity;
-
   @Index('exif_text_searchable', { synchronize: false })
   @Column({
     type: 'tsvector',
diff --git a/server/libs/infra/src/db/entities/shared-link.entity.ts b/server/libs/infra/src/db/entities/shared-link.entity.ts
index 22e06c143f..5825d8b080 100644
--- a/server/libs/infra/src/db/entities/shared-link.entity.ts
+++ b/server/libs/infra/src/db/entities/shared-link.entity.ts
@@ -1,4 +1,13 @@
-import { Column, Entity, Index, ManyToMany, ManyToOne, PrimaryGeneratedColumn, Unique } from 'typeorm';
+import {
+  Column,
+  CreateDateColumn,
+  Entity,
+  Index,
+  ManyToMany,
+  ManyToOne,
+  PrimaryGeneratedColumn,
+  Unique,
+} from 'typeorm';
 import { AlbumEntity } from './album.entity';
 import { AssetEntity } from './asset.entity';
 import { UserEntity } from './user.entity';
@@ -25,7 +34,7 @@ export class SharedLinkEntity {
   @Column()
   type!: SharedLinkType;
 
-  @Column({ type: 'timestamptz' })
+  @CreateDateColumn({ type: 'timestamptz' })
   createdAt!: string;
 
   @Column({ type: 'timestamptz', nullable: true })
@@ -56,5 +65,3 @@ export enum SharedLinkType {
    */
   INDIVIDUAL = 'INDIVIDUAL',
 }
-
-// npm run typeorm -- migration:generate ./libs/infra/src/db/AddMorePermissionToSharedLink -d ./libs/infra/src/db/config/database.config.ts
diff --git a/server/libs/infra/src/db/entities/smart-info.entity.ts b/server/libs/infra/src/db/entities/smart-info.entity.ts
index f40990f59f..ae3edd8404 100644
--- a/server/libs/infra/src/db/entities/smart-info.entity.ts
+++ b/server/libs/infra/src/db/entities/smart-info.entity.ts
@@ -1,13 +1,13 @@
-import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
+import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm';
 import { AssetEntity } from './asset.entity';
 
 @Entity('smart_info')
 export class SmartInfoEntity {
-  @PrimaryGeneratedColumn()
-  id!: string;
+  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
+  @JoinColumn({ name: 'assetId', referencedColumnName: 'id' })
+  asset?: AssetEntity;
 
-  @Index({ unique: true })
-  @Column({ type: 'uuid' })
+  @PrimaryColumn()
   assetId!: string;
 
   @Column({ type: 'text', array: true, nullable: true })
@@ -15,8 +15,4 @@ export class SmartInfoEntity {
 
   @Column({ type: 'text', array: true, nullable: true })
   objects!: string[] | null;
-
-  @OneToOne(() => AssetEntity, { onDelete: 'CASCADE', nullable: true })
-  @JoinColumn({ name: 'assetId', referencedColumnName: 'id' })
-  asset?: AssetEntity;
 }
diff --git a/server/libs/infra/src/db/entities/tag.entity.ts b/server/libs/infra/src/db/entities/tag.entity.ts
index b3564337a6..cad4d4c97a 100644
--- a/server/libs/infra/src/db/entities/tag.entity.ts
+++ b/server/libs/infra/src/db/entities/tag.entity.ts
@@ -14,6 +14,9 @@ export class TagEntity {
   @Column()
   name!: string;
 
+  @ManyToOne(() => UserEntity, (user) => user.tags)
+  user!: UserEntity;
+
   @Column()
   userId!: string;
 
@@ -22,9 +25,6 @@ export class TagEntity {
 
   @ManyToMany(() => AssetEntity, (asset) => asset.tags)
   assets!: AssetEntity[];
-
-  @ManyToOne(() => UserEntity, (user) => user.tags)
-  user!: UserEntity;
 }
 
 export enum TagType {
diff --git a/server/libs/infra/src/db/migrations/1676848629119-ExifEntityDefinitionFixes.ts b/server/libs/infra/src/db/migrations/1676848629119-ExifEntityDefinitionFixes.ts
new file mode 100644
index 0000000000..35d4c77eba
--- /dev/null
+++ b/server/libs/infra/src/db/migrations/1676848629119-ExifEntityDefinitionFixes.ts
@@ -0,0 +1,28 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class ExifEntityDefinitionFixes1676848629119 implements MigrationInterface {
+    name = 'ExifEntityDefinitionFixes1676848629119'
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "exif" ALTER COLUMN "description" SET NOT NULL`);
+
+        await queryRunner.query(`DROP INDEX "public"."IDX_c0117fdbc50b917ef9067740c4"`);
+        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "PK_28663352d85078ad0046dafafaa"`);
+        await queryRunner.query(`ALTER TABLE "exif" DROP COLUMN "id"`);
+        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "FK_c0117fdbc50b917ef9067740c44"`);
+        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "PK_c0117fdbc50b917ef9067740c44" PRIMARY KEY ("assetId")`);
+        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "FK_c0117fdbc50b917ef9067740c44" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "exif" ALTER COLUMN "description" DROP NOT NULL`);
+
+        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "FK_c0117fdbc50b917ef9067740c44"`);
+        await queryRunner.query(`ALTER TABLE "exif" DROP CONSTRAINT "PK_c0117fdbc50b917ef9067740c44"`);
+        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "FK_c0117fdbc50b917ef9067740c44" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
+        await queryRunner.query(`ALTER TABLE "exif" ADD "id" SERIAL NOT NULL`);
+        await queryRunner.query(`ALTER TABLE "exif" ADD CONSTRAINT "PK_28663352d85078ad0046dafafaa" PRIMARY KEY ("id")`);
+        await queryRunner.query(`CREATE UNIQUE INDEX "IDX_c0117fdbc50b917ef9067740c4" ON "exif" ("assetId") `);
+    }
+
+}
diff --git a/server/libs/infra/src/db/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts b/server/libs/infra/src/db/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts
new file mode 100644
index 0000000000..d48f543fef
--- /dev/null
+++ b/server/libs/infra/src/db/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts
@@ -0,0 +1,14 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class SharedLinkEntityDefinitionFixes1676848694786 implements MigrationInterface {
+    name = 'SharedLinkEntityDefinitionFixes1676848694786'
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "shared_links" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "shared_links" ALTER COLUMN "createdAt" DROP DEFAULT`);
+    }
+
+}
diff --git a/server/libs/infra/src/db/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts b/server/libs/infra/src/db/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts
new file mode 100644
index 0000000000..f89c7acdd2
--- /dev/null
+++ b/server/libs/infra/src/db/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts
@@ -0,0 +1,24 @@
+import { MigrationInterface, QueryRunner } from "typeorm";
+
+export class SmartInfoEntityDefinitionFixes1676852143506 implements MigrationInterface {
+    name = 'SmartInfoEntityDefinitionFixes1676852143506'
+
+    public async up(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`DROP INDEX "public"."IDX_5e3753aadd956110bf3ec0244a"`);
+        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "PK_0beace66440e9713f5c40470e46"`);
+        await queryRunner.query(`ALTER TABLE "smart_info" DROP COLUMN "id"`);
+        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac"`);
+        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "PK_5e3753aadd956110bf3ec0244ac" PRIMARY KEY ("assetId")`);
+        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
+    }
+
+    public async down(queryRunner: QueryRunner): Promise<void> {
+        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac"`);
+        await queryRunner.query(`ALTER TABLE "smart_info" DROP CONSTRAINT "PK_5e3753aadd956110bf3ec0244ac"`);
+        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "FK_5e3753aadd956110bf3ec0244ac" FOREIGN KEY ("assetId") REFERENCES "assets"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
+        await queryRunner.query(`ALTER TABLE "smart_info" ADD "id" SERIAL NOT NULL`);
+        await queryRunner.query(`ALTER TABLE "smart_info" ADD CONSTRAINT "PK_0beace66440e9713f5c40470e46" PRIMARY KEY ("id")`);
+        await queryRunner.query(`CREATE UNIQUE INDEX "IDX_5e3753aadd956110bf3ec0244a" ON "smart_info" ("assetId") `);
+    }
+
+}
diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts
index af632f290f..ad6f206418 100644
--- a/web/src/api/open-api/api.ts
+++ b/web/src/api/open-api/api.ts
@@ -1054,12 +1054,6 @@ export interface EditSharedLinkDto {
  * @interface ExifResponseDto
  */
 export interface ExifResponseDto {
-    /**
-     * 
-     * @type {number}
-     * @memberof ExifResponseDto
-     */
-    'id'?: number | null;
     /**
      * 
      * @type {number}
@@ -1730,12 +1724,6 @@ export interface SignUpDto {
  * @interface SmartInfoResponseDto
  */
 export interface SmartInfoResponseDto {
-    /**
-     * 
-     * @type {string}
-     * @memberof SmartInfoResponseDto
-     */
-    'id'?: string;
     /**
      * 
      * @type {Array<string>}