Files
dh-inspeccion-v2/api-v3/src/inspection-reports/inspection-report-revision-file.ts
T

39 lines
2.3 KiB
TypeScript

import { BadRequestException } from '@nestjs/common';
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const execFileAsync = promisify(execFile);
export const MAX_INSPECTION_REPORT_REVISION_BYTES = 15 * 1024 * 1024;
export const INSPECTION_REPORT_WORD_MIME = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
export interface UploadedInspectionReportRevisionFile {
originalname: string;
mimetype: string;
size: number;
buffer: Buffer;
}
function invalidFile(message: string): BadRequestException {
return new BadRequestException({ code: 'INSPECTION_REPORT_REVISION_INVALID_FILE', message });
}
export function inspectInspectionReportRevisionUpload(file: UploadedInspectionReportRevisionFile | undefined): void {
if (!file?.buffer?.length) throw invalidFile('Debés adjuntar un archivo Word .docx');
if (file.size <= 0 || file.size > MAX_INSPECTION_REPORT_REVISION_BYTES) throw invalidFile('El Word corregido debe pesar hasta 15 MB');
if (!file.originalname.toLowerCase().endsWith('.docx')) throw invalidFile('La versión corregida debe ser un archivo .docx');
if (file.mimetype && file.mimetype !== INSPECTION_REPORT_WORD_MIME && file.mimetype !== 'application/octet-stream') throw invalidFile('El tipo de archivo no corresponde a un Word .docx');
if (file.buffer.length < 4 || file.buffer[0] !== 0x50 || file.buffer[1] !== 0x4b || file.buffer[2] !== 0x03 || file.buffer[3] !== 0x04) throw invalidFile('El archivo no tiene una estructura DOCX válida');
}
export async function validateInspectionReportRevisionContainer(filePath: string): Promise<void> {
let stdout = '';
try {
({ stdout } = await execFileAsync('unzip', ['-Z1', filePath], { encoding: 'utf8', maxBuffer: 4 * 1024 * 1024 }));
} catch {
throw invalidFile('No se pudo validar la estructura interna del Word');
}
const entries = stdout.split(/\r?\n/).map((item) => item.trim()).filter(Boolean);
if (!entries.includes('[Content_Types].xml') || !entries.includes('word/document.xml')) throw invalidFile('El archivo no contiene la estructura mínima de un documento Word');
if (entries.some((entry) => /(^|\/)vbaProject\.bin$/i.test(entry) || /(^|\/)embeddings\//i.test(entry))) throw invalidFile('No se permiten macros ni objetos embebidos en las versiones del informe');
}