diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 64b85939b..ab9814d0f 100644 Binary files a/mobile/openapi/README.md and b/mobile/openapi/README.md differ diff --git a/mobile/openapi/lib/api.dart b/mobile/openapi/lib/api.dart index aa8ae348a..d3a342db6 100644 Binary files a/mobile/openapi/lib/api.dart and b/mobile/openapi/lib/api.dart differ diff --git a/mobile/openapi/lib/api/server_api.dart b/mobile/openapi/lib/api/server_api.dart index 629949db3..a0fd54f3d 100644 Binary files a/mobile/openapi/lib/api/server_api.dart and b/mobile/openapi/lib/api/server_api.dart differ diff --git a/mobile/openapi/lib/api/system_metadata_api.dart b/mobile/openapi/lib/api/system_metadata_api.dart index 3bd8bddca..3fcceb8e4 100644 Binary files a/mobile/openapi/lib/api/system_metadata_api.dart and b/mobile/openapi/lib/api/system_metadata_api.dart differ diff --git a/mobile/openapi/lib/api_client.dart b/mobile/openapi/lib/api_client.dart index a1240c800..cc01fd2c0 100644 Binary files a/mobile/openapi/lib/api_client.dart and b/mobile/openapi/lib/api_client.dart differ 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 000000000..d3f9a6cd9 Binary files /dev/null and b/mobile/openapi/lib/model/version_check_state_response_dto.dart differ diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index f42f4204b..536d366c5 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -5563,6 +5563,38 @@ ] } }, + "/server/version-check": { + "get": { + "operationId": "getVersionCheck", + "parameters": [], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionCheckStateResponseDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Server" + ] + } + }, "/server/version-history": { "get": { "operationId": "getVersionHistory", @@ -6846,6 +6878,38 @@ ] } }, + "/system-metadata/version-check-state": { + "get": { + "operationId": "getVersionCheckState", + "parameters": [], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VersionCheckStateResponseDto" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "System Metadata" + ] + } + }, "/tags": { "get": { "operationId": "getAllTags", @@ -14939,6 +15003,23 @@ }, "type": "object" }, + "VersionCheckStateResponseDto": { + "properties": { + "checkedAt": { + "nullable": true, + "type": "string" + }, + "releaseVersion": { + "nullable": true, + "type": "string" + } + }, + "required": [ + "checkedAt", + "releaseVersion" + ], + "type": "object" + }, "VideoCodec": { "enum": [ "h264", diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 866e9cb6b..b119bc01f 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -1076,6 +1076,10 @@ export type ServerVersionResponseDto = { minor: number; patch: number; }; +export type VersionCheckStateResponseDto = { + checkedAt: string | null; + releaseVersion: string | null; +}; export type ServerVersionHistoryResponseDto = { createdAt: string; id: string; @@ -2947,6 +2951,14 @@ export function getServerVersion(opts?: Oazapfts.RequestOpts) { ...opts })); } +export function getVersionCheck(opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: VersionCheckStateResponseDto; + }>("/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 }; + } }