mirror of
https://github.com/kmc7468/arkvault.git
synced 2026-11-04 08:10:28 +09:00
서버 코드를 Router, Service, Repository 계층으로 분리하고 오류 처리 및 파일 삭제 로직 개선
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ed732be999
commit
6a6aa1765b
72 files changed
+1928
-1509
No files matched your search
@@ -0,0 +1,92 @@
|
||||
import { access } from "fs/promises";
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { UploadRepo } from "#lib/server/db/index.js";
|
||||
import { DirectoryService, FileService } from "#lib/server/services/index.js";
|
||||
import { processPendingFileDeletions } from "#lib/server/services/fileDeletion.js";
|
||||
import {
|
||||
ciphertext,
|
||||
createDirectory,
|
||||
createFile,
|
||||
createUser,
|
||||
getQueuedDeletions,
|
||||
newEntryParams,
|
||||
resetDatabase,
|
||||
} from "../helpers/database";
|
||||
import { createStoredFile } from "../helpers/storage";
|
||||
|
||||
const exists = (path: string) =>
|
||||
access(path).then(
|
||||
() => true,
|
||||
() => false,
|
||||
);
|
||||
|
||||
beforeEach(resetDatabase);
|
||||
|
||||
describe("file deletion", () => {
|
||||
it("deletes the stored file after the database row is deleted", async () => {
|
||||
const { userId } = await createUser();
|
||||
const path = await createStoredFile();
|
||||
const fileId = await createFile(userId, "root", path);
|
||||
|
||||
await FileService.deleteFile(userId, fileId);
|
||||
await processPendingFileDeletions();
|
||||
|
||||
expect(await exists(path)).toBe(false);
|
||||
expect(await getQueuedDeletions()).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps failed deletions in the queue", async () => {
|
||||
const { userId } = await createUser();
|
||||
const fileId = await createFile(userId, "root", "/proc/version"); // Can't be deleted
|
||||
|
||||
await FileService.deleteFile(userId, fileId);
|
||||
await processPendingFileDeletions();
|
||||
|
||||
expect(await getQueuedDeletions()).toEqual(["/proc/version"]);
|
||||
});
|
||||
|
||||
it("deletes directories recursively including pending uploads", async () => {
|
||||
const { userId } = await createUser();
|
||||
const rootId = await createDirectory(userId);
|
||||
const childId = await createDirectory(userId, rootId);
|
||||
const grandchildId = await createDirectory(userId, childId);
|
||||
const otherId = await createDirectory(userId);
|
||||
|
||||
const paths = await Promise.all([1, 2, 3, 4].map(() => createStoredFile()));
|
||||
const fileIds = [
|
||||
await createFile(userId, rootId, paths[0]!),
|
||||
await createFile(userId, grandchildId, paths[1]!),
|
||||
];
|
||||
const otherFileId = await createFile(userId, otherId, paths[2]!);
|
||||
await UploadRepo.createFileUploadSession({
|
||||
...newEntryParams(userId, childId),
|
||||
id: crypto.randomUUID(),
|
||||
path: paths[3]!,
|
||||
totalChunks: 1,
|
||||
expiresAt: new Date(Date.now() + 60_000),
|
||||
hskVersion: null,
|
||||
contentType: "image/png",
|
||||
encCreatedAt: null,
|
||||
encLastModifiedAt: ciphertext(),
|
||||
});
|
||||
|
||||
const { deletedFileIds } = await DirectoryService.deleteDirectory(userId, rootId);
|
||||
|
||||
expect(deletedFileIds.sort()).toEqual(fileIds.sort());
|
||||
expect(await getQueuedDeletions()).toEqual([paths[0], paths[1], paths[3]].sort());
|
||||
await expect(DirectoryService.getDirectory(userId, grandchildId)).rejects.toMatchObject({
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
expect((await FileService.getFile(userId, otherFileId)).id).toBe(otherFileId);
|
||||
});
|
||||
|
||||
it("rejects deleting another user's directory", async () => {
|
||||
const { userId: ownerId } = await createUser();
|
||||
const { userId: otherId } = await createUser();
|
||||
const directoryId = await createDirectory(ownerId);
|
||||
|
||||
await expect(DirectoryService.deleteDirectory(otherId, directoryId)).rejects.toMatchObject({
|
||||
code: "NOT_FOUND",
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user