refactor(server): delete album (#2570)

This commit is contained in:
Jason Rasmussen
2023-05-26 09:04:09 -04:00
committed by GitHub
parent 065fb166c2
commit b7516f31c6
13 changed files with 116 additions and 88 deletions

View File

@@ -20,4 +20,5 @@ export interface IAlbumRepository {
getAll(): Promise<AlbumEntity[]>;
create(album: Partial<AlbumEntity>): Promise<AlbumEntity>;
update(album: Partial<AlbumEntity>): Promise<AlbumEntity>;
delete(album: AlbumEntity): Promise<void>;
}

View File

@@ -176,7 +176,22 @@ describe(AlbumService.name, () => {
).rejects.toBeInstanceOf(ForbiddenException);
});
it('should all the owner to update the album', async () => {
it('should require a valid thumbnail asset id', async () => {
albumMock.getByIds.mockResolvedValue([albumStub.oneAsset]);
albumMock.update.mockResolvedValue(albumStub.oneAsset);
albumMock.hasAsset.mockResolvedValue(false);
await expect(
sut.update(authStub.admin, albumStub.oneAsset.id, {
albumThumbnailAssetId: 'not-in-album',
}),
).rejects.toBeInstanceOf(BadRequestException);
expect(albumMock.hasAsset).toHaveBeenCalledWith(albumStub.oneAsset.id, 'not-in-album');
expect(albumMock.update).not.toHaveBeenCalled();
});
it('should allow the owner to update the album', async () => {
albumMock.getByIds.mockResolvedValue([albumStub.oneAsset]);
albumMock.update.mockResolvedValue(albumStub.oneAsset);
@@ -195,4 +210,33 @@ describe(AlbumService.name, () => {
});
});
});
describe('delete', () => {
it('should throw an error for an album not found', async () => {
albumMock.getByIds.mockResolvedValue([]);
await expect(sut.delete(authStub.admin, albumStub.sharedWithAdmin.id)).rejects.toBeInstanceOf(
BadRequestException,
);
expect(albumMock.delete).not.toHaveBeenCalled();
});
it('should not let a shared user delete the album', async () => {
albumMock.getByIds.mockResolvedValue([albumStub.sharedWithAdmin]);
await expect(sut.delete(authStub.admin, albumStub.sharedWithAdmin.id)).rejects.toBeInstanceOf(ForbiddenException);
expect(albumMock.delete).not.toHaveBeenCalled();
});
it('should let the owner delete an album', async () => {
albumMock.getByIds.mockResolvedValue([albumStub.empty]);
await sut.delete(authStub.admin, albumStub.empty.id);
expect(albumMock.delete).toHaveBeenCalledTimes(1);
expect(albumMock.delete).toHaveBeenCalledWith(albumStub.empty);
});
});
});

View File

@@ -98,4 +98,18 @@ export class AlbumService {
return mapAlbum(updatedAlbum);
}
async delete(authUser: AuthUserDto, id: string): Promise<void> {
const [album] = await this.albumRepository.getByIds([id]);
if (!album) {
throw new BadRequestException('Album not found');
}
if (album.ownerId !== authUser.id) {
throw new ForbiddenException('Album not owned by user');
}
await this.albumRepository.delete(album);
await this.jobRepository.queue({ name: JobName.SEARCH_REMOVE_ALBUM, data: { ids: [id] } });
}
}

View File

@@ -14,5 +14,6 @@ export const newAlbumRepositoryMock = (): jest.Mocked<IAlbumRepository> => {
hasAsset: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
};
};

View File

@@ -53,7 +53,7 @@ export class SharedLinkEntity {
assets!: AssetEntity[];
@Index('IDX_sharedlink_albumId')
@ManyToOne(() => AlbumEntity, (album) => album.sharedLinks)
@ManyToOne(() => AlbumEntity, (album) => album.sharedLinks, { onDelete: 'CASCADE', onUpdate: 'CASCADE' })
album?: AlbumEntity;
}

View File

@@ -0,0 +1,16 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class AddSharedLinkCascade1685044328272 implements MigrationInterface {
name = 'AddSharedLinkCascade1685044328272'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "shared_links" DROP CONSTRAINT "FK_0c6ce9058c29f07cdf7014eac66"`);
await queryRunner.query(`ALTER TABLE "shared_links" ADD CONSTRAINT "FK_0c6ce9058c29f07cdf7014eac66" FOREIGN KEY ("albumId") REFERENCES "albums"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "shared_links" DROP CONSTRAINT "FK_0c6ce9058c29f07cdf7014eac66"`);
await queryRunner.query(`ALTER TABLE "shared_links" ADD CONSTRAINT "FK_0c6ce9058c29f07cdf7014eac66" FOREIGN KEY ("albumId") REFERENCES "albums"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
}
}

View File

@@ -143,10 +143,14 @@ export class AlbumRepository implements IAlbumRepository {
return this.save(album);
}
async update(album: Partial<AlbumEntity>) {
async update(album: Partial<AlbumEntity>): Promise<AlbumEntity> {
return this.save(album);
}
async delete(album: AlbumEntity): Promise<void> {
await this.repository.remove(album);
}
private async save(album: Partial<AlbumEntity>) {
const { id } = await this.repository.save(album);
return this.repository.findOneOrFail({ where: { id }, relations: { owner: true } });