diff --git a/app/server/modules/volumes/__tests__/volumes.service.test.ts b/app/server/modules/volumes/__tests__/volumes.service.test.ts index d852e768..5b560da0 100644 --- a/app/server/modules/volumes/__tests__/volumes.service.test.ts +++ b/app/server/modules/volumes/__tests__/volumes.service.test.ts @@ -9,6 +9,87 @@ import path from "node:path"; import { createTestSession } from "~/test/helpers/auth"; import { withContext } from "~/server/core/request-context"; +describe("volumeService", () => { + describe("findVolume", () => { + test("should find volume by numeric id", async () => { + const { organizationId, user } = await createTestSession(); + + const [volume] = await db + .insert(volumesTable) + .values({ + shortId: randomUUID().slice(0, 8), + name: `test-vol-${randomUUID().slice(0, 8)}`, + type: "directory", + status: "mounted", + config: { backend: "directory", path: "/" }, + autoRemount: true, + organizationId, + }) + .returning(); + + await withContext({ organizationId, userId: user.id }, async () => { + const result = await volumeService.getVolume(String(volume.id)); + expect(result.volume.id).toBe(volume.id); + expect(result.volume.shortId).toBe(volume.shortId); + }); + }); + + test("should find volume by shortId", async () => { + const { organizationId, user } = await createTestSession(); + + const [volume] = await db + .insert(volumesTable) + .values({ + shortId: "test1234", + name: `test-vol-${randomUUID().slice(0, 8)}`, + type: "directory", + status: "mounted", + config: { backend: "directory", path: "/" }, + autoRemount: true, + organizationId, + }) + .returning(); + + await withContext({ organizationId, userId: user.id }, async () => { + const result = await volumeService.getVolume(volume.shortId); + expect(result.volume.id).toBe(volume.id); + expect(result.volume.shortId).toBe(volume.shortId); + }); + }); + + test("should find volume by numeric-looking shortId", async () => { + const { organizationId, user } = await createTestSession(); + + const [volume] = await db + .insert(volumesTable) + .values({ + shortId: "499780", + name: `test-vol-${randomUUID().slice(0, 8)}`, + type: "directory", + status: "mounted", + config: { backend: "directory", path: "/" }, + autoRemount: true, + organizationId, + }) + .returning(); + + await withContext({ organizationId, userId: user.id }, async () => { + const result = await volumeService.getVolume("499780"); + expect(result.volume.id).toBe(volume.id); + expect(result.volume.shortId).toBe("499780"); + }); + }); + + test("should throw NotFoundError for non-existent volume", async () => { + const { organizationId, user } = await createTestSession(); + + await withContext({ organizationId, userId: user.id }, async () => { + expect(volumeService.getVolume("nonexistent")).rejects.toThrow("Volume not found"); + }); + }); + }); +}); + describe("volumeService security", () => { describe("path traversal", () => { test("should reject traversal outside the volume root in listFiles", async () => { diff --git a/app/server/modules/volumes/volume.service.ts b/app/server/modules/volumes/volume.service.ts index a79d39db..714557f9 100644 --- a/app/server/modules/volumes/volume.service.ts +++ b/app/server/modules/volumes/volume.service.ts @@ -54,11 +54,10 @@ const listVolumes = async () => { const findVolume = async (idOrShortId: string | number) => { const organizationId = getOrganizationId(); - const isNumeric = typeof idOrShortId === "number" || /^\d+$/.test(String(idOrShortId)); return await db.query.volumesTable.findFirst({ where: { AND: [ - isNumeric ? { id: Number(idOrShortId) } : { shortId: String(idOrShortId) }, + { OR: [{ id: Number(idOrShortId) }, { shortId: String(idOrShortId) }] }, { organizationId: organizationId }, ], },