mirror of
https://github.com/immich-app/immich.git
synced 2025-02-04 01:09:14 -05:00
fix(server): exclude archived assets from orphaned files (#7334)
* fix(server): exclude archived assets from orphaned files * add e2e test
This commit is contained in:
parent
b3131dfe14
commit
07ef008b40
4 changed files with 68 additions and 2 deletions
|
@ -4,6 +4,7 @@ name: immich-e2e
|
||||||
|
|
||||||
x-server-build: &server-common
|
x-server-build: &server-common
|
||||||
image: immich-server:latest
|
image: immich-server:latest
|
||||||
|
container_name: immich-e2e-server
|
||||||
build:
|
build:
|
||||||
context: ../
|
context: ../
|
||||||
dockerfile: server/Dockerfile
|
dockerfile: server/Dockerfile
|
||||||
|
|
51
e2e/src/api/specs/audit.e2e-spec.ts
Normal file
51
e2e/src/api/specs/audit.e2e-spec.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import {
|
||||||
|
deleteAssets,
|
||||||
|
getAuditFiles,
|
||||||
|
updateAsset,
|
||||||
|
type LoginResponseDto,
|
||||||
|
} from '@immich/sdk';
|
||||||
|
import { apiUtils, asBearerAuth, dbUtils, fileUtils } from 'src/utils';
|
||||||
|
import { beforeAll, describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
describe('/audit', () => {
|
||||||
|
let admin: LoginResponseDto;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
apiUtils.setup();
|
||||||
|
await dbUtils.reset();
|
||||||
|
await fileUtils.reset();
|
||||||
|
|
||||||
|
admin = await apiUtils.adminSetup();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('GET :/file-report', () => {
|
||||||
|
it('excludes assets without issues from report', async () => {
|
||||||
|
const [trashedAsset, archivedAsset, _] = await Promise.all([
|
||||||
|
apiUtils.createAsset(admin.accessToken),
|
||||||
|
apiUtils.createAsset(admin.accessToken),
|
||||||
|
apiUtils.createAsset(admin.accessToken),
|
||||||
|
]);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
deleteAssets(
|
||||||
|
{ assetBulkDeleteDto: { ids: [trashedAsset.id] } },
|
||||||
|
{ headers: asBearerAuth(admin.accessToken) }
|
||||||
|
),
|
||||||
|
updateAsset(
|
||||||
|
{
|
||||||
|
id: archivedAsset.id,
|
||||||
|
updateAssetDto: { isArchived: true },
|
||||||
|
},
|
||||||
|
{ headers: asBearerAuth(admin.accessToken) }
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const body = await getAuditFiles({
|
||||||
|
headers: asBearerAuth(admin.accessToken),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(body.orphans).toHaveLength(0);
|
||||||
|
expect(body.extras).toHaveLength(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -17,14 +17,17 @@ import {
|
||||||
updatePerson,
|
updatePerson,
|
||||||
} from '@immich/sdk';
|
} from '@immich/sdk';
|
||||||
import { BrowserContext } from '@playwright/test';
|
import { BrowserContext } from '@playwright/test';
|
||||||
import { spawn } from 'child_process';
|
import { exec, spawn } from 'child_process';
|
||||||
import { randomBytes } from 'node:crypto';
|
import { randomBytes } from 'node:crypto';
|
||||||
import { access } from 'node:fs/promises';
|
import { access } from 'node:fs/promises';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
|
import { promisify } from 'node:util';
|
||||||
import pg from 'pg';
|
import pg from 'pg';
|
||||||
import { loginDto, signupDto } from 'src/fixtures';
|
import { loginDto, signupDto } from 'src/fixtures';
|
||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
|
|
||||||
|
const execPromise = promisify(exec);
|
||||||
|
|
||||||
export const app = 'http://127.0.0.1:2283/api';
|
export const app = 'http://127.0.0.1:2283/api';
|
||||||
|
|
||||||
const directoryExists = (directory: string) =>
|
const directoryExists = (directory: string) =>
|
||||||
|
@ -35,6 +38,9 @@ const directoryExists = (directory: string) =>
|
||||||
// TODO move test assets into e2e/assets
|
// TODO move test assets into e2e/assets
|
||||||
export const testAssetDir = path.resolve(`./../server/test/assets/`);
|
export const testAssetDir = path.resolve(`./../server/test/assets/`);
|
||||||
|
|
||||||
|
const serverContainerName = 'immich-e2e-server';
|
||||||
|
const uploadMediaDir = '/usr/src/app/upload/upload';
|
||||||
|
|
||||||
if (!(await directoryExists(`${testAssetDir}/albums`))) {
|
if (!(await directoryExists(`${testAssetDir}/albums`))) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Test assets not found. Please checkout https://github.com/immich-app/test-assets into ${testAssetDir} before testing`
|
`Test assets not found. Please checkout https://github.com/immich-app/test-assets into ${testAssetDir} before testing`
|
||||||
|
@ -50,6 +56,14 @@ export const asKeyAuth = (key: string) => ({ 'x-api-key': key });
|
||||||
|
|
||||||
let client: pg.Client | null = null;
|
let client: pg.Client | null = null;
|
||||||
|
|
||||||
|
export const fileUtils = {
|
||||||
|
reset: async () => {
|
||||||
|
await execPromise(
|
||||||
|
`docker exec -i "${serverContainerName}" rm -R "${uploadMediaDir}"`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const dbUtils = {
|
export const dbUtils = {
|
||||||
createFace: async ({
|
createFace: async ({
|
||||||
assetId,
|
assetId,
|
||||||
|
|
|
@ -167,7 +167,7 @@ export class AuditService {
|
||||||
`Found ${libraryFiles.size} original files, ${thumbFiles.size} thumbnails, ${videoFiles.size} encoded videos, ${profileFiles.size} profile files`,
|
`Found ${libraryFiles.size} original files, ${thumbFiles.size} thumbnails, ${videoFiles.size} encoded videos, ${profileFiles.size} profile files`,
|
||||||
);
|
);
|
||||||
const pagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (options) =>
|
const pagination = usePagination(JOBS_ASSET_PAGINATION_SIZE, (options) =>
|
||||||
this.assetRepository.getAll(options, { withDeleted: true }),
|
this.assetRepository.getAll(options, { withDeleted: true, withArchived: true }),
|
||||||
);
|
);
|
||||||
|
|
||||||
let assetCount = 0;
|
let assetCount = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue