Project-Image-Uploader/frontend/src/services/adminErrorHandler.js
matthias.lotz 6332b82c6a Feature Request: admin session security
- replace bearer auth with session+CSRF flow and add admin user directory

- update frontend moderation flow, force password change gate, and new CLI

- refresh changelog/docs/feature plan + ensure swagger dev experience
2025-11-23 21:18:42 +01:00

109 lines
2.8 KiB
JavaScript

import Swal from 'sweetalert2/dist/sweetalert2.js';
/**
* Zentrale Error-Handler für Admin API Fehler
*/
/**
* Behandelt Admin API Fehler mit benutzerfreundlichen Meldungen
* @param {Error} error - Der aufgetretene Fehler
* @param {string} context - Kontext der Operation (z.B. "Gruppe laden")
* @returns {Promise<void>}
*/
export const handleAdminError = async (error, context = 'Operation') => {
console.error(`Admin API Error [${context}]:`, error);
const status = error?.status;
const reason = error?.reason || error?.code || error?.payload?.reason;
// Session missing or expired
if (status === 401 || reason === 'SESSION_REQUIRED') {
await Swal.fire({
icon: 'warning',
title: 'Anmeldung erforderlich',
text: 'Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.',
confirmButtonText: 'Zum Login'
});
return;
}
// CSRF token invalid or missing
if (status === 403 && (reason === 'CSRF_INVALID' || reason === 'CSRF_REQUIRED')) {
await Swal.fire({
icon: 'warning',
title: 'Sicherheitsüberprüfung fehlgeschlagen',
text: 'Bitte laden Sie die Seite neu und versuchen Sie es erneut.',
confirmButtonText: 'Neu laden'
});
return;
}
// Generic forbidden
if (status === 403) {
await Swal.fire({
icon: 'error',
title: 'Keine Berechtigung',
text: 'Sie besitzen keine Berechtigung für diese Aktion.',
confirmButtonText: 'OK'
});
return;
}
// Rate limit
if (status === 429) {
await Swal.fire({
icon: 'warning',
title: 'Zu viele Anfragen',
text: 'Bitte warten Sie einen Moment und versuchen Sie es erneut.',
timer: 3000,
showConfirmButton: false
});
return;
}
// Not found
if (status === 404) {
await Swal.fire({
icon: 'error',
title: 'Nicht gefunden',
text: 'Die angeforderte Ressource wurde nicht gefunden.',
confirmButtonText: 'OK'
});
return;
}
// Server error
if (status && status >= 500) {
await Swal.fire({
icon: 'error',
title: 'Server-Fehler',
text: 'Ein interner Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.',
confirmButtonText: 'OK'
});
return;
}
// Generic fallback
await Swal.fire({
icon: 'error',
title: `Fehler: ${context}`,
text: error?.message || 'Ein unbekannter Fehler ist aufgetreten.',
confirmButtonText: 'OK'
});
};
/**
* Wrapper für async Operationen mit automatischem Error-Handling
* @param {Function} operation - Die auszuführende async Operation
* @param {string} context - Kontext der Operation
* @returns {Promise<any>} - Ergebnis der Operation oder null bei Fehler
*/
export const withErrorHandling = async (operation, context) => {
try {
return await operation();
} catch (error) {
await handleAdminError(error, context);
return null;
}
};