import { NextResponse } from 'next/server'; import { getServerSession } from 'next-auth'; import { authOptions } from "@/app/api/auth/options"; import { prisma } from '@/lib/prisma'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { GetObjectCommand } from '@aws-sdk/client-s3'; import { s3Client, S3_CONFIG } from '@/lib/s3'; // 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 }; } // GET endpoint to download an attachment export async function GET( request: Request, props: { params: Promise<{ missionId: string, attachmentId: string }> } ) { const params = await props.params; try { const { authorized, userId } = await checkAuth(request); if (!authorized || !userId) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const { missionId, attachmentId } = params; if (!missionId || !attachmentId) { return NextResponse.json({ error: 'Mission ID and Attachment ID are required' }, { status: 400 }); } // Check if mission exists and user has access to it const mission = await prisma.mission.findFirst({ where: { id: missionId, OR: [ { creatorId: userId }, { missionUsers: { some: { userId } } } ] }, }); if (!mission) { return NextResponse.json({ error: 'Mission not found or access denied' }, { status: 404 }); } // Get the attachment const attachment = await prisma.attachment.findUnique({ where: { id: attachmentId, missionId } }); if (!attachment) { return NextResponse.json({ error: 'Attachment not found' }, { status: 404 }); } // Generate a presigned URL for downloading const command = new GetObjectCommand({ Bucket: S3_CONFIG.bucket, Key: attachment.filePath }); // Set a short expiry for security (5 minutes) const url = await getSignedUrl(s3Client, command, { expiresIn: 300 }); // Redirect the user to the presigned URL for direct download return NextResponse.redirect(url); } catch (error) { console.error('Error downloading attachment:', error); return NextResponse.json({ error: 'Internal server error', details: error instanceof Error ? error.message : String(error) }, { status: 500 }); } }