feat: paste Meta token after App Review; Google-only discover

While Meta review is pending, agency can match Google Ads alone and
paste the system user token later without a redeploy.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-22 21:11:03 +02:00
parent c13001c69d
commit 6607a02bff
5 changed files with 215 additions and 35 deletions

View File

@@ -0,0 +1,25 @@
import { NextRequest, NextResponse } from 'next/server';
import { createClient } from '@/lib/supabase/server';
import { isAgencyRole, userRole } from '@/lib/agency';
import { saveMetaAccessToken } from '@/lib/ads-discovery';
export const dynamic = 'force-dynamic';
/** POST { token } — save Meta system user token (after App Review). */
export async function POST(req: NextRequest) {
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user || !isAgencyRole(userRole(user))) {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
const body = await req.json().catch(() => ({}));
const token = typeof body.token === 'string' ? body.token : '';
const result = await saveMetaAccessToken(token);
if (!result.ok) {
return NextResponse.json({ error: result.error }, { status: 400 });
}
return NextResponse.json({ ok: true, name: result.name });
}

View File

@@ -4,6 +4,7 @@ import { isAgencyRole, userRole } from '@/lib/agency';
import {
googleAdsConfigured,
metaConfigured,
metaEnvConfigured,
} from '@/lib/ads-discovery';
export const dynamic = 'force-dynamic';
@@ -18,8 +19,13 @@ export async function GET() {
return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
}
const metaReady = await metaConfigured();
return NextResponse.json({
meta: { configured: metaConfigured() },
meta: {
configured: metaReady,
envFallback: metaEnvConfigured(),
pendingReview: !metaReady,
},
googleAds: { configured: googleAdsConfigured() },
});
}