From be3a8a82ab1aa1c33401ad258d9403c65b7f2b59 Mon Sep 17 00:00:00 2001 From: Daniel S Date: Sat, 8 Aug 2026 18:56:21 +0200 Subject: [PATCH] feat(api): add SSR config update endpoints and DSGVO contact processing --- src/pages/api/config.ts | 39 +++++++++++++++++++++++++++++ src/pages/api/contact.ts | 30 +++++++++++++++++++++++ src/pages/api/update-config.ts | 45 ++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/pages/api/config.ts create mode 100644 src/pages/api/contact.ts create mode 100644 src/pages/api/update-config.ts diff --git a/src/pages/api/config.ts b/src/pages/api/config.ts new file mode 100644 index 0000000..71b1662 --- /dev/null +++ b/src/pages/api/config.ts @@ -0,0 +1,39 @@ +import type { APIRoute } from 'astro'; +import fs from 'fs'; +import path from 'path'; +import { loadWaasConfigs } from '../../utils/configLoader'; + +export const POST: APIRoute = async ({ request }) => { + try { + const body = await request.json(); + const dataDir = process.env.DATA_DIR || path.join(process.cwd(), 'app', 'data'); + if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); + } + + const { siteConfig: currentSite, themeConfig: currentTheme, smtpConfig: currentSmtp } = loadWaasConfigs(); + + if (body.siteConfig) { + const newSite = { + ...currentSite, + ...body.siteConfig, + hero: { ...currentSite.hero, ...body.siteConfig.hero } + }; + fs.writeFileSync(path.join(dataDir, 'site.config.json'), JSON.stringify(newSite, null, 2), 'utf8'); + } + + if (body.themeConfig) { + const newTheme = { ...currentTheme, ...body.themeConfig }; + fs.writeFileSync(path.join(dataDir, 'theme.config.json'), JSON.stringify(newTheme, null, 2), 'utf8'); + } + + if (body.smtpConfig) { + const newSmtp = { ...currentSmtp, ...body.smtpConfig }; + fs.writeFileSync(path.join(dataDir, 'smtp.config.json'), JSON.stringify(newSmtp, null, 2), 'utf8'); + } + + return new Response(JSON.stringify({ success: true, message: 'Konfiguration gespeichert' }), { status: 200, headers: { 'Content-Type': 'application/json' } }); + } catch (err: any) { + return new Response(JSON.stringify({ success: false, message: err.message }), { status: 500, headers: { 'Content-Type': 'application/json' } }); + } +}; \ No newline at end of file diff --git a/src/pages/api/contact.ts b/src/pages/api/contact.ts new file mode 100644 index 0000000..7208579 --- /dev/null +++ b/src/pages/api/contact.ts @@ -0,0 +1,30 @@ +import type { APIRoute } from 'astro'; +import { loadWaasConfigs } from '../../utils/configLoader'; +import nodemailer from 'nodemailer'; + +export const POST: APIRoute = async ({ request }) => { + try { + const data = await request.formData(); + const name = data.get('name')?.toString() || ''; + const email = data.get('email')?.toString() || ''; + const message = data.get('message')?.toString() || ''; + + if (!name || !email || !message) { + return new Response(JSON.stringify({ success: false, message: 'Bitte füllen Sie alle Pflichtfelder aus.' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); + } + + const { smtpConfig, siteConfig } = loadWaasConfigs(); + + if (!smtpConfig.isConfigured || smtpConfig.host === 'smtp.placeholder.local') { + console.log('[WaaS Contact API] (Demo Mode) Received Submission:', { name, email, message }); + return new Response(JSON.stringify({ success: true, mode: 'placeholder', message: 'Anfrage erfolgreich empfangen! (Demo-Modus)' }), { status: 200, headers: { 'Content-Type': 'application/json' } }); + } + + const transporter = nodemailer.createTransport({ host: smtpConfig.host, port: smtpConfig.port, secure: smtpConfig.secure, auth: { user: smtpConfig.user, pass: smtpConfig.pass } }); + const sender = smtpConfig.fromName + ' ' + smtpConfig.fromEmail; + await transporter.sendMail({ from: sender, to: siteConfig.contact.recipientEmail, replyTo: email, subject: '[Webseite] Neue Nachricht von ' + name, text: 'Name: ' + name + '\nEmail: ' + email + '\n\nNachricht:\n' + message }); + return new Response(JSON.stringify({ success: true, message: 'Vielen Dank für Ihre Anfrage! Wir melden uns umgehend.' }), { status: 200, headers: { 'Content-Type': 'application/json' } }); + } catch (err: any) { + return new Response(JSON.stringify({ success: false, message: 'Fehler beim Senden: ' + err.message }), { status: 500, headers: { 'Content-Type': 'application/json' } }); + } +}; \ No newline at end of file diff --git a/src/pages/api/update-config.ts b/src/pages/api/update-config.ts new file mode 100644 index 0000000..0d978b5 --- /dev/null +++ b/src/pages/api/update-config.ts @@ -0,0 +1,45 @@ +import type { APIRoute } from 'astro'; +import fs from 'fs'; +import path from 'path'; + +export const POST: APIRoute = async ({ request }) => { + try { + const body = await request.json(); + + if (!body || typeof body !== 'object') { + return new Response(JSON.stringify({ success: false, message: 'Invalid JSON payload' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }); + } + + // Validate critical fields + if (body.siteName && typeof body.siteName !== 'string') { + return new Response(JSON.stringify({ success: false, message: 'siteName must be a string' }), { + status: 400, + headers: { 'Content-Type': 'application/json' } + }); + } + + const dataDir = process.env.DATA_DIR || path.join(process.cwd(), 'app', 'data'); + if (!fs.existsSync(dataDir)) { + fs.mkdirSync(dataDir, { recursive: true }); + } + + const sitePath = path.join(dataDir, 'site.config.json'); + fs.writeFileSync(sitePath, JSON.stringify(body, null, 2), 'utf-8'); + + return new Response(JSON.stringify({ + success: true, + message: 'Site configuration successfully updated in /app/data/site.config.json' + }), { + status: 200, + headers: { 'Content-Type': 'application/json' } + }); + } catch (err: any) { + return new Response(JSON.stringify({ success: false, message: 'Fehler beim Speichern: ' + err.message }), { + status: 500, + headers: { 'Content-Type': 'application/json' } + }); + } +};