diff --git a/src/lib/modules/file/upload.ts b/src/lib/modules/file/upload.ts index a2a9707..71a38fb 100644 --- a/src/lib/modules/file/upload.ts +++ b/src/lib/modules/file/upload.ts @@ -15,6 +15,7 @@ import type { DuplicateFileScanRequest, DuplicateFileScanResponse, FileUploadRequest, + FileUploadResponse, } from "$lib/server/schemas"; import { fileUploadStatusStore, @@ -131,7 +132,7 @@ const requestFileUpload = limitFunction( return value; }); - await axios.post("/api/file/upload", form, { + const res = await axios.post("/api/file/upload", form, { onUploadProgress: ({ progress, rate, estimated }) => { status.update((value) => { value.progress = progress; @@ -141,11 +142,14 @@ const requestFileUpload = limitFunction( }); }, }); + const { file }: FileUploadResponse = res.data; status.update((value) => { value.status = "uploaded"; return value; }); + + return { fileId: file }; }, { concurrency: 1 }, ); @@ -156,7 +160,7 @@ export const uploadFile = async ( hmacSecret: HmacSecret, masterKey: MasterKey, onDuplicate: () => Promise, -) => { +): Promise<{ fileId: number; fileBuffer: ArrayBuffer } | undefined> => { const status = writable({ name: file.name, parentId, @@ -182,7 +186,7 @@ export const uploadFile = async ( value = value.filter((v) => v !== status); return value; }); - return false; + return undefined; } const { @@ -219,8 +223,8 @@ export const uploadFile = async ( form.set("content", new Blob([fileEncrypted.ciphertext])); form.set("checksum", fileEncryptedHash); - await requestFileUpload(status, form); - return true; + const { fileId } = await requestFileUpload(status, form); + return { fileId, fileBuffer }; } catch (e) { status.update((value) => { value.status = "error"; diff --git a/src/lib/server/db/client.ts b/src/lib/server/db/client.ts index 08f2c98..cb873c7 100644 --- a/src/lib/server/db/client.ts +++ b/src/lib/server/db/client.ts @@ -50,7 +50,7 @@ export const createClient = async (encPubKey: string, sigPubKey: string, userId: .insertInto("user_client") .values({ user_id: userId, client_id: clientId }) .execute(); - return { clientId }; + return { id: clientId }; }); }; diff --git a/src/lib/server/db/file.ts b/src/lib/server/db/file.ts index 219dc42..20343b2 100644 --- a/src/lib/server/db/file.ts +++ b/src/lib/server/db/file.ts @@ -203,7 +203,7 @@ export const registerFile = async (params: NewFile) => { throw new Error("Invalid arguments"); } - await db.transaction().execute(async (trx) => { + return await db.transaction().execute(async (trx) => { const mek = await trx .selectFrom("master_encryption_key") .select("version") @@ -259,6 +259,7 @@ export const registerFile = async (params: NewFile) => { new_name: params.encName, }) .execute(); + return { id: fileId }; }); }; diff --git a/src/lib/server/schemas/file.ts b/src/lib/server/schemas/file.ts index ed0af94..cb6af28 100644 --- a/src/lib/server/schemas/file.ts +++ b/src/lib/server/schemas/file.ts @@ -60,3 +60,8 @@ export const fileUploadRequest = z.object({ lastModifiedAtIv: z.string().base64().nonempty(), }); export type FileUploadRequest = z.infer; + +export const fileUploadResponse = z.object({ + file: z.number().int().positive(), +}); +export type FileUploadResponse = z.infer; diff --git a/src/lib/server/services/client.ts b/src/lib/server/services/client.ts index 0d0b82d..ee1b5b3 100644 --- a/src/lib/server/services/client.ts +++ b/src/lib/server/services/client.ts @@ -63,7 +63,7 @@ export const registerUserClient = async ( } try { - const { clientId } = await createClient(encPubKey, sigPubKey, userId); + const { id: clientId } = await createClient(encPubKey, sigPubKey, userId); return { challenge: await createUserClientChallenge(ip, userId, clientId, encPubKey) }; } catch (e) { if (e instanceof IntegrityError && e.message === "Public key(s) already registered") { diff --git a/src/lib/server/services/file.ts b/src/lib/server/services/file.ts index 519bdfd..1f7f34f 100644 --- a/src/lib/server/services/file.ts +++ b/src/lib/server/services/file.ts @@ -131,11 +131,12 @@ export const uploadFile = async ( throw new Error("Invalid checksum"); } - await registerFile({ + const { id: fileId } = await registerFile({ ...params, path, encContentHash: hash, }); + return { fileId }; } catch (e) { await safeUnlink(path); diff --git a/src/routes/(main)/directory/[[id]]/service.ts b/src/routes/(main)/directory/[[id]]/service.ts index c9a62b2..8d36fb2 100644 --- a/src/routes/(main)/directory/[[id]]/service.ts +++ b/src/routes/(main)/directory/[[id]]/service.ts @@ -1,7 +1,7 @@ import { callGetApi, callPostApi } from "$lib/hooks"; import { storeHmacSecrets } from "$lib/indexedDB"; import { generateDataKey, wrapDataKey, unwrapHmacSecret, encryptString } from "$lib/modules/crypto"; -import { deleteFileCache, uploadFile } from "$lib/modules/file"; +import { storeFileCache, deleteFileCache, uploadFile } from "$lib/modules/file"; import type { DirectoryRenameRequest, DirectoryCreateRequest, @@ -63,7 +63,11 @@ export const requestFileUpload = async ( masterKey: MasterKey, onDuplicate: () => Promise, ) => { - return await uploadFile(file, parentId, hmacSecret, masterKey, onDuplicate); + const res = await uploadFile(file, parentId, hmacSecret, masterKey, onDuplicate); + if (!res) return false; + + storeFileCache(res.fileId, res.fileBuffer); // Intended + return true; }; export const requestDirectoryEntryRename = async ( diff --git a/src/routes/api/file/upload/+server.ts b/src/routes/api/file/upload/+server.ts index b54a542..55db93f 100644 --- a/src/routes/api/file/upload/+server.ts +++ b/src/routes/api/file/upload/+server.ts @@ -1,8 +1,12 @@ import Busboy from "@fastify/busboy"; -import { error, text } from "@sveltejs/kit"; +import { error, json } from "@sveltejs/kit"; import { Readable, Writable } from "stream"; import { authorize } from "$lib/server/modules/auth"; -import { fileUploadRequest } from "$lib/server/schemas"; +import { + fileUploadRequest, + fileUploadResponse, + type FileUploadResponse, +} from "$lib/server/schemas"; import { uploadFile } from "$lib/server/services/file"; import type { RequestHandler } from "./$types"; @@ -87,8 +91,8 @@ export const POST: RequestHandler = async ({ locals, request }) => { if (!metadata || content) error(400, "Invalid request body"); content = file; - await uploadFile(metadata, content, checksum); - resolve(text("File uploaded", { headers: { "Content-Type": "text/plain" } })); + const { fileId } = await uploadFile(metadata, content, checksum); + resolve(json(fileUploadResponse.parse({ file: fileId } satisfies FileUploadResponse))); }), ); bb.on("finish", () => rejectChecksum(new Error("Invalid request body")));