feat: dashboard widgets, auth fix, profile names, dynamic groups
- Add VehicleDashboardCard: self-contained widget modelled after AtemschutzDashboardCard, shows einsatzbereit ratio and inspection warnings inline; replaces StatsCard + InspectionAlerts in Dashboard - Add EquipmentDashboardCard: consolidated equipment status widget showing only aggregated counts (no per-item listing); replaces EquipmentAlerts component in Dashboard - Fix auth race condition: add authInitialized flag to api.ts so 401 responses during initial token validation no longer trigger a spurious redirect to /login; save intended destination before login redirect and restore it after successful auth callback - Fix profile firstname/lastname: add extractNames() helper to auth.controller.ts that falls back to splitting userinfo.name when Authentik does not provide separate given_name/family_name fields; applied on both create and update paths - Dynamic groups endpoint: replace hardcoded KNOWN_GROUPS array in events.controller.ts with a DB query (SELECT DISTINCT unnest (authentik_groups) FROM users); known slugs get German labels via lookup map, unknown slugs are humanized automatically Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,21 +9,6 @@ import {
|
||||
} from '../models/events.model';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Known Authentik groups exposed to the frontend for event targeting
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const KNOWN_GROUPS = [
|
||||
{ id: 'dashboard_admin', label: 'Administratoren' },
|
||||
{ id: 'dashboard_moderator', label: 'Moderatoren' },
|
||||
{ id: 'dashboard_mitglied', label: 'Mitglieder' },
|
||||
{ id: 'dashboard_fahrmeister', label: 'Fahrmeister' },
|
||||
{ id: 'dashboard_zeugmeister', label: 'Zeugmeister' },
|
||||
{ id: 'dashboard_atemschutz', label: 'Atemschutzwart' },
|
||||
{ id: 'dashboard_jugend', label: 'Feuerwehrjugend' },
|
||||
{ id: 'dashboard_kommandant', label: 'Kommandanten' },
|
||||
];
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helper — extract userGroups from request
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -124,7 +109,13 @@ class EventsController {
|
||||
// GET /api/events/groups
|
||||
// -------------------------------------------------------------------------
|
||||
getAvailableGroups = async (_req: Request, res: Response): Promise<void> => {
|
||||
res.json({ success: true, data: KNOWN_GROUPS });
|
||||
try {
|
||||
const groups = await eventsService.getAvailableGroups();
|
||||
res.json({ success: true, data: groups });
|
||||
} catch (error) {
|
||||
logger.error('getAvailableGroups error', { error });
|
||||
res.status(500).json({ success: false, message: 'Fehler beim Laden der Gruppen' });
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user