diff --git a/server/api/v1/admin/auth/invitation/index.delete.ts b/server/api/v1/admin/auth/invitation/index.delete.ts index 4e8760c..195aae5 100644 --- a/server/api/v1/admin/auth/invitation/index.delete.ts +++ b/server/api/v1/admin/auth/invitation/index.delete.ts @@ -1,5 +1,5 @@ import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; @@ -15,7 +15,7 @@ export default defineEventHandler<{ ]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, DeleteInvite); + const body = await readDropValidatedBody(h3, DeleteInvite); await prisma.invitation.delete({ where: { id: body.id } }); return {}; diff --git a/server/api/v1/admin/auth/invitation/index.post.ts b/server/api/v1/admin/auth/invitation/index.post.ts index 2ae9415..90ad5e7 100644 --- a/server/api/v1/admin/auth/invitation/index.post.ts +++ b/server/api/v1/admin/auth/invitation/index.post.ts @@ -1,5 +1,5 @@ import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; @@ -18,7 +18,7 @@ export default defineEventHandler<{ ]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, CreateInvite); + const body = await readDropValidatedBody(h3, CreateInvite); const invitation = await prisma.invitation.create({ data: body, diff --git a/server/api/v1/admin/game/image/index.delete.ts b/server/api/v1/admin/game/image/index.delete.ts index fe9a650..d89ae76 100644 --- a/server/api/v1/admin/game/image/index.delete.ts +++ b/server/api/v1/admin/game/image/index.delete.ts @@ -2,7 +2,7 @@ import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; import objectHandler from "~/server/internal/objects"; import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; const DeleteGameImage = type({ gameId: "string", @@ -15,7 +15,7 @@ export default defineEventHandler<{ const allowed = await aclManager.allowSystemACL(h3, ["game:image:delete"]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, DeleteGameImage); + const body = await readDropValidatedBody(h3, DeleteGameImage); const gameId = body.gameId; const imageId = body.imageId; diff --git a/server/api/v1/admin/game/version/index.delete.ts b/server/api/v1/admin/game/version/index.delete.ts index 08d182b..caf4242 100644 --- a/server/api/v1/admin/game/version/index.delete.ts +++ b/server/api/v1/admin/game/version/index.delete.ts @@ -1,5 +1,5 @@ import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; @@ -15,7 +15,7 @@ export default defineEventHandler<{ body: typeof DeleteVersion }>( ]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, DeleteVersion); + const body = await readDropValidatedBody(h3, DeleteVersion); const gameId = body.id.toString(); const version = body.versionName.toString(); diff --git a/server/api/v1/admin/game/version/index.patch.ts b/server/api/v1/admin/game/version/index.patch.ts index 009c502..3833840 100644 --- a/server/api/v1/admin/game/version/index.patch.ts +++ b/server/api/v1/admin/game/version/index.patch.ts @@ -1,5 +1,5 @@ import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; @@ -15,7 +15,7 @@ export default defineEventHandler<{ body: typeof UpdateVersionOrder }>( ]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, UpdateVersionOrder); + const body = await readDropValidatedBody(h3, UpdateVersionOrder); const gameId = body.id; // We expect an array of the version names for this game const versions = body.versions; diff --git a/server/api/v1/admin/import/game/index.post.ts b/server/api/v1/admin/import/game/index.post.ts index 6123346..4d4bd5b 100644 --- a/server/api/v1/admin/import/game/index.post.ts +++ b/server/api/v1/admin/import/game/index.post.ts @@ -1,5 +1,5 @@ import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import libraryManager from "~/server/internal/library"; import metadataHandler from "~/server/internal/metadata"; @@ -19,7 +19,7 @@ export default defineEventHandler<{ body: typeof ImportGameBody.infer }>( const allowed = await aclManager.allowSystemACL(h3, ["import:game:new"]); if (!allowed) throw createError({ statusCode: 403 }); - const { library, path, metadata } = await readValidatedBody( + const { library, path, metadata } = await readDropValidatedBody( h3, ImportGameBody, ); diff --git a/server/api/v1/admin/import/version/index.post.ts b/server/api/v1/admin/import/version/index.post.ts index d52042b..8faf0d1 100644 --- a/server/api/v1/admin/import/version/index.post.ts +++ b/server/api/v1/admin/import/version/index.post.ts @@ -1,4 +1,5 @@ import { type } from "arktype"; +import { readDropValidatedBody } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; import libraryManager from "~/server/internal/library"; @@ -33,7 +34,7 @@ export default defineEventHandler(async (h3) => { onlySetup, delta, umuId, - } = await readValidatedBody(h3, ImportVersion); + } = await readDropValidatedBody(h3, ImportVersion); const platformParsed = parsePlatform(platform); if (!platformParsed) diff --git a/server/api/v1/admin/library/sources/index.delete.ts b/server/api/v1/admin/library/sources/index.delete.ts index eaef699..d852041 100644 --- a/server/api/v1/admin/library/sources/index.delete.ts +++ b/server/api/v1/admin/library/sources/index.delete.ts @@ -1,5 +1,5 @@ import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; @@ -14,7 +14,7 @@ export default defineEventHandler<{ body: typeof DeleteLibrarySource.infer }>( ]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, DeleteLibrarySource); + const body = await readDropValidatedBody(h3, DeleteLibrarySource); return await prisma.library.delete({ where: { diff --git a/server/api/v1/admin/library/sources/index.patch.ts b/server/api/v1/admin/library/sources/index.patch.ts index 43dbeb5..be0ccc7 100644 --- a/server/api/v1/admin/library/sources/index.patch.ts +++ b/server/api/v1/admin/library/sources/index.patch.ts @@ -1,5 +1,5 @@ import { type } from "arktype"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; import libraryManager from "~/server/internal/library"; @@ -19,7 +19,7 @@ export default defineEventHandler<{ body: typeof UpdateLibrarySource.infer }>( ]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, UpdateLibrarySource); + const body = await readDropValidatedBody(h3, UpdateLibrarySource); const source = await prisma.library.findUnique({ where: { id: body.id } }); if (!source) diff --git a/server/api/v1/admin/library/sources/index.post.ts b/server/api/v1/admin/library/sources/index.post.ts index e44c5bd..f8522b4 100644 --- a/server/api/v1/admin/library/sources/index.post.ts +++ b/server/api/v1/admin/library/sources/index.post.ts @@ -1,7 +1,7 @@ import { type } from "arktype"; import { randomUUID } from "crypto"; import { LibraryBackend } from "~/prisma/client"; -import { throwingArktype } from "~/server/arktype"; +import { readDropValidatedBody, throwingArktype } from "~/server/arktype"; import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; import libraryManager from "~/server/internal/library"; @@ -21,7 +21,7 @@ export default defineEventHandler<{ body: typeof CreateLibrarySource.infer }>( ]); if (!allowed) throw createError({ statusCode: 403 }); - const body = await readValidatedBody(h3, CreateLibrarySource); + const body = await readDropValidatedBody(h3, CreateLibrarySource); const backend = Object.values(LibraryBackend).find( (e) => e == body.backend, ); diff --git a/server/arktype.ts b/server/arktype.ts index 667c3d6..6a9316b 100644 --- a/server/arktype.ts +++ b/server/arktype.ts @@ -1,4 +1,6 @@ +import { ArkErrors } from "arktype"; import { configure } from "arktype/config"; +import type { H3Event } from "h3"; export const throwingArktype = configure({ onFail: (errors) => errors.throw(), @@ -12,3 +14,24 @@ declare global { onFail: typeof throwingArktype.onFail; } } + +export async function readDropValidatedBody( + event: H3Event, + validate: (data: object) => T, +): Promise { + const _body = await readBody(event); + try { + return validate(_body); + } catch (e) { + if (e instanceof ArkErrors) { + throw createError({ + statusCode: 400, + statusMessage: `Invalid request body: ${e.summary}`, + }); + } + throw createError({ + statusCode: 400, + statusMessage: `Invalid request body: ${e}`, + }); + } +}