Files
Lageplan/src/app/api/admin/icons/upload/route.ts

90 lines
2.7 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/db'
import { uploadFile } from '@/lib/minio'
import { getSession, isAdmin } from '@/lib/auth'
import { v4 as uuidv4 } from 'uuid'
const ALLOWED_TYPES = ['image/png', 'image/svg+xml', 'image/jpeg', 'image/webp']
const MAX_SIZE = 5 * 1024 * 1024 // 5MB
export async function POST(req: NextRequest) {
try {
const user = await getSession()
if (!user || (user.role !== 'SERVER_ADMIN' && user.role !== 'TENANT_ADMIN')) {
return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 403 })
}
const formData = await req.formData()
const file = formData.get('file') as File | null
const categoryId = formData.get('categoryId') as string
const iconType = (formData.get('iconType') as string) || 'STANDARD'
const name = formData.get('name') as string
if (!file || !categoryId || !name) {
return NextResponse.json(
{ error: 'Datei, Kategorie und Name sind erforderlich' },
{ status: 400 }
)
}
if (!ALLOWED_TYPES.includes(file.type)) {
return NextResponse.json(
{ error: 'Nur PNG, SVG, JPEG und WebP Dateien erlaubt' },
{ status: 400 }
)
}
if (file.size > MAX_SIZE) {
return NextResponse.json(
{ error: 'Datei zu groß (max. 5MB)' },
{ status: 400 }
)
}
// Check category exists
const category = await (prisma as any).iconCategory.findUnique({
where: { id: categoryId },
})
if (!category) {
return NextResponse.json(
{ error: 'Kategorie nicht gefunden' },
{ status: 404 }
)
}
// Generate safe filename
const ext = file.name.split('.').pop()?.toLowerCase() || 'png'
const isTenantAdmin = user.role === 'TENANT_ADMIN'
const prefix = isTenantAdmin ? `tenant-${user.tenantId}/icons` : 'icons'
const safeFileName = `${uuidv4()}.${ext}`
const fileKey = `${prefix}/${safeFileName}`
// Upload to MinIO
const buffer = Buffer.from(await file.arrayBuffer())
await uploadFile(fileKey, buffer, file.type)
// Save to DB
const icon = await (prisma as any).iconAsset.create({
data: {
name: name.trim(),
categoryId,
iconType: iconType as any,
fileKey,
mimeType: file.type,
isSystem: !isTenantAdmin, // true für Server Admin, false für Tenant Admin
tenantId: isTenantAdmin ? user.tenantId : null,
ownerId: user.id,
},
include: {
category: true,
},
})
return NextResponse.json({ icon }, { status: 201 })
} catch (error) {
console.error('Error uploading icon:', error)
return NextResponse.json({ error: 'Upload fehlgeschlagen' }, { status: 500 })
}
}