From 5268dc4ee2b54cc16b2ddf9a9a07b810f04172ec Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Tue, 27 May 2025 16:33:23 +0200 Subject: [PATCH] feat: version check endpoint (#18572) --- mobile/openapi/README.md | Bin 35877 -> 36202 bytes mobile/openapi/lib/api.dart | Bin 12886 -> 12938 bytes mobile/openapi/lib/api/server_api.dart | Bin 18496 -> 19929 bytes .../openapi/lib/api/system_metadata_api.dart | Bin 4715 -> 6193 bytes mobile/openapi/lib/api_client.dart | Bin 32623 -> 32731 bytes .../version_check_state_response_dto.dart | Bin 0 -> 3656 bytes open-api/immich-openapi-specs.json | 81 ++++++++++++++++++ open-api/typescript-sdk/src/fetch-client.ts | 20 +++++ .../src/controllers/server.controller.spec.ts | 3 + server/src/controllers/server.controller.ts | 9 ++ .../controllers/system-metadata.controller.ts | 12 ++- server/src/dtos/system-metadata.dto.ts | 5 ++ .../src/services/system-metadata.service.ts | 6 ++ 13 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 mobile/openapi/lib/model/version_check_state_response_dto.dart diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 64b85939b3d8db35a6a5e06c1bdda77b53f0caef..ab9814d0f0bf7f6f90b88bf712134e5576609f6a 100644 GIT binary patch delta 159 zcmZ2FgXz^QrVTGFSe-Lcld~tkw@_eB2D22+MJCTPXJ^xea2d@cHb1oB;^R+GEeT64 zD$dN$gXoBNQ{yRv2tZU$byE_C3PAMg7MCQJq)yg%limEg0>Oikq+N*E0bC9o-Ks delta 12 TcmeB5y_T}!hW=(AgE}SvD0&4@ diff --git a/mobile/openapi/lib/api/server_api.dart b/mobile/openapi/lib/api/server_api.dart index 629949db32efbeaf25e62fbb8c410eaa3aeaff47..a0fd54f3d2bb7c1a771f2f054b9363e29cd00a40 100644 GIT binary patch delta 182 zcmX>wf$`>S#tnUDtjQUv$=Q<~4efZsQj3Z+^Yfg+0uRm7AX1zC%y%&AACAgh?XQ9~2OxXlkW%$Q7&m7p7MZSRscKRJ4*ln delta 12 TcmdmJ@LFX<0`F!uVQy9cA+rPu diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index a1240c800c9e5e813cbeafd22ad55369ff8eba3a..cc01fd2c064ee392feeb30b8cef6de0eb93bca12 100644 GIT binary patch delta 52 zcmaF=kMZ_@#tnN)xKoRYGxPJDGg6bYCm-}w5e!2T2rfx1Nu6Bir@eW1$rdgEeUcW} delta 18 acmccppYi=a#tnN)CfAp;ZPqJY%LM>rxd}u7 diff --git a/mobile/openapi/lib/model/version_check_state_response_dto.dart b/mobile/openapi/lib/model/version_check_state_response_dto.dart new file mode 100644 index 0000000000000000000000000000000000000000..d3f9a6cd959362f45117487e73fbe87fb957bba5 GIT binary patch literal 3656 zcmbVPU2oeq6n*!vxG9QS!Bn~1Q{l``gT@)!H8GH61qQTmj%A!hAHH_5%efN@* zEG4dz^`WUP-S2bmAw3!mMk6@;=XU=3ui4e?`s{Xg4i_Ij&3rhY!`1v2F6ZYTF8)12 zGqQXaGi4@!1i!x>&{wg_rQ%^CRhWp3kD<&<&Et?~e9d#?*WbmukjfnNVA+Okby$=p zRQy{h6uReZjeiTK@PEUV#^6dHc8_GP4a-d^VoWF!!IgE_2a{zY=Q_+}zCtsTvOIkI zCX7<1^k9JL49Emz!E;uK0RNo~22sYehR;}pkoo(RM_+FYGyIzC0yFb-BjJ7kFv4M6 zb5p8Z1B0AzVA1EZ1YygLc!17*mL5e1s7C`P6*`Eh4j!Kw|G-Oy!)KaTLCIowjEw-? z7$x%6DKy@lr(HMu>Ye<~mBPWI^PQ9#jYcse6-*}H{O${na9}3o>KGetMIcr zx@P-gy3hM7>e|{E56eCLR&p*?L(n>f>LQ!R+SO%z79zhLKIyiq7d~tl`-vyd(f+8r?wu; zqKZ|n&YB8ku~IB1P4#TCKD_8-_zRRZ(njK#wI_+ep6YM_9gbR)AY$4)Vyou_(g`hz zcyAk?%}T}%Wyi2)#b=uNJh|N#yvi{3Xg_f2TI4=ZOhWmUAQ z*=A`~LGwvq>wN>ALWU+6$e9jCu7`Vj0<4tWu)7SU6B35Y=^d?#? z_s~&zLXOHqfwvnG2z@2ZY+aab9UsxegU74V$PJ#L)^z{A#@lgW(u-k0n_;`ehN=M) zBzrDBk_U$vwHL5Bc8qIzy7AK@lVJx8H!o?c|E-NYgHvjszOtFDV(5-@U}q%>(fH-3EXjj3+MQiZ|Qil{*J?YxNF!u;G=6x-w80%UOO@Au236c zQhY?aNB7S@bY43bj8I8Dp33M-mvV}X)T?&=vUP$J>-yJmO3q|q2Rywsrll2P@bPATMZY#GhS(#$`Caih`8M~s>Af9I>(p|G*6_g* MWPe("/server/version-check", { + ...opts + })); +} export function getVersionHistory(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3284,6 +3296,14 @@ export function getReverseGeocodingState(opts?: Oazapfts.RequestOpts) { ...opts })); } +export function getVersionCheckState(opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: VersionCheckStateResponseDto; + }>("/system-metadata/version-check-state", { + ...opts + })); +} export function getAllTags(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; diff --git a/server/src/controllers/server.controller.spec.ts b/server/src/controllers/server.controller.spec.ts index cc373162e..6b00490d2 100644 --- a/server/src/controllers/server.controller.spec.ts +++ b/server/src/controllers/server.controller.spec.ts @@ -1,5 +1,6 @@ import { ServerController } from 'src/controllers/server.controller'; import { ServerService } from 'src/services/server.service'; +import { SystemMetadataService } from 'src/services/system-metadata.service'; import { VersionService } from 'src/services/version.service'; import request from 'supertest'; import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils'; @@ -7,11 +8,13 @@ import { ControllerContext, controllerSetup, mockBaseService } from 'test/utils' describe(ServerController.name, () => { let ctx: ControllerContext; const serverService = mockBaseService(ServerService); + const systemMetadataService = mockBaseService(SystemMetadataService); const versionService = mockBaseService(VersionService); beforeAll(async () => { ctx = await controllerSetup(ServerController, [ { provide: ServerService, useValue: serverService }, + { provide: SystemMetadataService, useValue: systemMetadataService }, { provide: VersionService, useValue: versionService }, ]); return () => ctx.close(); diff --git a/server/src/controllers/server.controller.ts b/server/src/controllers/server.controller.ts index 8327ff6d1..267fc42ef 100644 --- a/server/src/controllers/server.controller.ts +++ b/server/src/controllers/server.controller.ts @@ -13,8 +13,10 @@ import { ServerVersionHistoryResponseDto, ServerVersionResponseDto, } from 'src/dtos/server.dto'; +import { VersionCheckStateResponseDto } from 'src/dtos/system-metadata.dto'; import { Authenticated } from 'src/middleware/auth.guard'; import { ServerService } from 'src/services/server.service'; +import { SystemMetadataService } from 'src/services/system-metadata.service'; import { VersionService } from 'src/services/version.service'; @ApiTags('Server') @@ -22,6 +24,7 @@ import { VersionService } from 'src/services/version.service'; export class ServerController { constructor( private service: ServerService, + private systemMetadataService: SystemMetadataService, private versionService: VersionService, ) {} @@ -96,4 +99,10 @@ export class ServerController { getServerLicense(): Promise { return this.service.getLicense(); } + + @Get('version-check') + @Authenticated() + getVersionCheck(): Promise { + return this.systemMetadataService.getVersionCheckState(); + } } diff --git a/server/src/controllers/system-metadata.controller.ts b/server/src/controllers/system-metadata.controller.ts index bca5c65d8..71c37d02c 100644 --- a/server/src/controllers/system-metadata.controller.ts +++ b/server/src/controllers/system-metadata.controller.ts @@ -1,6 +1,10 @@ import { Body, Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AdminOnboardingUpdateDto, ReverseGeocodingStateResponseDto } from 'src/dtos/system-metadata.dto'; +import { + AdminOnboardingUpdateDto, + ReverseGeocodingStateResponseDto, + VersionCheckStateResponseDto, +} from 'src/dtos/system-metadata.dto'; import { Permission } from 'src/enum'; import { Authenticated } from 'src/middleware/auth.guard'; import { SystemMetadataService } from 'src/services/system-metadata.service'; @@ -28,4 +32,10 @@ export class SystemMetadataController { getReverseGeocodingState(): Promise { return this.service.getReverseGeocodingState(); } + + @Get('version-check-state') + @Authenticated({ permission: Permission.SYSTEM_METADATA_READ, admin: true }) + getVersionCheckState(): Promise { + return this.service.getVersionCheckState(); + } } diff --git a/server/src/dtos/system-metadata.dto.ts b/server/src/dtos/system-metadata.dto.ts index 1c0443534..c8e64f230 100644 --- a/server/src/dtos/system-metadata.dto.ts +++ b/server/src/dtos/system-metadata.dto.ts @@ -13,3 +13,8 @@ export class ReverseGeocodingStateResponseDto { lastUpdate!: string | null; lastImportFileName!: string | null; } + +export class VersionCheckStateResponseDto { + checkedAt!: string | null; + releaseVersion!: string | null; +} diff --git a/server/src/services/system-metadata.service.ts b/server/src/services/system-metadata.service.ts index 93449c7a7..750e6b1d0 100644 --- a/server/src/services/system-metadata.service.ts +++ b/server/src/services/system-metadata.service.ts @@ -3,6 +3,7 @@ import { AdminOnboardingResponseDto, AdminOnboardingUpdateDto, ReverseGeocodingStateResponseDto, + VersionCheckStateResponseDto, } from 'src/dtos/system-metadata.dto'; import { SystemMetadataKey } from 'src/enum'; import { BaseService } from 'src/services/base.service'; @@ -24,4 +25,9 @@ export class SystemMetadataService extends BaseService { const value = await this.systemMetadataRepository.get(SystemMetadataKey.REVERSE_GEOCODING_STATE); return { lastUpdate: null, lastImportFileName: null, ...value }; } + + async getVersionCheckState(): Promise { + const value = await this.systemMetadataRepository.get(SystemMetadataKey.VERSION_CHECK_STATE); + return { checkedAt: null, releaseVersion: null, ...value }; + } }