fix(server): clear activity when asset is removed from album (#19019)

This commit is contained in:
SGT 2025-07-10 14:37:56 -03:00 committed by GitHub
parent ed4c7817e7
commit 55fe67dd20
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 0 deletions

View File

@ -7,6 +7,7 @@ import {
ReactionType,
createActivity as create,
createAlbum,
removeAssetFromAlbum,
} from '@immich/sdk';
import { createUserDto, uuidDto } from 'src/fixtures';
import { errorDto } from 'src/responses';
@ -342,5 +343,36 @@ describe('/activities', () => {
expect(status).toBe(204);
});
it('should return empty list when asset is removed', async () => {
const album3 = await createAlbum(
{
createAlbumDto: {
albumName: 'Album 3',
assetIds: [asset.id],
},
},
{ headers: asBearerAuth(admin.accessToken) },
);
await createActivity({ albumId: album3.id, assetId: asset.id, type: ReactionType.Like });
await removeAssetFromAlbum(
{
id: album3.id,
bulkIdsDto: {
ids: [asset.id],
},
},
{ headers: asBearerAuth(admin.accessToken) },
);
const { status, body } = await request(app)
.get('/activities')
.query({ albumId: album.id })
.set('Authorization', `Bearer ${admin.accessToken}`);
expect(status).toEqual(200);
expect(body).toEqual([]);
});
});
});

View File

@ -0,0 +1,19 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<any>): Promise<void> {
await sql`DELETE FROM activity AS a
WHERE a."assetId" IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM albums_assets_assets AS aaa
WHERE a."albumId" = aaa."albumsId"
AND a."assetId" = aaa."assetsId"
);`.execute(db);
await sql`ALTER TABLE "activity" ADD CONSTRAINT "fk_activity_album_asset_composite" FOREIGN KEY ("albumId", "assetId") REFERENCES "albums_assets_assets" ("albumsId", "assetsId") ON UPDATE NO ACTION ON DELETE CASCADE;`.execute(db);
await sql`CREATE INDEX "IDX_86102d85cfa7f196073aebff68" ON "activity" ("albumId", "assetId")`.execute(db);
}
export async function down(db: Kysely<any>): Promise<void> {
await sql`DROP INDEX "IDX_86102d85cfa7f196073aebff68";`.execute(db);
await sql`ALTER TABLE "activity" DROP CONSTRAINT "fk_activity_album_asset_composite";`.execute(db);
}

View File

@ -1,4 +1,5 @@
import { UpdatedAtTrigger, UpdateIdColumn } from 'src/decorators';
import { AlbumAssetTable } from 'src/schema/tables/album-asset.table';
import { AlbumTable } from 'src/schema/tables/album.table';
import { AssetTable } from 'src/schema/tables/asset.table';
import { UserTable } from 'src/schema/tables/user.table';
@ -7,6 +8,7 @@ import {
Column,
CreateDateColumn,
ForeignKeyColumn,
ForeignKeyConstraint,
Generated,
Index,
PrimaryGeneratedColumn,
@ -27,6 +29,14 @@ import {
name: 'CHK_2ab1e70f113f450eb40c1e3ec8',
expression: `("comment" IS NULL AND "isLiked" = true) OR ("comment" IS NOT NULL AND "isLiked" = false)`,
})
@ForeignKeyConstraint({
name: 'fk_activity_album_asset_composite',
columns: ['albumId', 'assetId'],
referenceTable: () => AlbumAssetTable,
referenceColumns: ['albumsId', 'assetsId'],
onUpdate: 'NO ACTION',
onDelete: 'CASCADE',
})
export class ActivityTable {
@PrimaryGeneratedColumn()
id!: Generated<string>;