Merge-Konflikt aufgelöst: AuthService und ErrorHandler wiederhergestellt
- AuthService mit allen Methoden (register, login, forgotPassword, resetPassword, logout) - ErrorHandler für zentrale Fehlerbehandlung - authController.js auf neue Clean Code Architektur umgestellt - Alle Authentifizierungsendpunkte verwenden jetzt Service Layer Pattern
This commit is contained in:
@@ -1,71 +1,139 @@
|
||||
/**
|
||||
* Zentrale Fehlerbehandlung für die Anwendung
|
||||
*/
|
||||
class ErrorHandler {
|
||||
/**
|
||||
* Error in HTTP Response umwandeln
|
||||
* Erstellt eine standardisierte Fehlerantwort
|
||||
* @param {Object} res - Express Response Objekt
|
||||
* @param {number} statusCode - HTTP Status Code
|
||||
* @param {string} message - Fehlermeldung
|
||||
* @param {Object} details - Zusätzliche Fehlerdetails (optional)
|
||||
*/
|
||||
handleError(error, res) {
|
||||
console.error('Error:', error);
|
||||
|
||||
// Validation Errors
|
||||
if (error.message.startsWith('VALIDATION_ERROR:')) {
|
||||
const message = error.message.replace('VALIDATION_ERROR: ', '');
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: message,
|
||||
type: 'VALIDATION_ERROR'
|
||||
});
|
||||
}
|
||||
|
||||
// Business Logic Errors
|
||||
switch (error.message) {
|
||||
case 'USER_NOT_FOUND':
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Benutzer nicht gefunden',
|
||||
type: 'NOT_FOUND'
|
||||
});
|
||||
|
||||
case 'INVALID_CURRENT_PASSWORD':
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Aktuelles Passwort ist falsch',
|
||||
type: 'INVALID_PASSWORD'
|
||||
});
|
||||
|
||||
case 'EMAIL_ALREADY_EXISTS':
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: 'E-Mail-Adresse bereits vorhanden',
|
||||
type: 'DUPLICATE_EMAIL'
|
||||
});
|
||||
|
||||
default:
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: 'Ein interner Fehler ist aufgetreten',
|
||||
type: 'INTERNAL_ERROR'
|
||||
});
|
||||
static errorResponse(res, statusCode, message, details = null) {
|
||||
const error = {
|
||||
success: false,
|
||||
message,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
|
||||
if (details) {
|
||||
error.details = details;
|
||||
}
|
||||
|
||||
console.error(`[${statusCode}] ${message}`, details ? details : '');
|
||||
return res.status(statusCode).json(error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Success Response erstellen
|
||||
* Erstellt eine erfolgreiche Antwort
|
||||
* @param {Object} res - Express Response Objekt
|
||||
* @param {Object} data - Antwortdaten
|
||||
* @param {string} message - Erfolgsmeldung
|
||||
* @param {number} statusCode - HTTP Status Code (default: 200)
|
||||
*/
|
||||
successResponse(res, data, message = 'Erfolgreich', statusCode = 200) {
|
||||
return res.status(statusCode).json({
|
||||
static successResponse(res, data, message = 'Erfolgreich', statusCode = 200) {
|
||||
const response = {
|
||||
success: true,
|
||||
message: message,
|
||||
data: data
|
||||
});
|
||||
message,
|
||||
data,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
|
||||
return res.status(statusCode).json(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Async Error Wrapper für Controller
|
||||
* Wrapper für async Controller-Funktionen mit automatischer Fehlerbehandlung
|
||||
* @param {Function} fn - Async Controller-Funktion
|
||||
* @returns {Function} - Wrapped Controller-Funktion
|
||||
*/
|
||||
asyncHandler(fn) {
|
||||
static asyncHandler(fn) {
|
||||
return (req, res, next) => {
|
||||
Promise.resolve(fn(req, res, next)).catch(next);
|
||||
Promise.resolve(fn(req, res, next)).catch((error) => {
|
||||
console.error('Unhandled error in async handler:', error);
|
||||
this.errorResponse(res, 500, 'Ein unerwarteter Fehler ist aufgetreten', {
|
||||
error: error.message,
|
||||
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Behandelt Sequelize-Validierungsfehler
|
||||
* @param {Object} error - Sequelize Error
|
||||
* @returns {Object} - Standardisierte Fehlerantwort
|
||||
*/
|
||||
static handleSequelizeError(error) {
|
||||
if (error.name === 'SequelizeValidationError') {
|
||||
const validationErrors = error.errors.map(err => ({
|
||||
field: err.path,
|
||||
message: err.message,
|
||||
value: err.value
|
||||
}));
|
||||
return {
|
||||
statusCode: 400,
|
||||
message: 'Validierungsfehler',
|
||||
details: { validationErrors }
|
||||
};
|
||||
}
|
||||
|
||||
if (error.name === 'SequelizeUniqueConstraintError') {
|
||||
return {
|
||||
statusCode: 409,
|
||||
message: 'Eindeutigkeitsverletzung',
|
||||
details: { field: error.errors[0]?.path }
|
||||
};
|
||||
}
|
||||
|
||||
if (error.name === 'SequelizeForeignKeyConstraintError') {
|
||||
return {
|
||||
statusCode: 400,
|
||||
message: 'Referenzfehler',
|
||||
details: { field: error.fields[0] }
|
||||
};
|
||||
}
|
||||
|
||||
if (error.name === 'SequelizeDatabaseError') {
|
||||
return {
|
||||
statusCode: 500,
|
||||
message: 'Datenbankfehler',
|
||||
details: { original: error.original?.message }
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
statusCode: 500,
|
||||
message: 'Datenbankfehler',
|
||||
details: { error: error.message }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Behandelt JWT-Fehler
|
||||
* @param {Object} error - JWT Error
|
||||
* @returns {Object} - Standardisierte Fehlerantwort
|
||||
*/
|
||||
static handleJWTError(error) {
|
||||
if (error.name === 'JsonWebTokenError') {
|
||||
return {
|
||||
statusCode: 401,
|
||||
message: 'Ungültiger Token'
|
||||
};
|
||||
}
|
||||
|
||||
if (error.name === 'TokenExpiredError') {
|
||||
return {
|
||||
statusCode: 401,
|
||||
message: 'Token abgelaufen'
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
statusCode: 401,
|
||||
message: 'Authentifizierungsfehler'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ErrorHandler();
|
||||
module.exports = ErrorHandler;
|
||||
Reference in New Issue
Block a user