- 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
109 lines
2.8 KiB
JavaScript
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;
|
|
}
|
|
};
|