import { NextResponse } from 'next/server'; import { getAdminAuth, getAdminDb } from '@/lib/firebase/admin'; /** * Endpoint for the browser extension to link itself to a Vibn project. * Extension sends: workspace path + Vibn project ID * Backend stores: mapping for future requests */ export async function POST(request: Request) { try { // Verify auth const authHeader = request.headers.get('Authorization'); if (!authHeader?.startsWith('Bearer ')) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const idToken = authHeader.split('Bearer ')[1]; const adminAuth = getAdminAuth(); let userId: string; try { const decodedToken = await adminAuth.verifyIdToken(idToken); userId = decodedToken.uid; } catch (error) { return NextResponse.json({ error: 'Invalid token' }, { status: 401 }); } const body = await request.json(); const { projectId, workspacePath } = body; if (!projectId || !workspacePath) { return NextResponse.json( { error: 'Missing projectId or workspacePath' }, { status: 400 } ); } const adminDb = getAdminDb(); // Verify project exists and user has access const projectSnap = await adminDb.collection('projects').doc(projectId).get(); if (!projectSnap.exists) { return NextResponse.json({ error: 'Project not found' }, { status: 404 }); } const projectData = projectSnap.data(); if (projectData?.userId !== userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 403 }); } // Store the workspace → project mapping await adminDb .collection('extensionWorkspaceLinks') .doc(workspacePath) .set({ projectId, userId, workspacePath, linkedAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }, { merge: true }); // Also update project metadata to indicate extension is linked await adminDb.collection('projects').doc(projectId).set( { extensionLinked: true, extensionLinkedAt: new Date().toISOString(), }, { merge: true } ); console.log(`[Extension] Linked workspace "${workspacePath}" to project ${projectId}`); return NextResponse.json({ success: true, message: 'Extension linked to project', projectId, workspacePath, }); } catch (error) { console.error('[Extension] Link error:', error); return NextResponse.json( { error: 'Failed to link extension', details: error instanceof Error ? error.message : String(error), }, { status: 500 } ); } } /** * Get the Vibn project ID for a given workspace path */ export async function GET(request: Request) { try { const { searchParams } = new URL(request.url); const workspacePath = searchParams.get('workspacePath'); if (!workspacePath) { return NextResponse.json( { error: 'Missing workspacePath query param' }, { status: 400 } ); } const adminDb = getAdminDb(); const linkSnap = await adminDb .collection('extensionWorkspaceLinks') .doc(workspacePath) .get(); if (!linkSnap.exists) { return NextResponse.json( { error: 'No project linked for this workspace' }, { status: 404 } ); } const linkData = linkSnap.data(); return NextResponse.json({ projectId: linkData?.projectId, linkedAt: linkData?.linkedAt, }); } catch (error) { console.error('[Extension] Get link error:', error); return NextResponse.json( { error: 'Failed to get link', details: error instanceof Error ? error.message : String(error), }, { status: 500 } ); } }