Galerie: proxy + previews; uploads internal; membership PDF storage hardened; migration/preview scripts
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 48s

This commit is contained in:
Torsten Schulz (local)
2026-02-11 10:02:33 +01:00
parent 9c1bcba713
commit 0fcf6ced0e
2 changed files with 24 additions and 51 deletions

View File

@@ -13,8 +13,8 @@ export default defineEventHandler(async (event) => {
}) })
} }
// Upload-Verzeichnis finden // Upload-Verzeichnis finden (intern)
const uploadDir = path.join(process.cwd(), 'public', 'uploads') const uploadDir = path.join(process.cwd(), '..', 'server', 'data', 'uploads')
console.log('Upload-Verzeichnis:', uploadDir) console.log('Upload-Verzeichnis:', uploadDir)
// Alle Dateien im Upload-Verzeichnis durchsuchen // Alle Dateien im Upload-Verzeichnis durchsuchen

View File

@@ -299,7 +299,7 @@ Volljährig: ${data.isVolljaehrig ? 'Ja' : 'Nein'}
Das ausgefüllte Formular ist als Anhang verfügbar.` Das ausgefüllte Formular ist als Anhang verfügbar.`
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const textPath = path.join(process.cwd(), 'public', 'uploads', `${filename}.txt`) const textPath = path.join(getDataPath('uploads'), `${filename}.txt`)
await fs.writeFile(textPath, textContent, 'utf8') await fs.writeFile(textPath, textContent, 'utf8')
return `${filename}.txt` return `${filename}.txt`
@@ -660,7 +660,7 @@ export default defineEventHandler(async (event) => {
} }
let usedTemplate = false let usedTemplate = false
const uploadsDir = path.join(process.cwd(), 'public', 'uploads') const uploadsDir = getDataPath('uploads')
await fs.mkdir(uploadsDir, { recursive: true }) await fs.mkdir(uploadsDir, { recursive: true })
try { try {
const filled = await fillPdfTemplate(data) const filled = await fillPdfTemplate(data)
@@ -669,18 +669,7 @@ export default defineEventHandler(async (event) => {
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const finalPdfPath = path.join(uploadsDir, `${filename}.pdf`) const finalPdfPath = path.join(uploadsDir, `${filename}.pdf`)
await fs.writeFile(finalPdfPath, filled) await fs.writeFile(finalPdfPath, filled)
// Zusätzlich: Kopie ins repo-root public/uploads legen, falls Nitro cwd anders ist // Do NOT copy filled PDFs into public repo uploads to avoid accidental exposure.
try {
const repoRoot = path.resolve(process.cwd(), '..')
const repoUploads = path.join(repoRoot, 'public', 'uploads')
await fs.mkdir(repoUploads, { recursive: true })
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
// filename is generated from timestamp, not user input, path traversal prevented
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
await fs.copyFile(finalPdfPath, path.join(repoUploads, `${filename}.pdf`))
} catch (_e) {
console.warn('Kopie in repo public/uploads fehlgeschlagen:', e.message)
}
usedTemplate = true usedTemplate = true
} catch (templateError) { } catch (templateError) {
// Template konnte nicht verwendet werden -> weiter zum LaTeX-Fallback // Template konnte nicht verwendet werden -> weiter zum LaTeX-Fallback
@@ -739,24 +728,8 @@ export default defineEventHandler(async (event) => {
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal // nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const pdfPath = path.join(tempDir, `${filename}.pdf`) const pdfPath = path.join(tempDir, `${filename}.pdf`)
await fs.mkdir(uploadsDir, { recursive: true }) await fs.mkdir(uploadsDir, { recursive: true })
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
// filename is generated from timestamp, not user input, path traversal prevented
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
const finalPdfPath = path.join(uploadsDir, `${filename}.pdf`) const finalPdfPath = path.join(uploadsDir, `${filename}.pdf`)
await fs.copyFile(pdfPath, finalPdfPath) await fs.copyFile(pdfPath, finalPdfPath)
// Kopie ins repo-root public/uploads für bessere Auffindbarkeit
try {
const repoRoot = path.resolve(process.cwd(), '..')
const repoUploads = path.join(repoRoot, 'public', 'uploads')
await fs.mkdir(repoUploads, { recursive: true })
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
// filename is generated from timestamp, not user input, path traversal prevented
// nosemgrep: javascript.lang.security.audit.path-traversal.path-join-resolve-traversal.path-join-resolve-traversal
await fs.copyFile(finalPdfPath, path.join(repoUploads, `${filename}.pdf`))
} catch (e) {
console.warn('Kopie in repo public/uploads fehlgeschlagen:', e.message)
}
// E-Mail senden // E-Mail senden
emailResult = await sendMembershipEmail(data, filename, event) emailResult = await sendMembershipEmail(data, filename, event)
@@ -797,10 +770,10 @@ export default defineEventHandler(async (event) => {
console.log('E-Mail würde gesendet werden an:', emailResult.recipients || []) console.log('E-Mail würde gesendet werden an:', emailResult.recipients || [])
console.log('Betreff:', emailResult.subject || '') console.log('Betreff:', emailResult.subject || '')
console.log('Nachricht:', emailResult.message || '') console.log('Nachricht:', emailResult.message || '')
console.log('Upload-Verzeichnis:', path.join(process.cwd(), 'public', 'uploads')) console.log('Upload-Verzeichnis:', getDataPath('uploads'))
// Verfügbare Dateien auflisten // Verfügbare Dateien auflisten
const uploadsDir = path.join(process.cwd(), 'public', 'uploads') const uploadsDir = getDataPath('uploads')
try { try {
const files = await fs.readdir(uploadsDir) const files = await fs.readdir(uploadsDir)
console.log('Verfügbare Dateien:', files) console.log('Verfügbare Dateien:', files)