import { NextRequest, NextResponse } from 'next/server' import { auth } from '@/lib/auth' import { netcupService, NetcupAuthError } from '@/lib/services/netcup-service' // Store pending device auth sessions (in-memory for simplicity) // In production, consider storing in Redis or database const pendingAuthSessions = new Map< string, { deviceCode: string expiresAt: number interval: number } >() /** * GET /api/v1/admin/netcup/auth * Get current authentication status */ export async function GET(request: NextRequest) { try { const session = await auth() if (!session || session.user.userType !== 'staff') { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const status = await netcupService.getAuthStatus() return NextResponse.json(status) } catch (error) { console.error('Error getting Netcup auth status:', error) return NextResponse.json( { error: 'Failed to get auth status' }, { status: 500 } ) } } /** * POST /api/v1/admin/netcup/auth * Initiate device auth flow or poll for token * * Body: * - action: 'initiate' | 'poll' | 'disconnect' * - sessionId?: string (for poll action) */ export async function POST(request: NextRequest) { try { const session = await auth() if (!session || session.user.userType !== 'staff') { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const body = await request.json() const { action, sessionId } = body as { action: 'initiate' | 'poll' | 'disconnect' sessionId?: string } if (!action || !['initiate', 'poll', 'disconnect'].includes(action)) { return NextResponse.json( { error: 'Invalid action. Must be: initiate, poll, or disconnect' }, { status: 400 } ) } switch (action) { case 'initiate': { // Start device auth flow const deviceAuth = await netcupService.initiateDeviceAuth() // Store session for polling const newSessionId = crypto.randomUUID() pendingAuthSessions.set(newSessionId, { deviceCode: deviceAuth.device_code, expiresAt: Date.now() + deviceAuth.expires_in * 1000, interval: deviceAuth.interval, }) // Clean up expired sessions for (const [id, sess] of pendingAuthSessions) { if (sess.expiresAt < Date.now()) { pendingAuthSessions.delete(id) } } return NextResponse.json({ success: true, sessionId: newSessionId, userCode: deviceAuth.user_code, verificationUri: deviceAuth.verification_uri, verificationUriComplete: deviceAuth.verification_uri_complete, expiresIn: deviceAuth.expires_in, interval: deviceAuth.interval, }) } case 'poll': { if (!sessionId) { return NextResponse.json( { error: 'Session ID required for polling' }, { status: 400 } ) } const pendingSession = pendingAuthSessions.get(sessionId) if (!pendingSession) { return NextResponse.json( { error: 'Session not found or expired' }, { status: 404 } ) } if (pendingSession.expiresAt < Date.now()) { pendingAuthSessions.delete(sessionId) return NextResponse.json( { error: 'Session expired' }, { status: 410 } ) } try { const tokens = await netcupService.pollForToken(pendingSession.deviceCode) if (!tokens) { // Still waiting for user authorization return NextResponse.json({ success: false, status: 'pending', message: 'Waiting for user authorization', }) } // Success! Clean up session pendingAuthSessions.delete(sessionId) return NextResponse.json({ success: true, status: 'authenticated', message: 'Successfully authenticated with Netcup', }) } catch (error) { if (error instanceof NetcupAuthError) { pendingAuthSessions.delete(sessionId) return NextResponse.json( { error: error.message }, { status: 400 } ) } throw error } } case 'disconnect': { // Clear stored tokens await netcupService.clearTokens() return NextResponse.json({ success: true, message: 'Disconnected from Netcup', }) } default: return NextResponse.json({ error: 'Invalid action' }, { status: 400 }) } } catch (error) { console.error('Error in Netcup auth:', error) if (error instanceof NetcupAuthError) { return NextResponse.json( { error: error.message }, { status: 400 } ) } return NextResponse.json( { error: 'Failed to process auth request' }, { status: 500 } ) } }