feat: partial user platform support + statusMessage -> message

This commit is contained in:
DecDuck
2025-08-27 11:25:23 +10:00
parent 3af00e085e
commit 8efddc07bc
143 changed files with 831 additions and 593 deletions

View File

@ -15,13 +15,13 @@ export default defineEventHandler(async (h3) => {
});
if (!company)
throw createError({ statusCode: 400, statusMessage: "Invalid company id" });
throw createError({ statusCode: 400, message: "Invalid company id" });
const result = await handleFileUpload(h3, {}, ["internal:read"], 1);
if (!result)
throw createError({
statusCode: 400,
statusMessage: "File upload required (multipart form)",
message: "File upload required (multipart form)",
});
const [ids, , pull, dump] = result;
@ -29,7 +29,7 @@ export default defineEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "Upload at least one file.",
message: "Upload at least one file.",
});
try {

View File

@ -20,7 +20,7 @@ export default defineEventHandler(async (h3) => {
if (!body.published && !body.developed)
throw createError({
statusCode: 400,
statusMessage: "Must be related (either developed or published).",
message: "Must be related (either developed or published).",
});
const publisherConnect = body.published

View File

@ -15,13 +15,13 @@ export default defineEventHandler(async (h3) => {
});
if (!company)
throw createError({ statusCode: 400, statusMessage: "Invalid company id" });
throw createError({ statusCode: 400, message: "Invalid company id" });
const result = await handleFileUpload(h3, {}, ["internal:read"], 1);
if (!result)
throw createError({
statusCode: 400,
statusMessage: "File upload required (multipart form)",
message: "File upload required (multipart form)",
});
const [ids, , pull, dump] = result;
@ -29,7 +29,7 @@ export default defineEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "Upload at least one file.",
message: "Upload at least one file.",
});
try {

View File

@ -9,6 +9,6 @@ export default defineEventHandler(async (h3) => {
const company = await prisma.company.deleteMany({ where: { id } });
if (company.count == 0)
throw createError({ statusCode: 404, statusMessage: "Company not found" });
throw createError({ statusCode: 404, message: "Company not found" });
return;
});

View File

@ -23,7 +23,7 @@ export default defineEventHandler(async (h3) => {
},
});
if (!company)
throw createError({ statusCode: 404, statusMessage: "Company not found" });
throw createError({ statusCode: 404, message: "Company not found" });
const games = await prisma.game.findMany({
where: {
OR: [

View File

@ -33,7 +33,7 @@ export default defineEventHandler(async (h3) => {
});
if (!game || !game.libraryId)
throw createError({ statusCode: 404, statusMessage: "Game ID not found" });
throw createError({ statusCode: 404, message: "Game ID not found" });
const unimportedVersions = await libraryManager.fetchUnimportedGameVersions(
game.libraryId,

View File

@ -1,8 +1,14 @@
import { ArkErrors, type } from "arktype";
import type { Prisma } from "~/prisma/client/client";
import aclManager from "~/server/internal/acls";
import prisma from "~/server/internal/db/database";
import { handleFileUpload } from "~/server/internal/utils/handlefileupload";
const UpdateMetadata = type({
name: "string?",
description: "string?",
});
export default defineEventHandler(async (h3) => {
const allowed = await aclManager.allowSystemACL(h3, ["game:update"]);
if (!allowed) throw createError({ statusCode: 403 });
@ -11,7 +17,7 @@ export default defineEventHandler(async (h3) => {
if (!form)
throw createError({
statusCode: 400,
statusMessage: "This endpoint requires multipart form data.",
message: "This endpoint requires multipart form data.",
});
const gameId = getRouterParam(h3, "id")!;
@ -20,20 +26,20 @@ export default defineEventHandler(async (h3) => {
if (!uploadResult)
throw createError({
statusCode: 400,
statusMessage: "Failed to upload file",
message: "Failed to upload file",
});
const [ids, options, pull, dump] = uploadResult;
const id = ids.at(0);
// handleFileUpload reads the rest of the options for us.
const name = options.name;
const description = options.description;
const body = UpdateMetadata(options);
if (body instanceof ArkErrors)
throw createError({ statusCode: 400, message: body.summary });
const updateModel: Prisma.GameUpdateInput = {
mName: name,
mShortDescription: description,
...(body.name ? { mName: body.name } : undefined),
...(body.description ? { mShortDescription: body.description } : undefined),
};
// handle if user uploaded new icon

View File

@ -32,11 +32,11 @@ export default defineEventHandler<{
});
if (!game)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
const imageIndex = game.mImageLibraryObjectIds.findIndex((e) => e == imageId);
if (imageIndex == -1)
throw createError({ statusCode: 400, statusMessage: "Image not found" });
throw createError({ statusCode: 400, message: "Image not found" });
game.mImageLibraryObjectIds.splice(imageIndex, 1);
await objectHandler.deleteAsSystem(imageId);

View File

@ -10,14 +10,14 @@ export default defineEventHandler(async (h3) => {
if (!form)
throw createError({
statusCode: 400,
statusMessage: "This endpoint requires multipart form data.",
message: "This endpoint requires multipart form data.",
});
const uploadResult = await handleFileUpload(h3, {}, ["internal:read"]);
if (!uploadResult)
throw createError({
statusCode: 400,
statusMessage: "Failed to upload file",
message: "Failed to upload file",
});
const [ids, options, pull, dump] = uploadResult;
@ -25,21 +25,21 @@ export default defineEventHandler(async (h3) => {
dump();
throw createError({
statusCode: 400,
statusMessage: "Did not upload a file",
message: "Did not upload a file",
});
}
const gameId = options.id;
const gameId = options.id as string;
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "No game ID attached",
message: "No game ID attached",
});
const hasGame = (await prisma.game.count({ where: { id: gameId } })) != 0;
if (!hasGame) {
dump();
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
}
const result = await prisma.game.update({

View File

@ -27,14 +27,14 @@ export default defineEventHandler<{ body: typeof ImportGameBody.infer }>(
if (!path)
throw createError({
statusCode: 400,
statusMessage: "Path missing from body",
message: "Path missing from body",
});
const valid = await libraryManager.checkUnimportedGamePath(library, path);
if (!valid)
throw createError({
statusCode: 400,
statusMessage: "Invalid library or game.",
message: "Invalid library or game.",
});
const taskId = metadata
@ -44,7 +44,7 @@ export default defineEventHandler<{ body: typeof ImportGameBody.infer }>(
if (!taskId)
throw createError({
statusCode: 400,
statusMessage:
message:
"Duplicate metadata import. Please chose a different game or metadata provider.",
});

View File

@ -8,14 +8,14 @@ export default defineEventHandler(async (h3) => {
const query = getQuery(h3);
const search = query.q?.toString();
if (!search)
throw createError({ statusCode: 400, statusMessage: "Invalid search" });
throw createError({ statusCode: 400, message: "Invalid search" });
const results = await metadataHandler.search(search);
if (results.length == 0)
throw createError({
statusCode: 404,
statusMessage: "No metadata provider returned search results.",
message: "No metadata provider returned search results.",
});
return results;

View File

@ -4,6 +4,7 @@ import { handleFileUpload } from "~/server/internal/utils/handlefileupload";
import * as jdenticon from "jdenticon";
import prisma from "~/server/internal/db/database";
import libraryManager from "~/server/internal/library";
import jsdom from "jsdom";
export const ImportRedist = type({
library: "string",
@ -11,6 +12,12 @@ export const ImportRedist = type({
name: "string",
description: "string",
"platform?": type({
name: "string",
icon: "string",
fileExts: type("string").pipe.try((s) => JSON.parse(s), type("string[]")),
}),
});
export default defineEventHandler(async (h3) => {
@ -18,14 +25,13 @@ export default defineEventHandler(async (h3) => {
if (!allowed) throw createError({ statusCode: 403 });
const body = await handleFileUpload(h3, {}, ["internal:read"], 1);
if (!body)
throw createError({ statusCode: 400, statusMessage: "Body required." });
if (!body) throw createError({ statusCode: 400, message: "Body required." });
const [[id], rawOptions, pull,, add] = body;
const [[id], rawOptions, pull, , add] = body;
const options = ImportRedist(rawOptions);
if (options instanceof ArkErrors)
throw createError({ statusCode: 400, statusMessage: options.summary });
throw createError({ statusCode: 400, message: options.summary });
const valid = await libraryManager.checkUnimportedGamePath(
options.library,
@ -34,11 +40,25 @@ export default defineEventHandler(async (h3) => {
if (!valid)
throw createError({
statusCode: 400,
statusMessage: "Invalid library or game.",
message: "Invalid library or game.",
});
const icon = id ?? add(jdenticon.toPng(options.name, 512));
let svgContent = "";
if (options.platform) {
const dom = new jsdom.JSDOM(options.platform.icon);
const svg = dom.window.document.getElementsByTagName("svg").item(0);
if (!svg)
throw createError({
statusCode: 400,
statusMessage: "No SVG in uploaded image.",
});
svg.removeAttribute("width");
svg.removeAttribute("height");
svgContent = svg.outerHTML;
}
const redist = await prisma.redist.create({
data: {
libraryId: options.library,
@ -47,6 +67,18 @@ export default defineEventHandler(async (h3) => {
mName: options.name,
mShortDescription: options.description,
mIconObjectId: icon,
platform: {
...(options.platform
? {
create: {
platformName: options.platform.name,
iconSvg: svgContent,
fileExtensions: options.platform.fileExts,
},
}
: undefined),
},
},
});

View File

@ -11,7 +11,7 @@ export default defineEventHandler(async (h3) => {
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "Missing id in request params",
message: "Missing id in request params",
});
const game = await prisma.game.findUnique({
@ -19,14 +19,14 @@ export default defineEventHandler(async (h3) => {
select: { libraryId: true, libraryPath: true },
});
if (!game || !game.libraryId)
throw createError({ statusCode: 404, statusMessage: "Game not found" });
throw createError({ statusCode: 404, message: "Game not found" });
const unimportedVersions = await libraryManager.fetchUnimportedGameVersions(
game.libraryId,
game.libraryPath,
);
if (!unimportedVersions)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
return unimportedVersions;
});

View File

@ -5,6 +5,13 @@ import aclManager from "~/server/internal/acls";
import prisma from "~/server/internal/db/database";
import libraryManager from "~/server/internal/library";
export const LaunchCommands = type({
name: "string > 0",
description: "string = ''",
launchCommand: "string > 0",
launchArgs: "string = ''",
}).array();
export const ImportVersion = type({
id: "string",
version: "string",
@ -17,12 +24,7 @@ export const ImportVersion = type({
delta: "boolean = false",
umuId: "string = ''",
launches: type({
name: "string > 0",
description: "string = ''",
launchCommand: "string > 0",
launchArgs: "string = ''",
}).array(),
launches: LaunchCommands,
}).configure(throwingArktype);
export default defineEventHandler(async (h3) => {
@ -41,7 +43,7 @@ export default defineEventHandler(async (h3) => {
if (validOverlayVersions == 0)
throw createError({
statusCode: 400,
statusMessage:
message:
"Update mode requires a pre-existing version for this platform.",
});
}
@ -50,13 +52,13 @@ export default defineEventHandler(async (h3) => {
if (!body.setup)
throw createError({
statusCode: 400,
statusMessage: 'Setup required in "setup mode".',
message: 'Setup required in "setup mode".',
});
} else {
if (!body.delta && body.launches.length == 0)
throw createError({
statusCode: 400,
statusMessage:
message:
"At least one launch command is required for non-delta versions",
});
}
@ -70,7 +72,7 @@ export default defineEventHandler(async (h3) => {
if (!taskId)
throw createError({
statusCode: 400,
statusMessage: "Invalid options for import",
message: "Invalid options for import",
});
return { taskId: taskId };

View File

@ -11,7 +11,7 @@ export default defineEventHandler(async (h3) => {
if (!gameId || !versionName)
throw createError({
statusCode: 400,
statusMessage: "Missing id or version in request params",
message: "Missing id or version in request params",
});
const preload = await libraryManager.fetchUnimportedVersionInformation(
@ -21,7 +21,7 @@ export default defineEventHandler(async (h3) => {
if (!preload)
throw createError({
statusCode: 400,
statusMessage: "Invalid game or version id/name",
message: "Invalid game or version id/name",
});
return preload;

View File

@ -26,7 +26,7 @@ export default defineEventHandler<{ body: typeof UpdateLibrarySource.infer }>(
if (!source)
throw createError({
statusCode: 400,
statusMessage: "Library source not found",
message: "Library source not found",
});
const constructor = libraryConstructors[source.backend];
@ -61,7 +61,7 @@ export default defineEventHandler<{ body: typeof UpdateLibrarySource.infer }>(
} catch (e) {
throw createError({
statusCode: 400,
statusMessage: `Failed to create source: ${e}`,
message: `Failed to create source: ${e}`,
});
}
},

View File

@ -29,7 +29,7 @@ export default defineEventHandler<{ body: typeof CreateLibrarySource.infer }>(
if (!backend)
throw createError({
statusCode: 400,
statusMessage: "Invalid source backend.",
message: "Invalid source backend.",
});
const constructor = libraryConstructors[backend];
@ -63,7 +63,7 @@ export default defineEventHandler<{ body: typeof CreateLibrarySource.infer }>(
} catch (e) {
throw createError({
statusCode: 400,
statusMessage: `Failed to create source: ${e}`,
message: `Failed to create source: ${e}`,
});
}
},

View File

@ -14,13 +14,13 @@ export default defineEventHandler(async (h3) => {
const orderBy = query.order as "asc" | "desc";
if (orderBy) {
if (typeof orderBy !== "string" || !["asc", "desc"].includes(orderBy))
throw createError({ statusCode: 400, statusMessage: "Invalid order" });
throw createError({ statusCode: 400, message: "Invalid order" });
}
const tags = query.tags as string[] | undefined;
if (tags) {
if (typeof tags !== "object" || !Array.isArray(tags))
throw createError({ statusCode: 400, statusMessage: "Invalid tags" });
throw createError({ statusCode: 400, message: "Invalid tags" });
}
const options = {

View File

@ -19,27 +19,27 @@ export default defineEventHandler(async (h3) => {
if (!form)
throw createError({
statusCode: 400,
statusMessage: "This endpoint requires multipart form data.",
message: "This endpoint requires multipart form data.",
});
const uploadResult = await handleFileUpload(h3, {}, ["internal:read"], 1);
if (!uploadResult)
throw createError({
statusCode: 400,
statusMessage: "Failed to upload file",
message: "Failed to upload file",
});
const [imageIds, options, pull, _dump] = uploadResult;
const body = await CreateNews(options);
if (body instanceof ArkErrors)
throw createError({ statusCode: 400, statusMessage: body.summary });
throw createError({ statusCode: 400, message: body.summary });
const parsedTags = JSON.parse(body.tags);
if (typeof parsedTags !== "object" || !Array.isArray(parsedTags))
throw createError({
statusCode: 400,
statusMessage: "Tags must be an array",
message: "Tags must be an array",
});
const imageId = imageIds.at(0);

View File

@ -9,6 +9,6 @@ export default defineEventHandler(async (h3) => {
const tag = await prisma.gameTag.deleteMany({ where: { id } });
if (tag.count == 0)
throw createError({ statusCode: 404, statusMessage: "Tag not found" });
throw createError({ statusCode: 404, message: "Tag not found" });
return;
});

View File

@ -10,7 +10,7 @@ export default defineEventHandler(async (h3) => {
if (!allAcls)
throw createError({
statusCode: 403,
statusMessage: "Somehow no ACLs on authenticated request.",
message: "Somehow no ACLs on authenticated request.",
});
const runningTasks = (await taskHandler.runningTasks()).map((e) => e.id);

View File

@ -18,14 +18,14 @@ export default defineEventHandler(async (h3) => {
if (!taskGroups[taskGroup])
throw createError({
statusCode: 400,
statusMessage: "Invalid task group.",
message: "Invalid task group.",
});
const task = await taskHandler.runTaskGroupByName(taskGroup);
if (!task)
throw createError({
statusCode: 500,
statusMessage: "Could not start task.",
message: "Could not start task.",
});
return { id: task };
});

View File

@ -10,14 +10,14 @@ export default defineEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "No id in router params",
message: "No id in router params",
});
const deleted = await prisma.aPIToken.delete({
where: { id: id, mode: APITokenMode.System },
})!;
if (!deleted)
throw createError({ statusCode: 404, statusMessage: "Token not found" });
throw createError({ statusCode: 404, message: "Token not found" });
return;
});

View File

@ -22,7 +22,7 @@ export default defineEventHandler(async (h3) => {
if (invalidACLs.length > 0)
throw createError({
statusCode: 400,
statusMessage: `Invalid ACLs: ${invalidACLs.join(", ")}`,
message: `Invalid ACLs: ${invalidACLs.join(", ")}`,
});
const token = await prisma.aPIToken.create({

View File

@ -19,12 +19,12 @@ export default defineEventHandler(async (h3) => {
if (userId === "system")
throw createError({
statusCode: 400,
statusMessage: "Cannot interact with system user.",
message: "Cannot interact with system user.",
});
const user = await prisma.user.findUnique({ where: { id: userId } });
if (!user)
throw createError({ statusCode: 404, statusMessage: "User not found." });
throw createError({ statusCode: 404, message: "User not found." });
await prisma.user.delete({ where: { id: userId } });
return { success: true };

View File

@ -9,18 +9,18 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 400,
statusMessage: "No userId in route.",
message: "No userId in route.",
});
if (userId == "system")
throw createError({
statusCode: 400,
statusMessage: "Cannot fetch system user.",
message: "Cannot fetch system user.",
});
const user = await prisma.user.findUnique({ where: { id: userId } });
if (!user)
throw createError({ statusCode: 404, statusMessage: "User not found." });
throw createError({ statusCode: 404, message: "User not found." });
return user;
});

View File

@ -23,7 +23,7 @@ export default defineEventHandler<{
if (!authManager.getAuthProviders().Simple)
throw createError({
statusCode: 403,
statusMessage: t("errors.auth.method.signinDisabled"),
message: t("errors.auth.method.signinDisabled"),
});
const body = signinValidator(await readBody(h3));
@ -33,7 +33,7 @@ export default defineEventHandler<{
throw createError({
statusCode: 400,
statusMessage: body.summary,
message: body.summary,
});
}
@ -57,13 +57,13 @@ export default defineEventHandler<{
if (!authMek)
throw createError({
statusCode: 401,
statusMessage: t("errors.auth.invalidUserOrPass"),
message: t("errors.auth.invalidUserOrPass"),
});
if (!authMek.user.enabled)
throw createError({
statusCode: 403,
statusMessage: t("errors.auth.disabled"),
message: t("errors.auth.disabled"),
});
// LEGACY bcrypt
@ -74,13 +74,13 @@ export default defineEventHandler<{
if (!hash)
throw createError({
statusCode: 500,
statusMessage: t("errors.auth.invalidPassState"),
message: t("errors.auth.invalidPassState"),
});
if (!(await checkHashBcrypt(body.password, hash)))
throw createError({
statusCode: 401,
statusMessage: t("errors.auth.invalidUserOrPass"),
message: t("errors.auth.invalidUserOrPass"),
});
// TODO: send user to forgot password screen or something to force them to change their password to new system
@ -93,13 +93,13 @@ export default defineEventHandler<{
if (!hash || typeof hash !== "string")
throw createError({
statusCode: 500,
statusMessage: t("errors.auth.invalidPassState"),
message: t("errors.auth.invalidPassState"),
});
if (!(await checkHashArgon2(body.password, hash)))
throw createError({
statusCode: 401,
statusMessage: t("errors.auth.invalidUserOrPass"),
message: t("errors.auth.invalidUserOrPass"),
});
await sessionHandler.signin(h3, authMek.userId, body.rememberMe);

View File

@ -8,7 +8,7 @@ export default defineEventHandler(async (h3) => {
if (!authManager.getAuthProviders().Simple)
throw createError({
statusCode: 403,
statusMessage: t("errors.auth.method.signinDisabled"),
message: t("errors.auth.method.signinDisabled"),
});
const query = getQuery(h3);
@ -16,7 +16,7 @@ export default defineEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: t("errors.auth.inviteIdRequired"),
message: t("errors.auth.inviteIdRequired"),
});
taskHandler.runTaskGroupByName("cleanup:invitations");
@ -24,7 +24,7 @@ export default defineEventHandler(async (h3) => {
if (!invitation)
throw createError({
statusCode: 404,
statusMessage: t("errors.auth.invalidInvite"),
message: t("errors.auth.invalidInvite"),
});
return invitation;

View File

@ -26,7 +26,7 @@ export default defineEventHandler<{
if (!authManager.getAuthProviders().Simple)
throw createError({
statusCode: 403,
statusMessage: t("errors.auth.method.signinDisabled"),
message: t("errors.auth.method.signinDisabled"),
});
const user = await readValidatedBody(h3, CreateUserValidator);
@ -37,7 +37,7 @@ export default defineEventHandler<{
if (!invitation)
throw createError({
statusCode: 401,
statusMessage: t("errors.auth.invalidInvite"),
message: t("errors.auth.invalidInvite"),
});
// reuse items from invite
@ -50,7 +50,7 @@ export default defineEventHandler<{
if (existing > 0)
throw createError({
statusCode: 400,
statusMessage: t("errors.auth.usernameTaken"),
message: t("errors.auth.usernameTaken"),
});
const userId = randomUUID();

View File

@ -12,13 +12,13 @@ export default defineEventHandler(async (h3) => {
if (!client)
throw createError({
statusCode: 400,
statusMessage: "Invalid or expired client ID.",
message: "Invalid or expired client ID.",
});
if (client.userId != user.userId)
throw createError({
statusCode: 403,
statusMessage: "Not allowed to authorize this client.",
message: "Not allowed to authorize this client.",
});
const token = await clientHandler.generateAuthToken(clientId);

View File

@ -10,12 +10,12 @@ export default defineEventHandler(async (h3) => {
if (!code)
throw createError({
statusCode: 400,
statusMessage: "Code required in query params.",
message: "Code required in query params.",
});
const clientId = await clientHandler.fetchClientIdByCode(code);
if (!clientId)
throw createError({ statusCode: 400, statusMessage: "Invalid code." });
throw createError({ statusCode: 400, message: "Invalid code." });
return clientId;
});

View File

@ -12,19 +12,19 @@ export default defineEventHandler(async (h3) => {
if (!client)
throw createError({
statusCode: 400,
statusMessage: "Invalid or expired client ID.",
message: "Invalid or expired client ID.",
});
if (client.userId != user.userId)
throw createError({
statusCode: 403,
statusMessage: "Not allowed to authorize this client.",
message: "Not allowed to authorize this client.",
});
if (!client.peer)
throw createError({
statusCode: 500,
statusMessage: "No client listening for authorization.",
message: "No client listening for authorization.",
});
const token = await clientHandler.generateAuthToken(clientId);

View File

@ -9,14 +9,14 @@ export default defineWebSocketHandler({
if (!code)
throw createError({
statusCode: 400,
statusMessage: "Code required in Authorization header.",
message: "Code required in Authorization header.",
});
await clientHandler.connectCodeListener(code, peer);
} catch (e) {
peer.send(
JSON.stringify({
type: "error",
value: (e as FetchError)?.statusMessage,
value: (e as FetchError)?.message,
}),
);
peer.close();

View File

@ -8,24 +8,24 @@ export default defineEventHandler(async (h3) => {
if (!clientId || !token)
throw createError({
statusCode: 400,
statusMessage: "Missing token or client ID from body",
message: "Missing token or client ID from body",
});
const metadata = await clientHandler.fetchClient(clientId);
if (!metadata)
throw createError({
statusCode: 403,
statusMessage: "Invalid client ID",
message: "Invalid client ID",
});
if (!metadata.authToken || !metadata.userId)
throw createError({
statusCode: 400,
statusMessage: "Un-authorized client ID",
message: "Un-authorized client ID",
});
if (metadata.authToken !== token)
throw createError({
statusCode: 403,
statusMessage: "Invalid token",
message: "Invalid token",
});
const certificateAuthority = useCertificateAuthority();

View File

@ -10,20 +10,20 @@ export default defineEventHandler(async (h3) => {
if (!providedClientId)
throw createError({
statusCode: 400,
statusMessage: "Provide client ID in request params as 'id'",
message: "Provide client ID in request params as 'id'",
});
const client = await clientHandler.fetchClient(providedClientId);
if (!client)
throw createError({
statusCode: 404,
statusMessage: "Request not found.",
message: "Request not found.",
});
if (client.userId && user.userId !== client.userId)
throw createError({
statusCode: 400,
statusMessage: "Client already claimed.",
message: "Client already claimed.",
});
await clientHandler.attachUserId(providedClientId, user.userId);

View File

@ -28,7 +28,7 @@ export default defineEventHandler(async (h3) => {
if (!platform)
throw createError({
statusCode: 400,
statusMessage: "Invalid or unsupported platform",
message: "Invalid or unsupported platform",
});
const capabilityIterable = Object.entries(capabilities) as Array<
@ -42,7 +42,7 @@ export default defineEventHandler(async (h3) => {
)
throw createError({
statusCode: 400,
statusMessage: "Invalid capabilities.",
message: "Invalid capabilities.",
});
if (
@ -57,7 +57,7 @@ export default defineEventHandler(async (h3) => {
)
throw createError({
statusCode: 400,
statusMessage: "Invalid capability configuration.",
message: "Invalid capability configuration.",
});
const result = await clientHandler.initiate({

View File

@ -14,13 +14,13 @@ export default defineClientEventHandler(
if (!rawCapability || typeof rawCapability !== "string")
throw createError({
statusCode: 400,
statusMessage: "capability must be a string",
message: "capability must be a string",
});
if (!configuration || typeof configuration !== "object")
throw createError({
statusCode: 400,
statusMessage: "configuration must be an object",
message: "configuration must be an object",
});
const capability = rawCapability as InternalClientCapability;
@ -28,7 +28,7 @@ export default defineClientEventHandler(
if (!validCapabilities.includes(capability))
throw createError({
statusCode: 400,
statusMessage: "Invalid capability.",
message: "Invalid capability.",
});
const isValid = await capabilityManager.validateCapabilityConfiguration(
@ -38,7 +38,7 @@ export default defineClientEventHandler(
if (!isValid)
throw createError({
statusCode: 400,
statusMessage: "Invalid capability configuration.",
message: "Invalid capability configuration.",
});
await capabilityManager.upsertClientCapability(

View File

@ -20,7 +20,7 @@ export default defineClientEventHandler(async (h3) => {
if (!gameId || !versionName || !filename || Number.isNaN(chunkIndex))
throw createError({
statusCode: 400,
statusMessage: "Invalid chunk arguments",
message: "Invalid chunk arguments",
});
let game = await gameLookupCache.getItem(gameId);
@ -35,7 +35,7 @@ export default defineClientEventHandler(async (h3) => {
},
});
if (!game || !game.libraryId)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
await gameLookupCache.setItem(gameId, game);
}
@ -43,7 +43,7 @@ export default defineClientEventHandler(async (h3) => {
if (!game.libraryId)
throw createError({
statusCode: 500,
statusMessage: "Somehow, we got here.",
message: "Somehow, we got here.",
});
const peek = await libraryManager.peekFile(
@ -53,7 +53,7 @@ export default defineClientEventHandler(async (h3) => {
filename,
);
if (!peek)
throw createError({ status: 400, statusMessage: "Failed to peek file" });
throw createError({ status: 400, message: "Failed to peek file" });
const start = chunkIndex * chunkSize;
const end = Math.min((chunkIndex + 1) * chunkSize, peek.size);
@ -63,7 +63,7 @@ export default defineClientEventHandler(async (h3) => {
if (start >= end)
throw createError({
statusCode: 400,
statusMessage: "Invalid chunk index",
message: "Invalid chunk index",
});
const gameReadStream = await libraryManager.readFile(
@ -76,7 +76,7 @@ export default defineClientEventHandler(async (h3) => {
if (!gameReadStream)
throw createError({
statusCode: 400,
statusMessage: "Failed to create stream",
message: "Failed to create stream",
});
return sendStream(h3, gameReadStream);

View File

@ -8,13 +8,13 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
const body = await readBody(h3);
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
const successful = await userLibraryManager.collectionRemove(
gameId,
@ -24,7 +24,7 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
if (!successful)
throw createError({
statusCode: 404,
statusMessage: "Collection not found",
message: "Collection not found",
});
return {};
});

View File

@ -8,13 +8,13 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
const body = await readBody(h3);
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
return await userLibraryManager.collectionAdd(gameId, id, user.id);
});

View File

@ -8,7 +8,7 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
// Verify collection exists and user owns it
@ -17,13 +17,13 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
if (!collection)
throw createError({
statusCode: 404,
statusMessage: "Collection not found",
message: "Collection not found",
});
if (collection.userId !== user.id)
throw createError({
statusCode: 403,
statusMessage: "Not authorized to delete this collection",
message: "Not authorized to delete this collection",
});
await userLibraryManager.deleteCollection(id);

View File

@ -8,7 +8,7 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
// Fetch specific collection
@ -17,14 +17,14 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
if (!collection)
throw createError({
statusCode: 404,
statusMessage: "Collection not found",
message: "Collection not found",
});
// Verify user owns this collection
if (collection.userId !== user.id)
throw createError({
statusCode: 403,
statusMessage: "Not authorized to access this collection",
message: "Not authorized to access this collection",
});
return collection;

View File

@ -8,7 +8,7 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
await userLibraryManager.libraryRemove(gameId, user.id);
return {};

View File

@ -7,7 +7,7 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
const body = await readBody(h3);
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
// Add the game to the default collection
await userLibraryManager.libraryAdd(gameId, user.id);

View File

@ -8,7 +8,7 @@ export default defineClientEventHandler(async (h3, { fetchUser }) => {
const name = body.name;
if (!name)
throw createError({ statusCode: 400, statusMessage: "Requires name" });
throw createError({ statusCode: 400, message: "Requires name" });
// Create the collection using the manager
const newCollection = await userLibraryManager.collectionCreate(

View File

@ -4,7 +4,7 @@ import prisma from "~/server/internal/db/database";
export default defineClientEventHandler(async (h3) => {
const id = getRouterParam(h3, "id");
if (!id)
throw createError({ statusCode: 400, statusMessage: "No ID in route" });
throw createError({ statusCode: 400, message: "No ID in route" });
const game = await prisma.game.findUnique({
where: {
@ -12,7 +12,7 @@ export default defineClientEventHandler(async (h3) => {
},
});
if (!game)
throw createError({ statusCode: 404, statusMessage: "Game not found" });
throw createError({ statusCode: 404, message: "Game not found" });
return game;
});

View File

@ -7,14 +7,14 @@ export default defineClientEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "Missing version id in query",
message: "Missing version id in query",
});
const manifest = await manifestGenerator.generateManifest(id);
if (!manifest)
throw createError({
statusCode: 400,
statusMessage: "Invalid game or version, or no versions added.",
message: "Invalid game or version, or no versions added.",
});
return manifest;
});

View File

@ -8,7 +8,7 @@ export default defineClientEventHandler(async (h3) => {
if (!id || !version)
throw createError({
statusCode: 400,
statusMessage: "Missing id or version in query",
message: "Missing id or version in query",
});
const gameVersion = await prisma.gameVersion.findUnique({
@ -20,7 +20,7 @@ export default defineClientEventHandler(async (h3) => {
if (!gameVersion)
throw createError({
statusCode: 404,
statusMessage: "Game version not found",
message: "Game version not found",
});
return gameVersion;

View File

@ -7,7 +7,7 @@ export default defineClientEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "No ID in request query",
message: "No ID in request query",
});
const versions = await prisma.gameVersion.findMany({

View File

@ -7,13 +7,13 @@ export default defineClientEventHandler(async (h3) => {
const orderBy = query.order as "asc" | "desc";
if (orderBy) {
if (typeof orderBy !== "string" || !["asc", "desc"].includes(orderBy))
throw createError({ statusCode: 400, statusMessage: "Invalid order" });
throw createError({ statusCode: 400, message: "Invalid order" });
}
const tags = query.tags as string[] | undefined;
if (tags) {
if (typeof tags !== "object" || !Array.isArray(tags))
throw createError({ statusCode: 400, statusMessage: "Invalid tags" });
throw createError({ statusCode: 400, message: "Invalid tags" });
}
const options = {

View File

@ -3,13 +3,13 @@ import objectHandler from "~/server/internal/objects";
export default defineClientEventHandler(async (h3, utils) => {
const id = getRouterParam(h3, "id");
if (!id) throw createError({ statusCode: 400, statusMessage: "Invalid ID" });
if (!id) throw createError({ statusCode: 400, message: "Invalid ID" });
const user = await utils.fetchUser();
const object = await objectHandler.fetchWithPermissions(id, user.id);
if (!object)
throw createError({ statusCode: 404, statusMessage: "Object not found" });
throw createError({ statusCode: 404, message: "Object not found" });
setHeader(h3, "Content-Type", object.mime);
return object.data;

View File

@ -8,27 +8,27 @@ export default defineClientEventHandler(
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
throw createError({
statusCode: 403,
statusMessage: "Capability not allowed.",
message: "Capability not allowed.",
});
const user = await fetchUser();
const gameId = getRouterParam(h3, "gameid");
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "No gameID in route params",
message: "No gameID in route params",
});
const slotIndexString = getRouterParam(h3, "slotindex");
if (!slotIndexString)
throw createError({
statusCode: 400,
statusMessage: "No slotIndex in route params",
message: "No slotIndex in route params",
});
const slotIndex = parseInt(slotIndexString);
if (Number.isNaN(slotIndex))
throw createError({
statusCode: 400,
statusMessage: "Invalid slotIndex",
message: "Invalid slotIndex",
});
const game = await prisma.game.findUnique({
@ -36,7 +36,7 @@ export default defineClientEventHandler(
select: { id: true },
});
if (!game)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
const save = await prisma.saveSlot.delete({
where: {
@ -48,6 +48,6 @@ export default defineClientEventHandler(
},
});
if (!save)
throw createError({ statusCode: 404, statusMessage: "Save not found" });
throw createError({ statusCode: 404, message: "Save not found" });
},
);

View File

@ -8,27 +8,27 @@ export default defineClientEventHandler(
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
throw createError({
statusCode: 403,
statusMessage: "Capability not allowed.",
message: "Capability not allowed.",
});
const user = await fetchUser();
const gameId = getRouterParam(h3, "gameid");
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "No gameID in route params",
message: "No gameID in route params",
});
const slotIndexString = getRouterParam(h3, "slotindex");
if (!slotIndexString)
throw createError({
statusCode: 400,
statusMessage: "No slotIndex in route params",
message: "No slotIndex in route params",
});
const slotIndex = parseInt(slotIndexString);
if (Number.isNaN(slotIndex))
throw createError({
statusCode: 400,
statusMessage: "Invalid slotIndex",
message: "Invalid slotIndex",
});
const game = await prisma.game.findUnique({
@ -36,7 +36,7 @@ export default defineClientEventHandler(
select: { id: true },
});
if (!game)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
const save = await prisma.saveSlot.findUnique({
where: {
@ -48,7 +48,7 @@ export default defineClientEventHandler(
},
});
if (!save)
throw createError({ statusCode: 404, statusMessage: "Save not found" });
throw createError({ statusCode: 404, message: "Save not found" });
return save;
},

View File

@ -9,27 +9,27 @@ export default defineClientEventHandler(
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
throw createError({
statusCode: 403,
statusMessage: "Capability not allowed.",
message: "Capability not allowed.",
});
const user = await fetchUser();
const gameId = getRouterParam(h3, "gameid");
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "No gameID in route params",
message: "No gameID in route params",
});
const slotIndexString = getRouterParam(h3, "slotindex");
if (!slotIndexString)
throw createError({
statusCode: 400,
statusMessage: "No slotIndex in route params",
message: "No slotIndex in route params",
});
const slotIndex = parseInt(slotIndexString);
if (Number.isNaN(slotIndex))
throw createError({
statusCode: 400,
statusMessage: "Invalid slotIndex",
message: "Invalid slotIndex",
});
const game = await prisma.game.findUnique({
@ -37,7 +37,7 @@ export default defineClientEventHandler(
select: { id: true },
});
if (!game)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
await saveManager.pushSave(
gameId,

View File

@ -8,14 +8,14 @@ export default defineClientEventHandler(
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
throw createError({
statusCode: 403,
statusMessage: "Capability not allowed.",
message: "Capability not allowed.",
});
const user = await fetchUser();
const gameId = getRouterParam(h3, "gameid");
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "No gameID in route params",
message: "No gameID in route params",
});
const game = await prisma.game.findUnique({
@ -23,7 +23,7 @@ export default defineClientEventHandler(
select: { id: true },
});
if (!game)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
const saves = await prisma.saveSlot.findMany({
where: {

View File

@ -9,14 +9,14 @@ export default defineClientEventHandler(
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
throw createError({
statusCode: 403,
statusMessage: "Capability not allowed.",
message: "Capability not allowed.",
});
const user = await fetchUser();
const gameId = getRouterParam(h3, "gameid");
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "No gameID in route params",
message: "No gameID in route params",
});
const game = await prisma.game.findUnique({
@ -24,7 +24,7 @@ export default defineClientEventHandler(
select: { id: true },
});
if (!game)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
const saves = await prisma.saveSlot.findMany({
where: {
@ -40,7 +40,7 @@ export default defineClientEventHandler(
if (saves.length + 1 > limit)
throw createError({
statusCode: 400,
statusMessage: "Out of save slots",
message: "Out of save slots",
});
let firstIndex = 0;

View File

@ -8,7 +8,7 @@ export default defineClientEventHandler(
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
throw createError({
statusCode: 403,
statusMessage: "Capability not allowed.",
message: "Capability not allowed.",
});
const user = await fetchUser();

View File

@ -7,7 +7,7 @@ export default defineClientEventHandler(async (_h3, { fetchClient }) => {
if (!client.capabilities.includes(ClientCapabilities.CloudSaves))
throw createError({
statusCode: 403,
statusMessage: "Capability not allowed.",
message: "Capability not allowed.",
});
const slotLimit = await applicationSettings.get("saveSlotCountLimit");

View File

@ -12,13 +12,13 @@ export default defineEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
const body = await readBody(h3);
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
const successful = await userLibraryManager.collectionRemove(
gameId,
@ -28,7 +28,7 @@ export default defineEventHandler(async (h3) => {
if (!successful)
throw createError({
statusCode: 404,
statusMessage: "Collection not found",
message: "Collection not found",
});
return {};
});

View File

@ -12,13 +12,13 @@ export default defineEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
const body = await readBody(h3);
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
return await userLibraryManager.collectionAdd(gameId, id, userId);
});

View File

@ -6,14 +6,14 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 403,
statusMessage: "Requires authentication",
message: "Requires authentication",
});
const id = getRouterParam(h3, "id");
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
// Verify collection exists and user owns it
@ -22,13 +22,13 @@ export default defineEventHandler(async (h3) => {
if (!collection)
throw createError({
statusCode: 404,
statusMessage: "Collection not found",
message: "Collection not found",
});
if (collection.userId !== userId)
throw createError({
statusCode: 403,
statusMessage: "Not authorized to delete this collection",
message: "Not authorized to delete this collection",
});
await userLibraryManager.deleteCollection(id);

View File

@ -6,14 +6,14 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 403,
statusMessage: "Requires authentication",
message: "Requires authentication",
});
const id = getRouterParam(h3, "id");
if (!id)
throw createError({
statusCode: 400,
statusMessage: "ID required in route params",
message: "ID required in route params",
});
// Fetch specific collection
@ -22,14 +22,14 @@ export default defineEventHandler(async (h3) => {
if (!collection)
throw createError({
statusCode: 404,
statusMessage: "Collection not found",
message: "Collection not found",
});
// Verify user owns this collection
if (collection.userId !== userId)
throw createError({
statusCode: 403,
statusMessage: "Not authorized to access this collection",
message: "Not authorized to access this collection",
});
return collection;

View File

@ -6,14 +6,14 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 403,
statusMessage: "Requires authentication",
message: "Requires authentication",
});
const body = await readBody(h3);
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
await userLibraryManager.libraryRemove(gameId, userId);
return {};

View File

@ -6,13 +6,13 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 403,
statusMessage: "Requires authentication",
message: "Requires authentication",
});
const body = await readBody(h3);
const gameId = body.id;
if (!gameId)
throw createError({ statusCode: 400, statusMessage: "Game ID required" });
throw createError({ statusCode: 400, message: "Game ID required" });
// Add the game to the default collection
await userLibraryManager.libraryAdd(gameId, userId);

View File

@ -6,7 +6,7 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 403,
statusMessage: "Requires authentication",
message: "Requires authentication",
});
const collection = await userLibraryManager.fetchLibrary(userId);

View File

@ -12,7 +12,7 @@ export default defineEventHandler(async (h3) => {
const name = body.name;
if (!name)
throw createError({ statusCode: 400, statusMessage: "Requires name" });
throw createError({ statusCode: 400, message: "Requires name" });
// Create the collection using the manager
const newCollection = await userLibraryManager.collectionCreate(name, userId);

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!companyId)
throw createError({
statusCode: 400,
statusMessage: "Missing gameId in route params (somehow...?)",
message: "Missing gameId in route params (somehow...?)",
});
const company = await prisma.company.findUnique({
@ -17,7 +17,7 @@ export default defineEventHandler(async (h3) => {
});
if (!company)
throw createError({ statusCode: 404, statusMessage: "Company not found" });
throw createError({ statusCode: 404, message: "Company not found" });
return { company };
});

View File

@ -9,13 +9,17 @@ export default defineEventHandler(async (h3) => {
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "Missing gameId in route params (somehow...?)",
message: "Missing gameId in route params (somehow...?)",
});
const game = await prisma.game.findUnique({
where: { id: gameId },
include: {
versions: true,
versions: {
include: {
userPlatform: true,
},
},
publishers: {
select: {
id: true,
@ -37,7 +41,7 @@ export default defineEventHandler(async (h3) => {
});
if (!game)
throw createError({ statusCode: 404, statusMessage: "Game not found" });
throw createError({ statusCode: 404, message: "Game not found" });
const rating = await prisma.gameRating.aggregate({
where: {

View File

@ -7,7 +7,7 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 403,
statusMessage: "Requires authentication",
message: "Requires authentication",
});
const id = h3.context.params?.id;

View File

@ -7,7 +7,7 @@ export default defineEventHandler(async (h3) => {
if (!userId)
throw createError({
statusCode: 403,
statusMessage: "Requires authentication",
message: "Requires authentication",
});
const query = getQuery(h3);
@ -15,13 +15,13 @@ export default defineEventHandler(async (h3) => {
const orderBy = query.order as "asc" | "desc";
if (orderBy) {
if (typeof orderBy !== "string" || !["asc", "desc"].includes(orderBy))
throw createError({ statusCode: 400, statusMessage: "Invalid order" });
throw createError({ statusCode: 400, message: "Invalid order" });
}
const tags = query.tags as string[] | undefined;
if (tags) {
if (typeof tags !== "object" || !Array.isArray(tags))
throw createError({ statusCode: 400, statusMessage: "Invalid tags" });
throw createError({ statusCode: 400, message: "Invalid tags" });
}
const options = {

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!notificationId)
throw createError({
statusCode: 400,
statusMessage: "Missing notification ID",
message: "Missing notification ID",
});
const userIds = [userId];
@ -30,7 +30,7 @@ export default defineEventHandler(async (h3) => {
if (!notification)
throw createError({
statusCode: 400,
statusMessage: "Invalid notification ID",
message: "Invalid notification ID",
});
return {};

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!notificationId)
throw createError({
statusCode: 400,
statusMessage: "Missing notification ID",
message: "Missing notification ID",
});
const userIds = [userId];
@ -30,7 +30,7 @@ export default defineEventHandler(async (h3) => {
if (!notification)
throw createError({
statusCode: 400,
statusMessage: "Invalid notification ID",
message: "Invalid notification ID",
});
return notification;

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!notificationId)
throw createError({
statusCode: 400,
statusMessage: "Missing notification ID",
message: "Missing notification ID",
});
const userIds = [userId];
@ -33,7 +33,7 @@ export default defineEventHandler(async (h3) => {
if (!notification)
throw createError({
statusCode: 400,
statusMessage: "Invalid notification ID",
message: "Invalid notification ID",
});
return notification;

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!acls)
throw createError({
statusCode: 500,
statusMessage: "Got userId but no ACLs - what?",
message: "Got userId but no ACLs - what?",
});
const notifications = await prisma.notification.findMany({

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!acls)
throw createError({
statusCode: 500,
statusMessage: "Got userId but no ACLs - what?",
message: "Got userId but no ACLs - what?",
});
await prisma.notification.updateMany({

View File

@ -5,7 +5,7 @@ import sanitize from "sanitize-filename";
export default defineEventHandler(async (h3) => {
const unsafeId = getRouterParam(h3, "id");
if (!unsafeId)
throw createError({ statusCode: 400, statusMessage: "Invalid ID" });
throw createError({ statusCode: 400, message: "Invalid ID" });
const userId = await aclManager.getUserIdACL(h3, ["object:delete"]);

View File

@ -5,14 +5,14 @@ import sanitize from "sanitize-filename";
export default defineEventHandler(async (h3) => {
const unsafeId = getRouterParam(h3, "id");
if (!unsafeId)
throw createError({ statusCode: 400, statusMessage: "Invalid ID" });
throw createError({ statusCode: 400, message: "Invalid ID" });
const userId = await aclManager.getUserIdACL(h3, ["object:read"]);
const id = sanitize(unsafeId);
const object = await objectHandler.fetchWithPermissions(id, userId);
if (!object)
throw createError({ statusCode: 404, statusMessage: "Object not found" });
throw createError({ statusCode: 404, message: "Object not found" });
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag
const etagRequestValue = h3.headers.get("If-None-Match");

View File

@ -6,14 +6,14 @@ import sanitize from "sanitize-filename";
export default defineEventHandler(async (h3) => {
const unsafeId = getRouterParam(h3, "id");
if (!unsafeId)
throw createError({ statusCode: 400, statusMessage: "Invalid ID" });
throw createError({ statusCode: 400, message: "Invalid ID" });
const userId = await aclManager.getUserIdACL(h3, ["object:read"]);
const id = sanitize(unsafeId);
const object = await objectHandler.fetchWithPermissions(id, userId);
if (!object)
throw createError({ statusCode: 404, statusMessage: "Object not found" });
throw createError({ statusCode: 404, message: "Object not found" });
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag
const etagRequestValue = h3.headers.get("If-None-Match");

View File

@ -5,13 +5,13 @@ import sanitize from "sanitize-filename";
export default defineEventHandler(async (h3) => {
const unsafeId = getRouterParam(h3, "id");
if (!unsafeId)
throw createError({ statusCode: 400, statusMessage: "Invalid ID" });
throw createError({ statusCode: 400, message: "Invalid ID" });
const body = await readRawBody(h3, "binary");
if (!body)
throw createError({
statusCode: 400,
statusMessage: "Invalid upload",
message: "Invalid upload",
});
const userId = await aclManager.getUserIdACL(h3, ["object:update"]);

View File

@ -11,7 +11,7 @@ export default defineEventHandler(async (h3) => {
if (!unsafeId)
throw createError({
statusCode: 400,
statusMessage: "Missing screenshot ID",
message: "Missing screenshot ID",
});
const screenshotId = sanitize(unsafeId);

View File

@ -11,7 +11,7 @@ export default defineEventHandler(async (h3) => {
if (!unsafeId)
throw createError({
statusCode: 400,
statusMessage: "Missing screenshot ID",
message: "Missing screenshot ID",
});
const result = await screenshotManager.get(sanitize(unsafeId));

View File

@ -10,7 +10,7 @@ export default defineEventHandler(async (h3) => {
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "Missing game ID",
message: "Missing game ID",
});
const results = await screenshotManager.getUserAllByGame(userId, gameId);

View File

@ -13,7 +13,7 @@ export default defineEventHandler(async (h3) => {
if (!gameId)
throw createError({
statusCode: 400,
statusMessage: "Missing game ID",
message: "Missing game ID",
});
const game = await prisma.game.findUnique({
@ -21,7 +21,7 @@ export default defineEventHandler(async (h3) => {
select: { id: true },
});
if (!game)
throw createError({ statusCode: 400, statusMessage: "Invalid game ID" });
throw createError({ statusCode: 400, message: "Invalid game ID" });
await screenshotManager.upload(userId, gameId, h3.node.req);
});

View File

@ -7,7 +7,7 @@ export default defineEventHandler(async (h3) => {
if (!allowed)
throw createError({
statusCode: 403,
statusMessage: "Must use a setup token.",
message: "Must use a setup token.",
});
await prisma.aPIToken.deleteMany({
where: {

View File

@ -28,7 +28,7 @@ export default defineEventHandler(async (h3) => {
const query = getQuery(h3);
const options = StoreRead(query);
if (options instanceof ArkErrors)
throw createError({ statusCode: 400, statusMessage: options.summary });
throw createError({ statusCode: 400, message: options.summary });
/**
* Generic filters

View File

@ -0,0 +1,16 @@
import aclManager from "~/server/internal/acls";
import prisma from "~/server/internal/db/database";
export default defineEventHandler(async (h3) => {
const userId = await aclManager.getUserIdACL(h3, ["store:read"]);
if (!userId) throw createError({ statusCode: 403 });
const platforms = await prisma.userPlatform.findMany({
orderBy: { platformName: "asc" },
select: {
id: true,
platformName: true,
},
});
return platforms;
});

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!tagId)
throw createError({
statusCode: 400,
statusMessage: "Missing gameId in route params (somehow...?)",
message: "Missing gameId in route params (somehow...?)",
});
const tag = await prisma.gameTag.findUnique({
@ -17,7 +17,7 @@ export default defineEventHandler(async (h3) => {
});
if (!tag)
throw createError({ statusCode: 404, statusMessage: "Tag not found" });
throw createError({ statusCode: 404, message: "Tag not found" });
return { tag };
});

View File

@ -9,7 +9,7 @@ export default defineEventHandler(async (h3) => {
if (!clientId)
throw createError({
statusCode: 400,
statusMessage: "Client ID missing in route params",
message: "Client ID missing in route params",
});
await clientHandler.removeClient(clientId);

View File

@ -10,14 +10,14 @@ export default defineEventHandler(async (h3) => {
if (!id)
throw createError({
statusCode: 400,
statusMessage: "No id in router params",
message: "No id in router params",
});
const deleted = await prisma.aPIToken.delete({
where: { id: id, userId: userId, mode: APITokenMode.User },
})!;
if (!deleted)
throw createError({ statusCode: 404, statusMessage: "Token not found" });
throw createError({ statusCode: 404, message: "Token not found" });
return;
});

View File

@ -22,7 +22,7 @@ export default defineEventHandler(async (h3) => {
if (invalidACLs.length > 0)
throw createError({
statusCode: 400,
statusMessage: `Invalid ACLs: ${invalidACLs.join(", ")}`,
message: `Invalid ACLs: ${invalidACLs.join(", ")}`,
});
const token = await prisma.aPIToken.create({