diff --git a/mobile/openapi/lib/model/asset_bulk_update_dto.dart b/mobile/openapi/lib/model/asset_bulk_update_dto.dart index ee55e6fc06..42edc40f51 100644 --- a/mobile/openapi/lib/model/asset_bulk_update_dto.dart +++ b/mobile/openapi/lib/model/asset_bulk_update_dto.dart @@ -94,7 +94,7 @@ class AssetBulkUpdateDto { /// Rating in range [1-5], or null for unrated /// - /// Minimum value: 1 + /// Minimum value: 0 /// Maximum value: 5 int? rating; diff --git a/mobile/openapi/lib/model/update_asset_dto.dart b/mobile/openapi/lib/model/update_asset_dto.dart index 927bb2c9f3..19cc90a12f 100644 --- a/mobile/openapi/lib/model/update_asset_dto.dart +++ b/mobile/openapi/lib/model/update_asset_dto.dart @@ -79,7 +79,7 @@ class UpdateAssetDto { /// Rating in range [1-5], or null for unrated /// - /// Minimum value: 1 + /// Minimum value: 0 /// Maximum value: 5 int? rating; diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 6c167297f2..812ff01535 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -15692,7 +15692,7 @@ "rating": { "description": "Rating in range [1-5], or null for unrated", "maximum": 5, - "minimum": 1, + "minimum": 0, "nullable": true, "type": "integer", "x-immich-history": [ @@ -25227,7 +25227,7 @@ "rating": { "description": "Rating in range [1-5], or null for unrated", "maximum": 5, - "minimum": 1, + "minimum": 0, "nullable": true, "type": "integer", "x-immich-history": [ diff --git a/server/src/controllers/asset.controller.spec.ts b/server/src/controllers/asset.controller.spec.ts index 3e3b792cfa..941ba1b19b 100644 --- a/server/src/controllers/asset.controller.spec.ts +++ b/server/src/controllers/asset.controller.spec.ts @@ -214,13 +214,20 @@ describe(AssetController.name, () => { }); it('should reject invalid rating', async () => { - for (const test of [{ rating: 0 }, { rating: 7 }, { rating: 3.5 }, { rating: -2 }]) { + for (const test of [{ rating: 7 }, { rating: 3.5 }, { rating: -2 }]) { const { status, body } = await request(ctx.getHttpServer()).put(`/assets/${factory.uuid()}`).send(test); expect(status).toBe(400); expect(body).toEqual(factory.responses.badRequest()); } }); + it('should convert rating 0 to null', async () => { + const assetId = factory.uuid(); + const { status } = await request(ctx.getHttpServer()).put(`/assets/${assetId}`).send({ rating: 0 }); + expect(service.update).toHaveBeenCalledWith(undefined, assetId, { rating: null }); + expect(status).toBe(200); + }); + it('should leave correct ratings as-is', async () => { const assetId = factory.uuid(); for (const test of [{ rating: 1 }, { rating: 5 }]) { diff --git a/server/src/dtos/asset.dto.ts b/server/src/dtos/asset.dto.ts index 7453ec3ad9..8dd29a4391 100644 --- a/server/src/dtos/asset.dto.ts +++ b/server/src/dtos/asset.dto.ts @@ -15,8 +15,9 @@ const UpdateAssetBaseSchema = z longitude: longitudeSchema.optional().describe('Longitude coordinate'), rating: z .int() - .min(1) + .min(0) .max(5) + .transform((value) => (value === 0 ? null : value)) .nullish() .describe('Rating in range [1-5], or null for unrated') .meta({