170 lines
4.5 KiB
TypeScript
170 lines
4.5 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server'
|
|
import { getServerSession } from 'next-auth'
|
|
import { authOptions } from '@/lib/auth'
|
|
import { uploadToR2, validateUploadFile } from '@/lib/r2-upload'
|
|
import { addPortfolioImage } from '@/lib/db'
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
// Check authentication
|
|
const session = await getServerSession(authOptions)
|
|
if (!session?.user) {
|
|
return NextResponse.json(
|
|
{ error: 'Unauthorized' },
|
|
{ status: 401 }
|
|
)
|
|
}
|
|
|
|
const formData = await request.formData()
|
|
const file = formData.get('file') as File
|
|
const key = formData.get('key') as string | undefined
|
|
const artistId = formData.get('artistId') as string | undefined
|
|
const caption = formData.get('caption') as string | undefined
|
|
const tags = formData.get('tags') as string | undefined
|
|
|
|
if (!file) {
|
|
return NextResponse.json(
|
|
{ error: 'No file provided' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Validate file
|
|
const validation = validateUploadFile(file, {
|
|
maxSize: 10 * 1024 * 1024, // 10MB
|
|
allowedTypes: ['image/jpeg', 'image/png', 'image/webp', 'image/gif']
|
|
})
|
|
|
|
if (!validation.valid) {
|
|
return NextResponse.json(
|
|
{ error: validation.error },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Upload to R2
|
|
const uploadResult = await uploadToR2(file, key, {
|
|
contentType: file.type,
|
|
metadata: {
|
|
uploadedBy: session.user.id,
|
|
uploadedAt: new Date().toISOString(),
|
|
originalName: file.name,
|
|
artistId: artistId || '',
|
|
caption: caption || '',
|
|
tags: tags || '',
|
|
}
|
|
})
|
|
|
|
if (!uploadResult.success) {
|
|
return NextResponse.json(
|
|
{ error: uploadResult.error || 'Upload failed' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
|
|
// If this is a portfolio image, save to database
|
|
if (artistId && uploadResult.url) {
|
|
try {
|
|
const parsedTags = tags ? JSON.parse(tags) : []
|
|
await addPortfolioImage(artistId, {
|
|
url: uploadResult.url,
|
|
caption: caption || undefined,
|
|
tags: parsedTags,
|
|
orderIndex: 0,
|
|
isPublic: true
|
|
})
|
|
} catch (dbError) {
|
|
console.error('Failed to save portfolio image to database:', dbError)
|
|
// Continue anyway - the file was uploaded successfully
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
url: uploadResult.url,
|
|
key: uploadResult.key,
|
|
filename: file.name,
|
|
size: file.size,
|
|
type: file.type
|
|
})
|
|
} catch (error) {
|
|
console.error('Upload error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Upload failed' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|
|
|
|
export async function DELETE(request: NextRequest) {
|
|
try {
|
|
// Check authentication
|
|
const session = await getServerSession(authOptions)
|
|
if (!session?.user) {
|
|
return NextResponse.json(
|
|
{ error: 'Unauthorized' },
|
|
{ status: 401 }
|
|
)
|
|
}
|
|
|
|
const { searchParams } = new URL(request.url)
|
|
const key = searchParams.get('key')
|
|
|
|
if (!key) {
|
|
return NextResponse.json(
|
|
{ error: 'File key is required' },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// TODO: Check if user has permission to delete this file
|
|
// For now, allow any authenticated user to delete
|
|
|
|
const { deleteFromR2 } = await import('@/lib/r2-upload')
|
|
const success = await deleteFromR2(key)
|
|
|
|
if (!success) {
|
|
return NextResponse.json(
|
|
{ error: 'Failed to delete file' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: 'File deleted successfully'
|
|
})
|
|
} catch (error) {
|
|
console.error('Delete error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Delete failed' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|
|
|
|
// GET /api/upload/presigned - Generate presigned upload URL (placeholder for future implementation)
|
|
export async function GET(request: NextRequest) {
|
|
try {
|
|
// Check authentication
|
|
const session = await getServerSession(authOptions)
|
|
if (!session?.user) {
|
|
return NextResponse.json(
|
|
{ error: 'Unauthorized' },
|
|
{ status: 401 }
|
|
)
|
|
}
|
|
|
|
// For now, return a message that presigned URLs are not implemented
|
|
return NextResponse.json({
|
|
error: 'Presigned URLs not implemented yet. Use direct upload via POST.'
|
|
}, { status: 501 })
|
|
} catch (error) {
|
|
console.error('Presigned URL error:', error)
|
|
return NextResponse.json(
|
|
{ error: 'Failed to generate presigned URL' },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|