From 46d3f5b3517628f9a960d70a6db1fcd44253b957 Mon Sep 17 00:00:00 2001 From: Matthias Hochmeister Date: Fri, 27 Feb 2026 20:33:43 +0100 Subject: [PATCH] add features --- .../src/controllers/incident.controller.ts | 14 +++++++------- backend/src/controllers/member.controller.ts | 11 ++++------- .../src/controllers/training.controller.ts | 10 +++++----- backend/src/controllers/vehicle.controller.ts | 18 +++++++++--------- backend/src/middleware/audit.middleware.ts | 4 ++-- backend/src/routes/admin.routes.ts | 4 ++-- backend/src/routes/member.routes.ts | 19 ++----------------- backend/src/services/member.service.ts | 2 +- backend/src/services/vehicle.service.ts | 3 +-- 9 files changed, 33 insertions(+), 52 deletions(-) diff --git a/backend/src/controllers/incident.controller.ts b/backend/src/controllers/incident.controller.ts index 114b4e9..272c186 100644 --- a/backend/src/controllers/incident.controller.ts +++ b/backend/src/controllers/incident.controller.ts @@ -74,7 +74,7 @@ class IncidentController { // ------------------------------------------------------------------------- async getIncident(req: AuthenticatedRequest, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const incident = await incidentService.getIncidentById(id); if (!incident) { @@ -147,7 +147,7 @@ class IncidentController { return; } - const { id } = req.params; + const { id } = req.params as Record; const parseResult = UpdateEinsatzSchema.safeParse(req.body); if (!parseResult.success) { res.status(400).json({ @@ -181,7 +181,7 @@ class IncidentController { return; } - const { id } = req.params; + const { id } = req.params as Record; await incidentService.deleteIncident(id, req.user.id); res.status(200).json({ success: true, message: 'Einsatz archiviert' }); @@ -200,7 +200,7 @@ class IncidentController { // ------------------------------------------------------------------------- async assignPersonnel(req: AuthenticatedRequest, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const parseResult = AssignPersonnelSchema.safeParse(req.body); if (!parseResult.success) { @@ -226,7 +226,7 @@ class IncidentController { // ------------------------------------------------------------------------- async removePersonnel(req: AuthenticatedRequest, res: Response): Promise { try { - const { id, userId } = req.params; + const { id, userId } = req.params as Record; await incidentService.removePersonnel(id, userId); res.status(200).json({ success: true, message: 'Person entfernt' }); @@ -245,7 +245,7 @@ class IncidentController { // ------------------------------------------------------------------------- async assignVehicle(req: AuthenticatedRequest, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const parseResult = AssignVehicleSchema.safeParse(req.body); if (!parseResult.success) { @@ -271,7 +271,7 @@ class IncidentController { // ------------------------------------------------------------------------- async removeVehicle(req: AuthenticatedRequest, res: Response): Promise { try { - const { id, fahrzeugId } = req.params; + const { id, fahrzeugId } = req.params as Record; await incidentService.removeVehicle(id, fahrzeugId); res.status(200).json({ success: true, message: 'Fahrzeug entfernt' }); diff --git a/backend/src/controllers/member.controller.ts b/backend/src/controllers/member.controller.ts index 7326923..7cd3a25 100644 --- a/backend/src/controllers/member.controller.ts +++ b/backend/src/controllers/member.controller.ts @@ -1,7 +1,6 @@ import { Request, Response } from 'express'; import memberService from '../services/member.service'; import logger from '../utils/logger'; -import { AppError } from '../middleware/error.middleware'; import { CreateMemberProfileSchema, UpdateMemberProfileSchema, @@ -79,7 +78,7 @@ class MemberController { * Returns aggregate member counts for each status. * Must be registered BEFORE /:userId to avoid route collision. */ - async getMemberStats(req: Request, res: Response): Promise { + async getMemberStats(_req: Request, res: Response): Promise { try { const stats = await memberService.getMemberStats(); res.status(200).json({ success: true, data: stats }); @@ -100,9 +99,7 @@ class MemberController { */ async getMemberById(req: Request, res: Response): Promise { try { - const { userId } = req.params; - const requestorId = req.user!.id; - const requestorRole = getRole(req); + const { userId } = req.params as Record; const ownProfile = isOwnProfile(req, userId); const member = await memberService.getMemberById(userId); @@ -151,7 +148,7 @@ class MemberController { */ async createMemberProfile(req: Request, res: Response): Promise { try { - const { userId } = req.params; + const { userId } = req.params as Record; const parseResult = CreateMemberProfileSchema.safeParse(req.body); if (!parseResult.success) { @@ -187,7 +184,7 @@ class MemberController { */ async updateMember(req: Request, res: Response): Promise { try { - const { userId } = req.params; + const { userId } = req.params as Record; const updaterId = req.user!.id; const ownProfile = isOwnProfile(req, userId); diff --git a/backend/src/controllers/training.controller.ts b/backend/src/controllers/training.controller.ts index d6f9260..b78015f 100644 --- a/backend/src/controllers/training.controller.ts +++ b/backend/src/controllers/training.controller.ts @@ -176,7 +176,7 @@ class TrainingController { // ------------------------------------------------------------------------- getById = async (req: Request, res: Response): Promise => { try { - const { id } = req.params; + const { id } = req.params as Record; const userId = req.user?.id; // Determine if the requester may see the full attendee list @@ -229,7 +229,7 @@ class TrainingController { // ------------------------------------------------------------------------- updateEvent = async (req: Request, res: Response): Promise => { try { - const { id } = req.params; + const { id } = req.params as Record; const parsed = UpdateUebungSchema.safeParse(req.body); if (!parsed.success) { @@ -258,7 +258,7 @@ class TrainingController { // ------------------------------------------------------------------------- cancelEvent = async (req: Request, res: Response): Promise => { try { - const { id } = req.params; + const { id } = req.params as Record; const parsed = CancelEventSchema.safeParse(req.body); if (!parsed.success) { @@ -287,7 +287,7 @@ class TrainingController { // ------------------------------------------------------------------------- updateRsvp = async (req: Request, res: Response): Promise => { try { - const { id: uebungId } = req.params; + const { id: uebungId } = req.params as Record; const userId = req.user!.id; const parsed = UpdateRsvpSchema.safeParse(req.body); @@ -319,7 +319,7 @@ class TrainingController { // ------------------------------------------------------------------------- markAttendance = async (req: Request, res: Response): Promise => { try { - const { id: uebungId } = req.params; + const { id: uebungId } = req.params as Record; const parsed = MarkAttendanceSchema.safeParse(req.body); if (!parsed.success) { diff --git a/backend/src/controllers/vehicle.controller.ts b/backend/src/controllers/vehicle.controller.ts index 90ac9b5..ac117fa 100644 --- a/backend/src/controllers/vehicle.controller.ts +++ b/backend/src/controllers/vehicle.controller.ts @@ -85,7 +85,7 @@ class VehicleController { * GET /api/vehicles * Fleet overview list with per-vehicle inspection badge data. */ - async listVehicles(req: Request, res: Response): Promise { + async listVehicles(_req: Request, res: Response): Promise { try { const vehicles = await vehicleService.getAllVehicles(); res.status(200).json({ success: true, data: vehicles }); @@ -99,7 +99,7 @@ class VehicleController { * GET /api/vehicles/stats * Aggregated KPI counts for the dashboard strip. */ - async getStats(req: Request, res: Response): Promise { + async getStats(_req: Request, res: Response): Promise { try { const stats = await vehicleService.getVehicleStats(); res.status(200).json({ success: true, data: stats }); @@ -140,7 +140,7 @@ class VehicleController { */ async getVehicle(req: Request, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const vehicle = await vehicleService.getVehicleById(id); if (!vehicle) { @@ -185,7 +185,7 @@ class VehicleController { */ async updateVehicle(req: Request, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const parsed = UpdateFahrzeugSchema.safeParse(req.body); if (!parsed.success) { res.status(400).json({ @@ -219,7 +219,7 @@ class VehicleController { */ async updateVehicleStatus(req: Request, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const parsed = UpdateStatusSchema.safeParse(req.body); if (!parsed.success) { @@ -262,7 +262,7 @@ class VehicleController { */ async addPruefung(req: Request, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const parsed = CreatePruefungSchema.safeParse(req.body); if (!parsed.success) { @@ -288,7 +288,7 @@ class VehicleController { */ async getPruefungen(req: Request, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const pruefungen = await vehicleService.getPruefungenForVehicle(id); res.status(200).json({ success: true, data: pruefungen }); } catch (error) { @@ -305,7 +305,7 @@ class VehicleController { */ async addWartung(req: Request, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const parsed = CreateWartungslogSchema.safeParse(req.body); if (!parsed.success) { @@ -331,7 +331,7 @@ class VehicleController { */ async getWartung(req: Request, res: Response): Promise { try { - const { id } = req.params; + const { id } = req.params as Record; const entries = await vehicleService.getWartungslogForVehicle(id); res.status(200).json({ success: true, data: entries }); } catch (error) { diff --git a/backend/src/middleware/audit.middleware.ts b/backend/src/middleware/audit.middleware.ts index f97c991..0db4bab 100644 --- a/backend/src/middleware/audit.middleware.ts +++ b/backend/src/middleware/audit.middleware.ts @@ -132,9 +132,9 @@ export function auditMiddleware( // Resource ID: prefer controller override, then route param, then body id. const resourceId = res.locals.auditResourceId ?? - req.params.id ?? + (req.params as Record).id ?? (body !== null && typeof body === 'object' - ? (body as Record)?.data?.id as string | undefined + ? ((body as Record)?.data as Record)?.id as string | undefined : undefined) ?? null; diff --git a/backend/src/routes/admin.routes.ts b/backend/src/routes/admin.routes.ts index ab1c503..0963d60 100644 --- a/backend/src/routes/admin.routes.ts +++ b/backend/src/routes/admin.routes.ts @@ -100,7 +100,7 @@ router.get( res.status(400).json({ success: false, message: 'Invalid query parameters', - errors: error.errors, + errors: error.issues, }); return; } @@ -152,7 +152,7 @@ router.get( res.status(400).json({ success: false, message: 'Invalid query parameters', - errors: error.errors, + errors: error.issues, }); return; } diff --git a/backend/src/routes/member.routes.ts b/backend/src/routes/member.routes.ts index 7b81287..9553811 100644 --- a/backend/src/routes/member.routes.ts +++ b/backend/src/routes/member.routes.ts @@ -28,21 +28,6 @@ const router = Router(); type AppRole = 'admin' | 'kommandant' | 'mitglied'; -// Extend the Express Request type to include role -declare global { - namespace Express { - interface Request { - user?: { - id: string; - email: string; - authentikSub: string; - role?: AppRole; - groups?: string[]; - }; - } - } -} - /** * Resolves the AppRole from Authentik groups attached to the JWT. * Mutates req.user.role so downstream controllers can read it directly. @@ -53,9 +38,9 @@ const resolveRole = (req: Request, _res: Response, next: NextFunction): void => if (groups.includes('feuerwehr-admin')) { req.user.role = 'admin'; } else if (groups.includes('feuerwehr-kommandant')) { - req.user.role = 'kommandant'; + req.user.role = 'kommandant' as any; } else { - req.user.role = 'mitglied'; + req.user.role = 'mitglied' as any; } logger.debug('resolveRole', { userId: req.user.id, role: req.user.role }); } diff --git a/backend/src/services/member.service.ts b/backend/src/services/member.service.ts index cf83718..f07bd50 100644 --- a/backend/src/services/member.service.ts +++ b/backend/src/services/member.service.ts @@ -375,7 +375,7 @@ class MemberService { await this.updateDienstgrad(userId, dienstgrad, updatedBy, dienstgrad_seit, client); } else if (dienstgrad_seit !== undefined) { // dienstgrad_seit can be updated independently - rest.dienstgrad_seit = dienstgrad_seit; + (rest as any).dienstgrad_seit = dienstgrad_seit; } // Build dynamic SET clause for remaining fields diff --git a/backend/src/services/vehicle.service.ts b/backend/src/services/vehicle.service.ts index 0aa0a08..37e0e99 100644 --- a/backend/src/services/vehicle.service.ts +++ b/backend/src/services/vehicle.service.ts @@ -1,4 +1,3 @@ -import { Server as SocketIOServer } from 'socket.io'; import pool from '../config/database'; import logger from '../utils/logger'; import { @@ -282,7 +281,7 @@ class VehicleService { status: FahrzeugStatus, bemerkung: string, updatedBy: string, - io?: SocketIOServer + io?: any ): Promise { try { // Fetch old status for Socket.IO payload and logging