fix: Robustheits-Luecken aus zweitem, unabhaengigem Sicherheitsaudit behoben
Ein zweiter, unabhaengiger Audit-Durchlauf (frischer Blick, keine Vorkenntnis meiner eigenen Fixes) bestaetigte alle bisherigen Fixes als korrekt verdrahtet und fand 3 LOW-severity Robustheitsluecken - keine davon war ausnutzbar, aber alle sind jetzt behoben: - HarvestsService.create/ExtractionsService.create pruefen jetzt, dass referenzierte colonyIds/harvestIds tatsaechlich existieren, bevor die Transaktion laeuft - vorher fuehrte eine unbekannte Id zu einem ungefangenen 500 mit rohem Prisma-Fehler statt einer sauberen 400. - Etiketten-Bildelemente durchlaufen jetzt denselben Magic-Byte-Check wie Avatar-/Dokument-Uploads, statt pdfkits Bildparser ungepruefte Bytes zu uebergeben. - Webhook-Secret-Redaktion im Audit-Log nutzt jetzt explizites delete statt sich auf Prismas JSON-Serialisierung zu verlassen, die undefined-Werte verwirft (fragil, falls sich die Serialisierung mal aendert). Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
f57cffe6a8
commit
4bd7e9791a
7 files changed
+173
-7
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { NotFoundException } from '@nestjs/common';
|
||||
import { BadRequestException, NotFoundException } from '@nestjs/common';
|
||||
import { ExtractionsService } from './extractions.service';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { AuditLogService } from '../audit/audit-log.service';
|
||||
@@ -7,6 +7,7 @@ describe('ExtractionsService', () => {
|
||||
let service: ExtractionsService;
|
||||
let prisma: {
|
||||
extraction: { findUnique: jest.Mock; update: jest.Mock };
|
||||
harvest: { findMany: jest.Mock };
|
||||
$transaction: jest.Mock;
|
||||
};
|
||||
let auditLog: { record: jest.Mock };
|
||||
@@ -24,6 +25,11 @@ describe('ExtractionsService', () => {
|
||||
};
|
||||
prisma = {
|
||||
extraction: { findUnique: jest.fn(), update: jest.fn() },
|
||||
harvest: {
|
||||
findMany: jest
|
||||
.fn()
|
||||
.mockResolvedValue([{ id: 'harvest-1' }, { id: 'harvest-2' }]),
|
||||
},
|
||||
$transaction: jest.fn((callback: (txArg: typeof tx) => unknown) =>
|
||||
callback(tx),
|
||||
),
|
||||
@@ -59,6 +65,18 @@ describe('ExtractionsService', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('create rejects an unknown harvest id instead of failing on the DB foreign-key constraint', async () => {
|
||||
prisma.harvest.findMany.mockResolvedValue([{ id: 'harvest-1' }]);
|
||||
|
||||
await expect(
|
||||
service.create(
|
||||
{ date: '2026-07-05', harvestIds: ['harvest-1', 'missing-harvest'] },
|
||||
'user-1',
|
||||
),
|
||||
).rejects.toBeInstanceOf(BadRequestException);
|
||||
expect(prisma.$transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('update writes an audit log entry with before and after data', async () => {
|
||||
const updated = { ...extraction, notes: 'geändert' };
|
||||
prisma.extraction.findUnique
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import {
|
||||
BadRequestException,
|
||||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { AuditLogService } from '../audit/audit-log.service';
|
||||
import { CreateExtractionDto } from './dto/create-extraction.dto';
|
||||
@@ -37,7 +41,22 @@ export class ExtractionsService {
|
||||
return extraction;
|
||||
}
|
||||
|
||||
private async assertHarvestsExist(harvestIds: string[]): Promise<void> {
|
||||
const found = await this.prisma.harvest.findMany({
|
||||
where: { id: { in: harvestIds } },
|
||||
select: { id: true },
|
||||
});
|
||||
const foundIds = new Set(found.map((harvest) => harvest.id));
|
||||
const missing = harvestIds.filter((id) => !foundIds.has(id));
|
||||
if (missing.length > 0) {
|
||||
throw new BadRequestException(
|
||||
`Unknown harvest id(s): ${missing.join(', ')}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async create(dto: CreateExtractionDto, actingUserId: string) {
|
||||
await this.assertHarvestsExist(dto.harvestIds);
|
||||
const extraction = await this.prisma.$transaction(async (tx) => {
|
||||
const created = await tx.extraction.create({
|
||||
data: {
|
||||
|
||||
Reference in new issue
Block a user