mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat: hide hidden person from memories (#20877)
* hide hidden person from memories * clean up * fix united test * clean up * moved sql to inline, rebased * clean up * clean up again * chore: sync sql --------- Co-authored-by: Jason Rasmussen <jason@rasm.me>
This commit is contained in:
@@ -42,6 +42,16 @@ select
|
|||||||
"memory_asset"."memoriesId" = "memory"."id"
|
"memory_asset"."memoriesId" = "memory"."id"
|
||||||
and "asset"."visibility" = 'timeline'
|
and "asset"."visibility" = 'timeline'
|
||||||
and "asset"."deletedAt" is null
|
and "asset"."deletedAt" is null
|
||||||
|
and not exists (
|
||||||
|
select
|
||||||
|
$1 as "one"
|
||||||
|
from
|
||||||
|
"asset_face"
|
||||||
|
inner join "person" on "person"."id" = "asset_face"."personId"
|
||||||
|
where
|
||||||
|
"asset_face"."assetId" = "asset"."id"
|
||||||
|
and "person"."isHidden" = $2
|
||||||
|
)
|
||||||
order by
|
order by
|
||||||
"asset"."fileCreatedAt" asc
|
"asset"."fileCreatedAt" asc
|
||||||
) as agg
|
) as agg
|
||||||
@@ -51,7 +61,7 @@ from
|
|||||||
"memory"
|
"memory"
|
||||||
where
|
where
|
||||||
"deletedAt" is null
|
"deletedAt" is null
|
||||||
and "ownerId" = $1
|
and "ownerId" = $3
|
||||||
order by
|
order by
|
||||||
"memoryAt" desc
|
"memoryAt" desc
|
||||||
|
|
||||||
@@ -71,6 +81,16 @@ select
|
|||||||
"memory_asset"."memoriesId" = "memory"."id"
|
"memory_asset"."memoriesId" = "memory"."id"
|
||||||
and "asset"."visibility" = 'timeline'
|
and "asset"."visibility" = 'timeline'
|
||||||
and "asset"."deletedAt" is null
|
and "asset"."deletedAt" is null
|
||||||
|
and not exists (
|
||||||
|
select
|
||||||
|
$1 as "one"
|
||||||
|
from
|
||||||
|
"asset_face"
|
||||||
|
inner join "person" on "person"."id" = "asset_face"."personId"
|
||||||
|
where
|
||||||
|
"asset_face"."assetId" = "asset"."id"
|
||||||
|
and "person"."isHidden" = $2
|
||||||
|
)
|
||||||
order by
|
order by
|
||||||
"asset"."fileCreatedAt" asc
|
"asset"."fileCreatedAt" asc
|
||||||
) as agg
|
) as agg
|
||||||
@@ -81,14 +101,14 @@ from
|
|||||||
where
|
where
|
||||||
(
|
(
|
||||||
"showAt" is null
|
"showAt" is null
|
||||||
or "showAt" <= $1
|
or "showAt" <= $3
|
||||||
)
|
)
|
||||||
and (
|
and (
|
||||||
"hideAt" is null
|
"hideAt" is null
|
||||||
or "hideAt" >= $2
|
or "hideAt" >= $4
|
||||||
)
|
)
|
||||||
and "deletedAt" is null
|
and "deletedAt" is null
|
||||||
and "ownerId" = $3
|
and "ownerId" = $5
|
||||||
order by
|
order by
|
||||||
"memoryAt" desc
|
"memoryAt" desc
|
||||||
|
|
||||||
|
|||||||
@@ -66,9 +66,21 @@ export class MemoryRepository implements IBulkAsset {
|
|||||||
.selectAll('asset')
|
.selectAll('asset')
|
||||||
.innerJoin('memory_asset', 'asset.id', 'memory_asset.assetId')
|
.innerJoin('memory_asset', 'asset.id', 'memory_asset.assetId')
|
||||||
.whereRef('memory_asset.memoriesId', '=', 'memory.id')
|
.whereRef('memory_asset.memoriesId', '=', 'memory.id')
|
||||||
.orderBy('asset.fileCreatedAt', 'asc')
|
|
||||||
.where('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
.where('asset.visibility', '=', sql.lit(AssetVisibility.Timeline))
|
||||||
.where('asset.deletedAt', 'is', null),
|
.where('asset.deletedAt', 'is', null)
|
||||||
|
.where((eb) =>
|
||||||
|
eb.not(
|
||||||
|
eb.exists(
|
||||||
|
eb
|
||||||
|
.selectFrom('asset_face')
|
||||||
|
.innerJoin('person', 'person.id', 'asset_face.personId')
|
||||||
|
.select((eb) => eb.val(1).as('one'))
|
||||||
|
.whereRef('asset_face.assetId', '=', 'asset.id')
|
||||||
|
.where('person.isHidden', '=', true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.orderBy('asset.fileCreatedAt', 'asc'),
|
||||||
).as('assets'),
|
).as('assets'),
|
||||||
)
|
)
|
||||||
.selectAll('memory')
|
.selectAll('memory')
|
||||||
|
|||||||
@@ -28,25 +28,26 @@ describe(MemoryService.name, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('search', () => {
|
describe('search', () => {
|
||||||
it('should search memories', async () => {
|
it('should search memories with assets', async () => {
|
||||||
const [userId] = newUuids();
|
const [userId] = newUuids();
|
||||||
|
|
||||||
const asset = AssetFactory.create();
|
const asset = AssetFactory.create();
|
||||||
const memory1 = MemoryFactory.from({ ownerId: userId }).asset(asset).build();
|
const memory1 = MemoryFactory.from({ ownerId: userId }).asset(asset).build();
|
||||||
const memory2 = MemoryFactory.create({ ownerId: userId });
|
const memory2 = MemoryFactory.create({ ownerId: userId });
|
||||||
|
|
||||||
mocks.memory.search.mockResolvedValue([getForMemory(memory1), getForMemory(memory2)]);
|
mocks.memory.search.mockResolvedValue([getForMemory(memory1), getForMemory(memory2)]);
|
||||||
|
|
||||||
await expect(sut.search(factory.auth({ user: { id: userId } }), {})).resolves.toEqual(
|
await expect(sut.search(factory.auth({ user: { id: userId } }), {})).resolves.toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({ id: memory1.id, assets: [expect.objectContaining({ id: asset.id })] }),
|
expect.objectContaining({
|
||||||
expect.objectContaining({ id: memory2.id, assets: [] }),
|
id: memory1.id,
|
||||||
|
assets: expect.arrayContaining([expect.objectContaining({ id: asset.id })]),
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should map ', async () => {
|
it('should map empty result', async () => {
|
||||||
mocks.memory.search.mockResolvedValue([]);
|
mocks.memory.search.mockResolvedValue([]);
|
||||||
|
|
||||||
await expect(sut.search(factory.auth(), {})).resolves.toEqual([]);
|
await expect(sut.search(factory.auth(), {})).resolves.toEqual([]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
import { Memory } from 'src/database';
|
||||||
import { OnJob } from 'src/decorators';
|
import { OnJob } from 'src/decorators';
|
||||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
@@ -71,7 +72,9 @@ export class MemoryService extends BaseService {
|
|||||||
|
|
||||||
async search(auth: AuthDto, dto: MemorySearchDto) {
|
async search(auth: AuthDto, dto: MemorySearchDto) {
|
||||||
const memories = await this.memoryRepository.search(auth.user.id, dto);
|
const memories = await this.memoryRepository.search(auth.user.id, dto);
|
||||||
return memories.map((memory) => mapMemory(memory, auth));
|
return memories
|
||||||
|
.filter((memory: Memory) => memory.assets && memory.assets.length > 0)
|
||||||
|
.map((memory: Memory) => mapMemory(memory, auth));
|
||||||
}
|
}
|
||||||
|
|
||||||
statistics(auth: AuthDto, dto: MemorySearchDto) {
|
statistics(auth: AuthDto, dto: MemorySearchDto) {
|
||||||
|
|||||||
Reference in New Issue
Block a user