From 9b14e833be4d778ad08a03f545e7d1114d50e46e Mon Sep 17 00:00:00 2001 From: static Date: Sat, 4 Jan 2025 23:19:44 +0900 Subject: [PATCH] =?UTF-8?q?=ED=94=84=EB=A1=A0=ED=8A=B8=EC=97=94=EB=93=9C?= =?UTF-8?q?=EC=97=90=EC=84=9C=EC=9D=98=20=ED=8C=8C=EC=9D=BC=20=EC=97=85?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=20=EC=9E=84=EC=8B=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 1 + .gitignore | 1 + .../(main)/directory/[[id]]/+page.svelte | 15 ++++++- .../directory/[[id]]/CreateBottomSheet.svelte | 2 +- src/routes/(main)/directory/[[id]]/service.ts | 43 ++++++++++++++++++- 5 files changed, 58 insertions(+), 4 deletions(-) diff --git a/.dockerignore b/.dockerignore index 80d8499..23674ef 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,6 +9,7 @@ node_modules /.svelte-kit /build /data +/library # OS .DS_Store diff --git a/.gitignore b/.gitignore index 310e494..1dbbe60 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ node_modules /.svelte-kit /build /data +/library # OS .DS_Store diff --git a/src/routes/(main)/directory/[[id]]/+page.svelte b/src/routes/(main)/directory/[[id]]/+page.svelte index ff116ec..53f4270 100644 --- a/src/routes/(main)/directory/[[id]]/+page.svelte +++ b/src/routes/(main)/directory/[[id]]/+page.svelte @@ -5,12 +5,14 @@ import CreateBottomSheet from "./CreateBottomSheet.svelte"; import CreateDirectoryModal from "./CreateDirectoryModal.svelte"; import DirectoryEntry from "./DirectoryEntry.svelte"; - import { decryptDirectroyMetadata, requestDirectroyCreation } from "./service"; + import { decryptDirectroyMetadata, requestDirectroyCreation, requestFileUpload } from "./service"; import IconAdd from "~icons/material-symbols/add"; let { data } = $props(); + let fileInput: HTMLInputElement | undefined = $state(); + let isCreateBottomSheetOpen = $state(false); let isCreateDirectoryModalOpen = $state(false); @@ -51,12 +53,21 @@ ); isCreateDirectoryModalOpen = false; }; + + const uploadFile = () => { + const file = fileInput?.files?.[0]; + if (!file) return; + + requestFileUpload(file, data.id, $masterKeyStore?.get(1)!, $clientKeyStore?.signKey!); + }; 파일 + +
{#if data.id !== "root"} {#if !metadata} @@ -95,7 +106,7 @@ }} onFileUpload={() => { isCreateBottomSheetOpen = false; - // TODO + fileInput?.click(); }} /> diff --git a/src/routes/(main)/directory/[[id]]/CreateBottomSheet.svelte b/src/routes/(main)/directory/[[id]]/CreateBottomSheet.svelte index 9ea26ce..d079980 100644 --- a/src/routes/(main)/directory/[[id]]/CreateBottomSheet.svelte +++ b/src/routes/(main)/directory/[[id]]/CreateBottomSheet.svelte @@ -15,7 +15,7 @@ -
+
diff --git a/src/routes/(main)/directory/[[id]]/service.ts b/src/routes/(main)/directory/[[id]]/service.ts index f90477f..8baead9 100644 --- a/src/routes/(main)/directory/[[id]]/service.ts +++ b/src/routes/(main)/directory/[[id]]/service.ts @@ -7,8 +7,14 @@ import { unwrapDataKey, encryptData, decryptData, + digestMessage, + signRequestBody, } from "$lib/modules/crypto"; -import type { DirectroyInfoResponse, DirectoryCreateRequest } from "$lib/server/schemas"; +import type { + DirectroyInfoResponse, + DirectoryCreateRequest, + FileUploadRequest, +} from "$lib/server/schemas"; import type { MasterKey } from "$lib/stores"; export const decryptDirectroyMetadata = async ( @@ -43,3 +49,38 @@ export const requestDirectroyCreation = async ( signKey, ); }; + +export const requestFileUpload = async ( + file: File, + parentId: "root" | number, + masterKey: MasterKey, + signKey: CryptoKey, +) => { + const { dataKey } = await generateDataKey(); + const fileEncrypted = await encryptData(await file.arrayBuffer(), dataKey); + const fileEncryptedHash = await digestMessage(fileEncrypted.ciphertext); + const nameEncrypted = await encryptData(new TextEncoder().encode(file.name), dataKey); + + const form = new FormData(); + form.set( + "metadata", + await signRequestBody( + { + parentId, + mekVersion: masterKey.version, + dek: await wrapDataKey(dataKey, masterKey.key), + contentHash: encodeToBase64(fileEncryptedHash), + contentIv: fileEncrypted.iv, + name: encodeToBase64(nameEncrypted.ciphertext), + nameIv: nameEncrypted.iv, + }, + signKey, + ), + ); + form.set("content", new Blob([fileEncrypted.ciphertext])); + + // TODO: Progress, Scheduling, ... + const xhr = new XMLHttpRequest(); + xhr.open("POST", "/api/file/upload"); + xhr.send(form); +};