import { NextRequest, NextResponse } from "next/server"; import { findUserByApiKey } from "./api-keys"; import { checkApiRateLimit } from "./api-rate-limit"; import { hasProFeatures } from "./edition"; import { getSessionUser } from "./session"; function extractBearerToken(req: NextRequest) { const auth = req.headers.get("authorization"); if (!auth?.startsWith("Bearer ")) return null; return auth.slice(7).trim(); } export async function requirePaidApiUser(req: NextRequest) { const token = extractBearerToken(req); if (!token) { return { error: NextResponse.json( { error: "Missing API key. Use Authorization: Bearer " }, { status: 401 }, ), user: null, }; } const user = await findUserByApiKey(token); if (!user) { return { error: NextResponse.json({ error: "Invalid API key" }, { status: 401 }), user: null, }; } if (!hasProFeatures(user.plan)) { return { error: NextResponse.json( { error: "API access requires an active Pro subscription" }, { status: 403 }, ), user: null, }; } if (!user.youtubeConnection) { return { error: NextResponse.json( { error: "YouTube account not connected. Sign in via the dashboard first." }, { status: 403 }, ), user: null, }; } const rateLimit = await checkApiRateLimit(user.id); if (!rateLimit.ok) { return { error: NextResponse.json( { error: "API rate limit exceeded. Try again shortly.", retryAfterSeconds: rateLimit.retryAfterSeconds, }, { status: 429, headers: { "Retry-After": String(rateLimit.retryAfterSeconds) }, }, ), user: null, }; } return { error: null, user }; } export async function requirePaidUserFromSessionOrApi(req: NextRequest) { const apiResult = await requirePaidApiUser(req); if (apiResult.user) return apiResult; const sessionUser = await getSessionUser(); if (!sessionUser) { return apiResult.error ? apiResult : { error: NextResponse.json({ error: "Unauthorized" }, { status: 401 }), user: null, }; } if (!hasProFeatures(sessionUser.plan)) { return { error: NextResponse.json( { error: "API access requires an active Pro subscription" }, { status: 403 }, ), user: null, }; } if (!sessionUser.youtubeConnection) { return { error: NextResponse.json({ error: "YouTube account not connected" }, { status: 403 }), user: null, }; } return { error: null, user: sessionUser }; }