import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from "@/app/api/auth/options"; import { PrismaClient } from '@prisma/client'; import { prisma } from '@/lib/prisma'; import { uploadMissionLogo, uploadMissionAttachment, generateMissionLogoUploadUrl, generateMissionAttachmentUploadUrl } from '@/lib/mission-uploads'; // Helper function to check authentication async function checkAuth(request: Request) { const session = await getServerSession(authOptions); if (!session?.user?.id) { console.error('Unauthorized access attempt:', { url: request.url, method: request.method, headers: Object.fromEntries(request.headers) }); return { authorized: false, userId: null }; } return { authorized: true, userId: session.user.id }; } // Generate presigned URL for direct upload to S3/Minio export async function GET(request: Request) { try { const { authorized, userId } = await checkAuth(request); if (!authorized || !userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { searchParams } = new URL(request.url); const missionId = searchParams.get('missionId'); const type = searchParams.get('type'); // 'logo' or 'attachment' const filename = searchParams.get('filename'); if (!missionId || !type || !filename) { return NextResponse.json({ error: 'Missing required parameters', required: { missionId: true, type: true, filename: true }, received: { missionId: !!missionId, type: !!type, filename: !!filename } }, { status: 400 }); } // Verify that the mission exists and user has access to it const mission = await prisma.mission.findUnique({ where: { id: missionId }, select: { id: true, creatorId: true } }); if (!mission) { return NextResponse.json({ error: 'Mission not found' }, { status: 404 }); } // Currently only allow creator to upload files // You can modify this to include other roles if needed if (mission.creatorId !== userId) { return NextResponse.json({ error: 'Not authorized to upload to this mission' }, { status: 403 }); } let result; if (type === 'logo') { // For logo, we expect filename to contain the file extension (e.g., '.jpg') const fileExtension = filename.substring(filename.lastIndexOf('.')); result = await generateMissionLogoUploadUrl(userId, missionId, fileExtension); } else if (type === 'attachment') { result = await generateMissionAttachmentUploadUrl(userId, missionId, filename); } else { return NextResponse.json({ error: 'Invalid upload type' }, { status: 400 }); } return NextResponse.json(result); } catch (error) { console.error('Error generating upload URL:', error); return NextResponse.json({ error: 'Internal server error', details: error instanceof Error ? error.message : String(error) }, { status: 500 }); } } // Handle file upload (server-side) export async function POST(request: Request) { try { const { authorized, userId } = await checkAuth(request); if (!authorized || !userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } // Parse the form data const formData = await request.formData(); const missionId = formData.get('missionId') as string; const type = formData.get('type') as string; // 'logo' or 'attachment' const file = formData.get('file') as File; if (!missionId || !type || !file) { return NextResponse.json({ error: 'Missing required fields', required: { missionId: true, type: true, file: true }, received: { missionId: !!missionId, type: !!type, file: !!file } }, { status: 400 }); } // Verify that the mission exists and user has access to it const mission = await prisma.mission.findUnique({ where: { id: missionId }, select: { id: true, creatorId: true } }); if (!mission) { return NextResponse.json({ error: 'Mission not found' }, { status: 404 }); } // Currently only allow creator to upload files if (mission.creatorId !== userId) { return NextResponse.json({ error: 'Not authorized to upload to this mission' }, { status: 403 }); } if (type === 'logo') { // Upload logo file to Minio const { filePath } = await uploadMissionLogo(userId, missionId, file); // Update mission record with logo path await prisma.mission.update({ where: { id: missionId }, data: { logo: filePath } }); return NextResponse.json({ success: true, filePath }); } else if (type === 'attachment') { // Upload attachment file to Minio const { filename, filePath, fileType, fileSize } = await uploadMissionAttachment( userId, missionId, file ); // Create attachment record in database const attachment = await prisma.attachment.create({ data: { filename, filePath, fileType, fileSize, missionId, uploaderId: userId } }); return NextResponse.json({ success: true, attachment: { id: attachment.id, filename: attachment.filename, filePath: attachment.filePath, fileType: attachment.fileType, fileSize: attachment.fileSize, createdAt: attachment.createdAt } }); } else { return NextResponse.json({ error: 'Invalid upload type' }, { status: 400 }); } } catch (error) { console.error('Error uploading file:', error); return NextResponse.json({ error: 'Internal server error', details: error instanceof Error ? error.message : String(error) }, { status: 500 }); } }