complete new audit system

This commit is contained in:
2026-03-21 18:23:54 +01:00
parent 4f359df161
commit 219e1930f7
159 changed files with 2841 additions and 736 deletions
+78 -3
View File
@@ -1,5 +1,7 @@
import { Request, Response } from 'express';
import prisma from '../lib/prisma.js';
import * as userService from '../services/user.service.js';
import { logChange } from '../services/audit.service.js';
import { ApiResponse } from '../types/index.js';
// Users
@@ -48,6 +50,11 @@ export async function getUser(req: Request, res: Response): Promise<void> {
export async function createUser(req: Request, res: Response): Promise<void> {
try {
const user = await userService.createUser(req.body);
await logChange({
req, action: 'CREATE', resourceType: 'User',
resourceId: user.id.toString(),
label: `Benutzer ${user.firstName} ${user.lastName} angelegt`,
});
res.status(201).json({ success: true, data: user } as ApiResponse);
} catch (error) {
res.status(400).json({
@@ -59,7 +66,49 @@ export async function createUser(req: Request, res: Response): Promise<void> {
export async function updateUser(req: Request, res: Response): Promise<void> {
try {
const user = await userService.updateUser(parseInt(req.params.id), req.body);
const userId = parseInt(req.params.id);
const data = req.body;
// Vorherigen Stand laden für Audit
const before = await prisma.user.findUnique({ where: { id: userId } });
const user = await userService.updateUser(userId, data);
if (user) {
// Audit: Geänderte Felder ermitteln und loggen
if (before) {
const changes: Record<string, { von: unknown; nach: unknown }> = {};
const fieldLabels: Record<string, string> = {
email: 'E-Mail', firstName: 'Vorname', lastName: 'Nachname', isActive: 'Aktiv',
};
for (const [key, newVal] of Object.entries(data)) {
if (['id', 'createdAt', 'updatedAt'].includes(key)) continue;
const oldVal = (before as any)[key];
const norm = (v: unknown) => (v === null || v === undefined || v === '' ? null : v);
if (JSON.stringify(norm(oldVal)) !== JSON.stringify(norm(newVal))) {
const label = fieldLabels[key] || key;
const formatVal = (v: unknown) => {
if (v === null || v === undefined || v === '') return '-';
if (typeof v === 'boolean') return v ? 'Ja' : 'Nein';
return String(v);
};
changes[label] = { von: formatVal(oldVal), nach: formatVal(newVal) };
}
}
const changeList = Object.entries(changes).map(([f, c]) => `${f}: ${c.von}${c.nach}`).join(', ');
await logChange({
req, action: 'UPDATE', resourceType: 'User',
resourceId: user.id.toString(),
label: changeList ? `Benutzer ${user.firstName} ${user.lastName} aktualisiert: ${changeList}` : `Benutzer ${user.firstName} ${user.lastName} aktualisiert`,
details: Object.keys(changes).length > 0 ? changes : undefined,
});
} else {
await logChange({
req, action: 'UPDATE', resourceType: 'User',
resourceId: user.id.toString(),
label: `Benutzer ${user.firstName} ${user.lastName} aktualisiert`,
});
}
}
res.json({ success: true, data: user } as ApiResponse);
} catch (error) {
res.status(400).json({
@@ -71,7 +120,14 @@ export async function updateUser(req: Request, res: Response): Promise<void> {
export async function deleteUser(req: Request, res: Response): Promise<void> {
try {
await userService.deleteUser(parseInt(req.params.id));
const userId = parseInt(req.params.id);
const userBefore = await userService.getUserById(userId);
await userService.deleteUser(userId);
await logChange({
req, action: 'DELETE', resourceType: 'User',
resourceId: userId.toString(),
label: `Benutzer ${userBefore?.firstName || ''} ${userBefore?.lastName || ''} gelöscht`,
});
res.json({ success: true, message: 'Benutzer gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({
@@ -116,6 +172,11 @@ export async function getRole(req: Request, res: Response): Promise<void> {
export async function createRole(req: Request, res: Response): Promise<void> {
try {
const role = await userService.createRole(req.body);
await logChange({
req, action: 'CREATE', resourceType: 'Role',
resourceId: role.id.toString(),
label: `Rolle ${role.name} angelegt`,
});
res.status(201).json({ success: true, data: role } as ApiResponse);
} catch (error) {
res.status(400).json({
@@ -128,6 +189,13 @@ export async function createRole(req: Request, res: Response): Promise<void> {
export async function updateRole(req: Request, res: Response): Promise<void> {
try {
const role = await userService.updateRole(parseInt(req.params.id), req.body);
if (role) {
await logChange({
req, action: 'UPDATE', resourceType: 'Role',
resourceId: role.id.toString(),
label: `Rolle ${role.name} aktualisiert`,
});
}
res.json({ success: true, data: role } as ApiResponse);
} catch (error) {
res.status(400).json({
@@ -139,7 +207,14 @@ export async function updateRole(req: Request, res: Response): Promise<void> {
export async function deleteRole(req: Request, res: Response): Promise<void> {
try {
await userService.deleteRole(parseInt(req.params.id));
const roleId = parseInt(req.params.id);
const role = await userService.getRoleById(roleId);
await userService.deleteRole(roleId);
await logChange({
req, action: 'DELETE', resourceType: 'Role',
resourceId: roleId.toString(),
label: `Rolle ${role?.name || roleId} gelöscht`,
});
res.json({ success: true, message: 'Rolle gelöscht' } as ApiResponse);
} catch (error) {
res.status(400).json({