@tiledesk/tiledesk-server 2.14.22 → 2.14.24

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/CHANGELOG.md CHANGED
@@ -5,7 +5,14 @@
5
5
  🚀 IN PRODUCTION 🚀
6
6
  (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77)
7
7
 
8
- # 2.14.22
8
+ # 2.14.24
9
+ - Improved extension management on file uploading to support .wav and .svg
10
+
11
+ # 2.14.23
12
+ - Updated whatsapp-connector to 1.0.22
13
+ - Added new endpoint for files uploading
14
+
15
+ # 2.14.22 - aborted
9
16
  - Updated whatsapp-connector to 1.0.20
10
17
  - Added new endpoint for files uploading
11
18
 
@@ -4,9 +4,46 @@ const fs = require('fs');
4
4
  // List of text-based MIME types that FileType cannot detect (they don't have binary signatures)
5
5
  const TEXT_MIME_TYPES = [
6
6
  'text/plain',
7
- 'text/csv'
7
+ 'text/csv',
8
+ 'image/svg+xml',
9
+ 'application/xml',
10
+ 'text/xml'
8
11
  ];
9
12
 
13
+ /**
14
+ * Checks if two MIME types are equivalent, accepting common aliases
15
+ * Examples:
16
+ * - audio/wav === audio/wave === audio/vnd.wave
17
+ * - image/jpeg === image/jpg
18
+ */
19
+ function areMimeTypesEquivalent(mimeType1, mimeType2) {
20
+ if (!mimeType1 || !mimeType2) return false;
21
+ if (mimeType1 === mimeType2) return true;
22
+
23
+ // Normalize to lowercase for comparison
24
+ const m1 = mimeType1.toLowerCase();
25
+ const m2 = mimeType2.toLowerCase();
26
+ if (m1 === m2) return true;
27
+
28
+ // Common MIME type aliases
29
+ const aliases = {
30
+ 'audio/wav': ['audio/wave', 'audio/x-wav', 'audio/vnd.wave'],
31
+ 'audio/wave': ['audio/wav', 'audio/x-wav', 'audio/vnd.wave'],
32
+ 'audio/x-wav': ['audio/wav', 'audio/wave', 'audio/vnd.wave'],
33
+ 'audio/vnd.wave': ['audio/wav', 'audio/wave', 'audio/x-wav'],
34
+ 'image/jpeg': ['image/jpg'],
35
+ 'image/jpg': ['image/jpeg'],
36
+ 'application/x-zip-compressed': ['application/zip'],
37
+ 'application/zip': ['application/x-zip-compressed'],
38
+ };
39
+
40
+ // Check if m1 is an alias of m2 or vice versa
41
+ if (aliases[m1] && aliases[m1].includes(m2)) return true;
42
+ if (aliases[m2] && aliases[m2].includes(m1)) return true;
43
+
44
+ return false;
45
+ }
46
+
10
47
  async function verifyFileContent(buffer, mimetype) {
11
48
  if (!buffer) throw new Error("No file provided");
12
49
 
@@ -26,6 +63,16 @@ async function verifyFileContent(buffer, mimetype) {
26
63
  err.source = "FileContentVerification";
27
64
  throw err;
28
65
  }
66
+ } else if (mimetype && mimetype.startsWith('image/svg')) {
67
+ // Handle SVG files (can be image/svg+xml or variants)
68
+ try {
69
+ buffer.toString('utf8');
70
+ return true;
71
+ } catch (e) {
72
+ const err = new Error(`File content is not valid text for mimetype: ${mimetype}`);
73
+ err.source = "FileContentVerification";
74
+ throw err;
75
+ }
29
76
  } else {
30
77
  // For non-text files, FileType should be able to detect them
31
78
  const err = new Error(`File content does not match mimetype. Detected: unknown, provided: ${mimetype}`);
@@ -34,8 +81,8 @@ async function verifyFileContent(buffer, mimetype) {
34
81
  }
35
82
  }
36
83
 
37
- // If FileType detected a type, it must match the declared mimetype
38
- if (mimetype && fileType.mime !== mimetype) {
84
+ // If FileType detected a type, it must match the declared mimetype (or be equivalent)
85
+ if (mimetype && !areMimeTypesEquivalent(fileType.mime, mimetype)) {
39
86
  const err = new Error(`File content does not match mimetype. Detected: ${fileType.mime}, provided: ${mimetype}`);
40
87
  err.source = "FileContentVerification";
41
88
  throw err;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-server",
3
3
  "description": "The Tiledesk server module",
4
- "version": "2.14.22",
4
+ "version": "2.14.24",
5
5
  "scripts": {
6
6
  "start": "node ./bin/www",
7
7
  "pretest": "mongodb-runner start",
@@ -52,7 +52,7 @@
52
52
  "@tiledesk/tiledesk-tybot-connector": "^2.0.43",
53
53
  "@tiledesk/tiledesk-voice-twilio-connector": "^0.1.28",
54
54
  "@tiledesk/tiledesk-vxml-connector": "^0.1.89",
55
- "@tiledesk/tiledesk-whatsapp-connector": "1.0.20",
55
+ "@tiledesk/tiledesk-whatsapp-connector": "1.0.22",
56
56
  "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.13",
57
57
  "amqplib": "^0.5.5",
58
58
  "app-root-path": "^3.0.0",
package/routes/filesp.js CHANGED
@@ -83,7 +83,7 @@ const fileFilter = (extensionsSource = 'chat') => {
83
83
  }
84
84
 
85
85
  const expectedMimeType = mime.lookup(ext);
86
- if (expectedMimeType && file.mimetype !== expectedMimeType) {
86
+ if (expectedMimeType && !areMimeTypesEquivalent(file.mimetype, expectedMimeType)) {
87
87
  const error = new Error(`File content does not match mimetype. Detected: ${file.mimetype}, provided: ${expectedMimeType}`);
88
88
  error.status = 403;
89
89
  return cb(error);
@@ -102,6 +102,41 @@ function getMimeTypes(allowed_extension) {
102
102
  return allowedMimeTypes;
103
103
  }
104
104
 
105
+ /**
106
+ * Checks if two MIME types are equivalent, accepting common aliases
107
+ * Examples:
108
+ * - audio/wav === audio/wave
109
+ * - audio/x-wav === audio/wave
110
+ * - image/jpeg === image/jpg
111
+ */
112
+ function areMimeTypesEquivalent(mimeType1, mimeType2) {
113
+ if (!mimeType1 || !mimeType2) return false;
114
+ if (mimeType1 === mimeType2) return true;
115
+
116
+ // Normalize to lowercase for comparison
117
+ const m1 = mimeType1.toLowerCase();
118
+ const m2 = mimeType2.toLowerCase();
119
+ if (m1 === m2) return true;
120
+
121
+ // Common MIME type aliases
122
+ const aliases = {
123
+ 'audio/wav': ['audio/wave', 'audio/x-wav', 'audio/vnd.wave'],
124
+ 'audio/wave': ['audio/wav', 'audio/x-wav', 'audio/vnd.wave'],
125
+ 'audio/x-wav': ['audio/wav', 'audio/wave', 'audio/vnd.wave'],
126
+ 'audio/vnd.wave': ['audio/wav', 'audio/wave', 'audio/x-wav'],
127
+ 'image/jpeg': ['image/jpg'],
128
+ 'image/jpg': ['image/jpeg'],
129
+ 'application/x-zip-compressed': ['application/zip'],
130
+ 'application/zip': ['application/x-zip-compressed'],
131
+ };
132
+
133
+ // Check if m1 is an alias of m2 or vice versa
134
+ if (aliases[m1] && aliases[m1].includes(m2)) return true;
135
+ if (aliases[m2] && aliases[m2].includes(m1)) return true;
136
+
137
+ return false;
138
+ }
139
+
105
140
  const uploadChat = multer({
106
141
  storage: fileService.getStorage("files"),
107
142
  fileFilter: fileFilter('chat'),