diff --git a/src/lib/hooks/callAPI.ts b/src/lib/hooks/callAPI.ts deleted file mode 100644 index 9edc9e4..0000000 --- a/src/lib/hooks/callAPI.ts +++ /dev/null @@ -1,15 +0,0 @@ -export const refreshToken = async () => { - return await fetch("/api/auth/refreshToken", { method: "POST" }); -}; - -export const callAPI = async (input: RequestInfo, init?: RequestInit) => { - let res = await fetch(input, init); - if (res.status === 401) { - res = await refreshToken(); - if (!res.ok) { - return res; - } - res = await fetch(input, init); - } - return res; -}; diff --git a/src/lib/hooks/callApi.ts b/src/lib/hooks/callApi.ts new file mode 100644 index 0000000..7189735 --- /dev/null +++ b/src/lib/hooks/callApi.ts @@ -0,0 +1,41 @@ +import { signRequest } from "$lib/modules/crypto"; + +export const refreshToken = async () => { + return await fetch("/api/auth/refreshToken", { method: "POST" }); +}; + +const callApi = async (input: RequestInfo, init?: RequestInit) => { + let res = await fetch(input, init); + if (res.status === 401) { + res = await refreshToken(); + if (!res.ok) { + return res; + } + res = await fetch(input, init); + } + return res; +}; + +export const callGetApi = async (input: RequestInfo) => { + return await callApi(input); +}; + +export const callPostApi = async (input: RequestInfo, payload: T) => { + return await callApi(input, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + }); +}; + +export const callSignedPostApi = async (input: RequestInfo, payload: T, signKey: CryptoKey) => { + return await callApi(input, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: await signRequest(payload, signKey), + }); +}; diff --git a/src/lib/hooks/index.ts b/src/lib/hooks/index.ts index e2f0392..e3b8dde 100644 --- a/src/lib/hooks/index.ts +++ b/src/lib/hooks/index.ts @@ -1,2 +1,2 @@ -export { callAPI } from "./callAPI"; -export { gotoStateful } from "./gotoStateful"; +export * from "./callApi"; +export * from "./gotoStateful"; diff --git a/src/lib/server/schemas/auth.ts b/src/lib/server/schemas/auth.ts new file mode 100644 index 0000000..220b029 --- /dev/null +++ b/src/lib/server/schemas/auth.ts @@ -0,0 +1,24 @@ +import { z } from "zod"; + +export const loginRequest = z.object({ + email: z.string().email().nonempty(), + password: z.string().trim().nonempty(), +}); +export type LoginRequest = z.infer; + +export const tokenUpgradeRequest = z.object({ + encPubKey: z.string().base64().nonempty(), + sigPubKey: z.string().base64().nonempty(), +}); +export type TokenUpgradeRequest = z.infer; + +export const tokenUpgradeResponse = z.object({ + challenge: z.string().base64().nonempty(), +}); +export type TokenUpgradeResponse = z.infer; + +export const tokenUpgradeVerifyRequest = z.object({ + answer: z.string().base64().nonempty(), + sigAnswer: z.string().base64().nonempty(), +}); +export type TokenUpgradeVerifyRequest = z.infer; diff --git a/src/lib/server/schemas/client.ts b/src/lib/server/schemas/client.ts new file mode 100644 index 0000000..8bda49e --- /dev/null +++ b/src/lib/server/schemas/client.ts @@ -0,0 +1,35 @@ +import { z } from "zod"; + +export const clientListResponse = z.object({ + clients: z.array( + z.object({ + id: z.number().int().positive(), + state: z.enum(["pending", "active"]), + }), + ), +}); +export type ClientListResponse = z.infer; + +export const clientRegisterRequest = z.object({ + encPubKey: z.string().base64().nonempty(), + sigPubKey: z.string().base64().nonempty(), +}); +export type ClientRegisterRequest = z.infer; + +export const clientRegisterResponse = z.object({ + challenge: z.string().base64().nonempty(), +}); +export type ClientRegisterResponse = z.infer; + +export const clientRegisterVerifyRequest = z.object({ + answer: z.string().base64().nonempty(), + sigAnswer: z.string().base64().nonempty(), +}); +export type ClientRegisterVerifyRequest = z.infer; + +export const clientStatusResponse = z.object({ + id: z.number().int().positive(), + state: z.enum(["pending", "active"]), + isInitialMekNeeded: z.boolean(), +}); +export type ClientStatusResponse = z.infer; diff --git a/src/lib/server/schemas/directory.ts b/src/lib/server/schemas/directory.ts new file mode 100644 index 0000000..1c2f6c1 --- /dev/null +++ b/src/lib/server/schemas/directory.ts @@ -0,0 +1,27 @@ +import { z } from "zod"; + +export const directroyEntriesResponse = z.object({ + metadata: z + .object({ + createdAt: z.date(), + mekVersion: z.number().int().positive(), + dek: z.string().base64().nonempty(), + dekIv: z.string().base64().nonempty(), + name: z.string().base64().nonempty(), + nameIv: z.string().base64().nonempty(), + }) + .optional(), + subDirectories: z.number().int().positive().array(), + files: z.number().int().positive().array(), +}); +export type DirectroyEntriesResponse = z.infer; + +export const directoryCreateRequest = z.object({ + parentId: z.union([z.enum(["root"]), z.number().int().positive()]), + mekVersion: z.number().int().positive(), + dek: z.string().base64().nonempty(), + dekIv: z.string().base64().nonempty(), + name: z.string().base64().nonempty(), + nameIv: z.string().base64().nonempty(), +}); +export type DirectoryCreateRequest = z.infer; diff --git a/src/lib/server/schemas/index.ts b/src/lib/server/schemas/index.ts new file mode 100644 index 0000000..0328467 --- /dev/null +++ b/src/lib/server/schemas/index.ts @@ -0,0 +1,4 @@ +export * from "./auth"; +export * from "./client"; +export * from "./directory"; +export * from "./mek"; diff --git a/src/lib/server/schemas/mek.ts b/src/lib/server/schemas/mek.ts new file mode 100644 index 0000000..e79f810 --- /dev/null +++ b/src/lib/server/schemas/mek.ts @@ -0,0 +1,19 @@ +import { z } from "zod"; + +export const masterKeyListResponse = z.object({ + meks: z.array( + z.object({ + version: z.number().int().positive(), + state: z.enum(["active", "retired"]), + mek: z.string().base64().nonempty(), + mekSig: z.string().base64().nonempty(), + }), + ), +}); +export type MasterKeyListResponse = z.infer; + +export const initialMasterKeyRegisterRequest = z.object({ + mek: z.string().base64().nonempty(), + mekSig: z.string().base64().nonempty(), +}); +export type InitialMasterKeyRegisterRequest = z.infer; diff --git a/src/lib/server/services/client.ts b/src/lib/server/services/client.ts index 8893973..004ef1a 100644 --- a/src/lib/server/services/client.ts +++ b/src/lib/server/services/client.ts @@ -8,7 +8,6 @@ import { createUserClient, getAllUserClients, getUserClient, - getUserClientWithDetails, setUserClientStateToPending, registerUserClientChallenge, getUserClientChallenge, @@ -18,15 +17,6 @@ import { verifyPubKey, verifySignature, generateChallenge } from "$lib/server/mo import { isInitialMekNeeded } from "$lib/server/modules/mek"; import env from "$lib/server/loadenv"; -export const getUserClientEncPubKey = async (userId: number, clientId: number) => { - const userClient = await getUserClientWithDetails(userId, clientId); - if (!userClient || userClient.user_client.state === "challenging") { - error(400, "Invalid client ID"); - } - - return { encPubKey: userClient.client.encPubKey }; -}; - export const getUserClientList = async (userId: number) => { const userClients = await getAllUserClients(userId); return { diff --git a/src/lib/server/services/mek.ts b/src/lib/server/services/mek.ts index 9fc0452..94babfe 100644 --- a/src/lib/server/services/mek.ts +++ b/src/lib/server/services/mek.ts @@ -6,11 +6,11 @@ import { isInitialMekNeeded, verifyClientEncMekSig } from "$lib/server/modules/m export const getClientMekList = async (userId: number, clientId: number) => { const clientMeks = await getAllValidClientMeks(userId, clientId); return { - meks: clientMeks.map((clientMek) => ({ + encMeks: clientMeks.map((clientMek) => ({ version: clientMek.master_encryption_key.version, state: clientMek.master_encryption_key.state, - mek: clientMek.client_master_encryption_key.encMek, - mekSig: clientMek.client_master_encryption_key.encMekSig, + encMek: clientMek.client_master_encryption_key.encMek, + encMekSig: clientMek.client_master_encryption_key.encMekSig, })), }; }; diff --git a/src/lib/services/auth.ts b/src/lib/services/auth.ts index 865b056..7a0936b 100644 --- a/src/lib/services/auth.ts +++ b/src/lib/services/auth.ts @@ -4,6 +4,11 @@ import { decryptRSACiphertext, signRSAMessage, } from "$lib/modules/crypto"; +import type { + TokenUpgradeRequest, + TokenUpgradeResponse, + TokenUpgradeVerifyRequest, +} from "$lib/server/schemas"; export const requestTokenUpgrade = async ( encryptKeyBase64: string, @@ -19,11 +24,11 @@ export const requestTokenUpgrade = async ( body: JSON.stringify({ encPubKey: encryptKeyBase64, sigPubKey: verifyKeyBase64, - }), + } satisfies TokenUpgradeRequest), }); if (!res.ok) return false; - const { challenge } = await res.json(); + const { challenge }: TokenUpgradeResponse = await res.json(); const answer = await decryptRSACiphertext(decodeFromBase64(challenge), decryptKey); const sigAnswer = await signRSAMessage(answer, signKey); @@ -35,7 +40,7 @@ export const requestTokenUpgrade = async ( body: JSON.stringify({ answer: encodeToBase64(answer), sigAnswer: encodeToBase64(sigAnswer), - }), + } satisfies TokenUpgradeVerifyRequest), }); return res.ok; }; diff --git a/src/lib/services/key.ts b/src/lib/services/key.ts index 2eba920..2a38a5a 100644 --- a/src/lib/services/key.ts +++ b/src/lib/services/key.ts @@ -1,4 +1,4 @@ -import { callAPI } from "$lib/hooks"; +import { callGetApi, callPostApi } from "$lib/hooks"; import { storeMasterKeys } from "$lib/indexedDB"; import { encodeToBase64, @@ -9,6 +9,12 @@ import { unwrapAESKeyUsingRSA, verifyMasterKeyWrappedSig, } from "$lib/modules/crypto"; +import type { + ClientRegisterRequest, + ClientRegisterResponse, + ClientRegisterVerifyRequest, + MasterKeyListResponse, +} from "$lib/server/schemas"; import { masterKeyStore } from "$lib/stores"; export const requestClientRegistration = async ( @@ -17,49 +23,28 @@ export const requestClientRegistration = async ( verifyKeyBase64: string, signKey: CryptoKey, ) => { - let res = await callAPI("/api/client/register", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - encPubKey: encryptKeyBase64, - sigPubKey: verifyKeyBase64, - }), + let res = await callPostApi("/api/client/register", { + encPubKey: encryptKeyBase64, + sigPubKey: verifyKeyBase64, }); if (!res.ok) return false; - const { challenge } = await res.json(); + const { challenge }: ClientRegisterResponse = await res.json(); const answer = await decryptRSACiphertext(decodeFromBase64(challenge), decryptKey); const sigAnswer = await signRSAMessage(answer, signKey); - res = await callAPI("/api/client/register/verify", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - answer: encodeToBase64(answer), - sigAnswer: encodeToBase64(sigAnswer), - }), + res = await callPostApi("/api/client/register/verify", { + answer: encodeToBase64(answer), + sigAnswer: encodeToBase64(sigAnswer), }); return res.ok; }; export const requestMasterKeyDownload = async (decryptKey: CryptoKey, verfiyKey: CryptoKey) => { - const res = await callAPI("/api/mek/list", { method: "GET" }); + const res = await callGetApi("/api/mek/list"); if (!res.ok) return false; - const data = await res.json(); - const { meks: masterKeysWrapped } = data as { - meks: { - version: number; - state: "active" | "retired"; - mek: string; - mekSig: string; - }[]; - }; - + const { meks: masterKeysWrapped }: MasterKeyListResponse = await res.json(); const masterKeys = await Promise.all( masterKeysWrapped.map( async ({ version, state, mek: masterKeyWrapped, mekSig: masterKeyWrappedSig }) => ({ diff --git a/src/routes/(fullscreen)/auth/login/+page.svelte b/src/routes/(fullscreen)/auth/login/+page.svelte index c86a483..9ab6c0c 100644 --- a/src/routes/(fullscreen)/auth/login/+page.svelte +++ b/src/routes/(fullscreen)/auth/login/+page.svelte @@ -4,7 +4,7 @@ import { Button, TextButton } from "$lib/components/buttons"; import { TitleDiv, BottomDiv } from "$lib/components/divs"; import { TextInput } from "$lib/components/inputs"; - import { refreshToken } from "$lib/hooks/callAPI"; + import { refreshToken } from "$lib/hooks/callApi"; import { clientKeyStore, masterKeyStore } from "$lib/stores"; import { requestLogin, requestTokenUpgrade, requestMasterKeyDownload } from "./service"; diff --git a/src/routes/(fullscreen)/auth/login/service.ts b/src/routes/(fullscreen)/auth/login/service.ts index e9002af..0227edc 100644 --- a/src/routes/(fullscreen)/auth/login/service.ts +++ b/src/routes/(fullscreen)/auth/login/service.ts @@ -1,4 +1,5 @@ import { exportRSAKeyToBase64 } from "$lib/modules/crypto"; +import type { LoginRequest } from "$lib/server/schemas"; import { requestTokenUpgrade as requestTokenUpgradeInternal } from "$lib/services/auth"; import { requestClientRegistration } from "$lib/services/key"; import type { ClientKeys } from "$lib/stores"; @@ -11,7 +12,7 @@ export const requestLogin = async (email: string, password: string) => { headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ email, password }), + body: JSON.stringify({ email, password } satisfies LoginRequest), }); return res.ok; }; diff --git a/src/routes/(fullscreen)/key/export/service.ts b/src/routes/(fullscreen)/key/export/service.ts index cc8e7be..fd1fadd 100644 --- a/src/routes/(fullscreen)/key/export/service.ts +++ b/src/routes/(fullscreen)/key/export/service.ts @@ -1,6 +1,7 @@ -import { callAPI } from "$lib/hooks"; +import { callSignedPostApi } from "$lib/hooks"; import { storeClientKey } from "$lib/indexedDB"; -import { encodeToBase64, signRequest, signMasterKeyWrapped } from "$lib/modules/crypto"; +import { encodeToBase64, signMasterKeyWrapped } from "$lib/modules/crypto"; +import type { InitialMasterKeyRegisterRequest } from "$lib/server/schemas"; import type { ClientKeys } from "$lib/stores"; export { requestTokenUpgrade } from "$lib/services/auth"; @@ -45,18 +46,13 @@ export const requestInitialMasterKeyRegistration = async ( masterKeyWrapped: ArrayBuffer, signKey: CryptoKey, ) => { - const res = await callAPI("/api/mek/register/initial", { - method: "POST", - headers: { - "Content-Type": "application/json", + const res = await callSignedPostApi( + "/api/mek/register/initial", + { + mek: encodeToBase64(masterKeyWrapped), + mekSig: await signMasterKeyWrapped(1, masterKeyWrapped, signKey), }, - body: await signRequest( - { - mek: encodeToBase64(masterKeyWrapped), - mekSig: await signMasterKeyWrapped(1, masterKeyWrapped, signKey), - }, - signKey, - ), - }); + signKey, + ); return res.ok || res.status === 409; }; diff --git a/src/routes/api/auth/login/+server.ts b/src/routes/api/auth/login/+server.ts index ec4f254..9f652df 100644 --- a/src/routes/api/auth/login/+server.ts +++ b/src/routes/api/auth/login/+server.ts @@ -1,17 +1,12 @@ import { error, text } from "@sveltejs/kit"; import ms from "ms"; -import { z } from "zod"; import env from "$lib/server/loadenv"; +import { loginRequest } from "$lib/server/schemas/auth"; import { login } from "$lib/server/services/auth"; import type { RequestHandler } from "./$types"; export const POST: RequestHandler = async ({ request, cookies }) => { - const zodRes = z - .object({ - email: z.string().email().nonempty(), - password: z.string().trim().nonempty(), - }) - .safeParse(await request.json()); + const zodRes = loginRequest.safeParse(await request.json()); if (!zodRes.success) error(400, "Invalid request body"); const { email, password } = zodRes.data; diff --git a/src/routes/api/auth/upgradeToken/+server.ts b/src/routes/api/auth/upgradeToken/+server.ts index 90c5e60..99b987d 100644 --- a/src/routes/api/auth/upgradeToken/+server.ts +++ b/src/routes/api/auth/upgradeToken/+server.ts @@ -1,5 +1,5 @@ import { error, json } from "@sveltejs/kit"; -import { z } from "zod"; +import { tokenUpgradeRequest, tokenUpgradeResponse } from "$lib/server/schemas/auth"; import { createTokenUpgradeChallenge } from "$lib/server/services/auth"; import type { RequestHandler } from "./$types"; @@ -7,12 +7,7 @@ export const POST: RequestHandler = async ({ request, cookies, getClientAddress const token = cookies.get("refreshToken"); if (!token) error(401, "Refresh token not found"); - const zodRes = z - .object({ - encPubKey: z.string().base64().nonempty(), - sigPubKey: z.string().base64().nonempty(), - }) - .safeParse(await request.json()); + const zodRes = tokenUpgradeRequest.safeParse(await request.json()); if (!zodRes.success) error(400, "Invalid request body"); const { encPubKey, sigPubKey } = zodRes.data; @@ -22,5 +17,5 @@ export const POST: RequestHandler = async ({ request, cookies, getClientAddress encPubKey, sigPubKey, ); - return json({ challenge }); + return json(tokenUpgradeResponse.parse({ challenge })); }; diff --git a/src/routes/api/auth/upgradeToken/verify/+server.ts b/src/routes/api/auth/upgradeToken/verify/+server.ts index ca72695..84f8e82 100644 --- a/src/routes/api/auth/upgradeToken/verify/+server.ts +++ b/src/routes/api/auth/upgradeToken/verify/+server.ts @@ -1,5 +1,5 @@ import { error, text } from "@sveltejs/kit"; -import { z } from "zod"; +import { tokenUpgradeVerifyRequest } from "$lib/server/schemas/auth"; import { upgradeToken } from "$lib/server/services/auth"; import type { RequestHandler } from "./$types"; @@ -7,12 +7,7 @@ export const POST: RequestHandler = async ({ request, cookies, getClientAddress const token = cookies.get("refreshToken"); if (!token) error(401, "Refresh token not found"); - const zodRes = z - .object({ - answer: z.string().base64().nonempty(), - sigAnswer: z.string().base64().nonempty(), - }) - .safeParse(await request.json()); + const zodRes = tokenUpgradeVerifyRequest.safeParse(await request.json()); if (!zodRes.success) error(400, "Invalid request body"); const { answer, sigAnswer } = zodRes.data; diff --git a/src/routes/api/client/[id]/key/+server.ts b/src/routes/api/client/[id]/key/+server.ts deleted file mode 100644 index 8e031f9..0000000 --- a/src/routes/api/client/[id]/key/+server.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { error, json } from "@sveltejs/kit"; -import { z } from "zod"; -import { authorize } from "$lib/server/modules/auth"; -import { getUserClientEncPubKey } from "$lib/server/services/client"; -import type { RequestHandler } from "./$types"; - -export const GET: RequestHandler = async ({ cookies, params }) => { - const { userId } = await authorize(cookies, "activeClient"); - - const zodRes = z - .object({ - id: z.coerce.number().int().positive(), - }) - .safeParse(params); - if (!zodRes.success) error(400, "Invalid path parameters"); - const { id } = zodRes.data; - - const { encPubKey } = await getUserClientEncPubKey(userId, id); - return json({ encPubKey }); -}; diff --git a/src/routes/api/client/list/+server.ts b/src/routes/api/client/list/+server.ts index 7769658..f16124c 100644 --- a/src/routes/api/client/list/+server.ts +++ b/src/routes/api/client/list/+server.ts @@ -1,10 +1,11 @@ import { json } from "@sveltejs/kit"; import { authenticate } from "$lib/server/modules/auth"; +import { clientListResponse } from "$lib/server/schemas/client"; import { getUserClientList } from "$lib/server/services/client"; import type { RequestHandler } from "@sveltejs/kit"; export const GET: RequestHandler = async ({ cookies }) => { const { userId } = authenticate(cookies); const { userClients } = await getUserClientList(userId); - return json({ clients: userClients }); + return json(clientListResponse.parse({ clients: userClients })); }; diff --git a/src/routes/api/client/register/+server.ts b/src/routes/api/client/register/+server.ts index 361f38f..474995c 100644 --- a/src/routes/api/client/register/+server.ts +++ b/src/routes/api/client/register/+server.ts @@ -1,6 +1,6 @@ import { error, json } from "@sveltejs/kit"; -import { z } from "zod"; import { authenticate } from "$lib/server/modules/auth"; +import { clientRegisterRequest, clientRegisterResponse } from "$lib/server/schemas/client"; import { registerUserClient } from "$lib/server/services/client"; import type { RequestHandler } from "./$types"; @@ -10,15 +10,10 @@ export const POST: RequestHandler = async ({ request, cookies, getClientAddress error(403, "Forbidden"); } - const zodRes = z - .object({ - encPubKey: z.string().base64().nonempty(), - sigPubKey: z.string().base64().nonempty(), - }) - .safeParse(await request.json()); + const zodRes = clientRegisterRequest.safeParse(await request.json()); if (!zodRes.success) error(400, "Invalid request body"); const { encPubKey, sigPubKey } = zodRes.data; const { challenge } = await registerUserClient(userId, getClientAddress(), encPubKey, sigPubKey); - return json({ challenge }); + return json(clientRegisterResponse.parse({ challenge })); }; diff --git a/src/routes/api/client/register/verify/+server.ts b/src/routes/api/client/register/verify/+server.ts index 9a34558..a2f2f9c 100644 --- a/src/routes/api/client/register/verify/+server.ts +++ b/src/routes/api/client/register/verify/+server.ts @@ -1,6 +1,6 @@ import { error, text } from "@sveltejs/kit"; -import { z } from "zod"; import { authenticate } from "$lib/server/modules/auth"; +import { clientRegisterVerifyRequest } from "$lib/server/schemas/client"; import { verifyUserClient } from "$lib/server/services/client"; import type { RequestHandler } from "./$types"; @@ -10,12 +10,7 @@ export const POST: RequestHandler = async ({ request, cookies, getClientAddress error(403, "Forbidden"); } - const zodRes = z - .object({ - answer: z.string().base64().nonempty(), - sigAnswer: z.string().base64().nonempty(), - }) - .safeParse(await request.json()); + const zodRes = clientRegisterVerifyRequest.safeParse(await request.json()); if (!zodRes.success) error(400, "Invalid request body"); const { answer, sigAnswer } = zodRes.data; diff --git a/src/routes/api/client/status/+server.ts b/src/routes/api/client/status/+server.ts index dcd12a6..8bd7616 100644 --- a/src/routes/api/client/status/+server.ts +++ b/src/routes/api/client/status/+server.ts @@ -1,5 +1,6 @@ import { error, json } from "@sveltejs/kit"; import { authenticate } from "$lib/server/modules/auth"; +import { clientStatusResponse } from "$lib/server/schemas/client"; import { getUserClientStatus } from "$lib/server/services/client"; import type { RequestHandler } from "@sveltejs/kit"; @@ -10,5 +11,5 @@ export const GET: RequestHandler = async ({ cookies }) => { } const { state, isInitialMekNeeded } = await getUserClientStatus(userId, clientId); - return json({ id: clientId, state, isInitialMekNeeded }); + return json(clientStatusResponse.parse({ id: clientId, state, isInitialMekNeeded })); }; diff --git a/src/routes/api/directory/[id]/+server.ts b/src/routes/api/directory/[id]/+server.ts index 6decc3b..2a68763 100644 --- a/src/routes/api/directory/[id]/+server.ts +++ b/src/routes/api/directory/[id]/+server.ts @@ -1,6 +1,7 @@ import { error, json } from "@sveltejs/kit"; import { z } from "zod"; import { authorize } from "$lib/server/modules/auth"; +import { directroyEntriesResponse } from "$lib/server/schemas/directory"; import { getDirectroyInformation } from "$lib/server/services/file"; import type { RequestHandler } from "./$types"; @@ -16,16 +17,18 @@ export const GET: RequestHandler = async ({ cookies, params }) => { const { id } = zodRes.data; const { metadata, directories, files } = await getDirectroyInformation(userId, id); - return json({ - metadata: metadata && { - createdAt: metadata.createdAt, - mekVersion: metadata.mekVersion, - dek: metadata.encDek.ciphertext, - dekIv: metadata.encDek.iv, - name: metadata.encName.ciphertext, - nameIv: metadata.encName.iv, - }, - subDirectories: directories, - files, - }); + return json( + directroyEntriesResponse.parse({ + metadata: metadata && { + createdAt: metadata.createdAt, + mekVersion: metadata.mekVersion, + dek: metadata.encDek.ciphertext, + dekIv: metadata.encDek.iv, + name: metadata.encName.ciphertext, + nameIv: metadata.encName.iv, + }, + subDirectories: directories, + files, + }), + ); }; diff --git a/src/routes/api/directory/create/+server.ts b/src/routes/api/directory/create/+server.ts index e51ec80..86db802 100644 --- a/src/routes/api/directory/create/+server.ts +++ b/src/routes/api/directory/create/+server.ts @@ -1,7 +1,7 @@ import { text } from "@sveltejs/kit"; -import { z } from "zod"; import { authorize } from "$lib/server/modules/auth"; import { parseSignedRequest } from "$lib/server/modules/crypto"; +import { directoryCreateRequest } from "$lib/server/schemas/directory"; import { createDirectory } from "$lib/server/services/file"; import type { RequestHandler } from "./$types"; @@ -10,14 +10,7 @@ export const POST: RequestHandler = async ({ request, cookies }) => { const { parentId, mekVersion, dek, dekIv, name, nameIv } = await parseSignedRequest( clientId, await request.json(), - z.object({ - parentId: z.union([z.enum(["root"]), z.number().int().positive()]), - mekVersion: z.number().int().positive(), - dek: z.string().base64().nonempty(), - dekIv: z.string().base64().nonempty(), - name: z.string().base64().nonempty(), - nameIv: z.string().base64().nonempty(), - }), + directoryCreateRequest, ); await createDirectory({ diff --git a/src/routes/api/mek/list/+server.ts b/src/routes/api/mek/list/+server.ts index 4801df1..6fcc9f6 100644 --- a/src/routes/api/mek/list/+server.ts +++ b/src/routes/api/mek/list/+server.ts @@ -1,10 +1,20 @@ import { json } from "@sveltejs/kit"; import { authorize } from "$lib/server/modules/auth"; +import { masterKeyListResponse } from "$lib/server/schemas/mek"; import { getClientMekList } from "$lib/server/services/mek"; -import type { RequestHandler } from "@sveltejs/kit"; +import type { RequestHandler } from "./$types"; export const GET: RequestHandler = async ({ cookies }) => { const { userId, clientId } = await authorize(cookies, "activeClient"); - const { meks } = await getClientMekList(userId, clientId); - return json({ meks }); + const { encMeks } = await getClientMekList(userId, clientId); + return json( + masterKeyListResponse.parse({ + meks: encMeks.map(({ version, state, encMek, encMekSig }) => ({ + version, + state, + mek: encMek, + mekSig: encMekSig, + })), + }), + ); }; diff --git a/src/routes/api/mek/register/initial/+server.ts b/src/routes/api/mek/register/initial/+server.ts index a5aa6d9..be1c8ee 100644 --- a/src/routes/api/mek/register/initial/+server.ts +++ b/src/routes/api/mek/register/initial/+server.ts @@ -1,9 +1,9 @@ import { error, text } from "@sveltejs/kit"; -import { z } from "zod"; import { authenticate } from "$lib/server/modules/auth"; import { parseSignedRequest } from "$lib/server/modules/crypto"; +import { initialMasterKeyRegisterRequest } from "$lib/server/schemas/mek"; import { registerInitialActiveMek } from "$lib/server/services/mek"; -import type { RequestHandler } from "@sveltejs/kit"; +import type { RequestHandler } from "./$types"; export const POST: RequestHandler = async ({ request, cookies }) => { const { userId, clientId } = authenticate(cookies); @@ -14,10 +14,7 @@ export const POST: RequestHandler = async ({ request, cookies }) => { const { mek, mekSig } = await parseSignedRequest( clientId, await request.json(), - z.object({ - mek: z.string().base64().nonempty(), - mekSig: z.string().base64().nonempty(), - }), + initialMasterKeyRegisterRequest, ); await registerInitialActiveMek(userId, clientId, mek, mekSig);