wip(phase2): Task 17 - Management-Link in Upload-Erfolg & Rate-Limiter Anpassung
- Task 17: Management-Link im Upload-Erfolg angezeigt mit Copy-Button - Widerruf-Dialoge überarbeitet: Klarstellung zu Scope & Kontakt für Social Media Posts - Rate-Limiter für Dev-Umgebung erhöht (100/h statt 10/h) - Mailto-Link Verhalten noch nicht final getestet (Browser vs. Mail-Client) ACHTUNG: Noch nicht vollständig getestet! Mailto-Funktionalität muss in verschiedenen Browsern validiert werden.
This commit is contained in:
parent
cedc1380dd
commit
e065f2bbc4
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <strong>${consentName}</strong> widerrufen?<br><br>
|
||||
<small>Ihre Bilder werden dann nicht mehr für diesen Zweck verwendet.</small>`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ja, widerrufen',
|
||||
cancelButtonText: 'Abbrechen'
|
||||
});
|
||||
if (consentType === 'workshop') {
|
||||
const result = await Swal.fire({
|
||||
title: `Einwilligung widerrufen?`,
|
||||
html: `Möchten Sie Ihre Einwilligung für <strong>${consentName}</strong> widerrufen?<br><br>
|
||||
<small>Ihre Bilder werden aus der Werkstatt-Anzeige entfernt.</small>`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ja, widerrufen',
|
||||
cancelButtonText: 'Abbrechen'
|
||||
});
|
||||
|
||||
if (!result.isConfirmed) return;
|
||||
if (!result.isConfirmed) return;
|
||||
} else {
|
||||
// Social Media Widerruf
|
||||
const result = await Swal.fire({
|
||||
title: `Einwilligung widerrufen?`,
|
||||
html: `Möchten Sie Ihre Einwilligung für <strong>${consentName}</strong> widerrufen?<br><br>
|
||||
<small>Ihre Bilder werden nicht mehr auf ${consentName} veröffentlicht.<br>
|
||||
Bereits veröffentlichte Beiträge bleiben bestehen, aber es werden keine neuen Posts mit Ihren Bildern erstellt.</small>`,
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#d33',
|
||||
cancelButtonColor: '#3085d6',
|
||||
confirmButtonText: 'Ja, widerrufen',
|
||||
cancelButtonText: 'Abbrechen',
|
||||
footer: `<div style="font-size: 13px; color: #666;">Wenn Sie die Löschung bereits veröffentlichter Beiträge wünschen, kontaktieren Sie uns nach dem Widerruf.</div>`
|
||||
});
|
||||
|
||||
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.<br><br>
|
||||
<div style="background: #f5f5f5; padding: 15px; border-radius: 8px; margin-top: 15px;">
|
||||
<strong>Bereits veröffentlichte Beiträge löschen?</strong><br>
|
||||
<small>Kontaktieren Sie uns mit Ihrer Gruppen-ID:</small><br>
|
||||
<div style="margin-top: 10px;">
|
||||
<strong>Gruppen-ID:</strong> ${group.groupId}<br>
|
||||
<strong>E-Mail:</strong> <span style="color: #1976d2; cursor: pointer;" onclick="window.open='${mailtoLink}'">it@hobbyhimmel.de</span>
|
||||
</div>
|
||||
</div>`,
|
||||
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',
|
||||
|
|
|
|||
|
|
@ -362,6 +362,80 @@ function MultiUploadPage() {
|
|||
</Typography>
|
||||
</Box>
|
||||
|
||||
{uploadResult?.managementToken && (
|
||||
<Box sx={{
|
||||
bgcolor: 'rgba(255,255,255,0.95)',
|
||||
borderRadius: '8px',
|
||||
p: 2.5,
|
||||
mb: 2,
|
||||
border: '2px solid rgba(255,255,255,0.3)'
|
||||
}}>
|
||||
<Typography sx={{ fontSize: '16px', fontWeight: 'bold', mb: 1.5, color: '#2e7d32' }}>
|
||||
🔗 Verwaltungslink für Ihren Upload
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: '13px', mb: 1.5, color: '#333' }}>
|
||||
Mit diesem Link können Sie später Ihre Bilder verwalten, Einwilligungen widerrufen oder die Gruppe löschen:
|
||||
</Typography>
|
||||
|
||||
<Box sx={{
|
||||
bgcolor: '#f5f5f5',
|
||||
p: 1.5,
|
||||
borderRadius: '6px',
|
||||
mb: 1.5,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
flexWrap: 'wrap'
|
||||
}}>
|
||||
<Typography sx={{
|
||||
fontSize: '13px',
|
||||
fontFamily: 'monospace',
|
||||
color: '#1976d2',
|
||||
wordBreak: 'break-all',
|
||||
flex: 1,
|
||||
minWidth: '200px'
|
||||
}}>
|
||||
{window.location.origin}/manage/{uploadResult.managementToken}
|
||||
</Typography>
|
||||
<Button
|
||||
size="small"
|
||||
sx={{
|
||||
minWidth: 'auto',
|
||||
px: 2,
|
||||
py: 0.5,
|
||||
fontSize: '12px',
|
||||
textTransform: 'none',
|
||||
bgcolor: '#1976d2',
|
||||
color: 'white',
|
||||
'&:hover': {
|
||||
bgcolor: '#1565c0'
|
||||
}
|
||||
}}
|
||||
onClick={() => {
|
||||
const link = `${window.location.origin}/manage/${uploadResult.managementToken}`;
|
||||
navigator.clipboard.writeText(link);
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Link kopiert!',
|
||||
text: 'Der Verwaltungslink wurde in die Zwischenablage kopiert.',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
}}
|
||||
>
|
||||
📋 Kopieren
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Typography sx={{ fontSize: '11px', color: '#666', mb: 0.5 }}>
|
||||
⚠️ <strong>Wichtig:</strong> Bewahren Sie diesen Link sicher auf! Jeder mit diesem Link kann Ihren Upload verwalten.
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: '11px', color: '#666', fontStyle: 'italic' }}>
|
||||
ℹ️ <strong>Hinweis:</strong> Ü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.
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Typography sx={{ fontSize: '13px', mb: 2, opacity: 0.95 }}>
|
||||
Die Bilder werden geprüft und nach Freigabe auf dem Werkstatt-Monitor angezeigt.
|
||||
{' '}Bei Social Media Einwilligung werden sie entsprechend veröffentlicht.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user