From c6e5a7be8afcebc9289d1fedfb407bcb4fe5a3a4 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Tue, 5 May 2026 18:05:59 +0000 Subject: [PATCH] fix: bind credit usage to authenticated user Co-authored-by: Cole Collins --- app/api/credits/summary/route.ts | 21 ++++++++++++ app/api/generate-scaffold/route.ts | 52 ++++++++++++++++-------------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/app/api/credits/summary/route.ts b/app/api/credits/summary/route.ts index 6445841..2a1c89b 100644 --- a/app/api/credits/summary/route.ts +++ b/app/api/credits/summary/route.ts @@ -1,9 +1,24 @@ import { NextRequest, NextResponse } from 'next/server' import { getOrCreateUserCredits, getCreditUsageSummary } from '@/lib/credits' +import { getCurrentUser } from '@/lib/auth' export async function GET(request: NextRequest) { try { const userId = request.nextUrl.searchParams.get('userId') + const user = await getCurrentUser() + + if (!user) { + return NextResponse.json( + { error: 'Sign in with GitHub to view credits.' }, + { status: 401 } + ) + } + if (!user.id) { + return NextResponse.json( + { error: 'Unable to load your account. Please sign in again.' }, + { status: 401 } + ) + } if (!userId) { return NextResponse.json( @@ -11,6 +26,12 @@ export async function GET(request: NextRequest) { { status: 400 } ) } + if (userId !== user.id) { + return NextResponse.json( + { error: 'You can only view credits for your own account.' }, + { status: 403 } + ) + } // Get credits and usage summary const [credits, summary] = await Promise.all([ diff --git a/app/api/generate-scaffold/route.ts b/app/api/generate-scaffold/route.ts index 8ad1b70..796cb4f 100644 --- a/app/api/generate-scaffold/route.ts +++ b/app/api/generate-scaffold/route.ts @@ -18,11 +18,14 @@ export async function POST(request: NextRequest) { ) } - const { appName, description, technologies, existingFiles, missingFiles, userId } = await request.json() + const { appName, description, technologies, existingFiles, missingFiles } = await request.json() const user = await getCurrentUser() if (!user) { return NextResponse.json({ error: 'Sign in with GitHub to generate scaffolds.' }, { status: 401 }) } + if (!user.id) { + return NextResponse.json({ error: 'Unable to load your account. Please sign in again.' }, { status: 401 }) + } let sub = await getSubscriptionByGithubId(user.github_id).catch(() => null) if (!sub) { @@ -40,19 +43,17 @@ export async function POST(request: NextRequest) { } // Check credit balance before proceeding - if (userId) { - const currentBalance = await getCreditBalance(userId) - if (currentBalance < CREDITS.SCAFFOLD_COST) { - return NextResponse.json( - { - error: 'Insufficient credits', - required: CREDITS.SCAFFOLD_COST, - available: currentBalance, - message: 'Upgrade to Pro to get unlimited scaffold generation with 5,000 monthly credits.', - }, - { status: 402 } - ) - } + const currentBalance = await getCreditBalance(user.id) + if (currentBalance < CREDITS.SCAFFOLD_COST) { + return NextResponse.json( + { + error: 'Insufficient credits', + required: CREDITS.SCAFFOLD_COST, + available: currentBalance, + message: 'Upgrade to Pro to get unlimited scaffold generation with 5,000 monthly credits.', + }, + { status: 402 } + ) } console.log('[v0] Generating scaffold for app:', appName) @@ -140,18 +141,21 @@ Example structure: // Deduct credits after successful generation let creditsUsed = 0 - if (userId) { - const deductResult = await deductCredits(userId, CREDITS.SCAFFOLD_COST, 'scaffold', { - appName, - technologies, - }) - - if (deductResult.success) { - creditsUsed = CREDITS.SCAFFOLD_COST - console.log(`[v0] Deducted ${CREDITS.SCAFFOLD_COST} credits from user ${userId}`) - } + const deductResult = await deductCredits(user.id, CREDITS.SCAFFOLD_COST, 'scaffold', { + appName, + technologies, + }) + + if (!deductResult.success) { + return NextResponse.json( + { error: deductResult.error ?? 'Failed to deduct scaffold credits' }, + { status: 402 } + ) } + creditsUsed = CREDITS.SCAFFOLD_COST + console.log(`[v0] Deducted ${CREDITS.SCAFFOLD_COST} credits from user ${user.id}`) + return NextResponse.json({ success: true, scaffold,