1
import { Injectable } from '@nestjs/common';
2
import { DomainConflictError } from '../../../common/errors/domain-conflict.error';
3
4
const POLICIES:Record<string,{maxBytes:number;mime:string[]}>={
5
recipe_media:{maxBytes:15*1024*1024,mime:['image/jpeg','image/png','image/webp']},
6
training_media:{maxBytes:250*1024*1024,mime:['image/jpeg','image/png','image/webp','video/mp4','application/pdf']},
7
task_evidence:{maxBytes:20*1024*1024,mime:['image/jpeg','image/png','image/webp','application/pdf']},
8
incident_evidence:{maxBytes:20*1024*1024,mime:['image/jpeg','image/png','image/webp','application/pdf']},
9
safety_evidence:{maxBytes:20*1024*1024,mime:['image/jpeg','image/png','image/webp','application/pdf']},
10
employee_document:{maxBytes:20*1024*1024,mime:['application/pdf','image/jpeg','image/png']},
11
supplier_document:{maxBytes:30*1024*1024,mime:['application/pdf','image/jpeg','image/png']},
12
invoice_document:{maxBytes:30*1024*1024,mime:['application/pdf','image/jpeg','image/png']},
13
import_source:{maxBytes:25*1024*1024,mime:['text/csv','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']},
14
export_result:{maxBytes:100*1024*1024,mime:['text/csv','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','application/pdf']},
15
other:{maxBytes:10*1024*1024,mime:['application/pdf','image/jpeg','image/png','image/webp','text/plain']},
16
};
17
18
@Injectable()
19
export class FilePolicyService {
20
validate(input:{purpose:string;sizeBytes:number;mimeType:string;fileName:string}) {
21
const policy=POLICIES[input.purpose];
22
if(!policy) throw new DomainConflictError('files.purpose_invalid');
23
if(input.sizeBytes<0 || input.sizeBytes>policy.maxBytes) {
24
throw new DomainConflictError('files.size_invalid',{maxBytes:policy.maxBytes});
25
}
26
if(!policy.mime.includes(input.mimeType)) {
27
throw new DomainConflictError('files.mime_invalid',{mimeType:input.mimeType});
28
}
29
const lower=input.fileName.toLowerCase();
30
if(lower.endsWith('.html') || lower.endsWith('.svg') || lower.endsWith('.js') ||
31
lower.endsWith('.exe') || lower.endsWith('.sh')) {
32
throw new DomainConflictError('files.extension_forbidden');
33
}
34
}
35
}
36