사소한 리팩토링 2

This commit is contained in:
static
2025-12-26 15:45:03 +09:00
parent d94d14cf83
commit c9d4b10356
16 changed files with 54 additions and 84 deletions

View File

@@ -23,15 +23,14 @@ import {
type HmacSecret, type HmacSecret,
type FileUploadStatus, type FileUploadStatus,
} from "$lib/stores"; } from "$lib/stores";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
const requestDuplicateFileScan = limitFunction( const requestDuplicateFileScan = limitFunction(
async (file: File, hmacSecret: HmacSecret, onDuplicate: () => Promise<boolean>) => { async (file: File, hmacSecret: HmacSecret, onDuplicate: () => Promise<boolean>) => {
const trpc = useTRPC();
const fileBuffer = await file.arrayBuffer(); const fileBuffer = await file.arrayBuffer();
const fileSigned = encodeToBase64(await signMessageHmac(fileBuffer, hmacSecret.secret)); const fileSigned = encodeToBase64(await signMessageHmac(fileBuffer, hmacSecret.secret));
const files = await trpc.file.listByHash.query({ const files = await trpc().file.listByHash.query({
hskVersion: hmacSecret.version, hskVersion: hmacSecret.version,
contentHmac: fileSigned, contentHmac: fileSigned,
}); });

View File

@@ -18,7 +18,7 @@ import {
type CategoryId, type CategoryId,
} from "$lib/indexedDB"; } from "$lib/indexedDB";
import { unwrapDataKey, decryptString } from "$lib/modules/crypto"; import { unwrapDataKey, decryptString } from "$lib/modules/crypto";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export type DirectoryInfo = export type DirectoryInfo =
| { | {
@@ -101,10 +101,9 @@ const fetchDirectoryInfoFromServer = async (
info: Writable<DirectoryInfo | null>, info: Writable<DirectoryInfo | null>,
masterKey: CryptoKey, masterKey: CryptoKey,
) => { ) => {
const trpc = useTRPC();
let data; let data;
try { try {
data = await trpc.directory.get.query({ id }); data = await trpc().directory.get.query({ id });
} catch (e) { } catch (e) {
if (e instanceof TRPCClientError && e.data?.code === "NOT_FOUND") { if (e instanceof TRPCClientError && e.data?.code === "NOT_FOUND") {
info.set(null); info.set(null);
@@ -174,10 +173,9 @@ const fetchFileInfoFromServer = async (
info: Writable<FileInfo | null>, info: Writable<FileInfo | null>,
masterKey: CryptoKey, masterKey: CryptoKey,
) => { ) => {
const trpc = useTRPC();
let metadata; let metadata;
try { try {
metadata = await trpc.file.get.query({ id }); metadata = await trpc().file.get.query({ id });
} catch (e) { } catch (e) {
if (e instanceof TRPCClientError && e.data?.code === "NOT_FOUND") { if (e instanceof TRPCClientError && e.data?.code === "NOT_FOUND") {
info.set(null); info.set(null);
@@ -270,10 +268,9 @@ const fetchCategoryInfoFromServer = async (
info: Writable<CategoryInfo | null>, info: Writable<CategoryInfo | null>,
masterKey: CryptoKey, masterKey: CryptoKey,
) => { ) => {
const trpc = useTRPC();
let data; let data;
try { try {
data = await trpc.category.get.query({ id }); data = await trpc().category.get.query({ id });
} catch (e) { } catch (e) {
if (e instanceof TRPCClientError && e.data?.code === "NOT_FOUND") { if (e instanceof TRPCClientError && e.data?.code === "NOT_FOUND") {
info.set(null); info.set(null);
@@ -293,7 +290,7 @@ const fetchCategoryInfoFromServer = async (
let files; let files;
try { try {
files = await trpc.category.files.query({ id, recurse: true }); files = await trpc().category.files.query({ id, recurse: true });
} catch { } catch {
throw new Error("Failed to fetch category files"); throw new Error("Failed to fetch category files");
} }

View File

@@ -1,6 +1,6 @@
import { TRPCClientError } from "@trpc/client"; import { TRPCClientError } from "@trpc/client";
import { encodeToBase64, decryptChallenge, signMessageRSA } from "$lib/modules/crypto"; import { encodeToBase64, decryptChallenge, signMessageRSA } from "$lib/modules/crypto";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export const requestSessionUpgrade = async ( export const requestSessionUpgrade = async (
encryptKeyBase64: string, encryptKeyBase64: string,
@@ -9,10 +9,9 @@ export const requestSessionUpgrade = async (
signKey: CryptoKey, signKey: CryptoKey,
force = false, force = false,
) => { ) => {
const trpc = useTRPC();
let id, challenge; let id, challenge;
try { try {
({ id, challenge } = await trpc.auth.upgrade.mutate({ ({ id, challenge } = await trpc().auth.upgrade.mutate({
encPubKey: encryptKeyBase64, encPubKey: encryptKeyBase64,
sigPubKey: verifyKeyBase64, sigPubKey: verifyKeyBase64,
})); }));
@@ -26,7 +25,7 @@ export const requestSessionUpgrade = async (
const answerSig = await signMessageRSA(answer, signKey); const answerSig = await signMessageRSA(answer, signKey);
try { try {
await trpc.auth.verifyUpgrade.mutate({ await trpc().auth.verifyUpgrade.mutate({
id, id,
answerSig: encodeToBase64(answerSig), answerSig: encodeToBase64(answerSig),
force, force,
@@ -42,9 +41,8 @@ export const requestSessionUpgrade = async (
}; };
export const requestLogout = async () => { export const requestLogout = async () => {
const trpc = useTRPC();
try { try {
await trpc.auth.logout.mutate(); await trpc().auth.logout.mutate();
return true; return true;
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling

View File

@@ -1,18 +1,17 @@
import { generateDataKey, wrapDataKey, encryptString } from "$lib/modules/crypto"; import { generateDataKey, wrapDataKey, encryptString } from "$lib/modules/crypto";
import type { MasterKey } from "$lib/stores"; import type { MasterKey } from "$lib/stores";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export const requestCategoryCreation = async ( export const requestCategoryCreation = async (
name: string, name: string,
parentId: "root" | number, parentId: "root" | number,
masterKey: MasterKey, masterKey: MasterKey,
) => { ) => {
const trpc = useTRPC();
const { dataKey, dataKeyVersion } = await generateDataKey(); const { dataKey, dataKeyVersion } = await generateDataKey();
const nameEncrypted = await encryptString(name, dataKey); const nameEncrypted = await encryptString(name, dataKey);
try { try {
await trpc.category.create.mutate({ await trpc().category.create.mutate({
parent: parentId, parent: parentId,
mekVersion: masterKey.version, mekVersion: masterKey.version,
dek: await wrapDataKey(dataKey, masterKey.key), dek: await wrapDataKey(dataKey, masterKey.key),
@@ -28,10 +27,9 @@ export const requestCategoryCreation = async (
}; };
export const requestFileRemovalFromCategory = async (fileId: number, categoryId: number) => { export const requestFileRemovalFromCategory = async (fileId: number, categoryId: number) => {
const trpc = useTRPC();
try { try {
await trpc.category.removeFile.mutate({ id: categoryId, file: fileId }); await trpc().category.removeFile.mutate({ id: categoryId, file: fileId });
return true; return true;
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling

View File

@@ -12,7 +12,7 @@ import {
} from "$lib/modules/file"; } from "$lib/modules/file";
import { getThumbnailUrl } from "$lib/modules/thumbnail"; import { getThumbnailUrl } from "$lib/modules/thumbnail";
import type { FileThumbnailUploadRequest } from "$lib/server/schemas"; import type { FileThumbnailUploadRequest } from "$lib/server/schemas";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export const requestFileDownload = async ( export const requestFileDownload = async (
fileId: number, fileId: number,
@@ -49,10 +49,9 @@ export const requestFileThumbnailDownload = async (fileId: number, dataKey?: Cry
const cache = await getFileThumbnailCache(fileId); const cache = await getFileThumbnailCache(fileId);
if (cache || !dataKey) return cache; if (cache || !dataKey) return cache;
const trpc = useTRPC();
let thumbnailInfo; let thumbnailInfo;
try { try {
thumbnailInfo = await trpc.file.thumbnail.query({ id: fileId }); thumbnailInfo = await trpc().file.thumbnail.query({ id: fileId });
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling
return null; return null;
@@ -70,10 +69,9 @@ export const requestFileThumbnailDownload = async (fileId: number, dataKey?: Cry
}; };
export const requestDeletedFilesCleanup = async () => { export const requestDeletedFilesCleanup = async () => {
const trpc = useTRPC();
let liveFiles; let liveFiles;
try { try {
liveFiles = await trpc.file.list.query(); liveFiles = await trpc().file.list.query();
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling
return; return;

View File

@@ -11,7 +11,7 @@ import {
} from "$lib/modules/crypto"; } from "$lib/modules/crypto";
import { requestSessionUpgrade } from "$lib/services/auth"; import { requestSessionUpgrade } from "$lib/services/auth";
import { masterKeyStore, type ClientKeys } from "$lib/stores"; import { masterKeyStore, type ClientKeys } from "$lib/stores";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export const requestClientRegistration = async ( export const requestClientRegistration = async (
encryptKeyBase64: string, encryptKeyBase64: string,
@@ -19,16 +19,14 @@ export const requestClientRegistration = async (
verifyKeyBase64: string, verifyKeyBase64: string,
signKey: CryptoKey, signKey: CryptoKey,
) => { ) => {
const trpc = useTRPC();
try { try {
const { id, challenge } = await trpc.client.register.mutate({ const { id, challenge } = await trpc().client.register.mutate({
encPubKey: encryptKeyBase64, encPubKey: encryptKeyBase64,
sigPubKey: verifyKeyBase64, sigPubKey: verifyKeyBase64,
}); });
const answer = await decryptChallenge(challenge, decryptKey); const answer = await decryptChallenge(challenge, decryptKey);
const answerSig = await signMessageRSA(answer, signKey); const answerSig = await signMessageRSA(answer, signKey);
await trpc.client.verify.mutate({ await trpc().client.verify.mutate({
id, id,
answerSig: encodeToBase64(answerSig), answerSig: encodeToBase64(answerSig),
}); });
@@ -69,11 +67,9 @@ export const requestClientRegistrationAndSessionUpgrade = async (
}; };
export const requestMasterKeyDownload = async (decryptKey: CryptoKey, verifyKey: CryptoKey) => { export const requestMasterKeyDownload = async (decryptKey: CryptoKey, verifyKey: CryptoKey) => {
const trpc = useTRPC();
let masterKeysWrapped; let masterKeysWrapped;
try { try {
masterKeysWrapped = await trpc.mek.list.query(); masterKeysWrapped = await trpc().mek.list.query();
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling
return false; return false;
@@ -110,10 +106,8 @@ export const requestInitialMasterKeyAndHmacSecretRegistration = async (
hmacSecretWrapped: string, hmacSecretWrapped: string,
signKey: CryptoKey, signKey: CryptoKey,
) => { ) => {
const trpc = useTRPC();
try { try {
await trpc.mek.registerInitial.mutate({ await trpc().mek.registerInitial.mutate({
mek: masterKeyWrapped, mek: masterKeyWrapped,
mekSig: await signMasterKeyWrapped(masterKeyWrapped, 1, signKey), mekSig: await signMasterKeyWrapped(masterKeyWrapped, 1, signKey),
}); });
@@ -129,7 +123,7 @@ export const requestInitialMasterKeyAndHmacSecretRegistration = async (
} }
try { try {
await trpc.hsk.registerInitial.mutate({ await trpc().hsk.registerInitial.mutate({
mekVersion: 1, mekVersion: 1,
hsk: hmacSecretWrapped, hsk: hmacSecretWrapped,
}); });

View File

@@ -1,10 +1,8 @@
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export const requestPasswordChange = async (oldPassword: string, newPassword: string) => { export const requestPasswordChange = async (oldPassword: string, newPassword: string) => {
const trpc = useTRPC();
try { try {
await trpc.auth.changePassword.mutate({ oldPassword, newPassword }); await trpc().auth.changePassword.mutate({ oldPassword, newPassword });
return true; return true;
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling

View File

@@ -1,4 +1,4 @@
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export { requestLogout } from "$lib/services/auth"; export { requestLogout } from "$lib/services/auth";
export { requestDeletedFilesCleanup } from "$lib/services/file"; export { requestDeletedFilesCleanup } from "$lib/services/file";
@@ -8,10 +8,8 @@ export {
} from "$lib/services/key"; } from "$lib/services/key";
export const requestLogin = async (email: string, password: string) => { export const requestLogin = async (email: string, password: string) => {
const trpc = useTRPC();
try { try {
await trpc.auth.login.mutate({ email, password }); await trpc().auth.login.mutate({ email, password });
return true; return true;
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling

View File

@@ -1,7 +1,7 @@
import { encryptData } from "$lib/modules/crypto"; import { encryptData } from "$lib/modules/crypto";
import { storeFileThumbnailCache } from "$lib/modules/file"; import { storeFileThumbnailCache } from "$lib/modules/file";
import { requestFileThumbnailUpload } from "$lib/services/file"; import { requestFileThumbnailUpload } from "$lib/services/file";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export { requestCategoryCreation, requestFileRemovalFromCategory } from "$lib/services/category"; export { requestCategoryCreation, requestFileRemovalFromCategory } from "$lib/services/category";
export { requestFileDownload } from "$lib/services/file"; export { requestFileDownload } from "$lib/services/file";
@@ -22,10 +22,8 @@ export const requestThumbnailUpload = async (
}; };
export const requestFileAdditionToCategory = async (fileId: number, categoryId: number) => { export const requestFileAdditionToCategory = async (fileId: number, categoryId: number) => {
const trpc = useTRPC();
try { try {
await trpc.category.addFile.mutate({ id: categoryId, file: fileId }); await trpc().category.addFile.mutate({ id: categoryId, file: fileId });
return true; return true;
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling

View File

@@ -1,14 +1,13 @@
import { error } from "@sveltejs/kit"; import { error } from "@sveltejs/kit";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
import type { PageLoad } from "./$types"; import type { PageLoad } from "./$types";
export const load: PageLoad = async ({ fetch }) => { export const load: PageLoad = async ({ fetch }) => {
const trpc = useTRPC(fetch);
try { try {
const files = await trpc.file.listWithoutThumbnail.query(); const files = await trpc(fetch).file.listWithoutThumbnail.query();
return { files }; return { files };
} catch { } catch {
// TODO: Error Handling
error(500, "Internal server error"); error(500, "Internal server error");
} }
}; };

View File

@@ -1,7 +1,7 @@
import { getContext, setContext } from "svelte"; import { getContext, setContext } from "svelte";
import { encryptString } from "$lib/modules/crypto"; import { encryptString } from "$lib/modules/crypto";
import type { SelectedCategory } from "$lib/components/molecules"; import type { SelectedCategory } from "$lib/components/molecules";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export { requestCategoryCreation, requestFileRemovalFromCategory } from "$lib/services/category"; export { requestCategoryCreation, requestFileRemovalFromCategory } from "$lib/services/category";
@@ -17,11 +17,10 @@ export const useContext = () => {
}; };
export const requestCategoryRename = async (category: SelectedCategory, newName: string) => { export const requestCategoryRename = async (category: SelectedCategory, newName: string) => {
const trpc = useTRPC();
const newNameEncrypted = await encryptString(newName, category.dataKey); const newNameEncrypted = await encryptString(newName, category.dataKey);
try { try {
await trpc.category.rename.mutate({ await trpc().category.rename.mutate({
id: category.id, id: category.id,
dekVersion: category.dataKeyVersion, dekVersion: category.dataKeyVersion,
name: newNameEncrypted.ciphertext, name: newNameEncrypted.ciphertext,
@@ -35,10 +34,8 @@ export const requestCategoryRename = async (category: SelectedCategory, newName:
}; };
export const requestCategoryDeletion = async (category: SelectedCategory) => { export const requestCategoryDeletion = async (category: SelectedCategory) => {
const trpc = useTRPC();
try { try {
await trpc.category.delete.mutate({ id: category.id }); await trpc().category.delete.mutate({ id: category.id });
return true; return true;
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling

View File

@@ -9,7 +9,7 @@ import {
uploadFile, uploadFile,
} from "$lib/modules/file"; } from "$lib/modules/file";
import { hmacSecretStore, type MasterKey, type HmacSecret } from "$lib/stores"; import { hmacSecretStore, type MasterKey, type HmacSecret } from "$lib/stores";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
export interface SelectedEntry { export interface SelectedEntry {
type: "directory" | "file"; type: "directory" | "file";
@@ -33,11 +33,9 @@ export const useContext = () => {
export const requestHmacSecretDownload = async (masterKey: CryptoKey) => { export const requestHmacSecretDownload = async (masterKey: CryptoKey) => {
// TODO: MEK rotation // TODO: MEK rotation
const trpc = useTRPC();
let hmacSecretsWrapped; let hmacSecretsWrapped;
try { try {
hmacSecretsWrapped = await trpc.hsk.list.query(); hmacSecretsWrapped = await trpc().hsk.list.query();
} catch { } catch {
// TODO: Error Handling // TODO: Error Handling
return false; return false;
@@ -61,12 +59,11 @@ export const requestDirectoryCreation = async (
parentId: "root" | number, parentId: "root" | number,
masterKey: MasterKey, masterKey: MasterKey,
) => { ) => {
const trpc = useTRPC();
const { dataKey, dataKeyVersion } = await generateDataKey(); const { dataKey, dataKeyVersion } = await generateDataKey();
const nameEncrypted = await encryptString(name, dataKey); const nameEncrypted = await encryptString(name, dataKey);
try { try {
await trpc.directory.create.mutate({ await trpc().directory.create.mutate({
parent: parentId, parent: parentId,
mekVersion: masterKey.version, mekVersion: masterKey.version,
dek: await wrapDataKey(dataKey, masterKey.key), dek: await wrapDataKey(dataKey, masterKey.key),
@@ -100,19 +97,18 @@ export const requestFileUpload = async (
}; };
export const requestEntryRename = async (entry: SelectedEntry, newName: string) => { export const requestEntryRename = async (entry: SelectedEntry, newName: string) => {
const trpc = useTRPC();
const newNameEncrypted = await encryptString(newName, entry.dataKey); const newNameEncrypted = await encryptString(newName, entry.dataKey);
try { try {
if (entry.type === "directory") { if (entry.type === "directory") {
await trpc.directory.rename.mutate({ await trpc().directory.rename.mutate({
id: entry.id, id: entry.id,
dekVersion: entry.dataKeyVersion, dekVersion: entry.dataKeyVersion,
name: newNameEncrypted.ciphertext, name: newNameEncrypted.ciphertext,
nameIv: newNameEncrypted.iv, nameIv: newNameEncrypted.iv,
}); });
} else { } else {
await trpc.file.rename.mutate({ await trpc().file.rename.mutate({
id: entry.id, id: entry.id,
dekVersion: entry.dataKeyVersion, dekVersion: entry.dataKeyVersion,
name: newNameEncrypted.ciphertext, name: newNameEncrypted.ciphertext,
@@ -127,11 +123,9 @@ export const requestEntryRename = async (entry: SelectedEntry, newName: string)
}; };
export const requestEntryDeletion = async (entry: SelectedEntry) => { export const requestEntryDeletion = async (entry: SelectedEntry) => {
const trpc = useTRPC();
try { try {
if (entry.type === "directory") { if (entry.type === "directory") {
const { deletedFiles } = await trpc.directory.delete.mutate({ id: entry.id }); const { deletedFiles } = await trpc().directory.delete.mutate({ id: entry.id });
await Promise.all( await Promise.all(
deletedFiles.flatMap((fileId) => [ deletedFiles.flatMap((fileId) => [
deleteFileCache(fileId), deleteFileCache(fileId),
@@ -139,7 +133,7 @@ export const requestEntryDeletion = async (entry: SelectedEntry) => {
]), ]),
); );
} else { } else {
await trpc.file.delete.mutate({ id: entry.id }); await trpc().file.delete.mutate({ id: entry.id });
await Promise.all([deleteFileCache(entry.id), deleteFileThumbnailCache(entry.id)]); await Promise.all([deleteFileCache(entry.id), deleteFileThumbnailCache(entry.id)]);
} }
return true; return true;

View File

@@ -1,14 +1,13 @@
import { error } from "@sveltejs/kit"; import { error } from "@sveltejs/kit";
import { useTRPC } from "$trpc/client"; import { trpc } from "$trpc/client";
import type { PageLoad } from "./$types"; import type { PageLoad } from "./$types";
export const load: PageLoad = async ({ fetch }) => { export const load: PageLoad = async ({ fetch }) => {
const trpc = useTRPC(fetch);
try { try {
const { nickname } = await trpc.user.get.query(); const { nickname } = await trpc(fetch).user.get.query();
return { nickname }; return { nickname };
} catch { } catch {
// TODO: Error Handling
error(500, "Internal server error"); error(500, "Internal server error");
} }
}; };

View File

@@ -16,7 +16,7 @@ const createClient = (fetch: typeof globalThis.fetch) =>
let browserClient: ReturnType<typeof createClient>; let browserClient: ReturnType<typeof createClient>;
export const useTRPC = (fetch = globalThis.fetch) => { export const trpc = (fetch = globalThis.fetch) => {
const client = browserClient ?? createClient(fetch); const client = browserClient ?? createClient(fetch);
if (browser) { if (browser) {
browserClient ??= client; browserClient ??= client;

View File

@@ -108,11 +108,13 @@ const directoryRouter = router({
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
try { try {
const files = await FileRepo.unregisterDirectory(ctx.session.userId, input.id); const files = await FileRepo.unregisterDirectory(ctx.session.userId, input.id);
files.forEach(({ path, thumbnailPath }) => { return {
safeUnlink(path); // Intended deletedFiles: files.map((file) => {
safeUnlink(thumbnailPath); // Intended safeUnlink(file.path); // Intended
}); safeUnlink(file.thumbnailPath); // Intended
return { deletedFiles: files.map(({ id }) => id) }; return file.id;
}),
};
} catch (e) { } catch (e) {
if (e instanceof IntegrityError && e.message === "Directory not found") { if (e instanceof IntegrityError && e.message === "Directory not found") {
throw new TRPCError({ code: "NOT_FOUND", message: "Invalid directory id" }); throw new TRPCError({ code: "NOT_FOUND", message: "Invalid directory id" });

View File

@@ -115,6 +115,7 @@ const fileRouter = router({
if (!thumbnail) { if (!thumbnail) {
throw new TRPCError({ code: "NOT_FOUND", message: "File or its thumbnail not found" }); throw new TRPCError({ code: "NOT_FOUND", message: "File or its thumbnail not found" });
} }
return { updatedAt: thumbnail.updatedAt, contentIv: thumbnail.encContentIv }; return { updatedAt: thumbnail.updatedAt, contentIv: thumbnail.encContentIv };
}), }),
}); });