feat: replace raw error messages with structured error codes
Backend now returns { code: ErrorCode, message: string } for all errors,
making it language-agnostic. Frontend maps codes to localised strings via
Paraglide (en/de/es), so translations live in messages/*.json.
- Add ErrorCode enum and DomainException with static factory methods
- Update GlobalExceptionHandler to return ErrorResponse(code, message)
- Replace ResponseStatusException throughout controllers/services/aspects
- Add frontend errors.ts with parseBackendError() and getErrorMessage()
- getErrorMessage() delegates to Paraglide m.error_*() functions
- Add error_* keys to messages/en.json, de.json, es.json
- Update all page.server.ts files to use the new error utilities
- Fix hardcoded localhost URLs in admin and login pages
- Fix missing baseUrl in deleteTag action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { error, fail } from '@sveltejs/kit';
|
||||
import { env } from '$env/dynamic/private';
|
||||
import { parseBackendError, getErrorMessage } from '$lib/errors';
|
||||
|
||||
export async function load({ fetch, locals }) {
|
||||
// 1. Check Permissions (Adapt logic to your user object)
|
||||
@@ -8,7 +9,7 @@ export async function load({ fetch, locals }) {
|
||||
|
||||
// Assuming user.group.permissions is an array of strings
|
||||
const hasAdmin = user?.groups.some(g => g.permissions.includes("ADMIN"));
|
||||
if (!hasAdmin) throw error(403, 'Zugriff verweigert');
|
||||
if (!hasAdmin) throw error(403, getErrorMessage('FORBIDDEN'));
|
||||
|
||||
const baseUrl = env.API_INTERNAL_URL || 'http://localhost:8080';
|
||||
|
||||
@@ -50,8 +51,11 @@ export const actions = {
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!res.ok) return { success: false, message: 'Fehler beim Erstellen' };
|
||||
return { success: true, message: 'User angelegt' };
|
||||
if (!res.ok) {
|
||||
const backendError = await parseBackendError(res);
|
||||
return fail(res.status, { success: false, message: getErrorMessage(backendError?.code) });
|
||||
}
|
||||
return { success: true };
|
||||
},
|
||||
deleteUser: async ({ request, fetch }) => {
|
||||
const data = await request.formData();
|
||||
@@ -63,9 +67,10 @@ export const actions = {
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
return { success: false, message: 'Fehler beim Löschen des Benutzers' };
|
||||
const backendError = await parseBackendError(res);
|
||||
return fail(res.status, { success: false, message: getErrorMessage(backendError?.code) });
|
||||
}
|
||||
return { success: true, message: 'Benutzer erfolgreich gelöscht' };
|
||||
return { success: true };
|
||||
},
|
||||
updateTag: async ({ request, fetch }) => {
|
||||
const data = await request.formData();
|
||||
@@ -84,8 +89,13 @@ export const actions = {
|
||||
deleteTag: async ({ request, fetch }) => {
|
||||
const data = await request.formData();
|
||||
const id = data.get('id');
|
||||
const baseUrl = env.API_INTERNAL_URL || 'http://localhost:8080';
|
||||
|
||||
await fetch(`/api/tags/${id}`, { method: 'DELETE' });
|
||||
const res = await fetch(baseUrl + `/api/tags/${id}`, { method: 'DELETE' });
|
||||
if (!res.ok) {
|
||||
const backendError = await parseBackendError(res);
|
||||
return fail(res.status, { success: false, message: getErrorMessage(backendError?.code) });
|
||||
}
|
||||
return { success: true };
|
||||
},
|
||||
|
||||
@@ -104,7 +114,10 @@ export const actions = {
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!res.ok) return { success: false, message: 'Fehler beim Erstellen der Gruppe' };
|
||||
if (!res.ok) {
|
||||
const backendError = await parseBackendError(res);
|
||||
return fail(res.status, { success: false, message: getErrorMessage(backendError?.code) });
|
||||
}
|
||||
return { success: true };
|
||||
},
|
||||
|
||||
@@ -124,7 +137,10 @@ export const actions = {
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!res.ok) return { success: false, message: 'Fehler beim Aktualisieren' };
|
||||
if (!res.ok) {
|
||||
const backendError = await parseBackendError(res);
|
||||
return fail(res.status, { success: false, message: getErrorMessage(backendError?.code) });
|
||||
}
|
||||
return { success: true };
|
||||
},
|
||||
|
||||
@@ -135,7 +151,10 @@ export const actions = {
|
||||
const id = data.get('id');
|
||||
const res = await fetch(baseUrl + `/api/groups/${id}`, { method: 'DELETE' });
|
||||
|
||||
if (!res.ok) return { success: false, message: 'Gruppe kann nicht gelöscht werden (evtl. noch Benutzer zugeordnet?)' };
|
||||
if (!res.ok) {
|
||||
const backendError = await parseBackendError(res);
|
||||
return fail(res.status, { success: false, message: getErrorMessage(backendError?.code) });
|
||||
}
|
||||
return { success: true };
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user