@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.
@@ -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 isFileInValidPath = async (
68
- fieldname: string,
68
+ const getRequestUploadValidator = async (
69
69
  req: Express.Request,
70
- ): Promise<boolean> => {
70
+ odataRequest: uriParser.ParsedODataRequest,
71
+ ): Promise<(fieldName: string) => Promise<boolean>> => {
71
72
  if (req.method !== 'POST' && req.method !== 'PATCH') {
72
- return false;
73
+ return notValidUpload;
73
74
  }
74
75
 
75
76
  const apiRoot = getApiRoot(req);
76
77
  if (apiRoot == null) {
77
- return false;
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 false;
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 false;
101
+ return notValidUpload;
105
102
  }
106
103
 
107
- const dbFieldName = odataNameToSqlName(fieldname);
108
- return table.fields.some(
109
- (field) =>
110
- field.fieldName === dbFieldName && field.dataType === 'WebResource',
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 isFileInValidPath(fieldname, req))) {
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
- throw err;
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
- getLogger(getApiRoot(req)).error('Error uploading file', err);
225
- next(err);
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.ODataRequest,
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