diff --git a/backend/src/contracts/api-contracts.json b/backend/src/contracts/api-contracts.json index 66ea7b4..2907b37 100644 --- a/backend/src/contracts/api-contracts.json +++ b/backend/src/contracts/api-contracts.json @@ -42,7 +42,8 @@ "mimeTypes": [ "application/pdf", "image/png", - "image/jpeg" + "image/jpeg", + "image/svg+xml" ] } } diff --git a/backend/src/documents/documents.controller.ts b/backend/src/documents/documents.controller.ts index 4b69442..fb1d4ee 100644 --- a/backend/src/documents/documents.controller.ts +++ b/backend/src/documents/documents.controller.ts @@ -53,7 +53,9 @@ const fileFilter: multer.Options['fileFilter'] = (_req, file, callback) => { } return callback( - new BadRequestException('Only PDF, PNG, or JPEG files are allowed'), + new BadRequestException( + 'Only PDF, PNG, JPEG, or SVG files are allowed', + ), ); }; diff --git a/backend/src/documents/pipes/file-validation.pipe.spec.ts b/backend/src/documents/pipes/file-validation.pipe.spec.ts index d3a6fdc..5cf0085 100644 --- a/backend/src/documents/pipes/file-validation.pipe.spec.ts +++ b/backend/src/documents/pipes/file-validation.pipe.spec.ts @@ -44,6 +44,10 @@ async function createValidPng(): Promise { .toBuffer(); } +function createSvg(markup: string): Buffer { + return Buffer.from(markup, 'utf8'); +} + describe('FileValidationPipe', () => { let pipe: FileValidationPipe; @@ -90,6 +94,142 @@ describe('FileValidationPipe', () => { expect(result.mimetype).toBe('image/jpeg'); }); + it('should accept static SVG content and store a bounded PNG', async () => { + const buffer = createSvg(` + + Parcel A & B + + + + + + + Parcel A + + `); + const file = createFile(buffer, 'image/svg+xml', 'survey.svg'); + + const result = await pipe.transform(file); + + expect(result.mimetype).toBe('image/png'); + expect(result.buffer.subarray(1, 4).toString('ascii')).toBe('PNG'); + expect(result.size).toBe(result.buffer.length); + }); + + it.each<[string, RegExp]>([ + ['', /active or resource-bearing content/i], + ['