mirror of
https://github.com/immich-app/immich
synced 2025-10-17 18:19:27 +00:00
fix: prevent an offline asset from being used as a person feature photo (#21278)
This commit is contained in:
parent
d04675fb41
commit
8f1b505ba0
3 changed files with 11 additions and 9 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { ExpressionBuilder, Insertable, Kysely, Selectable, sql, Updateable } from 'kysely';
|
import { ExpressionBuilder, Insertable, Kysely, NotNull, Selectable, sql, Updateable } from 'kysely';
|
||||||
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
import { jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
||||||
|
|
@ -68,12 +68,6 @@ const withPerson = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
|
||||||
).as('person');
|
).as('person');
|
||||||
};
|
};
|
||||||
|
|
||||||
const withAsset = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
|
|
||||||
return jsonObjectFrom(eb.selectFrom('asset').selectAll('asset').whereRef('asset.id', '=', 'asset_face.assetId')).as(
|
|
||||||
'asset',
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const withFaceSearch = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
|
const withFaceSearch = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
|
||||||
return jsonObjectFrom(
|
return jsonObjectFrom(
|
||||||
eb.selectFrom('face_search').selectAll('face_search').whereRef('face_search.faceId', '=', 'asset_face.id'),
|
eb.selectFrom('face_search').selectAll('face_search').whereRef('face_search.faceId', '=', 'asset_face.id'),
|
||||||
|
|
@ -481,7 +475,12 @@ export class PersonRepository {
|
||||||
return this.db
|
return this.db
|
||||||
.selectFrom('asset_face')
|
.selectFrom('asset_face')
|
||||||
.selectAll('asset_face')
|
.selectAll('asset_face')
|
||||||
.select(withAsset)
|
.select((eb) =>
|
||||||
|
jsonObjectFrom(eb.selectFrom('asset').selectAll('asset').whereRef('asset.id', '=', 'asset_face.assetId')).as(
|
||||||
|
'asset',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.$narrowType<{ asset: NotNull }>()
|
||||||
.select(withPerson)
|
.select(withPerson)
|
||||||
.where('asset_face.assetId', 'in', assetIds)
|
.where('asset_face.assetId', 'in', assetIds)
|
||||||
.where('asset_face.personId', 'in', personIds)
|
.where('asset_face.personId', 'in', personIds)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@ describe(MediaService.name, () => {
|
||||||
mocks.assetJob.streamForThumbnailJob.mockReturnValue(makeStream([assetStub.image]));
|
mocks.assetJob.streamForThumbnailJob.mockReturnValue(makeStream([assetStub.image]));
|
||||||
|
|
||||||
mocks.person.getAll.mockReturnValue(makeStream([personStub.newThumbnail]));
|
mocks.person.getAll.mockReturnValue(makeStream([personStub.newThumbnail]));
|
||||||
mocks.person.getFacesByIds.mockResolvedValue([faceStub.face1]);
|
|
||||||
|
|
||||||
await sut.handleQueueGenerateThumbnails({ force: true });
|
await sut.handleQueueGenerateThumbnails({ force: true });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,10 @@ export class PersonService extends BaseService {
|
||||||
throw new BadRequestException('Invalid assetId for feature face');
|
throw new BadRequestException('Invalid assetId for feature face');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (face.asset.isOffline) {
|
||||||
|
throw new BadRequestException('An offline asset cannot be used for feature face');
|
||||||
|
}
|
||||||
|
|
||||||
faceId = face.id;
|
faceId = face.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue