import { NextRequest, NextResponse } from 'next/server' import { prisma } from '@/lib/prisma' import { auth } from '@/lib/auth' interface RouteContext { params: Promise<{ id: string }> } interface CommandRequest { type: string // SHELL, RESTART_SERVICE, UPDATE, ECHO, etc. payload?: Record } // Common command types const ALLOWED_COMMAND_TYPES = [ 'ECHO', // Test connectivity 'SHELL', // Execute shell command 'RESTART_SERVICE', // Restart a Docker service 'UPDATE', // Update orchestrator/agent 'DOCKER_COMPOSE_UP', // Start stack 'DOCKER_COMPOSE_DOWN', // Stop stack 'DOCKER_COMPOSE_RESTART', // Restart stack 'GET_LOGS', // Get container logs 'GET_STATUS', // Get system status ] /** * GET /api/v1/admin/servers/[id]/command * Get command history for a server */ export async function GET(request: NextRequest, context: RouteContext) { try { // Authentication check const session = await auth() if (!session || session.user.userType !== 'staff') { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const { id: orderId } = await context.params const searchParams = request.nextUrl.searchParams const limit = parseInt(searchParams.get('limit') || '50', 10) const offset = parseInt(searchParams.get('offset') || '0', 10) // Find server connection by order ID const serverConnection = await prisma.serverConnection.findUnique({ where: { orderId }, }) if (!serverConnection) { return NextResponse.json( { error: 'Server connection not found' }, { status: 404 } ) } // Get command history const [commands, total] = await Promise.all([ prisma.remoteCommand.findMany({ where: { serverConnectionId: serverConnection.id }, orderBy: { queuedAt: 'desc' }, take: limit, skip: offset, }), prisma.remoteCommand.count({ where: { serverConnectionId: serverConnection.id }, }), ]) return NextResponse.json({ commands, pagination: { total, limit, offset, hasMore: offset + commands.length < total, }, }) } catch (error) { console.error('Get commands error:', error) return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ) } } /** * POST /api/v1/admin/servers/[id]/command * Queue a command for a server */ export async function POST(request: NextRequest, context: RouteContext) { try { // Authentication check const session = await auth() if (!session || session.user.userType !== 'staff') { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const { id: orderId } = await context.params const body: CommandRequest = await request.json() // Validate command type if (!body.type) { return NextResponse.json( { error: 'Missing required field: type' }, { status: 400 } ) } if (!ALLOWED_COMMAND_TYPES.includes(body.type)) { return NextResponse.json( { error: `Invalid command type. Allowed types: ${ALLOWED_COMMAND_TYPES.join(', ')}`, }, { status: 400 } ) } // Find server connection by order ID const serverConnection = await prisma.serverConnection.findUnique({ where: { orderId }, include: { order: { select: { domain: true, serverIp: true }, }, }, }) if (!serverConnection) { return NextResponse.json( { error: 'Server connection not found' }, { status: 404 } ) } // Check if server is registered if (serverConnection.status === 'PENDING') { return NextResponse.json( { error: 'Server has not registered with Hub yet' }, { status: 400 } ) } // Queue the command const command = await prisma.remoteCommand.create({ data: { serverConnectionId: serverConnection.id, type: body.type, payload: (body.payload || {}) as object, initiatedBy: session?.user?.email || 'unknown', }, }) return NextResponse.json({ success: true, command: { id: command.id, type: command.type, status: command.status, queuedAt: command.queuedAt, }, server: { domain: serverConnection.order.domain, ip: serverConnection.order.serverIp, status: serverConnection.status, lastHeartbeat: serverConnection.lastHeartbeat, }, }) } catch (error) { console.error('Queue command error:', error) return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ) } }