@saltcorn/server 1.1.1 → 1.1.2-beta.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/routes/api.js CHANGED
@@ -30,6 +30,7 @@ const Trigger = require("@saltcorn/data/models/trigger");
30
30
  const File = require("@saltcorn/data/models/file");
31
31
  //const load_plugins = require("../load_plugins");
32
32
  const passport = require("passport");
33
+ const path = require("path");
33
34
 
34
35
  const {
35
36
  readState,
@@ -164,7 +165,7 @@ router.post(
164
165
  ) {
165
166
  const queries = view.queries(false, req);
166
167
  if (Object.prototype.hasOwnProperty.call(queries, queryName)) {
167
- const { args } = req.body;
168
+ const { args } = req.body || {};
168
169
  const resp = await queries[queryName](...args, true);
169
170
  res.json({ success: resp, alerts: getFlashes(req) });
170
171
  } else {
@@ -192,7 +193,7 @@ router.post(
192
193
  );
193
194
 
194
195
  router.get(
195
- "/serve-files/*",
196
+ "/serve-files/*serve_path",
196
197
  //passport.authenticate("api-bearer", { session: false }),
197
198
  error_catcher(async (req, res, next) => {
198
199
  await passport.authenticate(
@@ -201,7 +202,7 @@ router.get(
201
202
  async function (err, user, info) {
202
203
  const role = req?.user?.role_id || user?.role_id || 100;
203
204
  const user_id = req?.user?.id || user?.id;
204
- const serve_path = req.params[0];
205
+ const serve_path = path.join(...req.params.serve_path);
205
206
  const file = await File.findOne(serve_path);
206
207
  if (
207
208
  file &&
@@ -214,7 +215,7 @@ router.get(
214
215
  res.set("Cache-Control", `${cacheability}, max-age=${maxAge}`);
215
216
  if (file.s3_store)
216
217
  res.status(404).json({ error: req.__("Not found") });
217
- else res.sendFile(file.location);
218
+ else res.sendFile(file.location, { dotfiles: "allow" });
218
219
  } else {
219
220
  res.status(404).json({ error: req.__("Not found") });
220
221
  }
@@ -466,7 +467,7 @@ router.all(
466
467
  if (accessAllowed(req, user, trigger)) {
467
468
  try {
468
469
  let resp;
469
- const row = req.method === "GET" ? req.query : req.body;
470
+ const row = req.method === "GET" ? req.query : req.body || {};
470
471
  if (trigger.action === "Workflow") {
471
472
  resp = await trigger.runWithoutRow({
472
473
  req,
@@ -479,7 +480,7 @@ router.all(
479
480
  const action = getState().actions[trigger.action];
480
481
  resp = await action.run({
481
482
  configuration: trigger.configuration,
482
- body: req.body,
483
+ body: req.body || {},
483
484
  row,
484
485
  req,
485
486
  user: user || req.user,
@@ -533,7 +534,7 @@ router.post(
533
534
  { session: false },
534
535
  async function (err, user, info) {
535
536
  if (accessAllowedWrite(req, user, table)) {
536
- const { _versions, ...row } = req.body;
537
+ const { _versions, ...row } = req.body || {};
537
538
  const fields = table.getFields();
538
539
  readState(row, fields, req);
539
540
  const errors = await prepare_insert_row(row, fields);
@@ -588,7 +589,7 @@ router.post(
588
589
  if (id === "undefined") {
589
590
  const pk_name = table.pk_name;
590
591
  //const fields = table.getFields();
591
- const row = req.body;
592
+ const row = req.body || {};
592
593
  //readState(row, fields);
593
594
  await table.deleteRows(
594
595
  { [pk_name]: row[pk_name] },
@@ -635,7 +636,7 @@ router.post(
635
636
  { session: false },
636
637
  async function (err, user, info) {
637
638
  if (accessAllowedWrite(req, user, table)) {
638
- const { _versions, ...row } = req.body;
639
+ const { _versions, ...row } = req.body || {};
639
640
  const fields = table.getFields();
640
641
  readState(row, fields, req);
641
642
  const errors = await prepare_update_row(table, row, id);
@@ -692,7 +693,7 @@ router.delete(
692
693
  if (id === "undefined") {
693
694
  const pk_name = table.pk_name;
694
695
  //const fields = table.getFields();
695
- const row = req.body;
696
+ const row = req.body || {};
696
697
  //readState(row, fields);
697
698
  await table.deleteRows(
698
699
  { [pk_name]: row[pk_name] },
package/routes/config.js CHANGED
@@ -48,8 +48,12 @@ router.post(
48
48
  const validKeyName = (k) =>
49
49
  k !== "_csrf" && k !== "constructor" && k !== "__proto__";
50
50
 
51
- for (const [k, v] of Object.entries(req.body)) {
52
- if (!state.isFixedConfig(k) && typeof v !== "undefined" && validKeyName(k)) {
51
+ for (const [k, v] of Object.entries(req.body || {})) {
52
+ if (
53
+ !state.isFixedConfig(k) &&
54
+ typeof v !== "undefined" &&
55
+ validKeyName(k)
56
+ ) {
53
57
  //TODO read value from type
54
58
  await state.setConfig(k, v);
55
59
  }
@@ -64,7 +68,7 @@ router.post(
64
68
  ? boolcheck
65
69
  : [boolcheck];
66
70
  for (const k of boolchecks) {
67
- if (typeof req.body[k] === "undefined" && validKeyName(k))
71
+ if (typeof (req.body || {})[k] === "undefined" && validKeyName(k))
68
72
  await state.setConfig(k, false);
69
73
  }
70
74
  res.json({ success: "ok" });
@@ -104,8 +104,8 @@ router.post(
104
104
  "/",
105
105
  error_catcher(async (req, res) => {
106
106
  const err = {
107
- stack: req.body.stack,
108
- message: `[JS] ${req.body.message}`,
107
+ stack: (req.body || {}).stack,
108
+ message: `[JS] ${(req.body || {}).message}`,
109
109
  };
110
110
  await Crash.create(err, req);
111
111
  res.json({});
@@ -298,7 +298,7 @@ router.post(
298
298
  isAdmin,
299
299
  error_catcher(async (req, res) => {
300
300
  const form = await customEventForm(req);
301
- form.validate(req.body);
301
+ form.validate(req.body || {});
302
302
  if (form.hasErrors) {
303
303
  send_events_page({
304
304
  res,
@@ -329,7 +329,7 @@ router.post(
329
329
  * @function
330
330
  */
331
331
  router.post(
332
- "/custom/delete/:name?",
332
+ "/custom/delete{/:name}",
333
333
  isAdmin,
334
334
  error_catcher(async (req, res) => {
335
335
  let { name } = req.params;
@@ -356,7 +356,7 @@ router.post(
356
356
  isAdmin,
357
357
  error_catcher(async (req, res) => {
358
358
  const form = await logSettingsForm(req);
359
- form.validate(req.body);
359
+ form.validate(req.body || {});
360
360
  if (form.hasErrors) {
361
361
  send_events_page({
362
362
  res,
package/routes/fields.js CHANGED
@@ -902,7 +902,7 @@ router.post(
902
902
  isAdminOrHasConfigMinRole("min_role_edit_tables"),
903
903
  error_catcher(async (req, res) => {
904
904
  const wf = fieldFlow(req);
905
- const wfres = await wf.run(req.body, req);
905
+ const wfres = await wf.run(req.body || {}, req);
906
906
  if (wfres.renderForm) {
907
907
  const table = Table.findOne({ id: wfres.context.table_id });
908
908
  res.sendWrap(req.__(`Field attributes`), {
@@ -953,7 +953,7 @@ router.post(
953
953
  "min_role_inspect_tables",
954
954
  ]),
955
955
  error_catcher(async (req, res) => {
956
- let { formula, tablename, stored } = req.body;
956
+ let { formula, tablename, stored } = req.body || {};
957
957
  if (stored === "false") stored = false;
958
958
 
959
959
  const table = Table.findOne({ name: tablename });
@@ -1017,7 +1017,7 @@ router.post(
1017
1017
  );
1018
1018
 
1019
1019
  const fields = table.getFields();
1020
- let row = { ...req.body };
1020
+ let row = { ...(req.body || {}) };
1021
1021
  if (row && Object.keys(row).length > 0) readState(row, fields);
1022
1022
 
1023
1023
  //need to get join fields from ownership into row
@@ -1280,7 +1280,7 @@ router.post(
1280
1280
  value = row && row[fieldName];
1281
1281
  }
1282
1282
 
1283
- const configuration = req.body.configuration;
1283
+ const configuration = (req.body || {}).configuration;
1284
1284
  if (!field) {
1285
1285
  res.send("");
1286
1286
  return;
@@ -1379,7 +1379,7 @@ router.post(
1379
1379
  agg_fieldview,
1380
1380
  agg_field,
1381
1381
  _columndef,
1382
- } = req.body;
1382
+ } = req.body || {};
1383
1383
  const table = Table.findOne({ name: tableName });
1384
1384
  if (agg_outcome_type && agg_fieldview) {
1385
1385
  const type = getState().types[agg_outcome_type];
package/routes/files.js CHANGED
@@ -221,11 +221,11 @@ router.get(
221
221
  * @function
222
222
  */
223
223
  router.get(
224
- "/download/*",
224
+ "/download/*serve_path",
225
225
  error_catcher(async (req, res) => {
226
226
  const role = req.user && req.user.id ? req.user.role_id : 100;
227
227
  const user_id = req.user && req.user.id;
228
- const serve_path = req.params[0];
228
+ const serve_path = path.join(...req.params.serve_path);
229
229
  const file = await File.findOne(serve_path);
230
230
 
231
231
  if (
@@ -234,7 +234,7 @@ router.get(
234
234
  ) {
235
235
  res.type(file.mimetype);
236
236
  if (file.s3_store) s3storage.serveObject(file, res, true);
237
- else res.download(file.location, file.filename);
237
+ else res.download(file.location, file.filename, { dotfiles: "allow" });
238
238
  } else {
239
239
  res
240
240
  .status(404)
@@ -250,8 +250,8 @@ router.post(
250
250
  error_catcher(async (req, res) => {
251
251
  const role = req.user && req.user.id ? req.user.role_id : 100;
252
252
  const user_id = req.user && req.user.id;
253
- const files = req.body.files;
254
- const location = req.body.location;
253
+ const files = (req.body || {}).files;
254
+ const location = (req.body || {}).location;
255
255
  const zip = new Zip();
256
256
 
257
257
  for (const fileNm of files) {
@@ -280,11 +280,11 @@ router.post(
280
280
  * @function
281
281
  */
282
282
  router.get(
283
- "/serve/*",
283
+ "/serve/*serve_path",
284
284
  error_catcher(async (req, res) => {
285
285
  const role = req.user && req.user.id ? req.user.role_id : 100;
286
286
  const user_id = req.user && req.user.id;
287
- const serve_path = req.params[0];
287
+ const serve_path = path.join(...req.params.serve_path);
288
288
  //let file;
289
289
  //if (typeof strictParseInt(id) !== "undefined")
290
290
  const file = await File.findOne(serve_path);
@@ -298,7 +298,7 @@ router.get(
298
298
  const maxAge = getState().getConfig("files_cache_maxage", 86400);
299
299
  res.set("Cache-Control", `${cacheability}, max-age=${maxAge}`);
300
300
  if (file.s3_store) s3storage.serveObject(file, res, false);
301
- else res.sendFile(file.location);
301
+ else res.sendFile(file.location, { dotfiles: "allow" });
302
302
  } else {
303
303
  getState().log(
304
304
  5,
@@ -320,12 +320,12 @@ router.get(
320
320
  * @function
321
321
  */
322
322
  router.get(
323
- "/resize/:width_str/:height_str/*",
323
+ "/resize/:width_str/:height_str/*serve_path",
324
324
  error_catcher(async (req, res) => {
325
325
  const role = req.user && req.user.id ? req.user.role_id : 100;
326
326
  const user_id = req.user && req.user.id;
327
327
  const { width_str, height_str } = req.params;
328
- const serve_path = req.params[0];
328
+ const serve_path = path.join(...req.params.serve_path);
329
329
 
330
330
  const file = await File.findOne(serve_path);
331
331
 
@@ -343,7 +343,7 @@ router.get(
343
343
  const height =
344
344
  height_str && height_str !== "0" ? strictParseInt(height_str) : null;
345
345
  if (!width) {
346
- res.sendFile(file.location);
346
+ res.sendFile(file.location, { dotfiles: "allow" });
347
347
  return;
348
348
  }
349
349
  const basenm = path.join(
@@ -359,7 +359,7 @@ router.get(
359
359
  toFileName: fnm,
360
360
  });
361
361
  }
362
- res.sendFile(fnm);
362
+ res.sendFile(fnm, { dotfiles: "allow" });
363
363
  }
364
364
  } else {
365
365
  res
@@ -376,12 +376,12 @@ router.get(
376
376
  * @function
377
377
  */
378
378
  router.post(
379
- "/setrole/*",
379
+ "/setrole/*serve_path",
380
380
  isAdmin,
381
381
  error_catcher(async (req, res) => {
382
- const serve_path = req.params[0];
382
+ const serve_path = path.join(...req.params.serve_path);
383
383
  const file = await File.findOne(serve_path);
384
- const role = req.body.role;
384
+ const role = (req.body || {}).role;
385
385
  const roles = await User.get_roles();
386
386
  const roleRow = roles.find((r) => r.id === +role);
387
387
 
@@ -396,12 +396,12 @@ router.post(
396
396
  );
397
397
 
398
398
  router.post(
399
- "/move/*",
399
+ "/move/*serve_path",
400
400
  isAdmin,
401
401
  error_catcher(async (req, res) => {
402
- const serve_path = req.params[0];
402
+ const serve_path = path.join(...req.params.serve_path);
403
403
  const file = await File.findOne(serve_path);
404
- const new_path = req.body.new_path;
404
+ const new_path = (req.body || {}).new_path;
405
405
 
406
406
  if (file) {
407
407
  await file.move_to_dir(new_path);
@@ -423,11 +423,11 @@ router.post(
423
423
  * @function
424
424
  */
425
425
  router.post(
426
- "/setname/*",
426
+ "/setname/*serve_path",
427
427
  isAdmin,
428
428
  error_catcher(async (req, res) => {
429
- const serve_path = req.params[0];
430
- const filename = req.body.value;
429
+ const serve_path = path.join(...req.params.serve_path);
430
+ const filename = (req.body || {}).value;
431
431
 
432
432
  const file = await File.findOne(serve_path);
433
433
  await file.rename(filename);
@@ -443,11 +443,11 @@ router.post(
443
443
  * @function
444
444
  */
445
445
  router.post(
446
- "/unzip/*",
446
+ "/unzip/*serve_path",
447
447
  isAdmin,
448
448
  error_catcher(async (req, res) => {
449
- const serve_path = req.params[0];
450
- const filename = req.body.value;
449
+ const serve_path = path.join(...req.params.serve_path);
450
+ const filename = (req.body || {}).value;
451
451
 
452
452
  const file = await File.findOne(serve_path);
453
453
  const dir = path.dirname(file.location);
@@ -460,7 +460,7 @@ router.post(
460
460
  "/new-folder",
461
461
  isAdmin,
462
462
  error_catcher(async (req, res) => {
463
- const { name, folder } = req.body;
463
+ const { name, folder } = req.body || {};
464
464
  await File.new_folder(name, folder);
465
465
 
466
466
  res.json({ success: "ok" });
@@ -477,7 +477,7 @@ router.post(
477
477
  "/upload",
478
478
  setTenant,
479
479
  error_catcher(async (req, res) => {
480
- let { folder, sortBy, sortDesc } = req.body;
480
+ let { folder, sortBy, sortDesc } = req.body || {};
481
481
  let jsonResp = {};
482
482
  const min_role_upload = getState().getConfig("min_role_upload", 1);
483
483
  const role = req.user && req.user.id ? req.user.role_id : 100;
@@ -489,7 +489,8 @@ router.post(
489
489
  if (!req.xhr) req.flash("warning", req.__("No file found"));
490
490
  else jsonResp = { error: "No file found" };
491
491
  } else {
492
- const min_role_read = req.body ? req.body.min_role_read || 1 : 1;
492
+ const min_role_read =
493
+ req.body || {} ? (req.body || {}).min_role_read || 1 : 1;
493
494
  const f = await File.from_req_files(
494
495
  req.files.file,
495
496
  req.user.id,
@@ -533,10 +534,10 @@ router.post(
533
534
  * @function
534
535
  */
535
536
  router.post(
536
- "/delete/*",
537
+ "/delete/*serve_path",
537
538
  isAdmin,
538
539
  error_catcher(async (req, res) => {
539
- const serve_path = req.params[0];
540
+ const serve_path = path.join(...req.params.serve_path);
540
541
  const { redirect } = req.query;
541
542
  const f = await File.findOne(serve_path);
542
543
  if (!f) {
@@ -625,7 +626,7 @@ router.post(
625
626
  isAdmin,
626
627
  error_catcher(async (req, res) => {
627
628
  const form = await storage_form(req);
628
- form.validate(req.body);
629
+ form.validate(req.body || {});
629
630
  if (form.hasErrors) {
630
631
  send_files_page({
631
632
  res,
@@ -702,7 +703,7 @@ router.post(
702
703
  isAdmin,
703
704
  error_catcher(async (req, res) => {
704
705
  const form = await files_settings_form(req);
705
- form.validate(req.body);
706
+ form.validate(req.body || {});
706
707
  if (form.hasErrors) {
707
708
  send_files_page({
708
709
  res,
@@ -252,8 +252,9 @@ router.post(
252
252
  return;
253
253
  }
254
254
  const cfgStrings = getState().getConfigCopy("localizer_strings");
255
- if (cfgStrings[lang]) cfgStrings[lang][defstring] = text(req.body.value);
256
- else cfgStrings[lang] = { [defstring]: text(req.body.value) };
255
+ if (cfgStrings[lang])
256
+ cfgStrings[lang][defstring] = text((req.body || {}).value);
257
+ else cfgStrings[lang] = { [defstring]: text((req.body || {}).value) };
257
258
  await getState().setConfig("localizer_strings", cfgStrings);
258
259
  res.redirect(`/site-structure/localizer/edit/${lang}`);
259
260
  })
@@ -270,7 +271,7 @@ router.post(
270
271
  isAdmin,
271
272
  error_catcher(async (req, res) => {
272
273
  const form = languageForm(req);
273
- form.validate(req.body);
274
+ form.validate(req.body || {});
274
275
  if (form.hasErrors)
275
276
  send_infoarch_page({
276
277
  res,
package/routes/library.js CHANGED
@@ -31,7 +31,7 @@ router.post(
31
31
  "/savefrombuilder",
32
32
  isAdmin,
33
33
  error_catcher(async (req, res) => {
34
- await Library.create(req.body);
34
+ await Library.create(req.body || {});
35
35
  res.json({ success: "ok" });
36
36
  })
37
37
  );
package/routes/menu.js CHANGED
@@ -579,7 +579,7 @@ router.post(
579
579
  "/",
580
580
  isAdminOrHasConfigMinRole("min_role_edit_menu"),
581
581
  error_catcher(async (req, res) => {
582
- const new_menu = req.body;
582
+ const new_menu = req.body || {};
583
583
  const menu_items = jQMEtoMenu(new_menu);
584
584
  await save_menu_items(menu_items);
585
585
  Trigger.emitEvent("AppChange", `Menu`, req.user, {});
package/routes/models.js CHANGED
@@ -88,7 +88,7 @@ router.post(
88
88
  const { table_id } = req.params;
89
89
  const table = await Table.findOne({ id: table_id });
90
90
  const form = newModelForm(table, req);
91
- form.validate(req.body);
91
+ form.validate(req.body || {});
92
92
  if (form.hasErrors) {
93
93
  res.sendWrap(req.__(`New model`), renderForm(form, req.csrfToken()));
94
94
  } else {
@@ -204,7 +204,7 @@ router.post(
204
204
  return;
205
205
  }
206
206
  const workflow = get_model_workflow(model, req);
207
- const wfres = await workflow.run(req.body, req);
207
+ const wfres = await workflow.run(req.body || {}, req);
208
208
  respondWorkflow(model, table, workflow, wfres, req, res);
209
209
  })
210
210
  );
@@ -394,7 +394,7 @@ router.post(
394
394
  const model = await Model.findOne({ id });
395
395
  const table = Table.findOne({ id: model.table_id });
396
396
  const form = model_train_form(model, table, req);
397
- form.validate(req.body);
397
+ form.validate(req.body || {});
398
398
  if (form.hasErrors) {
399
399
  res.sendWrap(req.__(`Train model`), renderForm(form, req.csrfToken()));
400
400
  } else {
@@ -435,7 +435,7 @@ router.post(
435
435
  error_catcher(async (req, res) => {
436
436
  const { id } = req.params;
437
437
  const model_instance = await ModelInstance.findOne({ id });
438
- await model_instance.make_default(!req.body.enabled);
438
+ await model_instance.make_default(!(req.body || {}).enabled);
439
439
  res.redirect(`/models/show/${model_instance.model_id}`);
440
440
  })
441
441
  );
@@ -170,7 +170,7 @@ router.post(
170
170
  error_catcher(async (req, res) => {
171
171
  const user = await User.findOne({ id: req.user.id });
172
172
  const form = notificationSettingsForm();
173
- form.validate(req.body);
173
+ form.validate(req.body || {});
174
174
  const _attributes = { ...user._attributes, ...form.values };
175
175
  await user.update({ _attributes });
176
176
  res.json({ success: "ok" });
@@ -216,14 +216,17 @@ router.post(
216
216
  } else res.json({ error: msg });
217
217
  } else {
218
218
  Trigger.emitEvent("ReceiveMobileShareData", null, req.user, {
219
- row: req.body,
219
+ row: req.body || {},
220
220
  });
221
221
  if (!req.smr) {
222
222
  req.flash(
223
223
  "success",
224
224
  req.__(
225
225
  "Shared: %s",
226
- req.body.title || req.body.text || req.body.url || ""
226
+ (req.body || {}).title ||
227
+ (req.body || {}).text ||
228
+ (req.body || {}).url ||
229
+ ""
227
230
  )
228
231
  );
229
232
  res.status(303).redirect("/");
@@ -234,7 +237,7 @@ router.post(
234
237
  );
235
238
 
236
239
  router.get(
237
- "/manifest.json:opt_cache_bust?",
240
+ "/manifest.json{:opt_cache_bust}",
238
241
  error_catcher(async (req, res) => {
239
242
  const { pretty } = req.query;
240
243
  const state = getState();
package/routes/packs.js CHANGED
@@ -223,7 +223,7 @@ router.post(
223
223
  model_instances: [],
224
224
  event_logs: [],
225
225
  };
226
- for (const k of Object.keys(req.body)) {
226
+ for (const k of Object.keys(req.body || {})) {
227
227
  const [type, name, ...rest] = k.split(".");
228
228
  switch (type) {
229
229
  case "table":
@@ -392,11 +392,11 @@ router.post(
392
392
  isAdmin,
393
393
  error_catcher(async (req, res) => {
394
394
  var pack, error;
395
- const source = req.body.source || "from_text";
395
+ const source = (req.body || {}).source || "from_text";
396
396
  try {
397
397
  switch (source) {
398
398
  case "from_text":
399
- pack = JSON.parse(req.body.pack);
399
+ pack = JSON.parse((req.body || {}).pack);
400
400
  break;
401
401
  case "from_file":
402
402
  if (req.files?.pack_file?.tempFilePath)
@@ -424,7 +424,7 @@ router.post(
424
424
  }
425
425
  if (error) {
426
426
  const form = install_pack_form(req);
427
- form.values = { pack: req.body.pack };
427
+ form.values = { pack: (req.body || {}).pack };
428
428
  req.flash("error", error);
429
429
  res.sendWrap(req.__(`Install Pack`), {
430
430
  above: [
@@ -234,7 +234,7 @@ router.post(
234
234
  if (cfg[v]) return req.__("Device already exists");
235
235
  };
236
236
  const form = deviceForm(req, validator);
237
- form.validate(req.body);
237
+ form.validate(req.body || {});
238
238
  if (form.hasErrors) {
239
239
  send_infoarch_page({
240
240
  res,
@@ -316,7 +316,7 @@ router.post(
316
316
  const form = deviceForm(req, validator, device);
317
317
  const deviceCfg = cfg[device];
318
318
  form.values = { device, ...deviceCfg };
319
- form.validate(req.body);
319
+ form.validate(req.body || {});
320
320
  if (form.hasErrors) {
321
321
  send_infoarch_page({
322
322
  res,
@@ -351,7 +351,7 @@ router.post(
351
351
  isAdmin,
352
352
  error_catcher(async (req, res) => {
353
353
  const form = pageGroupSettingsForm(req);
354
- form.validate(req.body);
354
+ form.validate(req.body || {});
355
355
  if (form.hasErrors) {
356
356
  send_infoarch_page({
357
357
  res,
@@ -392,9 +392,9 @@ router.post(
392
392
  "/edit-properties",
393
393
  isAdmin,
394
394
  error_catcher(async (req, res) => {
395
- const form = await groupPropsForm(req, !req.body.id);
395
+ const form = await groupPropsForm(req, !(req.body || {}).id);
396
396
  form.hidden("id");
397
- form.validate(req.body);
397
+ form.validate(req.body || {});
398
398
  if (form.hasErrors) {
399
399
  if (!req.xhr) {
400
400
  // from new
@@ -457,7 +457,7 @@ router.post(
457
457
  res.redirect(`/page_groupedit/${page_groupname}`);
458
458
  }
459
459
  const form = await addMemberForm(group, req);
460
- form.validate(req.body);
460
+ form.validate(req.body || {});
461
461
  if (form.hasErrors) {
462
462
  res.sendWrap(
463
463
  req.__(`%s add-member`, group.name),
@@ -554,7 +554,7 @@ router.post(
554
554
  const group = PageGroup.findOne({ id: member.page_group_id });
555
555
  const form = await editMemberForm(member, req);
556
556
  form.hidden("id");
557
- form.validate(req.body);
557
+ form.validate(req.body || {});
558
558
  if (form.hasErrors) {
559
559
  res.sendWrap(
560
560
  req.__(`%s edit-member`, member.name || member.id),
@@ -678,7 +678,7 @@ router.post(
678
678
  req.flash(
679
679
  "success",
680
680
  req.__(
681
- "Page %s added to menu. Adjust access permissions in <a href=\"/menu\">Settings &raquo; Menu</a>",
681
+ 'Page %s added to menu. Adjust access permissions in <a href="/menu">Settings &raquo; Menu</a>',
682
682
  group.name
683
683
  )
684
684
  );