import multer from 'multer' import fs from 'fs/promises' import path from 'path' import sharp from 'sharp' import { getUserFromToken, verifyToken, hasAnyRole } from '../../utils/auth.js' import { randomUUID } from 'crypto' // Handle both dev and production paths const getDataPath = (filename) => { const cwd = process.cwd() if (cwd.endsWith('.output')) { return path.join(cwd, '../server/data', filename) } return path.join(cwd, 'server/data', filename) } const PERSONEN_DIR = getDataPath('personen') // Multer-Konfiguration für Bild-Uploads const storage = multer.diskStorage({ destination: async (req, file, cb) => { try { await fs.mkdir(PERSONEN_DIR, { recursive: true }) cb(null, PERSONEN_DIR) } catch (error) { cb(error) } }, filename: (req, file, cb) => { const ext = path.extname(file.originalname) const filename = `${randomUUID()}${ext}` cb(null, filename) } }) const upload = multer({ storage, fileFilter: (req, file, cb) => { const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'] if (allowedMimes.includes(file.mimetype)) { cb(null, true) } else { cb(new Error('Nur Bilddateien sind erlaubt (JPEG, PNG, GIF, WebP)'), false) } }, limits: { fileSize: 10 * 1024 * 1024 // 10MB Limit } }) export default defineEventHandler(async (event) => { try { // Authentifizierung prüfen const token = getCookie(event, 'auth_token') || getHeader(event, 'authorization')?.replace('Bearer ', '') if (!token) { throw createError({ statusCode: 401, statusMessage: 'Nicht authentifiziert' }) } const decoded = verifyToken(token) if (!decoded) { throw createError({ statusCode: 401, statusMessage: 'Ungültiges Token' }) } const user = await getUserFromToken(token) if (!user || !hasAnyRole(user, 'admin', 'vorstand')) { throw createError({ statusCode: 403, statusMessage: 'Keine Berechtigung zum Hochladen von Bildern' }) } // Multer-Middleware für multipart/form-data await new Promise((resolve, reject) => { upload.single('image')(event.node.req, event.node.res, (err) => { if (err) reject(err) else resolve() }) }) const file = event.node.req.file if (!file) { throw createError({ statusCode: 400, statusMessage: 'Keine Bilddatei hochgeladen' }) } // Bild mit sharp verarbeiten (EXIF-Orientierung korrigieren und optional resize) const originalPath = file.path const ext = path.extname(file.originalname) const newFilename = `${randomUUID()}${ext}` const newPath = path.join(PERSONEN_DIR, newFilename) // Bild verarbeiten: EXIF-Orientierung korrigieren await sharp(originalPath) .rotate() .toFile(newPath) // Temporäre Datei löschen await fs.unlink(originalPath).catch(() => {}) return { success: true, message: 'Bild erfolgreich hochgeladen', filename: newFilename } } catch (error) { console.error('Fehler beim Hochladen des Personenfotos:', error) if (error.statusCode) { throw error } throw createError({ statusCode: 500, statusMessage: error.message || 'Fehler beim Hochladen des Bildes' }) } })