import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from "@/app/api/auth/options"; import { prisma } from '@/lib/prisma'; import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'; // S3 Configuration for missions - uses environment variables const MISSIONS_S3_CONFIG = { endpoint: (process.env.MINIO_S3_UPLOAD_BUCKET_URL || process.env.S3_ENDPOINT || 'https://dome-api.slm-lab.net').replace(/\/$/, ''), region: process.env.MINIO_AWS_REGION || process.env.S3_REGION || 'us-east-1', accessKey: process.env.MINIO_ACCESS_KEY || process.env.S3_ACCESS_KEY || '', secretKey: process.env.MINIO_SECRET_KEY || process.env.S3_SECRET_KEY || '', bucket: 'missions' // Missions bucket is always 'missions' }; // Validate required S3 configuration if (!MISSIONS_S3_CONFIG.accessKey || !MISSIONS_S3_CONFIG.secretKey) { const errorMsg = '⚠️ S3 credentials are missing! Please set MINIO_ACCESS_KEY and MINIO_SECRET_KEY environment variables.'; console.error(errorMsg); if (process.env.NODE_ENV === 'production') { throw new Error('S3 credentials are required in production environment'); } } // Use the exact same S3 client configuration as mission-uploads.ts const missionsS3Client = new S3Client({ region: MISSIONS_S3_CONFIG.region, endpoint: MISSIONS_S3_CONFIG.endpoint, credentials: { accessKeyId: MISSIONS_S3_CONFIG.accessKey, secretAccessKey: MISSIONS_S3_CONFIG.secretKey }, forcePathStyle: true // Required for MinIO }); const MISSIONS_BUCKET = MISSIONS_S3_CONFIG.bucket; // 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: folders cannot be created in closed missions' }, { status: 403 }); } if (!canManage) { return NextResponse.json({ error: 'Forbidden: You do not have permission to create folders' }, { status: 403 }); } const body = await request.json(); const { path } = body; if (!path) { return NextResponse.json({ error: 'Path is required' }, { status: 400 }); } // Construct the S3 key for the folder marker // Files are stored in MinIO without the "missions/" prefix // The path from frontend might be relative (e.g., "attachments/Content") or absolute // We need to ensure it includes the missionId let folderPath = path; if (!folderPath.startsWith(missionId)) { // If path doesn't start with missionId, prepend it folderPath = `${missionId}/${folderPath}`; } // Remove "missions/" prefix if present (for consistency) folderPath = folderPath.replace(/^missions\//, ''); const s3Key = folderPath.endsWith('/') ? `${folderPath}.placeholder` : `${folderPath}/.placeholder`; console.log(`[POST /api/missions/${missionId}/files/folder] Creating folder:`, { originalPath: path, folderPath: folderPath, s3Key: s3Key, bucket: MISSIONS_BUCKET }); // Create folder marker in S3 await missionsS3Client.send(new PutObjectCommand({ Bucket: MISSIONS_BUCKET, Key: s3Key, Body: Buffer.alloc(0), ContentType: 'application/octet-stream' })); return NextResponse.json({ success: true, folder: { type: 'folder', name: path.split('/').pop() || path, path: `missions/${path}`, key: `missions/${path}` } }); } catch (error: any) { console.error('Error creating folder:', error); return NextResponse.json( { error: 'Failed to create folder', details: error.message }, { status: 500 } ); } }