gdpr audit implemented, email log, vollmachten, pdf delete cancel data privacy and vollmachten, removed message no id card in engergy car, and other contracts that are not telecom contracts, added insert counter for engery

This commit is contained in:
2026-03-21 11:59:53 +01:00
parent 09e87c951b
commit c3edb8ad2e
1491 changed files with 265550 additions and 1292 deletions
+134
View File
@@ -0,0 +1,134 @@
import { PrismaClient, Prisma } from '@prisma/client';
import { setBeforeValues, setAfterValues } from '../middleware/auditContext.js';
// Modelle die für Before/After-Tracking relevant sind
const AUDITED_MODELS = [
'Customer',
'Contract',
'Address',
'BankCard',
'IdentityDocument',
'User',
'Meter',
'MeterReading',
'StressfreiEmail',
'Provider',
'Tariff',
'ContractCategory',
'AppSetting',
'CustomerConsent',
];
// Sensible Felder die aus dem Audit-Log gefiltert werden
const SENSITIVE_FIELDS = [
'password',
'passwordHash',
'portalPasswordHash',
'portalPasswordEncrypted',
'emailPasswordEncrypted',
'internetPasswordEncrypted',
'sipPasswordEncrypted',
'pin',
'puk',
'apiKey',
];
/**
* Filtert sensible Felder aus einem Objekt
*/
function filterSensitiveFields(obj: Record<string, unknown>): Record<string, unknown> {
const filtered: Record<string, unknown> = {};
for (const [key, value] of Object.entries(obj)) {
if (SENSITIVE_FIELDS.includes(key)) {
filtered[key] = '[REDACTED]';
} else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
filtered[key] = filterSensitiveFields(value as Record<string, unknown>);
} else {
filtered[key] = value;
}
}
return filtered;
}
/**
* Prüft ob ein Model für Audit-Tracking relevant ist
*/
function isAuditedModel(model: string | undefined): boolean {
return model !== undefined && AUDITED_MODELS.includes(model);
}
/**
* Erstellt einen Prisma Client mit Audit-Middleware
*/
function createPrismaClient(): PrismaClient {
const prisma = new PrismaClient();
// Middleware für Before/After-Tracking
prisma.$use(async (params: Prisma.MiddlewareParams, next: (params: Prisma.MiddlewareParams) => Promise<unknown>) => {
const { model, action, args } = params;
// Nur relevante Modelle und Aktionen tracken
if (!isAuditedModel(model)) {
return next(params);
}
// Update-Operationen: Vorherigen Stand abrufen
if (action === 'update' || action === 'updateMany') {
try {
const modelDelegate = (prisma as unknown as Record<string, { findUnique: (args: unknown) => Promise<unknown> }>)[
model!.charAt(0).toLowerCase() + model!.slice(1)
];
if (modelDelegate && args?.where) {
const before = await modelDelegate.findUnique({ where: args.where });
if (before) {
setBeforeValues(filterSensitiveFields(before as Record<string, unknown>));
}
}
} catch {
// Fehler beim Abrufen des vorherigen Stands ignorieren
}
}
// Delete-Operationen: Datensatz vor dem Löschen abrufen
if (action === 'delete' || action === 'deleteMany') {
try {
const modelDelegate = (prisma as unknown as Record<string, { findUnique: (args: unknown) => Promise<unknown> }>)[
model!.charAt(0).toLowerCase() + model!.slice(1)
];
if (modelDelegate && args?.where) {
const before = await modelDelegate.findUnique({ where: args.where });
if (before) {
setBeforeValues(filterSensitiveFields(before as Record<string, unknown>));
}
}
} catch {
// Fehler beim Abrufen ignorieren
}
}
// Operation ausführen
const result = await next(params);
// Nach Update/Create: Neuen Stand speichern
if ((action === 'update' || action === 'create') && result) {
setAfterValues(filterSensitiveFields(result as Record<string, unknown>));
}
return result;
});
return prisma;
}
// Singleton-Instanz
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined };
export const prisma = globalForPrisma.prisma ?? createPrismaClient();
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma;
}
export default prisma;