mirror of
https://github.com/rmoren97/mc-manager.git
synced 2026-03-28 17:26:47 -07:00
135 lines
4.4 KiB
TypeScript
135 lines
4.4 KiB
TypeScript
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 { getServerPath } from '@/lib/docker'
|
|
import { readdir, stat, writeFile } from 'fs/promises'
|
|
import path from 'path'
|
|
|
|
// GET /api/servers/[id]/mods — List mods
|
|
export async function GET(
|
|
request: NextRequest,
|
|
{ params }: { params: Promise<{ id: string }> }
|
|
) {
|
|
try {
|
|
const session = await validateSession(request)
|
|
if (!session) {
|
|
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
}
|
|
|
|
if (!hasPermission(session, 'mods:view')) {
|
|
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 (server.type !== 'forge' && server.type !== 'fabric') {
|
|
return NextResponse.json({ error: 'Mods are only available for Forge/Fabric servers' }, { status: 400 })
|
|
}
|
|
|
|
const modsDir = path.join(getServerPath(server._id.toString()), 'mods')
|
|
const mods = []
|
|
|
|
try {
|
|
const files = await readdir(modsDir)
|
|
for (const file of files) {
|
|
if (file.endsWith('.jar') || file.endsWith('.jar.disabled')) {
|
|
const filePath = path.join(modsDir, file)
|
|
const stats = await stat(filePath)
|
|
const enabled = file.endsWith('.jar') && !file.endsWith('.jar.disabled')
|
|
const name = file.replace(/\.jar(\.disabled)?$/, '')
|
|
mods.push({
|
|
name,
|
|
filename: file,
|
|
size: stats.size,
|
|
enabled,
|
|
})
|
|
}
|
|
}
|
|
} catch {
|
|
// Directory doesn't exist yet
|
|
}
|
|
|
|
return NextResponse.json({ success: true, data: mods })
|
|
} catch (error) {
|
|
console.error('Fetch mods error:', error)
|
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
|
|
}
|
|
}
|
|
|
|
// POST /api/servers/[id]/mods — Upload a mod
|
|
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, 'mods:install')) {
|
|
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 (server.type !== 'forge' && server.type !== 'fabric') {
|
|
return NextResponse.json({ error: 'Mods are only available for Forge/Fabric servers' }, { status: 400 })
|
|
}
|
|
|
|
const formData = await request.formData()
|
|
const file = formData.get('file') as File | null
|
|
if (!file || !file.name.endsWith('.jar')) {
|
|
return NextResponse.json({ error: 'A .jar file is required' }, { status: 400 })
|
|
}
|
|
|
|
const modsDir = path.join(getServerPath(server._id.toString()), 'mods')
|
|
const { execSync } = await import('child_process')
|
|
execSync(`mkdir -p "${modsDir}"`)
|
|
|
|
const buffer = Buffer.from(await file.arrayBuffer())
|
|
await writeFile(path.join(modsDir, file.name), buffer)
|
|
|
|
await createAuditLog({
|
|
action: 'mod_installed',
|
|
entityType: 'mod',
|
|
entityName: file.name,
|
|
userId: session._id,
|
|
userName: session.username,
|
|
userEmail: session.email,
|
|
newValues: { serverId: server._id.toString(), filename: file.name },
|
|
clientIP,
|
|
status: 'success',
|
|
statusCode: 201,
|
|
})
|
|
|
|
return NextResponse.json({ success: true, message: 'Mod uploaded. Restart the server to load it.' }, { status: 201 })
|
|
} catch (error) {
|
|
console.error('Upload mod error:', error)
|
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
|
|
}
|
|
}
|