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 -4
View File
@@ -4,16 +4,15 @@ import * as gdprService from '../services/gdpr.service.js';
import * as consentService from '../services/consent.service.js';
import * as consentPublicService from '../services/consent-public.service.js';
import * as appSettingService from '../services/appSetting.service.js';
import { createAuditLog } from '../services/audit.service.js';
import { ConsentType, DeletionRequestStatus, PrismaClient } from '@prisma/client';
import { createAuditLog, logChange } from '../services/audit.service.js';
import { ConsentType, DeletionRequestStatus } from '@prisma/client';
import prisma from '../lib/prisma.js';
import path from 'path';
import fs from 'fs';
import { sendEmail, SmtpCredentials } from '../services/smtpService.js';
import { getSystemEmailCredentials } from '../services/emailProvider/emailProviderService.js';
import * as authorizationService from '../services/authorization.service.js';
const prisma = new PrismaClient();
/**
* Kundendaten exportieren (DSGVO Art. 15)
*/
@@ -73,6 +72,13 @@ export async function createDeletionRequest(req: AuthRequest, res: Response) {
requestedBy: req.user?.email || 'unknown',
});
await logChange({
req, action: 'CREATE', resourceType: 'DeletionRequest',
resourceId: request.id.toString(),
label: `Löschanfrage erstellt für Kunde #${customerId}`,
customerId,
});
res.status(201).json({ success: true, data: request });
} catch (error) {
console.error('Fehler beim Erstellen der Löschanfrage:', error);
@@ -281,6 +287,13 @@ export async function updateCustomerConsent(req: AuthRequest, res: Response) {
return res.status(400).json({ success: false, error: 'Ungültiger Consent-Typ' });
}
const consentLabels: Record<string, string> = {
DATA_PROCESSING: 'Datenverarbeitung',
MARKETING_EMAIL: 'E-Mail-Marketing',
MARKETING_PHONE: 'Telefonmarketing',
DATA_SHARING_PARTNER: 'Datenweitergabe',
};
const consent = await consentService.updateConsent(customerId, consentType, {
status,
source: source || 'portal',
@@ -290,6 +303,14 @@ export async function updateCustomerConsent(req: AuthRequest, res: Response) {
createdBy: req.user?.email || 'unknown',
});
const consentName = consentLabels[consentType] || consentType;
await logChange({
req, action: 'UPDATE', resourceType: 'CustomerConsent',
label: status === 'GRANTED' ? `Einwilligung "${consentName}" erteilt` : `Einwilligung "${consentName}" widerrufen`,
details: { einwilligung: consentName, status, quelle: source || 'portal' },
customerId,
});
res.json({ success: true, data: consent });
} catch (error) {
console.error('Fehler beim Aktualisieren der Einwilligung:', error);
@@ -350,6 +371,11 @@ export async function updatePrivacyPolicy(req: AuthRequest, res: Response) {
await appSettingService.setSetting('privacyPolicyHtml', html);
await logChange({
req, action: 'UPDATE', resourceType: 'PrivacyPolicy',
label: `Datenschutzerklärung aktualisiert`,
});
res.json({ success: true, message: 'Datenschutzerklärung gespeichert' });
} catch (error) {
console.error('Fehler beim Speichern der Datenschutzerklärung:', error);
@@ -383,6 +409,11 @@ export async function updateAuthorizationTemplate(req: AuthRequest, res: Respons
await appSettingService.setSetting('authorizationTemplateHtml', html);
await logChange({
req, action: 'UPDATE', resourceType: 'AuthorizationTemplate',
label: `Vollmacht-Vorlage aktualisiert`,
});
res.json({ success: true, message: 'Vollmacht-Vorlage gespeichert' });
} catch (error) {
console.error('Fehler beim Speichern der Vollmacht-Vorlage:', error);
@@ -743,6 +774,15 @@ export async function grantAuthorization(req: AuthRequest, res: Response) {
notes,
});
const rep = await prisma.customer.findUnique({ where: { id: representativeId }, select: { firstName: true, lastName: true } });
const repName = rep ? `${rep.firstName} ${rep.lastName}` : `#${representativeId}`;
await logChange({
req, action: 'UPDATE', resourceType: 'Authorization',
resourceId: auth.id.toString(),
label: `Vollmacht für ${repName} erteilt (Admin)`,
customerId,
});
res.json({ success: true, data: auth });
} catch (error) {
console.error('Fehler beim Erteilen der Vollmacht:', error);
@@ -762,6 +802,16 @@ export async function withdrawAuthorization(req: AuthRequest, res: Response) {
const representativeId = parseInt(req.params.representativeId);
const auth = await authorizationService.withdrawAuthorization(customerId, representativeId);
const rep = await prisma.customer.findUnique({ where: { id: representativeId }, select: { firstName: true, lastName: true } });
const repName = rep ? `${rep.firstName} ${rep.lastName}` : `#${representativeId}`;
await logChange({
req, action: 'UPDATE', resourceType: 'Authorization',
resourceId: auth.id.toString(),
label: `Vollmacht für ${repName} widerrufen (Admin)`,
customerId,
});
res.json({ success: true, data: auth });
} catch (error) {
console.error('Fehler beim Widerrufen der Vollmacht:', error);
@@ -791,6 +841,13 @@ export async function uploadAuthorizationDocument(req: AuthRequest, res: Respons
documentPath
);
await logChange({
req, action: 'CREATE', resourceType: 'AuthorizationDocument',
resourceId: auth.id.toString(),
label: `Vollmacht-PDF hochgeladen für Vertreter #${representativeId}`,
customerId,
});
res.json({ success: true, data: auth });
} catch (error) {
console.error('Fehler beim Upload des Vollmacht-Dokuments:', error);
@@ -810,6 +867,14 @@ export async function deleteAuthorizationDocument(req: AuthRequest, res: Respons
const representativeId = parseInt(req.params.representativeId);
const auth = await authorizationService.deleteAuthorizationDocument(customerId, representativeId);
await logChange({
req, action: 'DELETE', resourceType: 'AuthorizationDocument',
resourceId: auth.id.toString(),
label: `Vollmacht-PDF gelöscht für Vertreter #${representativeId}`,
customerId,
});
res.json({ success: true, data: auth });
} catch (error) {
console.error('Fehler beim Löschen des Vollmacht-Dokuments:', error);
@@ -852,13 +917,22 @@ export async function toggleMyAuthorization(req: AuthRequest, res: Response) {
const representativeId = parseInt(req.params.representativeId);
const { grant } = req.body;
// Vertreter-Name laden
const representative = await prisma.customer.findUnique({
where: { id: representativeId },
select: { firstName: true, lastName: true },
});
const repName = representative ? `${representative.firstName} ${representative.lastName}` : `#${representativeId}`;
let auth;
if (grant) {
auth = await authorizationService.grantAuthorization(user.customerId, representativeId, {
source: 'portal',
});
await logChange({ req, action: 'UPDATE', resourceType: 'RepresentativeAuthorization', label: `Vollmacht für ${repName} erteilt`, details: { status: 'erteilt', vertreter: repName, quelle: 'portal' }, customerId: user.customerId });
} else {
auth = await authorizationService.withdrawAuthorization(user.customerId, representativeId);
await logChange({ req, action: 'UPDATE', resourceType: 'RepresentativeAuthorization', label: `Vollmacht für ${repName} widerrufen`, details: { status: 'widerrufen', vertreter: repName, quelle: 'portal' }, customerId: user.customerId });
}
res.json({ success: true, data: auth });