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:
sakshamchawla
2026-05-07 15:54:26 -04:00
committed by GitHub
parent 6050526360
commit e2ec04e86c
4 changed files with 49 additions and 13 deletions
+24 -4
View File
@@ -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
+14 -2
View File
@@ -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')
+7 -6
View File
@@ -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([]);
}); });
}); });
+4 -1
View File
@@ -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) {