@saltcorn/server 0.8.0-beta.4 → 0.8.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/routes/files.js CHANGED
@@ -18,7 +18,11 @@ const { isAdmin, error_catcher, setTenant } = require("./utils.js");
18
18
  const { h1, div, text } = require("@saltcorn/markup/tags");
19
19
  const { editRoleForm, fileUploadForm } = require("../markup/forms.js");
20
20
  const { strictParseInt } = require("@saltcorn/data/plugin-helper");
21
- const { send_files_page, config_fields_form, save_config_from_form } = require("../markup/admin");
21
+ const {
22
+ send_files_page,
23
+ config_fields_form,
24
+ save_config_from_form,
25
+ } = require("../markup/admin");
22
26
  const fs = require("fs");
23
27
  const path = require("path");
24
28
 
@@ -58,31 +62,33 @@ router.get(
58
62
  isAdmin,
59
63
  error_catcher(async (req, res) => {
60
64
  // todo limit select from file by 10 or 20
61
- const { dir } = req.query
62
- const safeDir = File.normalise(dir || "/")
65
+ const { dir } = req.query;
66
+ const safeDir = File.normalise(dir || "/");
63
67
  const rows = await File.find({ folder: dir }, { orderBy: "filename" });
64
68
  const roles = await User.get_roles();
65
69
  if (safeDir && safeDir !== "/" && safeDir !== ".") {
66
- let dirname = path.dirname(safeDir)
67
- if (dirname === ".") dirname = "/"
68
- rows.unshift(new File({
69
- filename: "..",
70
- location: dirname,
71
- isDirectory: true,
72
- mime_super: "",
73
- mime_sub: "",
74
- }))
70
+ let dirname = path.dirname(safeDir);
71
+ if (dirname === ".") dirname = "/";
72
+ rows.unshift(
73
+ new File({
74
+ filename: "..",
75
+ location: dirname,
76
+ isDirectory: true,
77
+ mime_super: "",
78
+ mime_sub: "",
79
+ })
80
+ );
75
81
  }
76
82
  if (req.xhr) {
77
83
  for (const file of rows) {
78
- file.location = file.path_to_serve
84
+ file.location = file.path_to_serve;
79
85
  }
80
- const directories = await File.allDirectories()
86
+ const directories = await File.allDirectories();
81
87
  for (const file of directories) {
82
- file.location = file.path_to_serve
88
+ file.location = file.path_to_serve;
83
89
  }
84
- res.json({ files: rows, roles, directories })
85
- return
90
+ res.json({ files: rows, roles, directories });
91
+ return;
86
92
  }
87
93
  send_files_page({
88
94
  res,
@@ -90,7 +96,7 @@ router.get(
90
96
  headers: [
91
97
  {
92
98
  script: `/static_assets/${db.connectObj.version_tag}/bundle.js`,
93
- defer: true
99
+ defer: true,
94
100
  },
95
101
  {
96
102
  css: `/static_assets/${db.connectObj.version_tag}/bundle.css`,
@@ -122,7 +128,10 @@ router.get(
122
128
  const serve_path = req.params[0];
123
129
  const file = await File.findOne(serve_path);
124
130
 
125
- if (file && (role <= file.min_role_read || (user_id && user_id === file.user_id))) {
131
+ if (
132
+ file &&
133
+ (role <= file.min_role_read || (user_id && user_id === file.user_id))
134
+ ) {
126
135
  res.type(file.mimetype);
127
136
  if (file.s3_store) s3storage.serveObject(file, res, true);
128
137
  else res.download(file.location, file.filename);
@@ -150,7 +159,10 @@ router.get(
150
159
  //if (typeof strictParseInt(id) !== "undefined")
151
160
  const file = await File.findOne(serve_path);
152
161
 
153
- if (file && (role <= file.min_role_read || (user_id && user_id === file.user_id))) {
162
+ if (
163
+ file &&
164
+ (role <= file.min_role_read || (user_id && user_id === file.user_id))
165
+ ) {
154
166
  res.type(file.mimetype);
155
167
  const cacheability = file.min_role_read === 10 ? "public" : "private";
156
168
  res.set("Cache-Control", `${cacheability}, max-age=86400`);
@@ -178,10 +190,12 @@ router.get(
178
190
  const { width_str, height_str } = req.params;
179
191
  const serve_path = req.params[0];
180
192
 
181
-
182
193
  const file = await File.findOne(serve_path);
183
194
 
184
- if (file && (role <= file.min_role_read || (user_id && user_id === file.user_id))) {
195
+ if (
196
+ file &&
197
+ (role <= file.min_role_read || (user_id && user_id === file.user_id))
198
+ ) {
185
199
  res.type(file.mimetype);
186
200
  const cacheability = file.min_role_read === 10 ? "public" : "private";
187
201
  res.set("Cache-Control", `${cacheability}, max-age=86400`);
@@ -189,13 +203,16 @@ router.get(
189
203
  if (file.s3_store) s3storage.serveObject(file, res, false);
190
204
  else {
191
205
  const width = strictParseInt(width_str);
192
- const height = height_str && height_str !== "0"
193
- ? strictParseInt(height_str) : null;
206
+ const height =
207
+ height_str && height_str !== "0" ? strictParseInt(height_str) : null;
194
208
  if (!width) {
195
209
  res.sendFile(file.location);
196
210
  return;
197
211
  }
198
- const basenm = path.join(path.dirname(file.location), '_resized_' + path.basename(file.location))
212
+ const basenm = path.join(
213
+ path.dirname(file.location),
214
+ "_resized_" + path.basename(file.location)
215
+ );
199
216
  const fnm = `${basenm}_w${width}${height ? `_h${height}` : ""}`;
200
217
  if (!fs.existsSync(fnm)) {
201
218
  await resizer({
@@ -233,15 +250,14 @@ router.post(
233
250
 
234
251
  if (roleRow && file) {
235
252
  await file.set_role(role);
236
-
237
253
  }
238
254
 
239
-
240
- res.redirect(file ? `/files?dir=${encodeURIComponent(file.current_folder)}` : "/files");
255
+ res.redirect(
256
+ file ? `/files?dir=${encodeURIComponent(file.current_folder)}` : "/files"
257
+ );
241
258
  })
242
259
  );
243
260
 
244
-
245
261
  router.post(
246
262
  "/move/*",
247
263
  isAdmin,
@@ -254,10 +270,12 @@ router.post(
254
270
  await file.move_to_dir(new_path);
255
271
  }
256
272
  if (req.xhr) {
257
- res.json({ success: "ok" })
258
- return
273
+ res.json({ success: "ok" });
274
+ return;
259
275
  }
260
- res.redirect(file ? `/files?dir=${encodeURIComponent(file.current_folder)}` : "/files");
276
+ res.redirect(
277
+ file ? `/files?dir=${encodeURIComponent(file.current_folder)}` : "/files"
278
+ );
261
279
  })
262
280
  );
263
281
 
@@ -278,7 +296,6 @@ router.post(
278
296
  await file.rename(filename);
279
297
 
280
298
  res.redirect(`/files?dir=${encodeURIComponent(file.current_folder)}`);
281
-
282
299
  })
283
300
  );
284
301
 
@@ -286,7 +303,7 @@ router.post(
286
303
  "/new-folder",
287
304
  isAdmin,
288
305
  error_catcher(async (req, res) => {
289
- const { name, folder } = req.body
306
+ const { name, folder } = req.body;
290
307
  await File.new_folder(name, folder);
291
308
 
292
309
  res.json({ success: "ok" });
@@ -303,11 +320,11 @@ router.post(
303
320
  "/upload",
304
321
  setTenant,
305
322
  error_catcher(async (req, res) => {
306
- let { folder } = req.body
323
+ let { folder } = req.body;
307
324
  let jsonResp = {};
308
325
  const min_role_upload = getState().getConfig("min_role_upload", 1);
309
326
  const role = req.user && req.user.id ? req.user.role_id : 10;
310
- let file_for_redirect
327
+ let file_for_redirect;
311
328
  if (role > +min_role_upload) {
312
329
  if (!req.xhr) req.flash("warning", req.__("Not authorized"));
313
330
  else jsonResp = { error: "Not authorized" };
@@ -323,7 +340,7 @@ router.post(
323
340
  folder ? File.normalise(folder) : undefined
324
341
  );
325
342
  const many = Array.isArray(f);
326
- file_for_redirect = many ? f[0] : f
343
+ file_for_redirect = many ? f[0] : f;
327
344
  if (!req.xhr)
328
345
  req.flash(
329
346
  "success",
@@ -346,10 +363,11 @@ router.post(
346
363
  };
347
364
  }
348
365
  if (!req.xhr)
349
- res.redirect(!file_for_redirect
350
- ? '/files'
351
- : `/files?dir=${encodeURIComponent(file_for_redirect.current_folder)}`);
352
-
366
+ res.redirect(
367
+ !file_for_redirect
368
+ ? "/files"
369
+ : `/files?dir=${encodeURIComponent(file_for_redirect.current_folder)}`
370
+ );
353
371
  else res.json(jsonResp);
354
372
  })
355
373
  );
@@ -438,7 +456,7 @@ router.post(
438
456
  const form = await storage_form(req);
439
457
  form.validate(req.body);
440
458
  if (form.hasErrors) {
441
- send_admin_page({
459
+ send_files_page({
442
460
  res,
443
461
  req,
444
462
  active_sub: "Storage",
@@ -465,17 +483,17 @@ router.post(
465
483
  * @returns {Promise<Form>} form
466
484
  */
467
485
  const files_settings_form = async (req) => {
468
- return await config_fields_form({
469
- req,
470
- field_names: [
471
- "min_role_upload",
472
- "file_accept_filter_default",
473
- "file_upload_debug",
474
- "file_upload_limit",
475
- "file_upload_timeout",
476
- ],
477
- action: "/files/settings",
478
- });
486
+ return await config_fields_form({
487
+ req,
488
+ field_names: [
489
+ "min_role_upload",
490
+ "file_accept_filter_default",
491
+ "file_upload_debug",
492
+ "file_upload_limit",
493
+ "file_upload_timeout",
494
+ ],
495
+ action: "/files/settings",
496
+ });
479
497
  };
480
498
 
481
499
  /**
@@ -484,21 +502,21 @@ const files_settings_form = async (req) => {
484
502
  * @memberof module:routes/admin~routes/adminRouter
485
503
  */
486
504
  router.get(
487
- "/settings",
488
- isAdmin,
489
- error_catcher(async (req, res) => {
490
- const form = await files_settings_form(req);
491
- send_files_page({
492
- res,
493
- req,
494
- active_sub: "Settings",
495
- contents: {
496
- type: "card",
497
- title: req.__("Files settings"),
498
- contents: [renderForm(form, req.csrfToken())],
499
- },
500
- });
501
- })
505
+ "/settings",
506
+ isAdmin,
507
+ error_catcher(async (req, res) => {
508
+ const form = await files_settings_form(req);
509
+ send_files_page({
510
+ res,
511
+ req,
512
+ active_sub: "Settings",
513
+ contents: {
514
+ type: "card",
515
+ title: req.__("Files settings"),
516
+ contents: [renderForm(form, req.csrfToken())],
517
+ },
518
+ });
519
+ })
502
520
  );
503
521
 
504
522
  /**
@@ -507,29 +525,29 @@ router.get(
507
525
  * @memberof module:routes/admin~routes/adminRouter
508
526
  */
509
527
  router.post(
510
- "/settings",
511
- isAdmin,
512
- error_catcher(async (req, res) => {
513
- const form = await files_settings_form(req);
514
- form.validate(req.body);
515
- if (form.hasErrors) {
516
- send_admin_page({
517
- res,
518
- req,
519
- active_sub: "Settings",
520
- contents: {
521
- type: "card",
522
- title: req.__("Files settings"),
523
- contents: [renderForm(form, req.csrfToken())],
524
- },
525
- });
526
- } else {
527
- await save_config_from_form(form);
528
-
529
- if (!req.xhr) {
530
- req.flash("success", req.__("Files settings updated"));
531
- res.redirect("/files/settings");
532
- } else res.json({ success: "ok" });
533
- }
534
- })
535
- );
528
+ "/settings",
529
+ isAdmin,
530
+ error_catcher(async (req, res) => {
531
+ const form = await files_settings_form(req);
532
+ form.validate(req.body);
533
+ if (form.hasErrors) {
534
+ send_files_page({
535
+ res,
536
+ req,
537
+ active_sub: "Settings",
538
+ contents: {
539
+ type: "card",
540
+ title: req.__("Files settings"),
541
+ contents: [renderForm(form, req.csrfToken())],
542
+ },
543
+ });
544
+ } else {
545
+ await save_config_from_form(form);
546
+
547
+ if (!req.xhr) {
548
+ req.flash("success", req.__("Files settings updated"));
549
+ res.redirect("/files/settings");
550
+ } else res.json({ success: "ok" });
551
+ }
552
+ })
553
+ );
@@ -481,7 +481,7 @@ const get_config_response = async (role_id, res, req) => {
481
481
  title: db_page.title,
482
482
  description: db_page.description,
483
483
  bodyClass: "page_" + db.sqlsanitize(homeCfg),
484
- } || `${pagename} page`,
484
+ },
485
485
  contents
486
486
  );
487
487
  } else res.redirect(homeCfg);
@@ -113,7 +113,7 @@ router.get(
113
113
  {
114
114
  label: req.__("Default"),
115
115
  key: (r) =>
116
- !!r.is_default
116
+ r.is_default
117
117
  ? i({
118
118
  class: "fas fa-check-circle text-success",
119
119
  })
package/routes/list.js CHANGED
@@ -51,7 +51,7 @@ router.get(
51
51
  isAdmin,
52
52
  error_catcher(async (req, res) => {
53
53
  const { tableName, id } = req.params;
54
- const table = await Table.findOne({ name : tableName });
54
+ const table = await Table.findOne({ name: tableName });
55
55
 
56
56
  const fields = await table.getFields();
57
57
  var tfields = fields.map((f) => ({ label: f.label, key: f.listKey }));
@@ -99,7 +99,7 @@ router.post(
99
99
  isAdmin,
100
100
  error_catcher(async (req, res) => {
101
101
  const { tableName, id, _version } = req.params;
102
- const table = await Table.findOne({ name : tableName });
102
+ const table = await Table.findOne({ name: tableName });
103
103
 
104
104
  const fields = await table.getFields();
105
105
  const row = await db.selectOne(`${db.sqlsanitize(table.name)}__history`, {
@@ -216,7 +216,7 @@ const arrangeIdFirst = (flds) => {
216
216
  const noId = flds.filter((f) => f.name !== "id");
217
217
  const id = flds.find((f) => f.name === "id");
218
218
  if (id) return [id, ...noId];
219
- else return flds
219
+ else return flds;
220
220
  };
221
221
 
222
222
  /**
@@ -369,8 +369,9 @@ router.get(
369
369
  })
370
370
  })
371
371
  window.tabulator_table = new Tabulator("#jsGrid", {
372
- ajaxURL:"/api/${table.name}${table.versioned ? "?versioncount=on" : ""
373
- }",
372
+ ajaxURL:"/api/${table.name}${
373
+ table.versioned ? "?versioncount=on" : ""
374
+ }",
374
375
  layout:"fitColumns",
375
376
  columns,
376
377
  height:"100%",
package/routes/packs.js CHANGED
@@ -335,8 +335,7 @@ router.post(
335
335
  const can_install = await can_install_pack(pack.pack);
336
336
 
337
337
  if (can_install.error) {
338
- error = can_install.error;
339
- req.flash("error", error);
338
+ req.flash("error", can_install.error);
340
339
  res.redirect(`/plugins`);
341
340
  return;
342
341
  } else if (can_install.warning) {
@@ -100,7 +100,7 @@ const pageBuilderData = async (req, context) => {
100
100
  const views = await View.find();
101
101
  const pages = await Page.find();
102
102
  const images = await File.find({ mime_super: "image" });
103
- images.forEach(im => im.location = im.path_to_serve)
103
+ images.forEach((im) => (im.location = im.path_to_serve));
104
104
  const roles = await User.get_roles();
105
105
  const stateActions = getState().actions;
106
106
  const actions = [
@@ -81,7 +81,7 @@ const formOptions = async (type, tag_id) => {
81
81
  case "triggers": {
82
82
  const ids = await tag.getTriggerIds();
83
83
  return {
84
- triggers: (Trigger.find()).filter(
84
+ triggers: Trigger.find().filter(
85
85
  (value) => ids.indexOf(value.id) === -1
86
86
  ),
87
87
  };
package/routes/utils.js CHANGED
@@ -218,7 +218,9 @@ const scan_for_page_title = (contents, viewname) => {
218
218
  try {
219
219
  scanstr =
220
220
  typeof contents === "string" ? contents : JSON.stringify(contents);
221
- } catch {}
221
+ } catch {
222
+ //ignore
223
+ }
222
224
  if (scanstr.includes("<!--SCPT:")) {
223
225
  const start = scanstr.indexOf("<!--SCPT:");
224
226
  const end = scanstr.indexOf("-->", start);
package/s3storage.js CHANGED
@@ -5,7 +5,7 @@ const { getState } = require("@saltcorn/data/db/state");
5
5
  const fileUpload = require("express-fileupload");
6
6
  const { v4: uuidv4 } = require("uuid");
7
7
  const contentDisposition = require("content-disposition");
8
-
8
+ const fs = require("fs");
9
9
  function createS3Client() {
10
10
  return new aws.S3({
11
11
  secretAccessKey: getState().getConfig("storage_s3_access_secret"),
@@ -52,19 +52,18 @@ module.exports = {
52
52
  createParentPath: true,
53
53
  tempFileDir: "/tmp/",
54
54
  // set to true - if you want to have debug
55
- debug: getState().getConfig("file_upload_debug",false),
55
+ debug: getState().getConfig("file_upload_debug", false),
56
56
  //uriDecodeFileNames: true,
57
57
  //safeFileNames: true,
58
- defCharset: 'utf8',
59
- defParamCharset: 'utf8',
58
+ defCharset: "utf8",
59
+ defParamCharset: "utf8",
60
60
  // 0 - means no upload limit check
61
61
  limits: {
62
62
  fileSize: fileSizeLimit,
63
63
  },
64
64
  abortOnLimit: fileSizeLimit !== 0,
65
65
  // 0 - means no upload limit check
66
- uploadTimeout: getState().getConfig("file_upload_timeout",0),
67
-
66
+ uploadTimeout: getState().getConfig("file_upload_timeout", 0),
68
67
  })(req, res, next);
69
68
  }
70
69
  },
@@ -146,7 +145,7 @@ module.exports = {
146
145
  // Forward the object
147
146
  s3.getObject(params)
148
147
  .on("httpHeaders", function (statusCode, headers) {
149
- if (!!download)
148
+ if (download)
150
149
  res.set("Content-Disposition", contentDisposition(file.filename));
151
150
  res.set("Content-Length", headers["content-length"]);
152
151
  this.response.httpResponse.createUnbufferedStream().pipe(res);
package/serve.js CHANGED
@@ -30,7 +30,11 @@ const { getConfig } = require("@saltcorn/data/models/config");
30
30
  const { migrate } = require("@saltcorn/data/migrate");
31
31
  const socketio = require("socket.io");
32
32
  const { createAdapter, setupPrimary } = require("@socket.io/cluster-adapter");
33
- const { setTenant, getSessionStore, get_tenant_from_req } = require("./routes/utils");
33
+ const {
34
+ setTenant,
35
+ getSessionStore,
36
+ get_tenant_from_req,
37
+ } = require("./routes/utils");
34
38
  const passport = require("passport");
35
39
  const { authenticate } = require("passport");
36
40
  const View = require("@saltcorn/data/models/view");
@@ -106,8 +110,8 @@ const workerDispatchMsg = ({ tenant, ...msg }) => {
106
110
  });
107
111
  }
108
112
  if (!getState()) {
109
- console.error("no State for tenant", tenant)
110
- return
113
+ console.error("no State for tenant", tenant);
114
+ return;
111
115
  }
112
116
  if (msg.refresh) getState()[`refresh_${msg.refresh}`](true);
113
117
  if (msg.createTenant) {
@@ -142,33 +146,33 @@ const workerDispatchMsg = ({ tenant, ...msg }) => {
142
146
  */
143
147
  const onMessageFromWorker =
144
148
  (masterState, { port, watchReaper, disableScheduler, pid }) =>
145
- (msg) => {
146
- //console.log("worker msg", typeof msg, msg);
147
- if (msg === "Start" && !masterState.started) {
148
- masterState.started = true;
149
- runScheduler({
150
- port,
151
- watchReaper,
152
- disableScheduler,
153
- eachTenant,
154
- auto_backup_now,
155
- take_snapshot,
156
- });
157
- require("./systemd")({ port });
158
- return true;
159
- } else if (msg === "RestartServer") {
160
- process.exit(0);
161
- return true;
162
- } else if (msg.tenant || msg.createTenant) {
163
- ///ie from saltcorn
164
- //broadcast
165
- Object.entries(cluster.workers).forEach(([wpid, w]) => {
166
- if (wpid !== pid) w.send(msg);
167
- });
168
- workerDispatchMsg(msg); //also master
169
- return true;
170
- }
171
- };
149
+ (msg) => {
150
+ //console.log("worker msg", typeof msg, msg);
151
+ if (msg === "Start" && !masterState.started) {
152
+ masterState.started = true;
153
+ runScheduler({
154
+ port,
155
+ watchReaper,
156
+ disableScheduler,
157
+ eachTenant,
158
+ auto_backup_now,
159
+ take_snapshot,
160
+ });
161
+ require("./systemd")({ port });
162
+ return true;
163
+ } else if (msg === "RestartServer") {
164
+ process.exit(0);
165
+ return true;
166
+ } else if (msg.tenant || msg.createTenant) {
167
+ ///ie from saltcorn
168
+ //broadcast
169
+ Object.entries(cluster.workers).forEach(([wpid, w]) => {
170
+ if (wpid !== pid) w.send(msg);
171
+ });
172
+ workerDispatchMsg(msg); //also master
173
+ return true;
174
+ }
175
+ };
172
176
 
173
177
  module.exports =
174
178
  /**
@@ -381,7 +385,7 @@ const setupSocket = (...servers) => {
381
385
  } catch (err) {
382
386
  getState().log(1, `Socket join_room error: ${err.stack}`);
383
387
  }
384
- }
388
+ };
385
389
  if (ten && ten !== "public") db.runWithTenant(ten, f);
386
390
  else f();
387
391
  });
package/systemd.js CHANGED
@@ -5,9 +5,9 @@
5
5
  const fetch = require("node-fetch");
6
6
 
7
7
  /**
8
- * @param {number} interval
9
- * @param {object} notify
10
- * @param {object} opts
8
+ * @param {number} interval
9
+ * @param {object} notify
10
+ * @param {object} opts
11
11
  * @param {string} opts.port
12
12
  * @returns {void}
13
13
  */
@@ -48,22 +48,24 @@ const watchDog = (interval, notify, { port }) => {
48
48
  }
49
49
  };
50
50
 
51
- module.exports =
52
- /**
53
- * @function
54
- * @name "module.exports function"
55
- * @param {object} opts
56
- */
57
- (opts) => {
58
- try {
59
- const notify = require("sd-notify");
60
- notify.ready();
61
- const watchdogInterval = notify.watchdogInterval();
62
- if (watchdogInterval && watchdogInterval > 0) {
63
- const interval = Math.floor(watchdogInterval / 2);
64
- setInterval(() => {
65
- watchDog(interval, notify, opts);
66
- }, interval);
51
+ module.exports =
52
+ /**
53
+ * @function
54
+ * @name "module.exports function"
55
+ * @param {object} opts
56
+ */
57
+ (opts) => {
58
+ try {
59
+ const notify = require("sd-notify");
60
+ notify.ready();
61
+ const watchdogInterval = notify.watchdogInterval();
62
+ if (watchdogInterval && watchdogInterval > 0) {
63
+ const interval = Math.floor(watchdogInterval / 2);
64
+ setInterval(() => {
65
+ watchDog(interval, notify, opts);
66
+ }, interval);
67
+ }
68
+ } catch {
69
+ //ignore, systemd lib not installed
67
70
  }
68
- } catch {}
69
- };
71
+ };