diff --git a/e2e/src/api/specs/server.e2e-spec.ts b/e2e/src/api/specs/server.e2e-spec.ts index 0ab53a0cb3..d19744674f 100644 --- a/e2e/src/api/specs/server.e2e-spec.ts +++ b/e2e/src/api/specs/server.e2e-spec.ts @@ -254,7 +254,7 @@ describe('/server', () => { .set('Authorization', `Bearer ${admin.accessToken}`) .send(serverLicense); const { status } = await request(app).get('/server/license').set('Authorization', `Bearer ${admin.accessToken}`); - expect(status).toBe(200); + expect(status).toBe(404); }); }); diff --git a/mobile/openapi/lib/api/server_api.dart b/mobile/openapi/lib/api/server_api.dart index 4987c6cd9c..9cb52514c2 100644 Binary files a/mobile/openapi/lib/api/server_api.dart and b/mobile/openapi/lib/api/server_api.dart differ diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index a6cd8913d2..de19f99bcf 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -5022,11 +5022,14 @@ "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/LicenseResponseDto" } } }, "description": "" + }, + "404": { + "description": "" } }, "security": [ diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 84d959a8da..9b6c3f2574 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -880,12 +880,12 @@ export type ServerVersionResponseDto = { minor: number; patch: number; }; -export type LicenseKeyDto = { +export type LicenseResponseDto = { + activatedAt: string; activationKey: string; licenseKey: string; }; -export type LicenseResponseDto = { - activatedAt: string; +export type LicenseKeyDto = { activationKey: string; licenseKey: string; }; @@ -2511,7 +2511,9 @@ export function deleteServerLicense(opts?: Oazapfts.RequestOpts) { export function getServerLicense(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; - data: object; + data: LicenseResponseDto; + } | { + status: 404; }>("/server/license", { ...opts })); diff --git a/server/src/controllers/server.controller.ts b/server/src/controllers/server.controller.ts index 009c36c793..0c615223e2 100644 --- a/server/src/controllers/server.controller.ts +++ b/server/src/controllers/server.controller.ts @@ -1,5 +1,5 @@ import { Body, Controller, Delete, Get, Put } from '@nestjs/common'; -import { ApiExcludeEndpoint, ApiTags } from '@nestjs/swagger'; +import { ApiExcludeEndpoint, ApiNotFoundResponse, ApiTags } from '@nestjs/swagger'; import { LicenseKeyDto, LicenseResponseDto } from 'src/dtos/license.dto'; import { ServerAboutResponseDto, @@ -95,7 +95,8 @@ export class ServerController { @Get('license') @Authenticated({ admin: true }) - getServerLicense(): Promise { + @ApiNotFoundResponse() + getServerLicense(): Promise { return this.service.getLicense(); } } diff --git a/server/src/services/server.service.ts b/server/src/services/server.service.ts index 1aaf85b1ba..22196c4e26 100644 --- a/server/src/services/server.service.ts +++ b/server/src/services/server.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Inject, Injectable } from '@nestjs/common'; +import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common'; import { getBuildMetadata, getServerLicensePublicKey } from 'src/config'; import { serverVersion } from 'src/constants'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; @@ -164,8 +164,12 @@ export class ServerService implements OnEvents { await this.systemMetadataRepository.delete(SystemMetadataKey.LICENSE); } - async getLicense(): Promise { - return this.systemMetadataRepository.get(SystemMetadataKey.LICENSE); + async getLicense(): Promise { + const license = await this.systemMetadataRepository.get(SystemMetadataKey.LICENSE); + if (!license) { + throw new NotFoundException(); + } + return license; } async setLicense(dto: LicenseKeyDto): Promise { diff --git a/web/src/lib/components/user-settings-page/license-settings.svelte b/web/src/lib/components/user-settings-page/license-settings.svelte index 6952d8139e..a88a89486f 100644 --- a/web/src/lib/components/user-settings-page/license-settings.svelte +++ b/web/src/lib/components/user-settings-page/license-settings.svelte @@ -10,6 +10,7 @@ getAboutInfo, getMyUser, getServerLicense, + isHttpError, type LicenseResponseDto, } from '@immich/sdk'; import Icon from '$lib/components/elements/icon.svelte'; @@ -36,7 +37,18 @@ } if (isServerLicense && $user.isAdmin) { - serverLicenseInfo = (await getServerLicense()) as LicenseResponseDto | null; + serverLicenseInfo = await getServerLicenseInfo(); + } + }; + + const getServerLicenseInfo = async () => { + try { + return await getServerLicense(); + } catch (error) { + if (isHttpError(error) && error.status === 404) { + return null; + } + throw error; } };