import { NextRequest, NextResponse } from 'next/server' import { validateSession, hasPermission } from '@/lib/auth' import connectToDatabase from '@/lib/mongodb' import { Server } from '@/lib/models' import { isValidObjectId } from '@/lib/input-validation' import { createAuditLog, getClientIP } from '@/lib/audit' import { getContainerByName } from '@/lib/docker' export async function POST( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { const clientIP = getClientIP(request) try { const session = await validateSession(request) if (!session) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } if (!hasPermission(session, 'servers:restart')) { return NextResponse.json({ error: 'Forbidden' }, { status: 403 }) } const { id } = await params if (!isValidObjectId(id)) { return NextResponse.json({ error: 'Invalid server ID' }, { status: 400 }) } await connectToDatabase() const server = await Server.findById(id) if (!server) { return NextResponse.json({ error: 'Server not found' }, { status: 404 }) } // If the server is currently offline, check for port conflicts before restarting if (server.status !== 'online' && server.status !== 'starting') { const portConflict = await Server.findOne({ _id: { $ne: server._id }, port: server.port, status: { $in: ['online', 'starting'] }, }) if (portConflict) { return NextResponse.json( { error: `Port ${server.port} is already in use by "${portConflict.name}"` }, { status: 409 } ) } } const container = await getContainerByName(`mc-${server._id}`) if (!container) { return NextResponse.json({ error: 'Docker container not found' }, { status: 500 }) } await Server.findByIdAndUpdate(id, { status: 'stopping' }) await container.restart({ t: 30 }) await Server.findByIdAndUpdate(id, { status: 'starting' }) // Poll for running state setTimeout(async () => { try { const inspect = await container.inspect() const status = inspect.State?.Running ? 'online' : 'offline' await Server.findByIdAndUpdate(id, { status }) } catch { await Server.findByIdAndUpdate(id, { status: 'crashed' }) } }, 15000) await createAuditLog({ action: 'server_restarted', entityType: 'server', entityId: server._id.toString(), entityName: server.name, userId: session._id, userName: session.username, userEmail: session.email, clientIP, status: 'success', statusCode: 200, }) return NextResponse.json({ success: true, message: 'Server restarting' }) } catch (error) { console.error('Restart server error:', error) return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } }