@balena/pinejs 20.0.2-build-compile-in-as-eq-any-cdd3d0c80b63550d7316739dc6050ed1382f8009-1 → 20.0.3-build-avoids-string-multipart-webresources-fields-2035384d89af750273ee83e87a1da5bde562a18a-1
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/.pinejs-cache.json +1 -1
- package/.versionbot/CHANGELOG.yml +32 -3
- package/CHANGELOG.md +8 -2
- package/VERSION +1 -1
- package/docs/Migrations.md +32 -18
- package/out/sbvr-api/abstract-sql.js +9 -19
- package/out/sbvr-api/abstract-sql.js.map +1 -1
- package/out/webresource-handler/index.d.ts +2 -0
- package/out/webresource-handler/index.js +29 -17
- package/out/webresource-handler/index.js.map +1 -1
- package/package.json +5 -5
- package/src/sbvr-api/abstract-sql.ts +9 -28
- package/src/webresource-handler/index.ts +50 -24
@@ -63,30 +63,27 @@ export const setupWebresourceHandler = (handler: WebResourceHandler): void => {
|
|
63
63
|
export const getWebresourceHandler = (): WebResourceHandler | undefined => {
|
64
64
|
return configuredWebResourceHandler;
|
65
65
|
};
|
66
|
+
const notValidUpload = () => Promise.resolve(false);
|
66
67
|
|
67
|
-
const
|
68
|
-
fieldname: string,
|
68
|
+
const getRequestUploadValidator = async (
|
69
69
|
req: Express.Request,
|
70
|
-
|
70
|
+
odataRequest: uriParser.ParsedODataRequest,
|
71
|
+
): Promise<(fieldName: string) => Promise<boolean>> => {
|
71
72
|
if (req.method !== 'POST' && req.method !== 'PATCH') {
|
72
|
-
return
|
73
|
+
return notValidUpload;
|
73
74
|
}
|
74
75
|
|
75
76
|
const apiRoot = getApiRoot(req);
|
76
77
|
if (apiRoot == null) {
|
77
|
-
return
|
78
|
+
return notValidUpload;
|
78
79
|
}
|
79
80
|
const model = getModel(apiRoot);
|
80
|
-
const odataRequest = uriParser.parseOData({
|
81
|
-
url: req.url,
|
82
|
-
method: req.method,
|
83
|
-
});
|
84
81
|
const sqlResourceName = sbvrUtils.resolveSynonym(odataRequest);
|
85
82
|
|
86
83
|
const table = model.abstractSql.tables[sqlResourceName];
|
87
84
|
|
88
85
|
if (table == null) {
|
89
|
-
return
|
86
|
+
return notValidUpload;
|
90
87
|
}
|
91
88
|
|
92
89
|
const permission = req.method === 'POST' ? 'create' : 'update';
|
@@ -101,20 +98,22 @@ const isFileInValidPath = async (
|
|
101
98
|
);
|
102
99
|
|
103
100
|
if (!hasPermissions) {
|
104
|
-
return
|
101
|
+
return notValidUpload;
|
105
102
|
}
|
106
103
|
|
107
|
-
|
108
|
-
|
109
|
-
(
|
110
|
-
field
|
111
|
-
|
104
|
+
return async (fieldname: string) => {
|
105
|
+
const dbFieldName = odataNameToSqlName(fieldname);
|
106
|
+
return table.fields.some(
|
107
|
+
(field) =>
|
108
|
+
field.fieldName === dbFieldName && field.dataType === 'WebResource',
|
109
|
+
);
|
110
|
+
};
|
112
111
|
};
|
113
112
|
|
114
113
|
export const getUploaderMiddlware = (
|
115
114
|
handler: WebResourceHandler,
|
116
115
|
): Express.RequestHandler => {
|
117
|
-
return (req, res, next) => {
|
116
|
+
return async (req, res, next) => {
|
118
117
|
if (!req.is('multipart')) {
|
119
118
|
next();
|
120
119
|
return;
|
@@ -125,6 +124,20 @@ export const getUploaderMiddlware = (
|
|
125
124
|
const bb = busboy({ headers: req.headers });
|
126
125
|
let isAborting = false;
|
127
126
|
|
127
|
+
const parsedOdataRequest = uriParser.parseOData({
|
128
|
+
url: req.url,
|
129
|
+
method: req.method,
|
130
|
+
});
|
131
|
+
const webResourcesFieldNames = getWebResourceFields(
|
132
|
+
parsedOdataRequest,
|
133
|
+
false,
|
134
|
+
);
|
135
|
+
|
136
|
+
const isValidUpload = await getRequestUploadValidator(
|
137
|
+
req,
|
138
|
+
parsedOdataRequest,
|
139
|
+
);
|
140
|
+
|
128
141
|
const finishFileUpload = () => {
|
129
142
|
req.unpipe(bb);
|
130
143
|
req.on('readable', req.read.bind(req));
|
@@ -152,7 +165,7 @@ export const getUploaderMiddlware = (
|
|
152
165
|
completeUploads.push(
|
153
166
|
(async () => {
|
154
167
|
try {
|
155
|
-
if (!(await
|
168
|
+
if (!(await isValidUpload(fieldname))) {
|
156
169
|
filestream.resume();
|
157
170
|
return;
|
158
171
|
}
|
@@ -174,7 +187,10 @@ export const getUploaderMiddlware = (
|
|
174
187
|
uploadedFilePaths.push(result.filename);
|
175
188
|
} catch (err: any) {
|
176
189
|
filestream.resume();
|
177
|
-
|
190
|
+
bb.emit(
|
191
|
+
'error',
|
192
|
+
new errors.BadRequestError(err.message ?? 'Error uploading file'),
|
193
|
+
);
|
178
194
|
}
|
179
195
|
})(),
|
180
196
|
);
|
@@ -184,6 +200,14 @@ export const getUploaderMiddlware = (
|
|
184
200
|
// This receives the form fields and transforms them into a standard JSON body
|
185
201
|
// This is a similar behavior as previous multer library did
|
186
202
|
bb.on('field', (name, val) => {
|
203
|
+
if (webResourcesFieldNames.includes(name)) {
|
204
|
+
isAborting = true;
|
205
|
+
bb.emit(
|
206
|
+
'error',
|
207
|
+
new errors.BadRequestError('WebResource field must be a blob.'),
|
208
|
+
);
|
209
|
+
return;
|
210
|
+
}
|
187
211
|
req.body[name] = val;
|
188
212
|
});
|
189
213
|
|
@@ -209,7 +233,7 @@ export const getUploaderMiddlware = (
|
|
209
233
|
}
|
210
234
|
});
|
211
235
|
|
212
|
-
bb.on('error', async (err) => {
|
236
|
+
bb.on('error', async (err: Error) => {
|
213
237
|
finishFileUpload();
|
214
238
|
await clearFiles();
|
215
239
|
|
@@ -221,15 +245,17 @@ export const getUploaderMiddlware = (
|
|
221
245
|
);
|
222
246
|
}
|
223
247
|
|
224
|
-
|
225
|
-
|
248
|
+
if (!sbvrUtils.handleHttpErrors(req, res, err)) {
|
249
|
+
getLogger(getApiRoot(req)).error('Error uploading file', err);
|
250
|
+
next(err);
|
251
|
+
}
|
226
252
|
});
|
227
253
|
req.pipe(bb);
|
228
254
|
};
|
229
255
|
};
|
230
256
|
|
231
|
-
const getWebResourceFields = (
|
232
|
-
request: uriParser.
|
257
|
+
export const getWebResourceFields = (
|
258
|
+
request: uriParser.ParsedODataRequest,
|
233
259
|
useTranslations = true,
|
234
260
|
): string[] => {
|
235
261
|
// Translations will use modifyFields(translated) rather than fields(original) so we need to
|