@reldens/server-utils 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/lib/file-handler.js +258 -0
- package/lib/uploader-factory.js +43 -50
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ A Node.js server toolkit providing secure application server creation, file hand
|
|
|
40
40
|
- Password hashing using PBKDF2 with configurable iterations
|
|
41
41
|
- Password validation against stored hashes
|
|
42
42
|
- AES-256-GCM data encryption and decryption
|
|
43
|
-
- Secure token generation with customizable length
|
|
43
|
+
- Secure token generation with a customizable length
|
|
44
44
|
- TOTP (Time-based One-Time Password) generation
|
|
45
45
|
- Data hashing with multiple algorithms (SHA-256, SHA-512, MD5)
|
|
46
46
|
- HMAC generation and verification
|
|
@@ -245,8 +245,9 @@ let serverResult = appServerFactory.createAppServer({
|
|
|
245
245
|
### FileHandler Methods
|
|
246
246
|
|
|
247
247
|
- `exists(path)` - Checks if file or folder exists
|
|
248
|
-
- `createFolder(path)` - Creates folder with recursive option
|
|
248
|
+
- `createFolder(path)` - Creates folder with a recursive option
|
|
249
249
|
- `remove(path)` - Removes file or folder recursively
|
|
250
|
+
- `removeMultiple(filePaths)` - Removes multiple files from an array of paths
|
|
250
251
|
- `copyFile(source, destination)` - Copies file to destination
|
|
251
252
|
- `copyFolderSync(source, destination)` - Copies folder recursively
|
|
252
253
|
- `readFile(path)` - Reads file contents as string
|
|
@@ -254,14 +255,14 @@ let serverResult = appServerFactory.createAppServer({
|
|
|
254
255
|
- `fetchFileJson(path)` - Reads and parses JSON file
|
|
255
256
|
- `fetchFileContents(path)` - Reads file with validation
|
|
256
257
|
- `updateFileContents(path, content)` - Updates existing file
|
|
257
|
-
- `isFile(path)` - Checks if path is file
|
|
258
|
-
- `isFolder(path)` - Checks if path is folder
|
|
258
|
+
- `isFile(path)` - Checks if a path is a file
|
|
259
|
+
- `isFolder(path)` - Checks if a path is folder
|
|
259
260
|
- `getFilesInFolder(path, extensions)` - Lists files with optional filtering
|
|
260
261
|
- `validateFileType(path, type, allowedTypes, maxSize)` - Validates file type and size
|
|
261
262
|
- `detectFileType(path)` - Detects MIME type from file signature
|
|
262
263
|
- `generateSecureFilename(originalName)` - Generates cryptographically secure filename
|
|
263
264
|
- `quarantineFile(path, reason)` - Moves file to quarantine folder
|
|
264
|
-
- `createTempFile(prefix, extension)` - Creates temporary file path
|
|
265
|
+
- `createTempFile(prefix, extension)` - Creates a temporary file path
|
|
265
266
|
|
|
266
267
|
### Encryptor Methods
|
|
267
268
|
|
|
@@ -281,9 +282,8 @@ let serverResult = appServerFactory.createAppServer({
|
|
|
281
282
|
|
|
282
283
|
- `createUploader(fields, buckets, allowedTypes)` - Creates multer upload middleware
|
|
283
284
|
- `validateFilenameSecurity(filename)` - Validates filename for security
|
|
284
|
-
- `validateFile(file, allowedType, callback)` - Validates file during upload
|
|
285
|
+
- `validateFile(file, allowedType, callback)` - Validates a file during upload
|
|
285
286
|
- `validateFileContents(file, allowedType)` - Validates file content after upload
|
|
286
|
-
- `cleanupFiles(files)` - Removes uploaded files on error
|
|
287
287
|
|
|
288
288
|
## Security Features
|
|
289
289
|
|
|
@@ -291,7 +291,7 @@ let serverResult = appServerFactory.createAppServer({
|
|
|
291
291
|
All file operations include comprehensive path validation to prevent directory traversal attacks and access to system files.
|
|
292
292
|
|
|
293
293
|
### Secure File Upload
|
|
294
|
-
File uploads are validated at multiple levels including filename, MIME type, file extension, file size, and content validation using magic number detection.
|
|
294
|
+
File uploads are validated at multiple levels including filename, MIME type, file extension, file size, and content validation using magic number detection. Failed uploads are automatically cleaned up using efficient file removal.
|
|
295
295
|
|
|
296
296
|
### Rate Limiting
|
|
297
297
|
Configurable rate limiting with development mode detection for appropriate thresholds in different environments.
|
package/lib/file-handler.js
CHANGED
|
@@ -22,6 +22,8 @@ class FileHandler
|
|
|
22
22
|
'C:\\Windows\\', 'C:\\System32\\',
|
|
23
23
|
'%2e%2e%2f', '%2e%2e%5c'
|
|
24
24
|
];
|
|
25
|
+
this.nativeHandler = fs;
|
|
26
|
+
this.nativePaths = path;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
joinPaths(...args)
|
|
@@ -29,6 +31,24 @@ class FileHandler
|
|
|
29
31
|
return path.join(...args);
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
getFileName(filePath)
|
|
35
|
+
{
|
|
36
|
+
if(!this.isValidPath(filePath)){
|
|
37
|
+
this.error = {message: 'Invalid file path.', filePath};
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
return path.basename(filePath);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getFolderName(filePath)
|
|
44
|
+
{
|
|
45
|
+
if(!this.isValidPath(filePath)){
|
|
46
|
+
this.error = {message: 'Invalid file path.', filePath};
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return path.dirname(filePath);
|
|
50
|
+
}
|
|
51
|
+
|
|
32
52
|
exists(fullPath)
|
|
33
53
|
{
|
|
34
54
|
if(!this.isValidPath(fullPath)){
|
|
@@ -121,6 +141,20 @@ class FileHandler
|
|
|
121
141
|
}
|
|
122
142
|
}
|
|
123
143
|
|
|
144
|
+
removeMultiple(filePaths)
|
|
145
|
+
{
|
|
146
|
+
if(!Array.isArray(filePaths)){
|
|
147
|
+
this.error = {message: 'File paths must be an array'};
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
for(let filePath of filePaths){
|
|
151
|
+
if(!this.remove(filePath)){
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
|
|
124
158
|
createFolder(folderPath)
|
|
125
159
|
{
|
|
126
160
|
if(!this.isValidPath(folderPath)){
|
|
@@ -507,6 +541,230 @@ class FileHandler
|
|
|
507
541
|
return this.joinPaths(tempDir, fileName);
|
|
508
542
|
}
|
|
509
543
|
|
|
544
|
+
moveFile(from, to)
|
|
545
|
+
{
|
|
546
|
+
if(!this.isValidPath(from) || !this.isValidPath(to)){
|
|
547
|
+
this.error = {message: 'Invalid path for file move.', from, to};
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
if(!this.exists(from)){
|
|
551
|
+
this.error = {message: 'Source file does not exist.', from};
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
try {
|
|
555
|
+
fs.renameSync(from, to);
|
|
556
|
+
return true;
|
|
557
|
+
} catch (error) {
|
|
558
|
+
this.error = {message: 'Failed to move file.', error, from, to};
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
getFileSize(filePath)
|
|
564
|
+
{
|
|
565
|
+
if(!this.isValidPath(filePath)){
|
|
566
|
+
this.error = {message: 'Invalid file path.', filePath};
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
if(!this.exists(filePath)){
|
|
570
|
+
this.error = {message: 'File does not exist.', filePath};
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
try {
|
|
574
|
+
return fs.statSync(filePath).size;
|
|
575
|
+
} catch (error) {
|
|
576
|
+
this.error = {message: 'Failed to get file size.', error, filePath};
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
compareFiles(file1, file2)
|
|
582
|
+
{
|
|
583
|
+
if(!this.isValidPath(file1) || !this.isValidPath(file2)){
|
|
584
|
+
this.error = {message: 'Invalid file paths for comparison.', file1, file2};
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
if(!this.exists(file1) || !this.exists(file2)){
|
|
588
|
+
this.error = {message: 'One or both files do not exist.', file1, file2};
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
try {
|
|
592
|
+
let content1 = this.readFile(file1);
|
|
593
|
+
let content2 = this.readFile(file2);
|
|
594
|
+
if(!content1 || !content2){
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
return content1 === content2;
|
|
598
|
+
} catch (error) {
|
|
599
|
+
this.error = {message: 'Failed to compare files.', error, file1, file2};
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
getRelativePath(from, to)
|
|
605
|
+
{
|
|
606
|
+
if(!this.isValidPath(from) || !this.isValidPath(to)){
|
|
607
|
+
this.error = {message: 'Invalid paths for relative calculation.', from, to};
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
try {
|
|
611
|
+
return path.relative(from, to);
|
|
612
|
+
} catch (error) {
|
|
613
|
+
this.error = {message: 'Failed to calculate relative path.', error, from, to};
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
isAbsolutePath(filePath)
|
|
619
|
+
{
|
|
620
|
+
if(!this.isValidPath(filePath)){
|
|
621
|
+
this.error = {message: 'Invalid file path.', filePath};
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
return path.isAbsolute(filePath);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
normalizePath(filePath)
|
|
628
|
+
{
|
|
629
|
+
if(!filePath){
|
|
630
|
+
this.error = {message: 'Path cannot be empty.', filePath};
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
try {
|
|
634
|
+
return path.normalize(filePath);
|
|
635
|
+
} catch (error) {
|
|
636
|
+
this.error = {message: 'Failed to normalize path.', error, filePath};
|
|
637
|
+
return false;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
walkDirectory(dirPath, callback)
|
|
642
|
+
{
|
|
643
|
+
if(!this.isValidPath(dirPath)){
|
|
644
|
+
this.error = {message: 'Invalid directory path.', dirPath};
|
|
645
|
+
return false;
|
|
646
|
+
}
|
|
647
|
+
if(!this.isFolder(dirPath)){
|
|
648
|
+
this.error = {message: 'Path is not a directory.', dirPath};
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
if('function' !== typeof callback){
|
|
652
|
+
this.error = {message: 'Callback must be a function.', dirPath};
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
try {
|
|
656
|
+
let items = this.readFolder(dirPath);
|
|
657
|
+
for(let item of items){
|
|
658
|
+
let itemPath = this.joinPaths(dirPath, item);
|
|
659
|
+
callback(itemPath);
|
|
660
|
+
if(this.isFolder(itemPath)){
|
|
661
|
+
this.walkDirectory(itemPath, callback);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return true;
|
|
665
|
+
} catch (error) {
|
|
666
|
+
this.error = {message: 'Failed to walk directory.', error, dirPath};
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
getDirectorySize(dirPath)
|
|
672
|
+
{
|
|
673
|
+
if(!this.isValidPath(dirPath)){
|
|
674
|
+
this.error = {message: 'Invalid directory path.', dirPath};
|
|
675
|
+
return false;
|
|
676
|
+
}
|
|
677
|
+
if(!this.isFolder(dirPath)){
|
|
678
|
+
this.error = {message: 'Path is not a directory.', dirPath};
|
|
679
|
+
return false;
|
|
680
|
+
}
|
|
681
|
+
let totalSize = 0;
|
|
682
|
+
let calculateSize = (itemPath) => {
|
|
683
|
+
if(this.isFile(itemPath)){
|
|
684
|
+
let size = this.getFileSize(itemPath);
|
|
685
|
+
if(false !== size){
|
|
686
|
+
totalSize += size;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
let walkResult = this.walkDirectory(dirPath, calculateSize);
|
|
691
|
+
if(!walkResult){
|
|
692
|
+
return false;
|
|
693
|
+
}
|
|
694
|
+
return totalSize;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
emptyDirectory(dirPath)
|
|
698
|
+
{
|
|
699
|
+
if(!this.isValidPath(dirPath)){
|
|
700
|
+
this.error = {message: 'Invalid directory path.', dirPath};
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
if(!this.isFolder(dirPath)){
|
|
704
|
+
this.error = {message: 'Path is not a directory.', dirPath};
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
try {
|
|
708
|
+
let items = this.readFolder(dirPath);
|
|
709
|
+
for(let item of items){
|
|
710
|
+
let itemPath = this.joinPaths(dirPath, item);
|
|
711
|
+
this.remove(itemPath);
|
|
712
|
+
}
|
|
713
|
+
return true;
|
|
714
|
+
} catch (error) {
|
|
715
|
+
this.error = {message: 'Failed to empty directory.', error, dirPath};
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
appendToFile(filePath, content)
|
|
721
|
+
{
|
|
722
|
+
if(!this.isValidPath(filePath)){
|
|
723
|
+
this.error = {message: 'Invalid file path.', filePath};
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
try {
|
|
727
|
+
fs.appendFileSync(filePath, content, this.encoding);
|
|
728
|
+
return true;
|
|
729
|
+
} catch (error) {
|
|
730
|
+
this.error = {message: 'Failed to append to file.', error, filePath};
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
prependToFile(filePath, content)
|
|
736
|
+
{
|
|
737
|
+
if(!this.isValidPath(filePath)){
|
|
738
|
+
this.error = {message: 'Invalid file path.', filePath};
|
|
739
|
+
return false;
|
|
740
|
+
}
|
|
741
|
+
if(!this.exists(filePath)){
|
|
742
|
+
return this.writeFile(filePath, content);
|
|
743
|
+
}
|
|
744
|
+
let existingContent = this.readFile(filePath);
|
|
745
|
+
if(!existingContent){
|
|
746
|
+
return false;
|
|
747
|
+
}
|
|
748
|
+
return this.writeFile(filePath, content + existingContent);
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
replaceInFile(filePath, searchValue, replaceValue)
|
|
752
|
+
{
|
|
753
|
+
if(!this.isValidPath(filePath)){
|
|
754
|
+
this.error = {message: 'Invalid file path.', filePath};
|
|
755
|
+
return false;
|
|
756
|
+
}
|
|
757
|
+
if(!this.exists(filePath)){
|
|
758
|
+
this.error = {message: 'File does not exist.', filePath};
|
|
759
|
+
return false;
|
|
760
|
+
}
|
|
761
|
+
let content = this.readFile(filePath);
|
|
762
|
+
if(!content){
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
return this.writeFile(filePath, content.replace(searchValue, replaceValue));
|
|
766
|
+
}
|
|
767
|
+
|
|
510
768
|
}
|
|
511
769
|
|
|
512
770
|
module.exports.FileHandler = new FileHandler();
|
package/lib/uploader-factory.js
CHANGED
|
@@ -31,32 +31,36 @@ class UploaderFactory
|
|
|
31
31
|
this.error = {message: 'Invalid uploader configuration: ' + this.error.message};
|
|
32
32
|
return false;
|
|
33
33
|
}
|
|
34
|
-
let
|
|
34
|
+
let storage = multer.diskStorage({
|
|
35
35
|
destination: (req, file, cb) => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
try{
|
|
37
|
+
let dest = buckets[file.fieldname];
|
|
38
|
+
if(!FileHandler.isValidPath(dest)){
|
|
39
|
+
return cb(new Error('Invalid destination path'));
|
|
40
|
+
}
|
|
41
|
+
FileHandler.createFolder(dest);
|
|
42
|
+
cb(null, dest);
|
|
43
|
+
} catch(error){
|
|
44
|
+
this.error = {message: 'Cannot prepare destination.', error: error};
|
|
45
|
+
cb(error);
|
|
39
46
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
},
|
|
48
|
+
filename: (req, file, cb) => {
|
|
49
|
+
if(!this.validateFilenameSecurity(file.originalname)){
|
|
50
|
+
return cb(new Error('Invalid filename'));
|
|
51
|
+
}
|
|
52
|
+
if(!this.applySecureFileNames) {
|
|
53
|
+
cb(null, file.originalname);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let secureFilename = FileHandler.generateSecureFilename(file.originalname);
|
|
57
|
+
if(!req.fileNameMapping){
|
|
58
|
+
req.fileNameMapping = {};
|
|
59
|
+
}
|
|
60
|
+
req.fileNameMapping[secureFilename] = file.originalname;
|
|
61
|
+
cb(null, secureFilename);
|
|
55
62
|
}
|
|
56
|
-
|
|
57
|
-
cb(null, secureFilename);
|
|
58
|
-
};
|
|
59
|
-
let storage = multer.diskStorage(diskStorageConfiguration);
|
|
63
|
+
});
|
|
60
64
|
let limits = {
|
|
61
65
|
fileSize: this.maxFileSize
|
|
62
66
|
};
|
|
@@ -74,14 +78,14 @@ class UploaderFactory
|
|
|
74
78
|
upload.fields(fields)(req, res, async (multerError) => {
|
|
75
79
|
if(multerError){
|
|
76
80
|
if(multerError instanceof multer.MulterError){
|
|
77
|
-
if(multerError.code
|
|
81
|
+
if('LIMIT_FILE_SIZE' === multerError.code){
|
|
78
82
|
let messageFile = 'File too large.';
|
|
79
83
|
if('function' === typeof this.processErrorResponse){
|
|
80
84
|
return this.processErrorResponse(413, messageFile, req, res);
|
|
81
85
|
}
|
|
82
86
|
return res.status(413).send(messageFile);
|
|
83
87
|
}
|
|
84
|
-
if(multerError.code
|
|
88
|
+
if('LIMIT_FILE_COUNT' === multerError.code){
|
|
85
89
|
let messageTooMany = 'Too many files.';
|
|
86
90
|
if('function' === typeof this.processErrorResponse){
|
|
87
91
|
return this.processErrorResponse(413, messageTooMany, req, res);
|
|
@@ -94,19 +98,19 @@ class UploaderFactory
|
|
|
94
98
|
}
|
|
95
99
|
return res.status(400).send(messageUpload);
|
|
96
100
|
}
|
|
97
|
-
let messageServer = 'Server error during file upload.';
|
|
101
|
+
let messageServer = this.error && this.error.message ? this.error.message : 'Server error during file upload.';
|
|
98
102
|
if('function' === typeof this.processErrorResponse){
|
|
99
|
-
return this.processErrorResponse(
|
|
103
|
+
return this.processErrorResponse(415, messageServer, req, res);
|
|
100
104
|
}
|
|
101
|
-
return res.status(
|
|
105
|
+
return res.status(415).send(messageServer);
|
|
102
106
|
}
|
|
103
107
|
if(!req.files){
|
|
104
108
|
return next();
|
|
105
109
|
}
|
|
106
110
|
let validationResult = await this.validateAllUploadedFiles(req, allowedFileTypes);
|
|
107
111
|
if(!validationResult){
|
|
108
|
-
|
|
109
|
-
let messageContents = 'File validation failed.';
|
|
112
|
+
FileHandler.removeMultiple(Object.values(req.files).flat().map(file => file.path));
|
|
113
|
+
let messageContents = this.error && this.error.message ? this.error.message : 'File validation failed.';
|
|
110
114
|
if('function' === typeof this.processErrorResponse){
|
|
111
115
|
return this.processErrorResponse(415, messageContents, req, res);
|
|
112
116
|
}
|
|
@@ -190,17 +194,17 @@ class UploaderFactory
|
|
|
190
194
|
validateFile(file, allowedFileType, cb)
|
|
191
195
|
{
|
|
192
196
|
if(!allowedFileType){
|
|
193
|
-
return cb();
|
|
197
|
+
return cb(null, true);
|
|
194
198
|
}
|
|
195
199
|
if(!this.validateFilenameSecurity(file.originalname)){
|
|
196
|
-
this.error = {message: 'Insecure filename: '
|
|
197
|
-
return cb(new Error('Insecure filename: '
|
|
200
|
+
this.error = {message: 'Insecure filename: '+file.originalname};
|
|
201
|
+
return cb(new Error('Insecure filename: '+file.originalname));
|
|
198
202
|
}
|
|
199
203
|
let fileExtension = FileHandler.extension(file.originalname).toLowerCase();
|
|
200
|
-
let allowedExtensions = this.allowedExtensions[allowedFileType];
|
|
204
|
+
let allowedExtensions = this.allowedExtensions && this.allowedExtensions[allowedFileType];
|
|
201
205
|
if(allowedExtensions && !allowedExtensions.includes(fileExtension)){
|
|
202
|
-
this.error = {message: 'Invalid file extension: '
|
|
203
|
-
return cb(new Error('Invalid file extension: '
|
|
206
|
+
this.error = {message: 'Invalid file extension: '+fileExtension};
|
|
207
|
+
return cb(new Error('Invalid file extension: '+fileExtension));
|
|
204
208
|
}
|
|
205
209
|
let allowedFileTypeRegex = this.convertToRegex(allowedFileType);
|
|
206
210
|
if(!allowedFileTypeRegex){
|
|
@@ -209,10 +213,10 @@ class UploaderFactory
|
|
|
209
213
|
}
|
|
210
214
|
let mimeTypeValid = allowedFileTypeRegex.test(file.mimetype);
|
|
211
215
|
if(!mimeTypeValid){
|
|
212
|
-
this.error = {message: 'Invalid MIME type: '
|
|
213
|
-
return cb(new Error('Invalid MIME type: '
|
|
216
|
+
this.error = {message: 'Invalid MIME type: '+file.mimetype};
|
|
217
|
+
return cb(new Error('Invalid MIME type: '+file.mimetype));
|
|
214
218
|
}
|
|
215
|
-
return cb();
|
|
219
|
+
return cb(null, true);
|
|
216
220
|
}
|
|
217
221
|
|
|
218
222
|
async validateFileContents(file, allowedFileType)
|
|
@@ -246,17 +250,6 @@ class UploaderFactory
|
|
|
246
250
|
return new RegExp(types.join('|'));
|
|
247
251
|
}
|
|
248
252
|
|
|
249
|
-
cleanupFiles(files)
|
|
250
|
-
{
|
|
251
|
-
if(!files){
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
for(let fieldName in files){
|
|
255
|
-
for(let file of files[fieldName]){
|
|
256
|
-
FileHandler.remove(file.path);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
253
|
}
|
|
261
254
|
|
|
262
255
|
module.exports.UploaderFactory = UploaderFactory;
|