From 5cd6442ccab643abc222d72e7d9cd7410174b54c Mon Sep 17 00:00:00 2001 From: Lncvrt Date: Sat, 31 Jan 2026 01:28:37 -0700 Subject: [PATCH] Make icon marketplace work with either `verifyCode` or `token` --- src/index.ts | 5 +- .../berrydash/icon-marketplace/upload/post.ts | 78 +++++++++++-------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/index.ts b/src/index.ts index 91acb18..3310e7a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1083,11 +1083,12 @@ app.post( { detail: { description: - 'The endpoint for uploading an icon to the icon marketplace.', + 'The endpoint for uploading an icon to the icon marketplace.\n\n`verifyCode` or `token` must be provided.', tags: ['Berry Dash', 'Icon Marketplace'] }, body: t.Object({ - verifyCode: t.String(), + verifyCode: t.Optional(t.String()), + token: t.Optional(t.String()), price: t.String(), name: t.String(), fileContent: t.String() diff --git a/src/routes/berrydash/icon-marketplace/upload/post.ts b/src/routes/berrydash/icon-marketplace/upload/post.ts index aac1541..03e2b1f 100644 --- a/src/routes/berrydash/icon-marketplace/upload/post.ts +++ b/src/routes/berrydash/icon-marketplace/upload/post.ts @@ -3,7 +3,8 @@ import { getClientIp, getDatabaseConnection, hash, - jsonResponse + jsonResponse, + validateTurnstile } from '../../../../lib/util' import { checkAuthorization } from '../../../../lib/auth' import { berryDashMarketplaceIcons, verifyCodes } from '../../../../lib/tables' @@ -14,6 +15,7 @@ import { Connection } from 'mysql2/typings/mysql/lib/Connection' type Body = { verifyCode: string + token: string price: string name: string fileContent: string @@ -72,13 +74,13 @@ export async function handler (context: Context) { const userId = authResult.id const body = context.body as Body - if (!body.name || !body.price || !body.fileContent) { + if (!body.verifyCode && !body.token) { connection0.end() connection1.end() return jsonResponse( { success: false, - message: 'Name, price and fileContent must be in POST data' + message: 'verifyCode or token must be provided in POST data' }, 400 ) @@ -134,41 +136,55 @@ export async function handler (context: Context) { ) const time = Math.floor(Date.now() / 1000) - const codeExists = await db0 - .select({ id: verifyCodes.id }) - .from(verifyCodes) - .where( - and( - eq(verifyCodes.ip, ip), - eq(verifyCodes.usedTimestamp, 0), - eq(verifyCodes.code, body.verifyCode), - sql`${verifyCodes.timestamp} >= UNIX_TIMESTAMP() - 600` - ) - ) - .orderBy(desc(verifyCodes.id)) - .limit(1) - .execute() - if (codeExists[0]) { - await db0 - .update(verifyCodes) - .set({ usedTimestamp: time }) + if (body.verifyCode) { + const codeExists = await db0 + .select({ id: verifyCodes.id }) + .from(verifyCodes) .where( and( - eq(verifyCodes.id, codeExists[0].id), eq(verifyCodes.ip, ip), eq(verifyCodes.usedTimestamp, 0), - eq(verifyCodes.code, body.verifyCode) + eq(verifyCodes.code, body.verifyCode), + sql`${verifyCodes.timestamp} >= UNIX_TIMESTAMP() - 600` ) ) + .orderBy(desc(verifyCodes.id)) + .limit(1) .execute() - } else - return jsonResponse( - { - success: false, - message: 'Invalid verify code (codes can only be used once)' - }, - 400 - ) + if (codeExists[0]) { + await db0 + .update(verifyCodes) + .set({ usedTimestamp: time }) + .where( + and( + eq(verifyCodes.id, codeExists[0].id), + eq(verifyCodes.ip, ip), + eq(verifyCodes.usedTimestamp, 0), + eq(verifyCodes.code, body.verifyCode) + ) + ) + .execute() + } else + return jsonResponse( + { + success: false, + message: 'Invalid verify code (codes can only be used once)' + }, + 400 + ) + } else { + const result = await validateTurnstile(body.token, ip) + if (!result.success) { + connection0.end() + return jsonResponse( + { + success: false, + message: 'Unable to verify captcha key' + }, + 400 + ) + } + } const hashResult = hash(atob(body.fileContent), 'sha512') const id = crypto.randomUUID()