From cefdd86b7fac01e795830cc9ca8752db6fafec26 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Thu, 8 Dec 2022 10:57:07 -0500 Subject: [PATCH] refactor(server): device info service (#1071) * refactor(server): device info service * use upsertDeviceInfo in mobile app * fix: return types and dedupe code Co-authored-by: Fynn Petersen-Frey --- .../backup/services/backup.service.dart | 4 +- .../providers/authentication.provider.dart | 4 +- mobile/openapi/.openapi-generator/FILES | 9 +- mobile/openapi/README.md | Bin 11423 -> 11476 bytes mobile/openapi/doc/DeviceInfoApi.md | Bin 3247 -> 4786 bytes mobile/openapi/doc/UpdateDeviceInfoDto.md | Bin 525 -> 0 bytes ...eviceInfoDto.md => UpsertDeviceInfoDto.md} | Bin 525 -> 525 bytes mobile/openapi/lib/api.dart | Bin 4063 -> 4021 bytes mobile/openapi/lib/api/device_info_api.dart | Bin 3841 -> 5647 bytes mobile/openapi/lib/api_client.dart | Bin 15102 -> 15012 bytes .../lib/model/create_device_info_dto.dart | Bin 4439 -> 0 bytes ...o_dto.dart => upsert_device_info_dto.dart} | Bin 4439 -> 4439 bytes mobile/openapi/test/device_info_api_test.dart | Bin 803 -> 1053 bytes .../test/update_device_info_dto_test.dart | Bin 801 -> 0 bytes ....dart => upsert_device_info_dto_test.dart} | Bin 801 -> 801 bytes .../device-info/device-info.controller.ts | 34 ++- .../device-info/device-info.service.spec.ts | 65 ++++++ .../api-v1/device-info/device-info.service.ts | 69 ++---- .../device-info/dto/update-device-info.dto.ts | 15 -- ...-info.dto.ts => upsert-device-info.dto.ts} | 2 +- ...nse.dto.ts => device-info-response.dto.ts} | 0 server/immich-openapi-specs.json | 62 +++-- web/src/api/open-api/api.ts | 218 +++++++++++------- 23 files changed, 285 insertions(+), 197 deletions(-) delete mode 100644 mobile/openapi/doc/UpdateDeviceInfoDto.md rename mobile/openapi/doc/{CreateDeviceInfoDto.md => UpsertDeviceInfoDto.md} (93%) delete mode 100644 mobile/openapi/lib/model/create_device_info_dto.dart rename mobile/openapi/lib/model/{update_device_info_dto.dart => upsert_device_info_dto.dart} (76%) delete mode 100644 mobile/openapi/test/update_device_info_dto_test.dart rename mobile/openapi/test/{create_device_info_dto_test.dart => upsert_device_info_dto_test.dart} (85%) create mode 100644 server/apps/immich/src/api-v1/device-info/device-info.service.spec.ts delete mode 100644 server/apps/immich/src/api-v1/device-info/dto/update-device-info.dto.ts rename server/apps/immich/src/api-v1/device-info/dto/{create-device-info.dto.ts => upsert-device-info.dto.ts} (91%) rename server/apps/immich/src/api-v1/device-info/response-dto/{create-device-info-response.dto.ts => device-info-response.dto.ts} (100%) diff --git a/mobile/lib/modules/backup/services/backup.service.dart b/mobile/lib/modules/backup/services/backup.service.dart index 325e1cbea..02b0a6863 100644 --- a/mobile/lib/modules/backup/services/backup.service.dart +++ b/mobile/lib/modules/backup/services/backup.service.dart @@ -376,8 +376,8 @@ class BackupService { DeviceTypeEnum deviceType, ) async { try { - var updatedDeviceInfo = await _apiService.deviceInfoApi.updateDeviceInfo( - UpdateDeviceInfoDto( + var updatedDeviceInfo = await _apiService.deviceInfoApi.upsertDeviceInfo( + UpsertDeviceInfoDto( deviceId: deviceId, deviceType: deviceType, isAutoBackup: status, diff --git a/mobile/lib/modules/login/providers/authentication.provider.dart b/mobile/lib/modules/login/providers/authentication.provider.dart index db1c2343c..9bf7d53eb 100644 --- a/mobile/lib/modules/login/providers/authentication.provider.dart +++ b/mobile/lib/modules/login/providers/authentication.provider.dart @@ -210,8 +210,8 @@ class AuthenticationNotifier extends StateNotifier { // Register device info try { DeviceInfoResponseDto? deviceInfo = - await _apiService.deviceInfoApi.createDeviceInfo( - CreateDeviceInfoDto( + await _apiService.deviceInfoApi.upsertDeviceInfo( + UpsertDeviceInfoDto( deviceId: state.deviceId, deviceType: state.deviceType, ), diff --git a/mobile/openapi/.openapi-generator/FILES b/mobile/openapi/.openapi-generator/FILES index 20453107c..15fce354b 100644 --- a/mobile/openapi/.openapi-generator/FILES +++ b/mobile/openapi/.openapi-generator/FILES @@ -24,7 +24,6 @@ doc/CheckDuplicateAssetResponseDto.md doc/CheckExistingAssetsDto.md doc/CheckExistingAssetsResponseDto.md doc/CreateAlbumDto.md -doc/CreateDeviceInfoDto.md doc/CreateProfileImageResponseDto.md doc/CreateTagDto.md doc/CreateUserDto.md @@ -72,9 +71,9 @@ doc/ThumbnailFormat.md doc/TimeGroupEnum.md doc/UpdateAlbumDto.md doc/UpdateAssetDto.md -doc/UpdateDeviceInfoDto.md doc/UpdateTagDto.md doc/UpdateUserDto.md +doc/UpsertDeviceInfoDto.md doc/UsageByUserDto.md doc/UserApi.md doc/UserCountResponseDto.md @@ -118,7 +117,6 @@ lib/model/check_duplicate_asset_response_dto.dart lib/model/check_existing_assets_dto.dart lib/model/check_existing_assets_response_dto.dart lib/model/create_album_dto.dart -lib/model/create_device_info_dto.dart lib/model/create_profile_image_response_dto.dart lib/model/create_tag_dto.dart lib/model/create_user_dto.dart @@ -160,9 +158,9 @@ lib/model/thumbnail_format.dart lib/model/time_group_enum.dart lib/model/update_album_dto.dart lib/model/update_asset_dto.dart -lib/model/update_device_info_dto.dart lib/model/update_tag_dto.dart lib/model/update_user_dto.dart +lib/model/upsert_device_info_dto.dart lib/model/usage_by_user_dto.dart lib/model/user_count_response_dto.dart lib/model/user_response_dto.dart @@ -189,7 +187,6 @@ test/check_duplicate_asset_response_dto_test.dart test/check_existing_assets_dto_test.dart test/check_existing_assets_response_dto_test.dart test/create_album_dto_test.dart -test/create_device_info_dto_test.dart test/create_profile_image_response_dto_test.dart test/create_tag_dto_test.dart test/create_user_dto_test.dart @@ -237,9 +234,9 @@ test/thumbnail_format_test.dart test/time_group_enum_test.dart test/update_album_dto_test.dart test/update_asset_dto_test.dart -test/update_device_info_dto_test.dart test/update_tag_dto_test.dart test/update_user_dto_test.dart +test/upsert_device_info_dto_test.dart test/usage_by_user_dto_test.dart test/user_api_test.dart test/user_count_response_dto_test.dart diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 3f71fdba579dd96374852ef14873bcafc2f51442..a0482b3e0322a1e1ff27ce8ae5f62f9bf0649528 100644 GIT binary patch delta 107 zcmbOqc_nf~fav7MB4RAXsYNA|CyJ;@mKK1RDXC?d$*GxnY5AH8H40i<0ihwAZA8O) pH=k4z;+QO`?W+k^<^opc2~_4%k{_#)lAo-vABrZkIZ)e=5dcn=CXWCB delta 100 zcmcZ-IX`kkfavDkqRzZ3E~#ai$*G=sY56WC`LP-)`N{hF&PAz-C8-FR&2N-cIIyY= SEl5F8Ir*Pf{N~Bpj*I|xoF%sa diff --git a/mobile/openapi/doc/DeviceInfoApi.md b/mobile/openapi/doc/DeviceInfoApi.md index d1c032e65af69bab4fc3eea749cd851f0552f66b..b4dcdb255b649b002a25fafa987bd560be8c5a71 100644 GIT binary patch delta 485 zcmZ24xk+_HGb3lTmR4y&acWV?#E0^d5LQZRS!Qx-W?ovprb3N^mR3M$$m9aXP-Td$ z3s}|@DC<&^ugL`j4k@VxMXAY&C8;T!3)r79N`Z_+QKn$45DK^en-kc-5E~>`qNqNC8UYNQ6sViHCKB(sm5c!76t9Q? delta 245 zcmdm_x?XZaGvnmzj81IHMX8A;shg8|KQYQc*e#{yqQyQCFA63b|;n;h}B;h zr9dnc%g?T~j zzljFpGNNyRv8D+e5W+SD4ZR+zZP$6ed8mqVTlv9>#BLgtArUgjj_9(O_L#!2y4crO WYJK*ZGSZ?pbYU?M{4+ddjC}#2R-17d9R>&_%%}XrE)XU9JNzKs17d9R>&_%%}XrE)XU9JNzKu7E=o--N!=*+oe=<_oC@dw diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index 7d403fe5922d1dd5edde4a530c26853218c05760..69efb7a304ee95c2e4256b30171862c4f5daa14c 100644 GIT binary patch delta 31 ncmcaFzg2z%C;Mh&_Gq@rJ9zC`3yM>VN+$R6s&4+y`+^Ywv*!z) delta 37 scmdlge_wtBC;Q};yvmdBv9WLFWRGS8a#SWa@Ul%#;kDm(|+^i7}E(K|x<%A3`cPq@)%Ur6wnqq^6*V`{kFUS}BBNWELyrrj}&nrzjMq zmXsFd6)Tivq$+rXgajx=2c;GlDEWfK7_thFIY1(D)3@Fp))uopm%LBx0$6H_f0 E0M*b9UjP6A delta 380 zcmeCzX_VWriBU8lwJ0sWD7RQ4F;BrGBqTsVJ-|PBawC7Zv~y8vVo9n?YFTD-s%KtW zzDr4dtU@waaIylA^5kqLbtx=rU`lj_WhS3sYGQ-v*c`w-opG`dlQaQittZ#A3gS1` zc=BylS(vf^SSK<~&gB@kE5BvZC delta 67 zcmZ2d`mc0DiQ?oK1I5V>ifmjisb!hTsh)Xh`I8wnlsD%ohVTL9lqWmrv!KaM-lIQz J^G1WuoB%hC7%Kn( diff --git a/mobile/openapi/lib/model/create_device_info_dto.dart b/mobile/openapi/lib/model/create_device_info_dto.dart deleted file mode 100644 index 1c2cf46e16be0bc5a46cca7fb3a4caf7975befa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4439 zcmds4TW{Mo6n^)wI0=ec!CYtU)8NiYyCxmnwaL(C0|p~7Xo-&5%A!Y735+!Vec$25 zQetIWp9ai8Vv9VNkLU6o>hQ34cu22*yEuRL^Xb{?$JZC9C-ipm{&YYm=X7>{K_AXf zCU5`PgBVM`Dui+47sKZ-diUD4=FLr&Yb8#;o7{b)W#2>iAl5$yk1((SHLCmw1@_MB3J?NwEL0^*ntjF^ zjcG^x_U>g!d=QzMeuJui3618lTX0ge#F!#Z&24Ye17u{)9_ znCA8Y&bFY}PFev=W#BMz*TaAN#loXBclwU2tKCg|4nW_Aq?9 zWBLQU6lP9C;7fEpFr{?@*K$?FqVOWaTv)eL9$6R^oKrO6X=Q7})Fqs!x0P6fL@OsS z#Qef`Ons3X%fuEH&%kr^eB@=kH$(}&+jo>NW&TALgnI&GSB1g=nahnv*yoZ7HVu!5 z=3cNloXfK~zAeVpdJR+HUV~c(Pp1_~WG}+Nu*P)CwvEBi65d}JE+CwWe3@kc-$aVV zqAG`Ln9d6oFF2t7$9Op*DAImc*FV9|W%Lc-f5b#@d z)9}jYC z2hXjKPSRA*!P8sXi}IvLQvYhL(m zSJ30${$F*(S=z>}RZD|y%QnqB_zw!~5U;0lTT5x=^RVVi3$8N$6>u*3N@jtdyGn$C i*_4sLr`@|RG^swi^(@xDIft1NS1_pjOZUqjO8zfRew9)H diff --git a/mobile/openapi/lib/model/update_device_info_dto.dart b/mobile/openapi/lib/model/upsert_device_info_dto.dart similarity index 76% rename from mobile/openapi/lib/model/update_device_info_dto.dart rename to mobile/openapi/lib/model/upsert_device_info_dto.dart index c11a2df567f90bc14ec27694d4014a84b4c41e19..7d642d28c5db2fa744a420a488d11bd23cf7f4db 100644 GIT binary patch delta 201 zcmcbvbX{qKCL>F6YEj8#T}E{X<2{@Btd*$_iT$H zlGE6iK!xl$lOe_|<;;i3NpNvMEqVoB;`T}E{X<2{@Btd*$_iT$H zlGE6iK!xl$lOe_|<;;i3NpNvM(^b delta 98 zcmbQsv6yYcMaId+%yN?@m;|Mqi&7IyQe9HZGLut1^V0HNO7azw!D5s5Fsn>XXR-z= gRhaymNl+pMLt$wFNDQb@ZL$@!DO;_kHCHVc0G@Cma{vGU diff --git a/mobile/openapi/test/update_device_info_dto_test.dart b/mobile/openapi/test/update_device_info_dto_test.dart deleted file mode 100644 index 46aefee1b8d3847da7a03cc8878437d6807f8439..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 801 zcmb7>QA@)x6oudWE3QwQFjw_S9DHWM&6S&T9(+MOwEb;>G@+7-{JRq4@URK<=i__`JY2-)I zNM(@K%CK6rcn-bnEmjO$>`=PNZWf(Z#tk}n`^Gnx>E1Deue~s2m%O7>b3=EB#!|Sk z!}d~1>$r4GR0I^YKojhC5Y`HbmbFSYBy%e++1W8GSKQbr+IEDI=H&}-@LXw>T#J~l zso#1u`z3K`UF?sYz(f6Pfj$W=b;TVfxE3X5vQ~*x(OQWLIxgh+5Z)sIGSouy7DU*i zM7S98jSpuLsT-quJsx?)kZLr6uhbw5`>-d~4BN%fwqXLw<`5f~fbBN%fwqXLw<`5dS diff --git a/server/apps/immich/src/api-v1/device-info/device-info.controller.ts b/server/apps/immich/src/api-v1/device-info/device-info.controller.ts index f2865d219..3e57f47e5 100644 --- a/server/apps/immich/src/api-v1/device-info/device-info.controller.ts +++ b/server/apps/immich/src/api-v1/device-info/device-info.controller.ts @@ -1,11 +1,10 @@ -import { Controller, Post, Body, Patch, ValidationPipe } from '@nestjs/common'; +import { Body, Controller, Patch, Post, Put, ValidationPipe } from '@nestjs/common'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; import { AuthUserDto, GetAuthUser } from '../../decorators/auth-user.decorator'; import { Authenticated } from '../../decorators/authenticated.decorator'; import { DeviceInfoService } from './device-info.service'; -import { CreateDeviceInfoDto } from './dto/create-device-info.dto'; -import { UpdateDeviceInfoDto } from './dto/update-device-info.dto'; -import { DeviceInfoResponseDto } from './response-dto/create-device-info-response.dto'; +import { UpsertDeviceInfoDto } from './dto/upsert-device-info.dto'; +import { DeviceInfoResponseDto, mapDeviceInfoResponse } from './response-dto/device-info-response.dto'; @Authenticated() @ApiBearerAuth() @@ -14,19 +13,30 @@ import { DeviceInfoResponseDto } from './response-dto/create-device-info-respons export class DeviceInfoController { constructor(private readonly deviceInfoService: DeviceInfoService) {} + /** @deprecated */ @Post() - async createDeviceInfo( - @Body(ValidationPipe) createDeviceInfoDto: CreateDeviceInfoDto, - @GetAuthUser() authUser: AuthUserDto, + public async createDeviceInfo( + @GetAuthUser() user: AuthUserDto, + @Body(ValidationPipe) dto: UpsertDeviceInfoDto, ): Promise { - return this.deviceInfoService.create(createDeviceInfoDto, authUser); + return this.upsertDeviceInfo(user, dto); } + /** @deprecated */ @Patch() - async updateDeviceInfo( - @Body(ValidationPipe) updateDeviceInfoDto: UpdateDeviceInfoDto, - @GetAuthUser() authUser: AuthUserDto, + public async updateDeviceInfo( + @GetAuthUser() user: AuthUserDto, + @Body(ValidationPipe) dto: UpsertDeviceInfoDto, ): Promise { - return this.deviceInfoService.update(authUser.id, updateDeviceInfoDto); + return this.upsertDeviceInfo(user, dto); + } + + @Put() + public async upsertDeviceInfo( + @GetAuthUser() user: AuthUserDto, + @Body(ValidationPipe) dto: UpsertDeviceInfoDto, + ): Promise { + const deviceInfo = await this.deviceInfoService.upsert({ ...dto, userId: user.id }); + return mapDeviceInfoResponse(deviceInfo); } } diff --git a/server/apps/immich/src/api-v1/device-info/device-info.service.spec.ts b/server/apps/immich/src/api-v1/device-info/device-info.service.spec.ts new file mode 100644 index 000000000..60f39c2a4 --- /dev/null +++ b/server/apps/immich/src/api-v1/device-info/device-info.service.spec.ts @@ -0,0 +1,65 @@ +import { DeviceInfoEntity, DeviceType } from '@app/database/entities/device-info.entity'; +import { Repository } from 'typeorm'; +import { DeviceInfoService } from './device-info.service'; + +const deviceId = 'device-123'; +const userId = 'user-123'; + +describe('DeviceInfoService', () => { + let sut: DeviceInfoService; + let repositoryMock: jest.Mocked>; + + beforeEach(async () => { + repositoryMock = { + findOne: jest.fn(), + save: jest.fn(), + } as unknown as jest.Mocked>; + + sut = new DeviceInfoService(repositoryMock); + }); + + it('should be defined', () => { + expect(sut).toBeDefined(); + }); + + describe('upsert', () => { + it('should create a new record', async () => { + const request = { deviceId, userId, deviceType: DeviceType.IOS } as DeviceInfoEntity; + const response = { ...request, id: 1 } as DeviceInfoEntity; + + repositoryMock.findOne.mockResolvedValue(null); + repositoryMock.save.mockResolvedValue(response); + + await expect(sut.upsert(request)).resolves.toEqual(response); + + expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); + expect(repositoryMock.save).toHaveBeenCalledTimes(1); + }); + + it('should update an existing record', async () => { + const request = { deviceId, userId, deviceType: DeviceType.IOS, isAutoBackup: true } as DeviceInfoEntity; + const response = { ...request, id: 1 } as DeviceInfoEntity; + + repositoryMock.findOne.mockResolvedValue(response); + repositoryMock.save.mockResolvedValue(response); + + await expect(sut.upsert(request)).resolves.toEqual(response); + + expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); + expect(repositoryMock.save).toHaveBeenCalledTimes(1); + }); + + it('should keep properties that were not updated', async () => { + const request = { deviceId, userId } as DeviceInfoEntity; + const response = { id: 1, isAutoBackup: true, deviceId, userId, deviceType: DeviceType.WEB } as DeviceInfoEntity; + + repositoryMock.findOne.mockResolvedValue(response); + repositoryMock.save.mockResolvedValue(response); + + await expect(sut.upsert(request)).resolves.toEqual(response); + + expect(repositoryMock.findOne).toHaveBeenCalledTimes(1); + expect(repositoryMock.save).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/server/apps/immich/src/api-v1/device-info/device-info.service.ts b/server/apps/immich/src/api-v1/device-info/device-info.service.ts index 76a546fbc..b5f3facec 100644 --- a/server/apps/immich/src/api-v1/device-info/device-info.service.ts +++ b/server/apps/immich/src/api-v1/device-info/device-info.service.ts @@ -1,70 +1,29 @@ -import { BadRequestException, Injectable, Logger, NotFoundException } from '@nestjs/common'; +import { DeviceInfoEntity } from '@app/database/entities/device-info.entity'; +import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { AuthUserDto } from '../../decorators/auth-user.decorator'; -import { CreateDeviceInfoDto } from './dto/create-device-info.dto'; -import { UpdateDeviceInfoDto } from './dto/update-device-info.dto'; -import { DeviceInfoEntity } from '@app/database/entities/device-info.entity'; -import { DeviceInfoResponseDto, mapDeviceInfoResponse } from './response-dto/create-device-info-response.dto'; + +type EntityKeys = Pick; +type Entity = EntityKeys & Partial; @Injectable() export class DeviceInfoService { constructor( @InjectRepository(DeviceInfoEntity) - private deviceRepository: Repository, + private repository: Repository, ) {} - async create(createDeviceInfoDto: CreateDeviceInfoDto, authUser: AuthUserDto): Promise { - const res = await this.deviceRepository.findOne({ - where: { - deviceId: createDeviceInfoDto.deviceId, - userId: authUser.id, - }, - }); + public async upsert(entity: Entity): Promise { + const { deviceId, userId } = entity; + const exists = await this.repository.findOne({ where: { userId, deviceId } }); - if (res) { - Logger.log('Device Info Exist', 'createDeviceInfo'); - return mapDeviceInfoResponse(res); + if (!exists) { + return await this.repository.save(entity); } - const deviceInfo = new DeviceInfoEntity(); - deviceInfo.deviceId = createDeviceInfoDto.deviceId; - deviceInfo.deviceType = createDeviceInfoDto.deviceType; - deviceInfo.userId = authUser.id; + exists.isAutoBackup = entity.isAutoBackup ?? exists.isAutoBackup; + exists.deviceType = entity.deviceType ?? exists.deviceType; - const newDeviceInfo = await this.deviceRepository.save(deviceInfo); - - return mapDeviceInfoResponse(newDeviceInfo); - } - - async update(userId: string, updateDeviceInfoDto: UpdateDeviceInfoDto): Promise { - const deviceInfo = await this.deviceRepository.findOne({ - where: { deviceId: updateDeviceInfoDto.deviceId, userId: userId }, - }); - - if (!deviceInfo) { - throw new NotFoundException('Device Not Found'); - } - - const res = await this.deviceRepository.update( - { - id: deviceInfo.id, - }, - updateDeviceInfoDto, - ); - - if (res.affected == 1) { - const updatedDeviceInfo = await this.deviceRepository.findOne({ - where: { deviceId: updateDeviceInfoDto.deviceId, userId: userId }, - }); - - if (!updatedDeviceInfo) { - throw new NotFoundException('Device Not Found'); - } - - return mapDeviceInfoResponse(updatedDeviceInfo); - } else { - throw new BadRequestException('Bad Request'); - } + return await this.repository.save(exists); } } diff --git a/server/apps/immich/src/api-v1/device-info/dto/update-device-info.dto.ts b/server/apps/immich/src/api-v1/device-info/dto/update-device-info.dto.ts deleted file mode 100644 index f267d9036..000000000 --- a/server/apps/immich/src/api-v1/device-info/dto/update-device-info.dto.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { DeviceType } from '@app/database/entities/device-info.entity'; -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsOptional } from 'class-validator'; - -export class UpdateDeviceInfoDto { - @IsNotEmpty() - deviceId!: string; - - @IsNotEmpty() - @ApiProperty({ enumName: 'DeviceTypeEnum', enum: DeviceType }) - deviceType!: DeviceType; - - @IsOptional() - isAutoBackup?: boolean; -} diff --git a/server/apps/immich/src/api-v1/device-info/dto/create-device-info.dto.ts b/server/apps/immich/src/api-v1/device-info/dto/upsert-device-info.dto.ts similarity index 91% rename from server/apps/immich/src/api-v1/device-info/dto/create-device-info.dto.ts rename to server/apps/immich/src/api-v1/device-info/dto/upsert-device-info.dto.ts index 29dddea81..e4233bc45 100644 --- a/server/apps/immich/src/api-v1/device-info/dto/create-device-info.dto.ts +++ b/server/apps/immich/src/api-v1/device-info/dto/upsert-device-info.dto.ts @@ -2,7 +2,7 @@ import { IsNotEmpty, IsOptional } from 'class-validator'; import { DeviceType } from '@app/database/entities/device-info.entity'; import { ApiProperty } from '@nestjs/swagger'; -export class CreateDeviceInfoDto { +export class UpsertDeviceInfoDto { @IsNotEmpty() deviceId!: string; diff --git a/server/apps/immich/src/api-v1/device-info/response-dto/create-device-info-response.dto.ts b/server/apps/immich/src/api-v1/device-info/response-dto/device-info-response.dto.ts similarity index 100% rename from server/apps/immich/src/api-v1/device-info/response-dto/create-device-info-response.dto.ts rename to server/apps/immich/src/api-v1/device-info/response-dto/device-info-response.dto.ts diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json index 23f921e5c..29533a036 100644 --- a/server/immich-openapi-specs.json +++ b/server/immich-openapi-specs.json @@ -1783,13 +1783,15 @@ "/device-info": { "post": { "operationId": "createDeviceInfo", + "summary": "", + "description": "@deprecated", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateDeviceInfoDto" + "$ref": "#/components/schemas/UpsertDeviceInfoDto" } } } @@ -1817,13 +1819,49 @@ }, "patch": { "operationId": "updateDeviceInfo", + "summary": "", + "description": "@deprecated", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateDeviceInfoDto" + "$ref": "#/components/schemas/UpsertDeviceInfoDto" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeviceInfoResponseDto" + } + } + } + } + }, + "tags": [ + "Device Info" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "put": { + "operationId": "upsertDeviceInfo", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpsertDeviceInfoDto" } } } @@ -3227,7 +3265,7 @@ "WEB" ] }, - "CreateDeviceInfoDto": { + "UpsertDeviceInfoDto": { "type": "object", "properties": { "deviceType": { @@ -3276,24 +3314,6 @@ "isAutoBackup" ] }, - "UpdateDeviceInfoDto": { - "type": "object", - "properties": { - "deviceType": { - "$ref": "#/components/schemas/DeviceTypeEnum" - }, - "deviceId": { - "type": "string" - }, - "isAutoBackup": { - "type": "boolean" - } - }, - "required": [ - "deviceType", - "deviceId" - ] - }, "ServerInfoResponseDto": { "type": "object", "properties": { diff --git a/web/src/api/open-api/api.ts b/web/src/api/open-api/api.ts index 4cdf22ac2..7e126a44b 100644 --- a/web/src/api/open-api/api.ts +++ b/web/src/api/open-api/api.ts @@ -564,31 +564,6 @@ export interface CreateAlbumDto { */ 'assetIds'?: Array; } -/** - * - * @export - * @interface CreateDeviceInfoDto - */ -export interface CreateDeviceInfoDto { - /** - * - * @type {DeviceTypeEnum} - * @memberof CreateDeviceInfoDto - */ - 'deviceType': DeviceTypeEnum; - /** - * - * @type {string} - * @memberof CreateDeviceInfoDto - */ - 'deviceId': string; - /** - * - * @type {boolean} - * @memberof CreateDeviceInfoDto - */ - 'isAutoBackup'?: boolean; -} /** * * @export @@ -1629,31 +1604,6 @@ export interface UpdateAssetDto { */ 'isFavorite'?: boolean; } -/** - * - * @export - * @interface UpdateDeviceInfoDto - */ -export interface UpdateDeviceInfoDto { - /** - * - * @type {DeviceTypeEnum} - * @memberof UpdateDeviceInfoDto - */ - 'deviceType': DeviceTypeEnum; - /** - * - * @type {string} - * @memberof UpdateDeviceInfoDto - */ - 'deviceId': string; - /** - * - * @type {boolean} - * @memberof UpdateDeviceInfoDto - */ - 'isAutoBackup'?: boolean; -} /** * * @export @@ -1722,6 +1672,31 @@ export interface UpdateUserDto { */ 'profileImagePath'?: string; } +/** + * + * @export + * @interface UpsertDeviceInfoDto + */ +export interface UpsertDeviceInfoDto { + /** + * + * @type {DeviceTypeEnum} + * @memberof UpsertDeviceInfoDto + */ + 'deviceType': DeviceTypeEnum; + /** + * + * @type {string} + * @memberof UpsertDeviceInfoDto + */ + 'deviceId': string; + /** + * + * @type {boolean} + * @memberof UpsertDeviceInfoDto + */ + 'isAutoBackup'?: boolean; +} /** * * @export @@ -4321,14 +4296,15 @@ export class AuthenticationApi extends BaseAPI { export const DeviceInfoApiAxiosParamCreator = function (configuration?: Configuration) { return { /** - * - * @param {CreateDeviceInfoDto} createDeviceInfoDto + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - createDeviceInfo: async (createDeviceInfoDto: CreateDeviceInfoDto, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'createDeviceInfoDto' is not null or undefined - assertParamExists('createDeviceInfo', 'createDeviceInfoDto', createDeviceInfoDto) + createDeviceInfo: async (upsertDeviceInfoDto: UpsertDeviceInfoDto, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'upsertDeviceInfoDto' is not null or undefined + assertParamExists('createDeviceInfo', 'upsertDeviceInfoDto', upsertDeviceInfoDto) const localVarPath = `/device-info`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -4352,7 +4328,7 @@ export const DeviceInfoApiAxiosParamCreator = function (configuration?: Configur setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(createDeviceInfoDto, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(upsertDeviceInfoDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -4360,14 +4336,15 @@ export const DeviceInfoApiAxiosParamCreator = function (configuration?: Configur }; }, /** - * - * @param {UpdateDeviceInfoDto} updateDeviceInfoDto + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - updateDeviceInfo: async (updateDeviceInfoDto: UpdateDeviceInfoDto, options: AxiosRequestConfig = {}): Promise => { - // verify required parameter 'updateDeviceInfoDto' is not null or undefined - assertParamExists('updateDeviceInfo', 'updateDeviceInfoDto', updateDeviceInfoDto) + updateDeviceInfo: async (upsertDeviceInfoDto: UpsertDeviceInfoDto, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'upsertDeviceInfoDto' is not null or undefined + assertParamExists('updateDeviceInfo', 'upsertDeviceInfoDto', upsertDeviceInfoDto) const localVarPath = `/device-info`; // use dummy base URL string because the URL constructor only accepts absolute URLs. const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); @@ -4391,7 +4368,46 @@ export const DeviceInfoApiAxiosParamCreator = function (configuration?: Configur setSearchParams(localVarUrlObj, localVarQueryParameter); let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; - localVarRequestOptions.data = serializeDataIfNeeded(updateDeviceInfoDto, localVarRequestOptions, configuration) + localVarRequestOptions.data = serializeDataIfNeeded(upsertDeviceInfoDto, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + upsertDeviceInfo: async (upsertDeviceInfoDto: UpsertDeviceInfoDto, options: AxiosRequestConfig = {}): Promise => { + // verify required parameter 'upsertDeviceInfoDto' is not null or undefined + assertParamExists('upsertDeviceInfo', 'upsertDeviceInfoDto', upsertDeviceInfoDto) + const localVarPath = `/device-info`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication bearer required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration) + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(upsertDeviceInfoDto, localVarRequestOptions, configuration) return { url: toPathString(localVarUrlObj), @@ -4409,23 +4425,35 @@ export const DeviceInfoApiFp = function(configuration?: Configuration) { const localVarAxiosParamCreator = DeviceInfoApiAxiosParamCreator(configuration) return { /** - * - * @param {CreateDeviceInfoDto} createDeviceInfoDto + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async createDeviceInfo(createDeviceInfoDto: CreateDeviceInfoDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.createDeviceInfo(createDeviceInfoDto, options); + async createDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.createDeviceInfo(upsertDeviceInfoDto, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async updateDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.updateDeviceInfo(upsertDeviceInfoDto, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, /** * - * @param {UpdateDeviceInfoDto} updateDeviceInfoDto + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async updateDeviceInfo(updateDeviceInfoDto: UpdateDeviceInfoDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { - const localVarAxiosArgs = await localVarAxiosParamCreator.updateDeviceInfo(updateDeviceInfoDto, options); + async upsertDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.upsertDeviceInfo(upsertDeviceInfoDto, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, } @@ -4439,22 +4467,33 @@ export const DeviceInfoApiFactory = function (configuration?: Configuration, bas const localVarFp = DeviceInfoApiFp(configuration) return { /** - * - * @param {CreateDeviceInfoDto} createDeviceInfoDto + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - createDeviceInfo(createDeviceInfoDto: CreateDeviceInfoDto, options?: any): AxiosPromise { - return localVarFp.createDeviceInfo(createDeviceInfoDto, options).then((request) => request(axios, basePath)); + createDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: any): AxiosPromise { + return localVarFp.createDeviceInfo(upsertDeviceInfoDto, options).then((request) => request(axios, basePath)); + }, + /** + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + updateDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: any): AxiosPromise { + return localVarFp.updateDeviceInfo(upsertDeviceInfoDto, options).then((request) => request(axios, basePath)); }, /** * - * @param {UpdateDeviceInfoDto} updateDeviceInfoDto + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} */ - updateDeviceInfo(updateDeviceInfoDto: UpdateDeviceInfoDto, options?: any): AxiosPromise { - return localVarFp.updateDeviceInfo(updateDeviceInfoDto, options).then((request) => request(axios, basePath)); + upsertDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: any): AxiosPromise { + return localVarFp.upsertDeviceInfo(upsertDeviceInfoDto, options).then((request) => request(axios, basePath)); }, }; }; @@ -4467,25 +4506,38 @@ export const DeviceInfoApiFactory = function (configuration?: Configuration, bas */ export class DeviceInfoApi extends BaseAPI { /** - * - * @param {CreateDeviceInfoDto} createDeviceInfoDto + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DeviceInfoApi */ - public createDeviceInfo(createDeviceInfoDto: CreateDeviceInfoDto, options?: AxiosRequestConfig) { - return DeviceInfoApiFp(this.configuration).createDeviceInfo(createDeviceInfoDto, options).then((request) => request(this.axios, this.basePath)); + public createDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: AxiosRequestConfig) { + return DeviceInfoApiFp(this.configuration).createDeviceInfo(upsertDeviceInfoDto, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * @deprecated + * @summary + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DeviceInfoApi + */ + public updateDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: AxiosRequestConfig) { + return DeviceInfoApiFp(this.configuration).updateDeviceInfo(upsertDeviceInfoDto, options).then((request) => request(this.axios, this.basePath)); } /** * - * @param {UpdateDeviceInfoDto} updateDeviceInfoDto + * @param {UpsertDeviceInfoDto} upsertDeviceInfoDto * @param {*} [options] Override http request option. * @throws {RequiredError} * @memberof DeviceInfoApi */ - public updateDeviceInfo(updateDeviceInfoDto: UpdateDeviceInfoDto, options?: AxiosRequestConfig) { - return DeviceInfoApiFp(this.configuration).updateDeviceInfo(updateDeviceInfoDto, options).then((request) => request(this.axios, this.basePath)); + public upsertDeviceInfo(upsertDeviceInfoDto: UpsertDeviceInfoDto, options?: AxiosRequestConfig) { + return DeviceInfoApiFp(this.configuration).upsertDeviceInfo(upsertDeviceInfoDto, options).then((request) => request(this.axios, this.basePath)); } }