mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-15 22:38:47 +00:00
클라이언트가 시작될 때 삭제된 파일이나 디렉터리 정보를 IndexedDB에서 삭제하도록 개선
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import type { ClientInit } from "@sveltejs/kit";
|
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 { prepareFileCache } from "$lib/modules/file";
|
||||||
import { prepareOpfs } from "$lib/modules/opfs";
|
import { prepareOpfs } from "$lib/modules/opfs";
|
||||||
import { clientKeyStore, masterKeyStore, hmacSecretStore } from "$lib/stores";
|
import { clientKeyStore, masterKeyStore, hmacSecretStore } from "$lib/stores";
|
||||||
@@ -38,4 +38,6 @@ export const init: ClientInit = async () => {
|
|||||||
prepareHmacSecretStore(),
|
prepareHmacSecretStore(),
|
||||||
prepareOpfs(),
|
prepareOpfs(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
cleanupDanglingInfos(); // Intended
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ export const storeDirectoryInfo = async (directoryInfo: DirectoryInfo) => {
|
|||||||
await filesystem.directory.put(directoryInfo);
|
await filesystem.directory.put(directoryInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const deleteDirectoryInfo = async (id: number) => {
|
||||||
|
await filesystem.directory.delete(id);
|
||||||
|
};
|
||||||
|
|
||||||
export const getFileInfos = async (parentId: DirectoryId) => {
|
export const getFileInfos = async (parentId: DirectoryId) => {
|
||||||
return await filesystem.file.where({ parentId }).toArray();
|
return await filesystem.file.where({ parentId }).toArray();
|
||||||
};
|
};
|
||||||
@@ -50,3 +54,33 @@ export const getFileInfo = async (id: number) => {
|
|||||||
export const storeFileInfo = async (fileInfo: FileInfo) => {
|
export const storeFileInfo = async (fileInfo: FileInfo) => {
|
||||||
await filesystem.file.put(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(),
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import {
|
|||||||
getDirectoryInfos as getDirectoryInfosFromIndexedDB,
|
getDirectoryInfos as getDirectoryInfosFromIndexedDB,
|
||||||
getDirectoryInfo as getDirectoryInfoFromIndexedDB,
|
getDirectoryInfo as getDirectoryInfoFromIndexedDB,
|
||||||
storeDirectoryInfo,
|
storeDirectoryInfo,
|
||||||
|
deleteDirectoryInfo,
|
||||||
getFileInfos as getFileInfosFromIndexedDB,
|
getFileInfos as getFileInfosFromIndexedDB,
|
||||||
getFileInfo as getFileInfoFromIndexedDB,
|
getFileInfo as getFileInfoFromIndexedDB,
|
||||||
storeFileInfo,
|
storeFileInfo,
|
||||||
|
deleteFileInfo,
|
||||||
type DirectoryId,
|
type DirectoryId,
|
||||||
} from "$lib/indexedDB";
|
} from "$lib/indexedDB";
|
||||||
import { unwrapDataKey, decryptString } from "$lib/modules/crypto";
|
import { unwrapDataKey, decryptString } from "$lib/modules/crypto";
|
||||||
@@ -72,7 +74,13 @@ const fetchDirectoryInfoFromServer = async (
|
|||||||
masterKey: CryptoKey,
|
masterKey: CryptoKey,
|
||||||
) => {
|
) => {
|
||||||
const res = await callGetApi(`/api/directory/${id}`);
|
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 {
|
const {
|
||||||
metadata,
|
metadata,
|
||||||
subDirectories: subDirectoryIds,
|
subDirectories: subDirectoryIds,
|
||||||
@@ -138,10 +146,16 @@ const fetchFileInfoFromServer = async (
|
|||||||
masterKey: CryptoKey,
|
masterKey: CryptoKey,
|
||||||
) => {
|
) => {
|
||||||
const res = await callGetApi(`/api/file/${id}`);
|
const res = await callGetApi(`/api/file/${id}`);
|
||||||
if (!res.ok) throw new Error("Failed to fetch file information"); // TODO: Handle 404
|
if (res.status === 404) {
|
||||||
const metadata: FileInfoResponse = await res.json();
|
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 { dataKey } = await unwrapDataKey(metadata.dek, masterKey);
|
||||||
|
|
||||||
const name = await decryptString(metadata.name, metadata.nameIv, dataKey);
|
const name = await decryptString(metadata.name, metadata.nameIv, dataKey);
|
||||||
const createdAt =
|
const createdAt =
|
||||||
metadata.createdAt && metadata.createdAtIv
|
metadata.createdAt && metadata.createdAtIv
|
||||||
|
|||||||
Reference in New Issue
Block a user