diff --git a/backend/src/middlewares/rateLimiter.js b/backend/src/middlewares/rateLimiter.js index c8da43d..c965541 100644 --- a/backend/src/middlewares/rateLimiter.js +++ b/backend/src/middlewares/rateLimiter.js @@ -13,7 +13,7 @@ const blockedIPs = new Map(); // IP -> { reason, blockedUntil, failedAttempts // Konfiguration const RATE_LIMIT = { - MAX_REQUESTS_PER_HOUR: 10, + MAX_REQUESTS_PER_HOUR: process.env.NODE_ENV === 'production' ? 10 : 100, // 100 für Dev, 10 für Production WINDOW_MS: 60 * 60 * 1000, // 1 Stunde BRUTE_FORCE_THRESHOLD: 20, BLOCK_DURATION_MS: 24 * 60 * 60 * 1000 // 24 Stunden diff --git a/frontend/src/Components/Pages/ManagementPortalPage.js b/frontend/src/Components/Pages/ManagementPortalPage.js index b3e68b8..3d0bdce 100644 --- a/frontend/src/Components/Pages/ManagementPortalPage.js +++ b/frontend/src/Components/Pages/ManagementPortalPage.js @@ -227,24 +227,43 @@ const ManagementPortalPage = () => { ? 'Werkstatt-Anzeige' : group.consents.socialMediaConsents.find(c => c.platformId === platformId)?.platformDisplayName || 'Social Media'; - const result = await Swal.fire({ - title: `Einwilligung widerrufen?`, - html: `Möchten Sie Ihre Einwilligung für ${consentName} widerrufen?

- Ihre Bilder werden dann nicht mehr für diesen Zweck verwendet.`, - icon: 'warning', - showCancelButton: true, - confirmButtonColor: '#d33', - cancelButtonColor: '#3085d6', - confirmButtonText: 'Ja, widerrufen', - cancelButtonText: 'Abbrechen' - }); - - if (!result.isConfirmed) return; + if (consentType === 'workshop') { + const result = await Swal.fire({ + title: `Einwilligung widerrufen?`, + html: `Möchten Sie Ihre Einwilligung für ${consentName} widerrufen?

+ Ihre Bilder werden aus der Werkstatt-Anzeige entfernt.`, + icon: 'warning', + showCancelButton: true, + confirmButtonColor: '#d33', + cancelButtonColor: '#3085d6', + confirmButtonText: 'Ja, widerrufen', + cancelButtonText: 'Abbrechen' + }); + + if (!result.isConfirmed) return; + } else { + // Social Media Widerruf + const result = await Swal.fire({ + title: `Einwilligung widerrufen?`, + html: `Möchten Sie Ihre Einwilligung für ${consentName} widerrufen?

+ Ihre Bilder werden nicht mehr auf ${consentName} veröffentlicht.
+ Bereits veröffentlichte Beiträge bleiben bestehen, aber es werden keine neuen Posts mit Ihren Bildern erstellt.
`, + icon: 'warning', + showCancelButton: true, + confirmButtonColor: '#d33', + cancelButtonColor: '#3085d6', + confirmButtonText: 'Ja, widerrufen', + cancelButtonText: 'Abbrechen', + footer: `
Wenn Sie die Löschung bereits veröffentlichter Beiträge wünschen, kontaktieren Sie uns nach dem Widerruf.
` + }); + + if (!result.isConfirmed) return; + } try { const payload = consentType === 'workshop' - ? { workshopConsent: false } - : { socialMediaConsents: [{ platformId, consented: false }] }; + ? { consentType: 'workshop', action: 'revoke' } + : { consentType: 'social_media', action: 'revoke', platformId }; const res = await fetch(`/api/manage/${token}/consents`, { method: 'PUT', @@ -257,13 +276,33 @@ const ManagementPortalPage = () => { throw new Error(body.error || 'Fehler beim Widerrufen'); } - await Swal.fire({ - icon: 'success', - title: 'Einwilligung widerrufen', - text: `Ihre Einwilligung für ${consentName} wurde widerrufen.`, - timer: 2000, - showConfirmButton: false - }); + // Erfolg - zeige Bestätigung mit Kontaktinfo für Social Media + if (consentType === 'social-media') { + const mailtoLink = `mailto:it@hobbyhimmel.de?subject=${encodeURIComponent(`Löschung Social Media Post - Gruppe ${group.groupId}`)}&body=${encodeURIComponent(`Hallo,\n\nBitte löschen Sie die bereits veröffentlichten Beiträge meiner Gruppe ${group.groupId} von ${consentName}.\n\nVielen Dank`)}`; + + await Swal.fire({ + icon: 'success', + title: 'Einwilligung widerrufen', + html: `Ihre Einwilligung für ${consentName} wurde widerrufen.

+
+ Bereits veröffentlichte Beiträge löschen?
+ Kontaktieren Sie uns mit Ihrer Gruppen-ID:
+
+ Gruppen-ID: ${group.groupId}
+ E-Mail: it@hobbyhimmel.de +
+
`, + confirmButtonText: 'Verstanden' + }); + } else { + await Swal.fire({ + icon: 'success', + title: 'Einwilligung widerrufen', + text: `Ihre Einwilligung für ${consentName} wurde widerrufen.`, + timer: 2000, + showConfirmButton: false + }); + } // Reload group to get updated consent status await loadGroup(); @@ -299,8 +338,8 @@ const ManagementPortalPage = () => { try { const payload = consentType === 'workshop' - ? { workshopConsent: true } - : { socialMediaConsents: [{ platformId, consented: true }] }; + ? { consentType: 'workshop', action: 'restore' } + : { consentType: 'social_media', action: 'restore', platformId }; const res = await fetch(`/api/manage/${token}/consents`, { method: 'PUT', diff --git a/frontend/src/Components/Pages/MultiUploadPage.js b/frontend/src/Components/Pages/MultiUploadPage.js index 4e2e8d9..ad75937 100644 --- a/frontend/src/Components/Pages/MultiUploadPage.js +++ b/frontend/src/Components/Pages/MultiUploadPage.js @@ -362,6 +362,80 @@ function MultiUploadPage() { + {uploadResult?.managementToken && ( + + + 🔗 Verwaltungslink für Ihren Upload + + + Mit diesem Link können Sie später Ihre Bilder verwalten, Einwilligungen widerrufen oder die Gruppe löschen: + + + + + {window.location.origin}/manage/{uploadResult.managementToken} + + + + + + ⚠️ Wichtig: Bewahren Sie diesen Link sicher auf! Jeder mit diesem Link kann Ihren Upload verwalten. + + + ℹ️ Hinweis: Über diesen Link können Sie nur die Bilder in der Werkstatt verwalten. Bereits auf Social Media Plattformen veröffentlichte Bilder müssen separat dort gelöscht werden. + + + )} + Die Bilder werden geprüft und nach Freigabe auf dem Werkstatt-Monitor angezeigt. {' '}Bei Social Media Einwilligung werden sie entsprechend veröffentlicht.