2024-10-04 20:04:37 +02:00
|
|
|
import { BadRequestException } from '@nestjs/common';
|
|
|
|
|
import { FileReportItemDto } from 'src/dtos/audit.dto';
|
2025-02-17 14:07:50 -05:00
|
|
|
import { AssetFileType, AssetPathType, JobStatus, PersonPathType, UserPathType } from 'src/enum';
|
2024-03-21 00:07:30 +01:00
|
|
|
import { AuditService } from 'src/services/audit.service';
|
2025-02-10 18:47:42 -05:00
|
|
|
import { newTestService, ServiceMocks } from 'test/utils';
|
2023-08-24 21:28:50 +02:00
|
|
|
|
|
|
|
|
describe(AuditService.name, () => {
|
|
|
|
|
let sut: AuditService;
|
2025-02-10 18:47:42 -05:00
|
|
|
let mocks: ServiceMocks;
|
2023-08-24 21:28:50 +02:00
|
|
|
|
2024-03-05 23:23:06 +01:00
|
|
|
beforeEach(() => {
|
2025-02-10 18:47:42 -05:00
|
|
|
({ sut, mocks } = newTestService(AuditService));
|
2023-08-24 21:28:50 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should work', () => {
|
|
|
|
|
expect(sut).toBeDefined();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('handleCleanup', () => {
|
|
|
|
|
it('should delete old audit entries', async () => {
|
2025-03-10 16:52:44 -04:00
|
|
|
mocks.audit.removeBefore.mockResolvedValue();
|
|
|
|
|
|
2024-03-15 14:16:54 +01:00
|
|
|
await expect(sut.handleCleanup()).resolves.toBe(JobStatus.SUCCESS);
|
2025-03-10 16:52:44 -04:00
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.audit.removeBefore).toHaveBeenCalledWith(expect.any(Date));
|
2023-08-24 21:28:50 +02:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2024-10-04 20:04:37 +02:00
|
|
|
describe('getChecksums', () => {
|
|
|
|
|
it('should fail if the file is not in the immich path', async () => {
|
|
|
|
|
await expect(sut.getChecksums({ filenames: ['foo/bar'] })).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.crypto.hashFile).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should get checksum for valid file', async () => {
|
|
|
|
|
await expect(sut.getChecksums({ filenames: ['./upload/my-file.jpg'] })).resolves.toEqual([
|
|
|
|
|
{ filename: './upload/my-file.jpg', checksum: expect.any(String) },
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.crypto.hashFile).toHaveBeenCalledWith('./upload/my-file.jpg');
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('fixItems', () => {
|
|
|
|
|
it('should fail if the file is not in the immich path', async () => {
|
|
|
|
|
await expect(
|
|
|
|
|
sut.fixItems([
|
|
|
|
|
{ entityId: 'my-id', pathType: AssetPathType.ORIGINAL, pathValue: 'foo/bar' } as FileReportItemDto,
|
|
|
|
|
]),
|
|
|
|
|
).rejects.toBeInstanceOf(BadRequestException);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.asset.upsertFile).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.person.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.user.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update encoded video path', async () => {
|
|
|
|
|
await sut.fixItems([
|
|
|
|
|
{
|
|
|
|
|
entityId: 'my-id',
|
|
|
|
|
pathType: AssetPathType.ENCODED_VIDEO,
|
|
|
|
|
pathValue: './upload/my-video.mp4',
|
|
|
|
|
} as FileReportItemDto,
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.update).toHaveBeenCalledWith({ id: 'my-id', encodedVideoPath: './upload/my-video.mp4' });
|
|
|
|
|
expect(mocks.asset.upsertFile).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.person.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.user.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update preview path', async () => {
|
|
|
|
|
await sut.fixItems([
|
|
|
|
|
{
|
|
|
|
|
entityId: 'my-id',
|
|
|
|
|
pathType: AssetPathType.PREVIEW,
|
|
|
|
|
pathValue: './upload/my-preview.png',
|
|
|
|
|
} as FileReportItemDto,
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.upsertFile).toHaveBeenCalledWith({
|
2024-10-04 20:04:37 +02:00
|
|
|
assetId: 'my-id',
|
|
|
|
|
type: AssetFileType.PREVIEW,
|
|
|
|
|
path: './upload/my-preview.png',
|
|
|
|
|
});
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.person.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.user.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update thumbnail path', async () => {
|
|
|
|
|
await sut.fixItems([
|
|
|
|
|
{
|
|
|
|
|
entityId: 'my-id',
|
|
|
|
|
pathType: AssetPathType.THUMBNAIL,
|
|
|
|
|
pathValue: './upload/my-thumbnail.webp',
|
|
|
|
|
} as FileReportItemDto,
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.upsertFile).toHaveBeenCalledWith({
|
2024-10-04 20:04:37 +02:00
|
|
|
assetId: 'my-id',
|
|
|
|
|
type: AssetFileType.THUMBNAIL,
|
|
|
|
|
path: './upload/my-thumbnail.webp',
|
|
|
|
|
});
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.person.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.user.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update original path', async () => {
|
|
|
|
|
await sut.fixItems([
|
|
|
|
|
{
|
|
|
|
|
entityId: 'my-id',
|
|
|
|
|
pathType: AssetPathType.ORIGINAL,
|
|
|
|
|
pathValue: './upload/my-original.png',
|
|
|
|
|
} as FileReportItemDto,
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.update).toHaveBeenCalledWith({ id: 'my-id', originalPath: './upload/my-original.png' });
|
|
|
|
|
expect(mocks.asset.upsertFile).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.person.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.user.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update sidecar path', async () => {
|
|
|
|
|
await sut.fixItems([
|
|
|
|
|
{
|
|
|
|
|
entityId: 'my-id',
|
|
|
|
|
pathType: AssetPathType.SIDECAR,
|
|
|
|
|
pathValue: './upload/my-sidecar.xmp',
|
|
|
|
|
} as FileReportItemDto,
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.asset.update).toHaveBeenCalledWith({ id: 'my-id', sidecarPath: './upload/my-sidecar.xmp' });
|
|
|
|
|
expect(mocks.asset.upsertFile).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.person.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.user.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update face path', async () => {
|
|
|
|
|
await sut.fixItems([
|
|
|
|
|
{
|
|
|
|
|
entityId: 'my-id',
|
|
|
|
|
pathType: PersonPathType.FACE,
|
|
|
|
|
pathValue: './upload/my-face.jpg',
|
|
|
|
|
} as FileReportItemDto,
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.person.update).toHaveBeenCalledWith({ id: 'my-id', thumbnailPath: './upload/my-face.jpg' });
|
|
|
|
|
expect(mocks.asset.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.asset.upsertFile).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.user.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should update profile path', async () => {
|
|
|
|
|
await sut.fixItems([
|
|
|
|
|
{
|
|
|
|
|
entityId: 'my-id',
|
|
|
|
|
pathType: UserPathType.PROFILE,
|
|
|
|
|
pathValue: './upload/my-profile-pic.jpg',
|
|
|
|
|
} as FileReportItemDto,
|
|
|
|
|
]);
|
|
|
|
|
|
2025-02-10 18:47:42 -05:00
|
|
|
expect(mocks.user.update).toHaveBeenCalledWith('my-id', { profileImagePath: './upload/my-profile-pic.jpg' });
|
|
|
|
|
expect(mocks.asset.update).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.asset.upsertFile).not.toHaveBeenCalled();
|
|
|
|
|
expect(mocks.person.update).not.toHaveBeenCalled();
|
2024-10-04 20:04:37 +02:00
|
|
|
});
|
|
|
|
|
});
|
2023-08-24 21:28:50 +02:00
|
|
|
});
|