클라이언트가 시작될 때 삭제된 파일이나 디렉터리 정보를 IndexedDB에서 삭제하도록 개선

This commit is contained in:
static
2025-01-17 13:02:21 +09:00
parent 7aa6ba0eab
commit 620d174e9b
3 changed files with 54 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
import type { ClientInit } from "@sveltejs/kit";
import { getClientKey, getMasterKeys, getHmacSecrets } from "$lib/indexedDB";
import { cleanupDanglingInfos, getClientKey, getMasterKeys, getHmacSecrets } from "$lib/indexedDB";
import { prepareFileCache } from "$lib/modules/file";
import { prepareOpfs } from "$lib/modules/opfs";
import { clientKeyStore, masterKeyStore, hmacSecretStore } from "$lib/stores";
@@ -38,4 +38,6 @@ export const init: ClientInit = async () => {
prepareHmacSecretStore(),
prepareOpfs(),
]);
cleanupDanglingInfos(); // Intended
};

View File

@@ -39,6 +39,10 @@ export const storeDirectoryInfo = async (directoryInfo: DirectoryInfo) => {
await filesystem.directory.put(directoryInfo);
};
export const deleteDirectoryInfo = async (id: number) => {
await filesystem.directory.delete(id);
};
export const getFileInfos = async (parentId: DirectoryId) => {
return await filesystem.file.where({ parentId }).toArray();
};
@@ -50,3 +54,33 @@ export const getFileInfo = async (id: number) => {
export const storeFileInfo = async (fileInfo: FileInfo) => {
await filesystem.file.put(fileInfo);
};
export const deleteFileInfo = async (id: number) => {
await filesystem.file.delete(id);
};
export const cleanupDanglingInfos = async () => {
const validDirectoryIds: number[] = [];
const validFileIds: number[] = [];
const queue: DirectoryId[] = ["root"];
while (true) {
const directoryId = queue.shift();
if (!directoryId) break;
const [subDirectories, files] = await Promise.all([
filesystem.directory.where({ parentId: directoryId }).toArray(),
filesystem.file.where({ parentId: directoryId }).toArray(),
]);
subDirectories.forEach(({ id }) => {
validDirectoryIds.push(id);
queue.push(id);
});
files.forEach(({ id }) => validFileIds.push(id));
}
await Promise.all([
filesystem.directory.where("id").noneOf(validDirectoryIds).delete(),
filesystem.file.where("id").noneOf(validFileIds).delete(),
]);
};

View File

@@ -4,9 +4,11 @@ import {
getDirectoryInfos as getDirectoryInfosFromIndexedDB,
getDirectoryInfo as getDirectoryInfoFromIndexedDB,
storeDirectoryInfo,
deleteDirectoryInfo,
getFileInfos as getFileInfosFromIndexedDB,
getFileInfo as getFileInfoFromIndexedDB,
storeFileInfo,
deleteFileInfo,
type DirectoryId,
} from "$lib/indexedDB";
import { unwrapDataKey, decryptString } from "$lib/modules/crypto";
@@ -72,7 +74,13 @@ const fetchDirectoryInfoFromServer = async (
masterKey: CryptoKey,
) => {
const res = await callGetApi(`/api/directory/${id}`);
if (!res.ok) throw new Error("Failed to fetch directory information"); // TODO: Handle 404
if (res.status === 404) {
info.set(null);
await deleteDirectoryInfo(id as number);
} else if (!res.ok) {
throw new Error("Failed to fetch directory information");
}
const {
metadata,
subDirectories: subDirectoryIds,
@@ -138,10 +146,16 @@ const fetchFileInfoFromServer = async (
masterKey: CryptoKey,
) => {
const res = await callGetApi(`/api/file/${id}`);
if (!res.ok) throw new Error("Failed to fetch file information"); // TODO: Handle 404
const metadata: FileInfoResponse = await res.json();
if (res.status === 404) {
info.set(null);
await deleteFileInfo(id);
} else if (!res.ok) {
throw new Error("Failed to fetch file information");
}
const metadata: FileInfoResponse = await res.json();
const { dataKey } = await unwrapDataKey(metadata.dek, masterKey);
const name = await decryptString(metadata.name, metadata.nameIv, dataKey);
const createdAt =
metadata.createdAt && metadata.createdAtIv