@saltcorn/server 0.8.0-beta.1 → 0.8.0-beta.3

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/plugins.js CHANGED
@@ -89,10 +89,10 @@ const pluginForm = (req, plugin) => {
89
89
  attributes: { options: "npm,local,github,git" },
90
90
  sublabel: req.__(
91
91
  "Source of module for install. Few options:" +
92
- "npm - download from npm repository," +
93
- "local - get from local file system," +
94
- "github - download from github," +
95
- "git - get from git"
92
+ "npm - download from npm repository," +
93
+ "local - get from local file system," +
94
+ "github - download from github," +
95
+ "git - get from git"
96
96
  ),
97
97
  }),
98
98
  new Field({
@@ -101,19 +101,19 @@ const pluginForm = (req, plugin) => {
101
101
  input_type: "text",
102
102
  sublabel: req.__(
103
103
  "For npm - name of npm package, e.g. @saltcorn/html or saltcorn-gantt, check at npmjs.com, " +
104
- "for local - absolute path to module folder in file system, e.g. C:\\gitsrc\\any-bootstrap-theme\\, " +
105
- "for github - name of github project."
104
+ "for local - absolute path to module folder in file system, e.g. C:\\gitsrc\\any-bootstrap-theme\\, " +
105
+ "for github - name of github project."
106
106
  ),
107
107
  }),
108
108
  ...(schema === db.connectObj.default_schema
109
109
  ? [
110
- new Field({
111
- label: req.__("Version"),
112
- name: "version",
113
- input_type: "text",
114
- sublabel: req.__("Version of module, latest is default value"),
115
- }),
116
- ]
110
+ new Field({
111
+ label: req.__("Version"),
112
+ name: "version",
113
+ input_type: "text",
114
+ sublabel: req.__("Version of module, latest is default value"),
115
+ }),
116
+ ]
117
117
  : []),
118
118
  new Field({
119
119
  label: req.__("Private SSH key"),
@@ -269,72 +269,72 @@ const store_item_html = (req) => (item) => ({
269
269
  div(item.description || ""),
270
270
  item.documentation_link
271
271
  ? div(
272
- a(
273
- { href: item.documentation_link, target: "_blank" },
274
- req.__("Documentation")
272
+ a(
273
+ { href: item.documentation_link, target: "_blank" },
274
+ req.__("Documentation")
275
+ )
275
276
  )
276
- )
277
277
  : ""
278
278
  ),
279
279
  footer: div(
280
280
  div(
281
281
  !item.installed &&
282
- item.plugin &&
283
- post_btn(
284
- `/plugins/install/${encodeURIComponent(item.name)}`,
285
- req.__("Install"),
286
- req.csrfToken(),
287
- {
288
- klass: "store-install",
289
- small: true,
290
- onClick: "press_store_button(this)",
291
- }
292
- ),
282
+ item.plugin &&
283
+ post_btn(
284
+ `/plugins/install/${encodeURIComponent(item.name)}`,
285
+ req.__("Install"),
286
+ req.csrfToken(),
287
+ {
288
+ klass: "store-install",
289
+ small: true,
290
+ onClick: "press_store_button(this)",
291
+ }
292
+ ),
293
293
  !item.installed &&
294
- item.pack &&
295
- post_btn(
296
- `/packs/install-named/${encodeURIComponent(item.name)}`,
297
- req.__("Install"),
298
- req.csrfToken(),
299
- {
300
- klass: "store-install",
301
- small: true,
302
- onClick: "press_store_button(this)",
303
- }
304
- ),
294
+ item.pack &&
295
+ post_btn(
296
+ `/packs/install-named/${encodeURIComponent(item.name)}`,
297
+ req.__("Install"),
298
+ req.csrfToken(),
299
+ {
300
+ klass: "store-install",
301
+ small: true,
302
+ onClick: "press_store_button(this)",
303
+ }
304
+ ),
305
305
 
306
306
  item.installed && item.plugin && cfg_link(req, item),
307
307
  item.installed && item.plugin && info_link(req, item),
308
308
 
309
309
  item.installed &&
310
- item.pack &&
311
- post_btn(
312
- `/packs/uninstall/${encodeURIComponent(item.name)}`,
313
- req.__("Uninstall"),
314
- req.csrfToken(),
315
- {
316
- klass: "store-install",
317
- small: true,
318
- btnClass: "btn-danger",
319
- formClass: "d-inline",
320
- onClick: "press_store_button(this)",
321
- }
322
- ),
310
+ item.pack &&
311
+ post_btn(
312
+ `/packs/uninstall/${encodeURIComponent(item.name)}`,
313
+ req.__("Uninstall"),
314
+ req.csrfToken(),
315
+ {
316
+ klass: "store-install",
317
+ small: true,
318
+ btnClass: "btn-danger",
319
+ formClass: "d-inline",
320
+ onClick: "press_store_button(this)",
321
+ }
322
+ ),
323
323
  item.installed &&
324
- item.plugin &&
325
- item.name !== "base" &&
326
- post_btn(
327
- `/plugins/delete/${encodeURIComponent(item.name)}`,
328
- req.__("Remove"),
329
- req.csrfToken(),
330
- {
331
- klass: "store-install",
332
- small: true,
333
- btnClass: "btn-danger",
334
- formClass: "d-inline",
335
- onClick: "press_store_button(this)",
336
- }
337
- )
324
+ item.plugin &&
325
+ item.name !== "base" &&
326
+ post_btn(
327
+ `/plugins/delete/${encodeURIComponent(item.name)}`,
328
+ req.__("Remove"),
329
+ req.csrfToken(),
330
+ {
331
+ klass: "store-install",
332
+ small: true,
333
+ btnClass: "btn-danger",
334
+ formClass: "d-inline",
335
+ onClick: "press_store_button(this)",
336
+ }
337
+ )
338
338
  )
339
339
  ),
340
340
  });
@@ -354,7 +354,7 @@ const storeNavPills = (req) => {
354
354
  "nav-link",
355
355
  (req.query.set === txt.toLowerCase() ||
356
356
  (txt === "All" && !req.query.set)) &&
357
- "active",
357
+ "active",
358
358
  ],
359
359
  },
360
360
  req.__(txt)
@@ -451,23 +451,23 @@ const store_actions_dropdown = (req) =>
451
451
  '<i class="fas fa-sync"></i>&nbsp;' + req.__("Refresh")
452
452
  ),
453
453
  db.getTenantSchema() === db.connectObj.default_schema &&
454
- a(
455
- {
456
- class: "dropdown-item",
457
- href: `/plugins/upgrade`,
458
- onClick: `notifyAlert('${req.__("Upgrading modules...")}', true)`,
459
- },
460
- '<i class="far fa-arrow-alt-circle-up"></i>&nbsp;' +
461
- req.__("Upgrade installed modules")
462
- ),
454
+ a(
455
+ {
456
+ class: "dropdown-item",
457
+ href: `/plugins/upgrade`,
458
+ onClick: `notifyAlert('${req.__("Upgrading modules...")}', true)`,
459
+ },
460
+ '<i class="far fa-arrow-alt-circle-up"></i>&nbsp;' +
461
+ req.__("Upgrade installed modules")
462
+ ),
463
463
  db.getTenantSchema() === db.connectObj.default_schema &&
464
- a(
465
- {
466
- class: "dropdown-item",
467
- href: `/plugins/new`,
468
- },
469
- '<i class="fas fa-plus"></i>&nbsp;' + req.__("Add another module")
470
- ),
464
+ a(
465
+ {
466
+ class: "dropdown-item",
467
+ href: `/plugins/new`,
468
+ },
469
+ '<i class="fas fa-plus"></i>&nbsp;' + req.__("Add another module")
470
+ ),
471
471
 
472
472
  a(
473
473
  {
@@ -534,7 +534,10 @@ router.get(
534
534
  error_catcher(async (req, res) => {
535
535
  const items = await get_store_items();
536
536
  const relevant_items = filter_items(items, req.query);
537
- res.sendWrap(req.__("Module store"), plugin_store_html(relevant_items, req));
537
+ res.sendWrap(
538
+ req.__("Module store"),
539
+ plugin_store_html(relevant_items, req)
540
+ );
538
541
  })
539
542
  );
540
543
 
@@ -574,8 +577,9 @@ router.get(
574
577
  onclick: "location.reload()",
575
578
  },
576
579
  ];
577
- wfres.renderForm.onChange = `${wfres.renderForm.onChange || ""
578
- };$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
580
+ wfres.renderForm.onChange = `${
581
+ wfres.renderForm.onChange || ""
582
+ };$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
579
583
  }
580
584
 
581
585
  res.sendWrap(req.__(`Configure %s Plugin`, plugin.name), {
@@ -619,8 +623,9 @@ router.post(
619
623
  onclick: "location.reload()",
620
624
  },
621
625
  ];
622
- wfres.renderForm.onChange = `${wfres.renderForm.onChange || ""
623
- };$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
626
+ wfres.renderForm.onChange = `${
627
+ wfres.renderForm.onChange || ""
628
+ };$('#btnReloadNow').removeClass('btn-outline-secondary').addClass('btn-secondary')`;
624
629
  }
625
630
  res.sendWrap(req.__(`Configure %s Plugin`, plugin.name), {
626
631
  type: "card",
@@ -785,7 +790,8 @@ router.get(
785
790
  db.getTenantSchema() === db.connectObj.default_schema &&
786
791
  plugin_db.source === "npm";
787
792
  const latest =
788
- update_permitted && (await get_latest_npm_version(plugin_db.location));
793
+ update_permitted &&
794
+ (await get_latest_npm_version(plugin_db.location, 1000));
789
795
  const can_update = update_permitted && latest && mod.version !== latest;
790
796
  let pkgjson;
791
797
  if (mod.location && fs.existsSync(path.join(mod.location, "package.json")))
@@ -806,35 +812,35 @@ router.get(
806
812
  latest || "",
807
813
  can_update
808
814
  ? a(
809
- {
810
- href: `/plugins/upgrade-plugin/${plugin_db.name}`,
811
- class: "btn btn-primary btn-sm ms-2",
812
- },
813
- req.__("Upgrade")
814
- )
815
+ {
816
+ href: `/plugins/upgrade-plugin/${plugin_db.name}`,
817
+ class: "btn btn-primary btn-sm ms-2",
818
+ },
819
+ req.__("Upgrade")
820
+ )
815
821
  : ""
816
822
  )
817
823
  ),
818
824
  mod.plugin_module.dependencies
819
825
  ? tr(
820
- th(req.__("Module dependencies")),
821
- td(
822
- mod.plugin_module.dependencies.map((d) =>
823
- span({ class: "badge bg-primary me-1" }, d)
826
+ th(req.__("Module dependencies")),
827
+ td(
828
+ mod.plugin_module.dependencies.map((d) =>
829
+ span({ class: "badge bg-primary me-1" }, d)
830
+ )
824
831
  )
825
832
  )
826
- )
827
833
  : null,
828
834
  store_item && store_item.documentation_link
829
835
  ? tr(
830
- th(req.__("Documentation")),
831
- td(
832
- link(
833
- store_item.documentation_link,
834
- store_item.documentation_link
836
+ th(req.__("Documentation")),
837
+ td(
838
+ link(
839
+ store_item.documentation_link,
840
+ store_item.documentation_link
841
+ )
835
842
  )
836
843
  )
837
- )
838
844
  : null,
839
845
  pkgjson && pkgjson.repository
840
846
  ? tr(th(req.__("Repository")), td(showRepository(pkgjson.repository)))
package/routes/tables.js CHANGED
@@ -328,6 +328,7 @@ router.get(
328
328
  name: "name",
329
329
  input_type: "text",
330
330
  },
331
+ // todo implement file mask filter like , accept: "text/csv"
331
332
  { label: req.__("File"), name: "file", input_type: "file" },
332
333
  ],
333
334
  }),
@@ -353,7 +354,7 @@ router.get(
353
354
  */
354
355
  router.post(
355
356
  "/create-from-csv",
356
- setTenant, // TODO why is this needed?????
357
+ setTenant,
357
358
  isAdmin,
358
359
  error_catcher(async (req, res) => {
359
360
  if (req.body.name && req.files && req.files.file) {
@@ -727,6 +728,7 @@ router.get(
727
728
  method: "post",
728
729
  action: `/table/upload_to_table/${table.name}`,
729
730
  encType: "multipart/form-data",
731
+ acceptCharset: "UTF-8",
730
732
  },
731
733
  input({ type: "hidden", name: "_csrf", value: req.csrfToken() }),
732
734
  label(
package/routes/utils.js CHANGED
@@ -73,6 +73,8 @@ function isAdmin(req, res, next) {
73
73
  const setLanguage = (req, res, state) => {
74
74
  if (req.user && req.user.language) {
75
75
  req.setLocale(req.user.language);
76
+ } else if (req.cookies?.lang) {
77
+ req.setLocale(req.cookies?.lang);
76
78
  }
77
79
  set_custom_http_headers(res, state);
78
80
  };
@@ -144,8 +146,7 @@ const setTenant = (req, res, next) => {
144
146
  next();
145
147
  });
146
148
  }
147
- }
148
- else {
149
+ } else {
149
150
  setLanguage(req, res);
150
151
  next();
151
152
  }
package/s3storage.js CHANGED
@@ -1,12 +1,10 @@
1
- var aws = require("aws-sdk");
2
- var express = require("express");
3
- var multer = require("multer");
4
- var multerS3 = require("multer-s3");
1
+ const aws = require("aws-sdk");
2
+ const multer = require("multer");
3
+ const multerS3 = require("multer-s3");
5
4
  const { getState } = require("@saltcorn/data/db/state");
6
5
  const fileUpload = require("express-fileupload");
7
6
  const { v4: uuidv4 } = require("uuid");
8
- const { create } = require("@saltcorn/data/models/file");
9
- var contentDisposition = require("content-disposition");
7
+ const contentDisposition = require("content-disposition");
10
8
 
11
9
  function createS3Client() {
12
10
  return new aws.S3({
@@ -47,11 +45,26 @@ module.exports = {
47
45
 
48
46
  s3upload(req, res, next);
49
47
  } else {
50
- // Use regular file upload
48
+ // Use regular file upload https://www.npmjs.com/package/express-fileupload
49
+ const fileSizeLimit = getState().getConfig("file_upload_limit", 0);
51
50
  fileUpload({
52
51
  useTempFiles: true,
53
52
  createParentPath: true,
54
53
  tempFileDir: "/tmp/",
54
+ // set to true - if you want to have debug
55
+ debug: getState().getConfig("file_upload_debug",false),
56
+ //uriDecodeFileNames: true,
57
+ //safeFileNames: true,
58
+ defCharset: 'utf8',
59
+ defParamCharset: 'utf8',
60
+ // 0 - means no upload limit check
61
+ limits: {
62
+ fileSize: fileSizeLimit,
63
+ },
64
+ abortOnLimit: fileSizeLimit !== 0,
65
+ // 0 - means no upload limit check
66
+ uploadTimeout: getState().getConfig("file_upload_timeout",0),
67
+
55
68
  })(req, res, next);
56
69
  }
57
70
  },
@@ -73,7 +86,7 @@ module.exports = {
73
86
  }
74
87
 
75
88
  // Create S3 object
76
- var s3 = createS3Client();
89
+ const s3 = createS3Client();
77
90
  const bucket = getState().getConfig("storage_s3_bucket");
78
91
 
79
92
  let newFileObject = {};
@@ -122,10 +135,10 @@ module.exports = {
122
135
  */
123
136
  serveObject: function (file, res, download) {
124
137
  if (file.s3_store) {
125
- var s3 = createS3Client();
138
+ const s3 = createS3Client();
126
139
  const bucket = getState().getConfig("storage_s3_bucket");
127
140
 
128
- var params = {
141
+ const params = {
129
142
  Bucket: bucket,
130
143
  Key: file.location,
131
144
  };
@@ -147,7 +160,7 @@ module.exports = {
147
160
 
148
161
  unlinkObject: function (file) {
149
162
  if (file.s3_store) {
150
- var s3 = createS3Client();
163
+ const s3 = createS3Client();
151
164
  return new Promise((resolve, reject) => {
152
165
  s3.deleteObject(
153
166
  {