From ef7a62bf0ba793a6da923478e15797570a36c601 Mon Sep 17 00:00:00 2001 From: DecDuck Date: Sat, 9 Aug 2025 22:18:34 +1000 Subject: [PATCH] partial: new documentation additions (company admin) --- server/api/v1/admin/auth/index.get.ts | 3 + .../v1/admin/auth/invitation/index.delete.ts | 3 +- .../api/v1/admin/auth/invitation/index.get.ts | 3 + .../v1/admin/auth/invitation/index.post.ts | 3 + .../api/v1/admin/company/[id]/banner.post.ts | 5 + .../api/v1/admin/company/[id]/game.delete.ts | 50 ++++---- .../api/v1/admin/company/[id]/game.patch.ts | 44 ++++--- server/api/v1/admin/company/[id]/game.post.ts | 112 +++++++++--------- server/api/v1/admin/company/[id]/icon.post.ts | 5 + .../api/v1/admin/company/[id]/index.delete.ts | 4 + server/api/v1/admin/company/[id]/index.get.ts | 4 + .../api/v1/admin/company/[id]/index.patch.ts | 5 + server/api/v1/admin/company/index.get.ts | 3 + server/api/v1/admin/company/index.post.ts | 57 +++++---- server/api/v1/index.get.ts | 2 +- 15 files changed, 181 insertions(+), 122 deletions(-) diff --git a/server/api/v1/admin/auth/index.get.ts b/server/api/v1/admin/auth/index.get.ts index 4ea1523..63ed73c 100644 --- a/server/api/v1/admin/auth/index.get.ts +++ b/server/api/v1/admin/auth/index.get.ts @@ -2,6 +2,9 @@ import { AuthMec } from "~/prisma/client/enums"; import aclManager from "~/server/internal/acls"; import authManager from "~/server/internal/auth"; +/** + * Fetches all the enabled authentication mechanisms on this instance, and their configuration, if enabled. + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, ["auth:read", "setup"]); if (!allowed) throw createError({ statusCode: 403 }); diff --git a/server/api/v1/admin/auth/invitation/index.delete.ts b/server/api/v1/admin/auth/invitation/index.delete.ts index 83b2d91..360abc9 100644 --- a/server/api/v1/admin/auth/invitation/index.delete.ts +++ b/server/api/v1/admin/auth/invitation/index.delete.ts @@ -8,7 +8,8 @@ const DeleteInvite = type({ }).configure(throwingArktype); /** - * Delete a simple auth invitation + * Deletes a "Simple" invitation + * @returns nothing */ export default defineEventHandler<{ body: typeof DeleteInvite.infer; diff --git a/server/api/v1/admin/auth/invitation/index.get.ts b/server/api/v1/admin/auth/invitation/index.get.ts index 0724e49..66a7f4f 100644 --- a/server/api/v1/admin/auth/invitation/index.get.ts +++ b/server/api/v1/admin/auth/invitation/index.get.ts @@ -3,6 +3,9 @@ import { systemConfig } from "~/server/internal/config/sys-conf"; import prisma from "~/server/internal/db/database"; import taskHandler from "~/server/internal/tasks"; +/** + * Fetches a "Simple" invitation + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, [ "auth:simple:invitation:read", diff --git a/server/api/v1/admin/auth/invitation/index.post.ts b/server/api/v1/admin/auth/invitation/index.post.ts index 69d3649..33e0e02 100644 --- a/server/api/v1/admin/auth/invitation/index.post.ts +++ b/server/api/v1/admin/auth/invitation/index.post.ts @@ -11,6 +11,9 @@ const CreateInvite = SharedRegisterValidator.partial() }) .configure(throwingArktype); +/** + * Creates a "Simple" invitation + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, [ "auth:simple:invitation:new", diff --git a/server/api/v1/admin/company/[id]/banner.post.ts b/server/api/v1/admin/company/[id]/banner.post.ts index 0c8744a..e15c083 100644 --- a/server/api/v1/admin/company/[id]/banner.post.ts +++ b/server/api/v1/admin/company/[id]/banner.post.ts @@ -3,6 +3,11 @@ import prisma from "~/server/internal/db/database"; import objectHandler from "~/server/internal/objects"; import { handleFileUpload } from "~/server/internal/utils/handlefileupload"; +/** + * Multi-part form upload for the banner. + * @request `multipart/form-data` data. Only one file, can be named anything. + * @param id Company ID + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); if (!allowed) throw createError({ statusCode: 403 }); diff --git a/server/api/v1/admin/company/[id]/game.delete.ts b/server/api/v1/admin/company/[id]/game.delete.ts index 0a9fe21..2824f7a 100644 --- a/server/api/v1/admin/company/[id]/game.delete.ts +++ b/server/api/v1/admin/company/[id]/game.delete.ts @@ -7,31 +7,37 @@ const GameDelete = type({ id: "string", }).configure(throwingArktype); -export default defineEventHandler(async (h3) => { - const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); - if (!allowed) throw createError({ statusCode: 403 }); +/** + * Delete a game's association with a company + * @param id Company ID + */ +export default defineEventHandler<{ body: typeof GameDelete.infer }>( + async (h3) => { + const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); + if (!allowed) throw createError({ statusCode: 403 }); - const companyId = getRouterParam(h3, "id")!; + const companyId = getRouterParam(h3, "id")!; - const body = await readDropValidatedBody(h3, GameDelete); + const body = await readDropValidatedBody(h3, GameDelete); - await prisma.game.update({ - where: { - id: body.id, - }, - data: { - publishers: { - disconnect: { - id: companyId, + await prisma.game.update({ + where: { + id: body.id, + }, + data: { + publishers: { + disconnect: { + id: companyId, + }, + }, + developers: { + disconnect: { + id: companyId, + }, }, }, - developers: { - disconnect: { - id: companyId, - }, - }, - }, - }); + }); - return; -}); + return; + }, +); diff --git a/server/api/v1/admin/company/[id]/game.patch.ts b/server/api/v1/admin/company/[id]/game.patch.ts index 9e0260f..1d93d77 100644 --- a/server/api/v1/admin/company/[id]/game.patch.ts +++ b/server/api/v1/admin/company/[id]/game.patch.ts @@ -9,29 +9,35 @@ const GamePatch = type({ id: "string", }).configure(throwingArktype); -export default defineEventHandler(async (h3) => { - const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); - if (!allowed) throw createError({ statusCode: 403 }); +/** + * Update a company's association with a game. + * @param id Company ID + */ +export default defineEventHandler<{ body: typeof GamePatch.infer }>( + async (h3) => { + const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); + if (!allowed) throw createError({ statusCode: 403 }); - const companyId = getRouterParam(h3, "id")!; + const companyId = getRouterParam(h3, "id")!; - const body = await readDropValidatedBody(h3, GamePatch); + const body = await readDropValidatedBody(h3, GamePatch); - const action = body.action === "developed" ? "developers" : "publishers"; - const actionType = body.enabled ? "connect" : "disconnect"; + const action = body.action === "developed" ? "developers" : "publishers"; + const actionType = body.enabled ? "connect" : "disconnect"; - await prisma.game.update({ - where: { - id: body.id, - }, - data: { - [action]: { - [actionType]: { - id: companyId, + await prisma.game.update({ + where: { + id: body.id, + }, + data: { + [action]: { + [actionType]: { + id: companyId, + }, }, }, - }, - }); + }); - return; -}); + return; + }, +); diff --git a/server/api/v1/admin/company/[id]/game.post.ts b/server/api/v1/admin/company/[id]/game.post.ts index f873118..6e7d46c 100644 --- a/server/api/v1/admin/company/[id]/game.post.ts +++ b/server/api/v1/admin/company/[id]/game.post.ts @@ -9,61 +9,67 @@ const GamePost = type({ id: "string", }).configure(throwingArktype); -export default defineEventHandler(async (h3) => { - const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); - if (!allowed) throw createError({ statusCode: 403 }); +/** + * Add a new game association to this company + * @param id Company ID + */ +export default defineEventHandler<{ body: typeof GamePost.infer }>( + async (h3) => { + const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); + if (!allowed) throw createError({ statusCode: 403 }); - const companyId = getRouterParam(h3, "id")!; + const companyId = getRouterParam(h3, "id")!; - const body = await readDropValidatedBody(h3, GamePost); + const body = await readDropValidatedBody(h3, GamePost); - if (!body.published && !body.developed) - throw createError({ - statusCode: 400, - statusMessage: "Must be related (either developed or published).", + if (!body.published && !body.developed) + throw createError({ + statusCode: 400, + statusMessage: "Must be related (either developed or published).", + }); + + const publisherConnect = body.published + ? { + publishers: { + connect: { + id: companyId, + }, + }, + } + : undefined; + + const developerConnect = body.developed + ? { + developers: { + connect: { + id: companyId, + }, + }, + } + : undefined; + + const game = await prisma.game.update({ + where: { + id: body.id, + }, + data: { + ...publisherConnect, + ...developerConnect, + }, + include: { + publishers: { + select: { + id: true, + }, + }, + developers: { + select: { + id: true, + }, + }, + }, }); - const publisherConnect = body.published - ? { - publishers: { - connect: { - id: companyId, - }, - }, - } - : undefined; - - const developerConnect = body.developed - ? { - developers: { - connect: { - id: companyId, - }, - }, - } - : undefined; - - const game = await prisma.game.update({ - where: { - id: body.id, - }, - data: { - ...publisherConnect, - ...developerConnect, - }, - include: { - publishers: { - select: { - id: true, - }, - }, - developers: { - select: { - id: true, - }, - }, - }, - }); - - return game; -}); + return game; + }, +); diff --git a/server/api/v1/admin/company/[id]/icon.post.ts b/server/api/v1/admin/company/[id]/icon.post.ts index 0a4cefd..9735bb0 100644 --- a/server/api/v1/admin/company/[id]/icon.post.ts +++ b/server/api/v1/admin/company/[id]/icon.post.ts @@ -3,6 +3,11 @@ import prisma from "~/server/internal/db/database"; import objectHandler from "~/server/internal/objects"; import { handleFileUpload } from "~/server/internal/utils/handlefileupload"; +/** + * Multi-part form upload for the icon of this company + * @request `multipart/form-data` data. Only one file, can be named anything. + * @param id Company ID + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); if (!allowed) throw createError({ statusCode: 403 }); diff --git a/server/api/v1/admin/company/[id]/index.delete.ts b/server/api/v1/admin/company/[id]/index.delete.ts index b27d393..d680b29 100644 --- a/server/api/v1/admin/company/[id]/index.delete.ts +++ b/server/api/v1/admin/company/[id]/index.delete.ts @@ -1,6 +1,10 @@ import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; +/** + * Delete this company + * @param id Company ID + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, ["company:delete"]); if (!allowed) throw createError({ statusCode: 403 }); diff --git a/server/api/v1/admin/company/[id]/index.get.ts b/server/api/v1/admin/company/[id]/index.get.ts index 50c4115..344b79d 100644 --- a/server/api/v1/admin/company/[id]/index.get.ts +++ b/server/api/v1/admin/company/[id]/index.get.ts @@ -1,6 +1,10 @@ import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; +/** + * Fetch a company and its associations + * @param id Company ID + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, ["company:read"]); if (!allowed) throw createError({ statusCode: 403 }); diff --git a/server/api/v1/admin/company/[id]/index.patch.ts b/server/api/v1/admin/company/[id]/index.patch.ts index 74511e2..d88482a 100644 --- a/server/api/v1/admin/company/[id]/index.patch.ts +++ b/server/api/v1/admin/company/[id]/index.patch.ts @@ -1,6 +1,11 @@ import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; +/** + * Update a company. Pass any fields into the body to be updated on the model + * @request Partial of the data returned by GET, minus the `developed` and `published` fields. + * @param id Company ID + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, ["company:update"]); if (!allowed) throw createError({ statusCode: 403 }); diff --git a/server/api/v1/admin/company/index.get.ts b/server/api/v1/admin/company/index.get.ts index dac5ae2..28b748e 100644 --- a/server/api/v1/admin/company/index.get.ts +++ b/server/api/v1/admin/company/index.get.ts @@ -1,6 +1,9 @@ import aclManager from "~/server/internal/acls"; import prisma from "~/server/internal/db/database"; +/** + * Fetch all companies on this instance + */ export default defineEventHandler(async (h3) => { const allowed = await aclManager.allowSystemACL(h3, ["company:read"]); if (!allowed) throw createError({ statusCode: 403 }); diff --git a/server/api/v1/admin/company/index.post.ts b/server/api/v1/admin/company/index.post.ts index cbea4a1..ad9ab4a 100644 --- a/server/api/v1/admin/company/index.post.ts +++ b/server/api/v1/admin/company/index.post.ts @@ -12,36 +12,41 @@ const CompanyCreate = type({ website: "string", }).configure(throwingArktype); -export default defineEventHandler(async (h3) => { - const allowed = await aclManager.allowSystemACL(h3, ["company:create"]); - if (!allowed) throw createError({ statusCode: 403 }); +/** + * Create a new company on this instance + */ +export default defineEventHandler<{ body: typeof CompanyCreate.infer }>( + async (h3) => { + const allowed = await aclManager.allowSystemACL(h3, ["company:create"]); + if (!allowed) throw createError({ statusCode: 403 }); - const body = await readDropValidatedBody(h3, CompanyCreate); - const obj = new ObjectTransactionalHandler(); - const [register, pull, _] = obj.new({}, ["internal:read"]); + const body = await readDropValidatedBody(h3, CompanyCreate); + const obj = new ObjectTransactionalHandler(); + const [register, pull, _] = obj.new({}, ["internal:read"]); - const icon = jdenticon.toPng(body.name, 512); - const logoId = register(icon); + const icon = jdenticon.toPng(body.name, 512); + const logoId = register(icon); - const banner = jdenticon.toPng(body.description, 1024); - const bannerId = register(banner); + const banner = jdenticon.toPng(body.description, 1024); + const bannerId = register(banner); - const company = await prisma.company.create({ - data: { - metadataSource: MetadataSource.Manual, - metadataId: crypto.randomUUID(), - metadataOriginalQuery: "", + const company = await prisma.company.create({ + data: { + metadataSource: MetadataSource.Manual, + metadataId: crypto.randomUUID(), + metadataOriginalQuery: "", - mName: body.name, - mShortDescription: body.description, - mDescription: "", - mLogoObjectId: logoId, - mBannerObjectId: bannerId, - mWebsite: body.website, - }, - }); + mName: body.name, + mShortDescription: body.description, + mDescription: "", + mLogoObjectId: logoId, + mBannerObjectId: bannerId, + mWebsite: body.website, + }, + }); - await pull(); + await pull(); - return company; -}); + return company; + }, +); diff --git a/server/api/v1/index.get.ts b/server/api/v1/index.get.ts index 4d25388..5500dd4 100644 --- a/server/api/v1/index.get.ts +++ b/server/api/v1/index.get.ts @@ -1,6 +1,6 @@ import { systemConfig } from "~/server/internal/config/sys-conf"; -export default defineEventHandler((_h3) => { +export default defineEventHandler(async (_h3) => { return { appName: "Drop", version: systemConfig.getDropVersion(),