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
+46 -30
View File
@@ -7,10 +7,10 @@ const express_1 = require("express");
const multer_1 = __importDefault(require("multer"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const client_1 = require("@prisma/client");
const prisma_js_1 = __importDefault(require("../lib/prisma.js"));
const auth_js_1 = require("../middleware/auth.js");
const audit_service_js_1 = require("../services/audit.service.js");
const router = (0, express_1.Router)();
const prisma = new client_1.PrismaClient();
// Uploads-Verzeichnis erstellen falls nicht vorhanden
const uploadsDir = path_1.default.join(process.cwd(), 'uploads');
if (!fs_1.default.existsSync(uploadsDir)) {
@@ -66,7 +66,7 @@ router.post('/bank-cards/:id', auth_js_1.authenticate, (0, auth_js_1.requirePerm
const bankCardId = parseInt(req.params.id);
const relativePath = `/uploads/bank-cards/${req.file.filename}`;
// Bankkarte in der DB aktualisieren
await prisma.bankCard.update({
await prisma_js_1.default.bankCard.update({
where: { id: bankCardId },
data: { documentPath: relativePath },
});
@@ -95,7 +95,7 @@ router.post('/documents/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermi
const documentId = parseInt(req.params.id);
const relativePath = `/uploads/documents/${req.file.filename}`;
// Ausweis in der DB aktualisieren
await prisma.identityDocument.update({
await prisma_js_1.default.identityDocument.update({
where: { id: documentId },
data: { documentPath: relativePath },
});
@@ -119,7 +119,7 @@ router.delete('/bank-cards/:id', auth_js_1.authenticate, (0, auth_js_1.requirePe
try {
const bankCardId = parseInt(req.params.id);
// Bankkarte aus DB holen um Dateipfad zu bekommen
const bankCard = await prisma.bankCard.findUnique({
const bankCard = await prisma_js_1.default.bankCard.findUnique({
where: { id: bankCardId },
});
if (!bankCard) {
@@ -136,7 +136,7 @@ router.delete('/bank-cards/:id', auth_js_1.authenticate, (0, auth_js_1.requirePe
fs_1.default.unlinkSync(filePath);
}
// documentPath in DB auf null setzen
await prisma.bankCard.update({
await prisma_js_1.default.bankCard.update({
where: { id: bankCardId },
data: { documentPath: null },
});
@@ -152,7 +152,7 @@ router.delete('/documents/:id', auth_js_1.authenticate, (0, auth_js_1.requirePer
try {
const documentId = parseInt(req.params.id);
// Ausweis aus DB holen um Dateipfad zu bekommen
const document = await prisma.identityDocument.findUnique({
const document = await prisma_js_1.default.identityDocument.findUnique({
where: { id: documentId },
});
if (!document) {
@@ -169,7 +169,7 @@ router.delete('/documents/:id', auth_js_1.authenticate, (0, auth_js_1.requirePer
fs_1.default.unlinkSync(filePath);
}
// documentPath in DB auf null setzen
await prisma.identityDocument.update({
await prisma_js_1.default.identityDocument.update({
where: { id: documentId },
data: { documentPath: null },
});
@@ -191,7 +191,7 @@ router.post('/customers/:id/business-registration', auth_js_1.authenticate, (0,
const customerId = parseInt(req.params.id);
const relativePath = `/uploads/business-registrations/${req.file.filename}`;
// Alte Datei löschen falls vorhanden
const customer = await prisma.customer.findUnique({ where: { id: customerId } });
const customer = await prisma_js_1.default.customer.findUnique({ where: { id: customerId } });
if (customer?.businessRegistrationPath) {
const oldPath = path_1.default.join(process.cwd(), customer.businessRegistrationPath);
if (fs_1.default.existsSync(oldPath)) {
@@ -199,7 +199,7 @@ router.post('/customers/:id/business-registration', auth_js_1.authenticate, (0,
}
}
// Kunde in der DB aktualisieren
await prisma.customer.update({
await prisma_js_1.default.customer.update({
where: { id: customerId },
data: { businessRegistrationPath: relativePath },
});
@@ -228,7 +228,7 @@ router.post('/customers/:id/commercial-register', auth_js_1.authenticate, (0, au
const customerId = parseInt(req.params.id);
const relativePath = `/uploads/commercial-registers/${req.file.filename}`;
// Alte Datei löschen falls vorhanden
const customer = await prisma.customer.findUnique({ where: { id: customerId } });
const customer = await prisma_js_1.default.customer.findUnique({ where: { id: customerId } });
if (customer?.commercialRegisterPath) {
const oldPath = path_1.default.join(process.cwd(), customer.commercialRegisterPath);
if (fs_1.default.existsSync(oldPath)) {
@@ -236,7 +236,7 @@ router.post('/customers/:id/commercial-register', auth_js_1.authenticate, (0, au
}
}
// Kunde in der DB aktualisieren
await prisma.customer.update({
await prisma_js_1.default.customer.update({
where: { id: customerId },
data: { commercialRegisterPath: relativePath },
});
@@ -259,7 +259,7 @@ router.post('/customers/:id/commercial-register', auth_js_1.authenticate, (0, au
router.delete('/customers/:id/business-registration', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('customers:update'), async (req, res) => {
try {
const customerId = parseInt(req.params.id);
const customer = await prisma.customer.findUnique({ where: { id: customerId } });
const customer = await prisma_js_1.default.customer.findUnique({ where: { id: customerId } });
if (!customer) {
res.status(404).json({ success: false, error: 'Kunde nicht gefunden' });
return;
@@ -274,7 +274,7 @@ router.delete('/customers/:id/business-registration', auth_js_1.authenticate, (0
fs_1.default.unlinkSync(filePath);
}
// Pfad in DB auf null setzen
await prisma.customer.update({
await prisma_js_1.default.customer.update({
where: { id: customerId },
data: { businessRegistrationPath: null },
});
@@ -289,7 +289,7 @@ router.delete('/customers/:id/business-registration', auth_js_1.authenticate, (0
router.delete('/customers/:id/commercial-register', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('customers:update'), async (req, res) => {
try {
const customerId = parseInt(req.params.id);
const customer = await prisma.customer.findUnique({ where: { id: customerId } });
const customer = await prisma_js_1.default.customer.findUnique({ where: { id: customerId } });
if (!customer) {
res.status(404).json({ success: false, error: 'Kunde nicht gefunden' });
return;
@@ -304,7 +304,7 @@ router.delete('/customers/:id/commercial-register', auth_js_1.authenticate, (0,
fs_1.default.unlinkSync(filePath);
}
// Pfad in DB auf null setzen
await prisma.customer.update({
await prisma_js_1.default.customer.update({
where: { id: customerId },
data: { commercialRegisterPath: null },
});
@@ -326,7 +326,7 @@ router.post('/customers/:id/privacy-policy', auth_js_1.authenticate, (0, auth_js
const customerId = parseInt(req.params.id);
const relativePath = `/uploads/privacy-policies/${req.file.filename}`;
// Alte Datei löschen falls vorhanden
const customer = await prisma.customer.findUnique({ where: { id: customerId } });
const customer = await prisma_js_1.default.customer.findUnique({ where: { id: customerId } });
if (customer?.privacyPolicyPath) {
const oldPath = path_1.default.join(process.cwd(), customer.privacyPolicyPath);
if (fs_1.default.existsSync(oldPath)) {
@@ -334,19 +334,27 @@ router.post('/customers/:id/privacy-policy', auth_js_1.authenticate, (0, auth_js
}
}
// Kunde in der DB aktualisieren
await prisma.customer.update({
await prisma_js_1.default.customer.update({
where: { id: customerId },
data: { privacyPolicyPath: relativePath },
});
// Alle Consents auf GRANTED setzen (PDF = vollständige Einwilligung)
const consentTypes = ['DATA_PROCESSING', 'MARKETING_EMAIL', 'MARKETING_PHONE', 'DATA_SHARING_PARTNER'];
for (const consentType of consentTypes) {
await prisma.customerConsent.upsert({
await prisma_js_1.default.customerConsent.upsert({
where: { customerId_consentType: { customerId, consentType } },
update: { status: 'GRANTED', grantedAt: new Date(), source: 'papier' },
create: { customerId, consentType, status: 'GRANTED', grantedAt: new Date(), source: 'papier', createdBy: req.user?.email || 'admin' },
});
}
// Audit
const cust = await prisma_js_1.default.customer.findUnique({ where: { id: customerId }, select: { firstName: true, lastName: true } });
await (0, audit_service_js_1.logChange)({
req, action: 'CREATE', resourceType: 'CustomerConsent',
label: `Datenschutzerklärung-PDF hochgeladen für ${cust?.firstName} ${cust?.lastName} alle Einwilligungen erteilt`,
details: { aktion: 'PDF hochgeladen', einwilligungen: 'alle erteilt', quelle: 'papier' },
customerId,
});
res.json({
success: true,
data: {
@@ -366,7 +374,7 @@ router.post('/customers/:id/privacy-policy', auth_js_1.authenticate, (0, auth_js
router.delete('/customers/:id/privacy-policy', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('customers:update'), async (req, res) => {
try {
const customerId = parseInt(req.params.id);
const customer = await prisma.customer.findUnique({ where: { id: customerId } });
const customer = await prisma_js_1.default.customer.findUnique({ where: { id: customerId } });
if (!customer) {
res.status(404).json({ success: false, error: 'Kunde nicht gefunden' });
return;
@@ -381,15 +389,23 @@ router.delete('/customers/:id/privacy-policy', auth_js_1.authenticate, (0, auth_
fs_1.default.unlinkSync(filePath);
}
// Pfad in DB auf null setzen
await prisma.customer.update({
await prisma_js_1.default.customer.update({
where: { id: customerId },
data: { privacyPolicyPath: null },
});
// Nur Consents widerrufen die per Papier erteilt wurden
await prisma.customerConsent.updateMany({
await prisma_js_1.default.customerConsent.updateMany({
where: { customerId, status: 'GRANTED', source: 'papier' },
data: { status: 'WITHDRAWN', withdrawnAt: new Date() },
});
// Audit
const cust = await prisma_js_1.default.customer.findUnique({ where: { id: customerId }, select: { firstName: true, lastName: true } });
await (0, audit_service_js_1.logChange)({
req, action: 'DELETE', resourceType: 'CustomerConsent',
label: `Datenschutzerklärung-PDF gelöscht für ${cust?.firstName} ${cust?.lastName} Papier-Einwilligungen widerrufen`,
details: { aktion: 'PDF gelöscht', einwilligungen: 'papier-basierte widerrufen' },
customerId,
});
res.json({ success: true });
}
catch (error) {
@@ -408,7 +424,7 @@ async function handleContractDocumentUpload(req, res, fieldName, subDir) {
const contractId = parseInt(req.params.id);
const relativePath = `/uploads/${subDir}/${req.file.filename}`;
// Alte Datei löschen falls vorhanden
const contract = await prisma.contract.findUnique({ where: { id: contractId } });
const contract = await prisma_js_1.default.contract.findUnique({ where: { id: contractId } });
if (!contract) {
res.status(404).json({ success: false, error: 'Vertrag nicht gefunden' });
return;
@@ -421,7 +437,7 @@ async function handleContractDocumentUpload(req, res, fieldName, subDir) {
}
}
// Vertrag in der DB aktualisieren
await prisma.contract.update({
await prisma_js_1.default.contract.update({
where: { id: contractId },
data: { [fieldName]: relativePath },
});
@@ -444,7 +460,7 @@ async function handleContractDocumentUpload(req, res, fieldName, subDir) {
async function handleContractDocumentDelete(req, res, fieldName) {
try {
const contractId = parseInt(req.params.id);
const contract = await prisma.contract.findUnique({ where: { id: contractId } });
const contract = await prisma_js_1.default.contract.findUnique({ where: { id: contractId } });
if (!contract) {
res.status(404).json({ success: false, error: 'Vertrag nicht gefunden' });
return;
@@ -460,7 +476,7 @@ async function handleContractDocumentDelete(req, res, fieldName) {
fs_1.default.unlinkSync(filePath);
}
// Pfad in DB auf null setzen
await prisma.contract.update({
await prisma_js_1.default.contract.update({
where: { id: contractId },
data: { [fieldName]: null },
});
@@ -494,7 +510,7 @@ router.post('/invoices/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermis
const invoiceId = parseInt(req.params.id);
const relativePath = `/uploads/invoices/${req.file.filename}`;
// Alte Datei löschen falls vorhanden
const invoice = await prisma.invoice.findUnique({ where: { id: invoiceId } });
const invoice = await prisma_js_1.default.invoice.findUnique({ where: { id: invoiceId } });
if (!invoice) {
res.status(404).json({ success: false, error: 'Rechnung nicht gefunden' });
return;
@@ -506,7 +522,7 @@ router.post('/invoices/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermis
}
}
// Invoice in der DB aktualisieren
await prisma.invoice.update({
await prisma_js_1.default.invoice.update({
where: { id: invoiceId },
data: { documentPath: relativePath },
});
@@ -529,7 +545,7 @@ router.post('/invoices/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermis
router.delete('/invoices/:id', auth_js_1.authenticate, (0, auth_js_1.requirePermission)('contracts:update'), async (req, res) => {
try {
const invoiceId = parseInt(req.params.id);
const invoice = await prisma.invoice.findUnique({ where: { id: invoiceId } });
const invoice = await prisma_js_1.default.invoice.findUnique({ where: { id: invoiceId } });
if (!invoice) {
res.status(404).json({ success: false, error: 'Rechnung nicht gefunden' });
return;
@@ -544,7 +560,7 @@ router.delete('/invoices/:id', auth_js_1.authenticate, (0, auth_js_1.requirePerm
fs_1.default.unlinkSync(filePath);
}
// documentPath in DB auf null setzen
await prisma.invoice.update({
await prisma_js_1.default.invoice.update({
where: { id: invoiceId },
data: { documentPath: null },
});