Add global error handling middleware for API routes and enhance rating update logic

Implemented a global error handling middleware in the server to standardize error responses for API routes. Additionally, updated the AutoUpdateRatingsService to retrieve the approved user club before updating ratings, ensuring proper access control. Modified the error handling in MyTischtennisAccount.vue to provide more informative login failure messages.
This commit is contained in:
Torsten Schulz (local)
2025-11-07 13:22:22 +01:00
parent eba8ba30aa
commit 94aab93f7d
3 changed files with 48 additions and 3 deletions

View File

@@ -71,6 +71,31 @@ process.on('unhandledRejection', (reason, promise) => {
console.error('[unhandledRejection]', reason);
});
// Globale Fehlerbehandlung für API-Routen
app.use((err, req, res, next) => {
if (res.headersSent) {
return next(err);
}
const status = err?.statusCode || err?.status || 500;
const message = err?.message || 'Interner Serverfehler';
const response = {
success: false,
message,
error: message
};
if (process.env.NODE_ENV === 'dev' || process.env.NODE_ENV === 'development') {
response.debug = {
stack: err?.stack || null
};
}
console.error('[ExpressError]', err);
res.status(status).json(response);
});
app.use('/api/auth', authRoutes);
app.use('/api/clubs', clubRoutes);
app.use('/api/clubmembers', memberRoutes);

View File

@@ -4,6 +4,7 @@ import memberService from './memberService.js';
import myTischtennisClient from '../clients/myTischtennisClient.js';
import MyTischtennis from '../models/MyTischtennis.js';
import { devLog } from '../utils/logger.js';
import UserClub from '../models/UserClub.js';
class AutoUpdateRatingsService {
/**
@@ -134,8 +135,27 @@ class AutoUpdateRatingsService {
devLog(`Updating ratings for ${account.email}`);
try {
// Use the memberService to update ratings from MyTischtennis
const result = await memberService.updateRatingsFromMyTischtennis(account.userId);
// Ermittle einen freigeschalteten Vereinszugang für den Benutzer
const userClub = await UserClub.findOne({
where: {
userId: account.userId,
approved: true
},
order: [['createdAt', 'ASC']],
attributes: ['clubId']
});
if (!userClub) {
throw new Error('Kein freigeschalteter Vereinszugang gefunden');
}
const clubId = userClub.clubId;
// Verwende den Service-Aufruf, der mit userId/clubId arbeitet
const result = await memberService.updateRatingsFromMyTischtennisByUserId(
account.userId,
clubId
);
return {
success: true,

View File

@@ -287,7 +287,7 @@ export default {
});
await this.loadAccount(); // Aktualisiere Account-Daten inkl. clubId, fedNickname
} catch (error) {
const message = error.response?.data?.message || 'Login fehlgeschlagen';
const message = error.response?.data?.message || error.response?.data?.error || error.message || 'Login fehlgeschlagen';
if (error.response?.status === 400 && message.includes('Kein Passwort gespeichert')) {
// Passwort-Dialog öffnen