complete new audit system
This commit is contained in:
@@ -3,6 +3,42 @@ import crypto from 'crypto';
|
||||
import { encrypt, decrypt } from '../utils/encryption.js';
|
||||
import prisma from '../lib/prisma.js';
|
||||
|
||||
/**
|
||||
* Vereinfachte Audit-Log-Funktion für gezielte Änderungsprotokolle.
|
||||
* Wird direkt in Controllern aufgerufen mit aussagekräftigen Details.
|
||||
*/
|
||||
export async function logChange(opts: {
|
||||
req: any; // Express Request (für userId, email, IP)
|
||||
action: AuditAction;
|
||||
resourceType: string;
|
||||
resourceId?: string;
|
||||
label: string; // Menschenlesbares Label z.B. "Vollmacht für Stefan Hacker widerrufen"
|
||||
details?: Record<string, unknown>; // Zusätzliche Details z.B. { vorher: 'erteilt', nachher: 'widerrufen' }
|
||||
customerId?: number;
|
||||
}) {
|
||||
try {
|
||||
const user = opts.req?.user;
|
||||
await createAuditLog({
|
||||
userId: user?.userId,
|
||||
userEmail: user?.email || 'system',
|
||||
userRole: user?.isCustomerPortal ? 'Kundenportal' : 'Mitarbeiter',
|
||||
customerId: user?.customerId,
|
||||
isCustomerPortal: user?.isCustomerPortal,
|
||||
action: opts.action,
|
||||
resourceType: opts.resourceType,
|
||||
resourceId: opts.resourceId,
|
||||
resourceLabel: opts.label,
|
||||
endpoint: opts.req?.path || '',
|
||||
httpMethod: opts.req?.method || '',
|
||||
ipAddress: opts.req?.socket?.remoteAddress || opts.req?.headers?.['x-forwarded-for'] || 'unknown',
|
||||
dataSubjectId: opts.customerId,
|
||||
changesAfter: opts.details,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[logChange] Fehler:', error);
|
||||
}
|
||||
}
|
||||
|
||||
export interface CreateAuditLogData {
|
||||
userId?: number;
|
||||
userEmail: string;
|
||||
@@ -101,16 +137,11 @@ function determineSensitivity(resourceType: string): AuditSensitivity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft ob Änderungen verschlüsselt werden sollen
|
||||
* Prüft ob Änderungen verschlüsselt werden sollen.
|
||||
* Deaktiviert - sensible Felder werden bereits von der Prisma-Middleware als [REDACTED] gefiltert.
|
||||
*/
|
||||
function shouldEncryptChanges(resourceType: string): boolean {
|
||||
const encryptedTypes = [
|
||||
'BankCard',
|
||||
'IdentityDocument',
|
||||
'User',
|
||||
'Customer', // Enthält Portal-Passwörter
|
||||
];
|
||||
return encryptedTypes.includes(resourceType);
|
||||
function shouldEncryptChanges(_resourceType: string): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,6 +412,49 @@ export async function verifyIntegrity(fromId?: number, toId?: number): Promise<{
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash-Kette komplett neu berechnen (Reparatur)
|
||||
*/
|
||||
export async function rehashAll(): Promise<{ rehashedCount: number }> {
|
||||
const logs = await prisma.auditLog.findMany({
|
||||
orderBy: { id: 'asc' },
|
||||
select: {
|
||||
id: true,
|
||||
userEmail: true,
|
||||
action: true,
|
||||
resourceType: true,
|
||||
resourceId: true,
|
||||
endpoint: true,
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
let previousHash: string | null = null;
|
||||
let count = 0;
|
||||
|
||||
for (const log of logs) {
|
||||
const hash = generateHash({
|
||||
userEmail: log.userEmail,
|
||||
action: log.action,
|
||||
resourceType: log.resourceType,
|
||||
resourceId: log.resourceId,
|
||||
endpoint: log.endpoint,
|
||||
createdAt: log.createdAt,
|
||||
previousHash,
|
||||
});
|
||||
|
||||
await prisma.auditLog.update({
|
||||
where: { id: log.id },
|
||||
data: { hash, previousHash },
|
||||
});
|
||||
|
||||
previousHash = hash;
|
||||
count++;
|
||||
}
|
||||
|
||||
return { rehashedCount: count };
|
||||
}
|
||||
|
||||
/**
|
||||
* Exportiert Audit-Logs als JSON oder CSV
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user