import fs from 'fs/promises' import path from 'path' import { getUserFromToken, verifyToken } from '../../utils/auth.js' // Handle both dev and production paths // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal // filename is always a hardcoded constant (e.g., 'galerie-metadata.json'), never user input const getDataPath = (filename) => { const cwd = process.cwd() if (cwd.endsWith('.output')) { // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal return path.join(cwd, '../server/data', filename) } // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal return path.join(cwd, 'server/data', filename) } const GALERIE_METADATA = getDataPath('galerie-metadata.json') async function readGalerieMetadata() { try { const data = await fs.readFile(GALERIE_METADATA, 'utf-8') return JSON.parse(data) } catch (error) { if (error.code === 'ENOENT') { return [] } throw error } } export default defineEventHandler(async (event) => { try { // Prüfe ob Benutzer eingeloggt ist let isLoggedIn = false const token = getCookie(event, 'auth_token') || getHeader(event, 'authorization')?.replace('Bearer ', '') if (token) { const decoded = verifyToken(token) if (decoded) { const user = await getUserFromToken(token) if (user && user.active) { isLoggedIn = true } } } let metadata = [] try { metadata = await readGalerieMetadata() if (!Array.isArray(metadata)) { console.warn('Galerie-Metadaten haben unerwartetes Format, verwende leere Liste') metadata = [] } } catch (e) { console.error('Fehler beim Lesen der Galerie-Metadaten, liefere leeres Ergebnis:', e.message) metadata = [] } // Filtere Bilder basierend auf Sichtbarkeit const visibleImages = metadata.filter(image => { // Defensive checks if (!image || typeof image !== 'object') return false if (image.isPublic) return true return isLoggedIn }) // Sortiere nach Upload-Datum (neueste zuerst) - defensive visibleImages.sort((a, b) => { const ta = new Date(a.uploadedAt || 0).getTime() const tb = new Date(b.uploadedAt || 0).getTime() return tb - ta }) // Pagination (defensive defaults) const page = Math.max(1, parseInt(getQuery(event).page) || 1) const perPage = Math.max(1, parseInt(getQuery(event).perPage) || 10) const start = (page - 1) * perPage const paginatedImages = visibleImages.slice(start, start + perPage) // Konsistente Rückgabeform return { success: true, images: paginatedImages.map(img => ({ id: img.id || img.filename || null, title: img.title || '', description: img.description || '', isPublic: !!img.isPublic, uploadedAt: img.uploadedAt || null, previewFilename: img.previewFilename || null })), pagination: { page, perPage, total: visibleImages.length, totalPages: Math.ceil(visibleImages.length / perPage) } } } catch (error) { console.error('Fehler beim Laden der Galerie:', error) throw createError({ statusCode: 500, statusMessage: 'Fehler beim Laden der Galerie' }) } })