import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from "@/app/api/auth/options"; import { prisma } from '@/lib/prisma'; import { uploadMissionAttachment } from '@/lib/mission-uploads'; // Helper function to check if user can manage files (creator or gardien) // Also checks if mission is closed (closed missions cannot be modified) async function checkCanManage(userId: string, missionId: string): Promise<{ canManage: boolean; isClosed: boolean }> { const mission = await prisma.mission.findFirst({ where: { id: missionId }, select: { creatorId: true, isClosed: true, missionUsers: { where: { userId }, select: { role: true } } } }); if (!mission) return { canManage: false, isClosed: false }; // If mission is closed, no one can manage files if (mission.isClosed) { return { canManage: false, isClosed: true }; } // Creator can always manage if (mission.creatorId === userId) return { canManage: true, isClosed: false }; // Gardiens can manage const userRole = mission.missionUsers[0]?.role; const canManage = userRole === 'gardien-temps' || userRole === 'gardien-parole' || userRole === 'gardien-memoire'; return { canManage, isClosed: false }; } export async function POST( request: Request, { params }: { params: Promise<{ missionId: string }> } ) { try { const session = await getServerSession(authOptions); if (!session?.user?.id) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { missionId } = await params; const userId = session.user.id; // Check if user can manage files and if mission is closed const { canManage, isClosed } = await checkCanManage(userId, missionId); if (isClosed) { return NextResponse.json({ error: 'Mission is closed: files cannot be uploaded to closed missions' }, { status: 403 }); } if (!canManage) { return NextResponse.json({ error: 'Forbidden: You do not have permission to upload files' }, { status: 403 }); } const formData = await request.formData(); const file = formData.get('file') as File; const path = formData.get('path') as string || 'attachments'; if (!file) { return NextResponse.json({ error: 'File is required' }, { status: 400 }); } // Use the existing uploadMissionAttachment function from mission-uploads.ts // This ensures we use the exact same S3 client configuration and logic console.log(`[POST /api/missions/${missionId}/files/upload] Uploading file:`, { fileName: file.name, fileSize: file.size, fileType: file.type, path: path }); // Upload using the proven function from mission-uploads.ts let uploadResult; try { uploadResult = await uploadMissionAttachment(userId, missionId, file); console.log(`[POST /api/missions/${missionId}/files/upload] Upload successful:`, { filePath: uploadResult.filePath }); } catch (uploadError: any) { console.error(`[POST /api/missions/${missionId}/files/upload] Upload failed:`, { error: uploadError.message, code: uploadError.Code, fileName: file.name }); throw uploadError; } // Create attachment record in database let attachment; try { attachment = await prisma.attachment.create({ data: { filename: uploadResult.filename, filePath: uploadResult.filePath, fileType: uploadResult.fileType, fileSize: uploadResult.fileSize, missionId: missionId, uploaderId: userId } }); console.log(`[POST /api/missions/${missionId}/files/upload] Attachment record created:`, { attachmentId: attachment.id }); } catch (dbError: any) { console.error(`[POST /api/missions/${missionId}/files/upload] Database error:`, { error: dbError.message, fileName: file.name }); // File was uploaded but DB record creation failed - still return success but log the error // The file exists in S3 even if the DB record doesn't } return NextResponse.json({ success: true, file: { type: 'file', name: uploadResult.filename, path: uploadResult.filePath, key: uploadResult.filePath, size: uploadResult.fileSize, lastModified: new Date().toISOString() } }); } catch (error: any) { console.error('Error uploading file:', error); return NextResponse.json( { error: 'Failed to upload file', details: error.message }, { status: 500 } ); } }