@saltcorn/server 0.6.1-beta.3 → 0.6.2-beta.2

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/markup/admin.js CHANGED
@@ -213,6 +213,22 @@ const send_users_page = (args) => {
213
213
  });
214
214
  };
215
215
 
216
+ /**
217
+ * @param {object} args
218
+ * @returns {void}
219
+ */
220
+ const send_files_page = (args) => {
221
+ return send_settings_page({
222
+ main_section: "Files",
223
+ main_section_href: "/files",
224
+ sub_sections: [
225
+ { text: "Files", href: "/files" },
226
+ { text: "Storage", href: "/files/storage" },
227
+ ],
228
+ ...args,
229
+ });
230
+ };
231
+
216
232
  /**
217
233
  * @param {object} args
218
234
  * @returns {void}
@@ -464,6 +480,7 @@ module.exports = {
464
480
  send_users_page,
465
481
  send_events_page,
466
482
  send_admin_page,
483
+ send_files_page,
467
484
  save_config_from_form,
468
485
  flash_restart_if_required,
469
486
  flash_restart,
package/markup/index.js CHANGED
@@ -4,4 +4,17 @@
4
4
  * @category server
5
5
  * @module markup/index
6
6
  * @subcategory markup
7
- */
7
+ */
8
+
9
+ /**
10
+ * All files in the auth module.
11
+ * @namespace markup_overview
12
+ * @property {module:markup/admin} admin
13
+ * @property {module:markup/blockly} blockly
14
+ * @property {module:markup/expression_blurb} expression_blurb
15
+ * @property {module:markup/forms} forms
16
+ * @property {module:markup/plugin-store} plugin-store
17
+ *
18
+ * @category server
19
+ * @subcategory markup
20
+ */
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "0.6.1-beta.3",
3
+ "version": "0.6.2-beta.2",
4
4
  "description": "Server app for Saltcorn, open-source no-code platform",
5
5
  "homepage": "https://saltcorn.com",
6
6
  "main": "index.js",
7
7
  "license": "MIT",
8
8
  "dependencies": {
9
- "@saltcorn/base-plugin": "0.6.1-beta.3",
10
- "@saltcorn/builder": "0.6.1-beta.3",
11
- "@saltcorn/data": "0.6.1-beta.3",
9
+ "@saltcorn/base-plugin": "0.6.2-beta.2",
10
+ "@saltcorn/builder": "0.6.2-beta.2",
11
+ "@saltcorn/data": "0.6.2-beta.2",
12
12
  "greenlock-express": "^4.0.3",
13
- "@saltcorn/markup": "0.6.1-beta.3",
14
- "@saltcorn/sbadmin2": "0.6.1-beta.3",
13
+ "@saltcorn/markup": "0.6.2-beta.2",
14
+ "@saltcorn/sbadmin2": "0.6.2-beta.2",
15
15
  "@socket.io/cluster-adapter": "^0.1.0",
16
16
  "@socket.io/sticky": "^1.0.1",
17
17
  "connect-flash": "^0.1.1",
@@ -33,13 +33,19 @@
33
33
  "live-plugin-manager": "^0.16.0",
34
34
  "moment": "^2.27.0",
35
35
  "node-fetch": "2.6.2",
36
+ "node-watch": "^0.7.2",
36
37
  "passport": "^0.4.1",
37
38
  "passport-custom": "^1.1.1",
38
39
  "passport-http-bearer": "^1.0.1",
39
40
  "pg": "^8.2.1",
40
41
  "pluralize": "^8.0.0",
41
42
  "socket.io": "4.2.0",
42
- "tmp-promise": "^3.0.2"
43
+ "tmp-promise": "^3.0.2",
44
+ "multer-s3": "^2.10.0",
45
+ "multer": "^1.4.3",
46
+ "aws-sdk": "^2.1037.0",
47
+ "uuid": "^8.2.0",
48
+ "content-disposition": "^0.5.3"
43
49
  },
44
50
  "optionalDependencies": {
45
51
  "sd-notify": "^2.8.0"
@@ -51,7 +57,9 @@
51
57
  },
52
58
  "scripts": {
53
59
  "dev": "nodemon index.js",
54
- "test": "jest --runInBand"
60
+ "test": "jest --runInBand",
61
+ "tsc": "echo \"Error: no TypeScript support yet\"",
62
+ "clean": "echo \"Error: no TypeScript support yet\""
55
63
  },
56
64
  "jest": {
57
65
  "testEnvironment": "node",
@@ -62,7 +70,12 @@
62
70
  "coveragePathIgnorePatterns": [
63
71
  "/node_modules/",
64
72
  "/plugin_packages/"
65
- ]
73
+ ],
74
+ "moduleNameMapper": {
75
+ "@saltcorn/sqlite/(.*)": "@saltcorn/sqlite/dist/$1",
76
+ "@saltcorn/db-common/(.*)": "@saltcorn/db-common/dist/$1",
77
+ "@saltcorn/data/(.*)": "@saltcorn/data/dist/$1"
78
+ }
66
79
  },
67
80
  "publishConfig": {
68
81
  "access": "public"
@@ -65,11 +65,11 @@ div.testrunoutput code {
65
65
  }
66
66
 
67
67
  div[data-inline-edit-dest-url] .editicon {
68
- display: none;
68
+ visibility: hidden;
69
69
  }
70
70
 
71
71
  div[data-inline-edit-dest-url]:hover .editicon {
72
- display: inline;
72
+ visibility: visible;
73
73
  }
74
74
  .searchbar-dropdown {
75
75
  left: unset;
@@ -306,6 +306,18 @@ function select_id(id) {
306
306
  function set_state_field(key, value) {
307
307
  pjax_to(updateQueryStringParameter(window.location.href, key, value));
308
308
  }
309
+
310
+ function check_state_field(that) {
311
+ const checked = that.checked;
312
+ const name = that.name;
313
+ const value = that.value;
314
+ var separator = window.location.href.indexOf("?") !== -1 ? "&" : "?";
315
+ let dest;
316
+ if (checked) dest = window.location.href + `${separator}${name}=${value}`;
317
+ else dest = window.location.href.replace(`${name}=${value}`, "");
318
+ pjax_to(dest.replace("&&", "&").replace("?&", "?"));
319
+ }
320
+
309
321
  function set_state_fields(kvs) {
310
322
  var newhref = window.location.href;
311
323
  Object.entries(kvs).forEach((kv) => {
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @category server
3
+ * @module restart_watcher
4
+ */
5
+
6
+ const path = require("path");
7
+ const { spawnSync } = require("child_process");
8
+ const watch = require("node-watch");
9
+ const Plugin = require("@saltcorn/data/models/plugin");
10
+ const db = require("@saltcorn/data/db");
11
+ const { eachTenant } = require("@saltcorn/data/models/tenant");
12
+
13
+ /**
14
+ * packages that should trigger a server re-start
15
+ */
16
+ const relevantPackages = [
17
+ "db-common",
18
+ "postgres",
19
+ "saltcorn-data",
20
+ "saltcorn-markup",
21
+ "server",
22
+ "sqlite",
23
+ ];
24
+
25
+ /**
26
+ * excluded directories or file name patterns
27
+ */
28
+ const excludePatterns = [
29
+ /\/node_modules/,
30
+ /\/public/,
31
+ /\.git/,
32
+ /\.docs/,
33
+ /\.docs/,
34
+ /\migrations/,
35
+ /.*test.js/,
36
+ ];
37
+
38
+ /**
39
+ * get the root directory of the saltcorn project
40
+ * @returns {string} project root path
41
+ */
42
+ const getProjectRoot = () => {
43
+ return path.normalize(`${__dirname}/../../`);
44
+ };
45
+
46
+ /**
47
+ * get the packages directory of the saltcorn project
48
+ * @returns {string} packages path
49
+ */
50
+ const getPackagesDirectory = () => {
51
+ return `${getProjectRoot()}/packages`;
52
+ };
53
+
54
+ /**
55
+ * get all package directories that should trigger a server re-start
56
+ * @returns {string[]} list of paths to relevant directories
57
+ */
58
+ const getRelevantPackages = () => {
59
+ const packagesDir = getPackagesDirectory();
60
+ return relevantPackages.map((packageName) => `${packagesDir}/${packageName}`);
61
+ };
62
+
63
+ /**
64
+ * get all plugin directories that should trigger a server re-start
65
+ * @returns {string[]} list of paths to relevant directories
66
+ */
67
+ const getPluginDirectories = async () => {
68
+ const getDirs = async () => {
69
+ const local_plugins = await Plugin.find({ source: "local" });
70
+ return local_plugins.map((p) => p.location);
71
+ };
72
+ const listOfDirs = [];
73
+ await eachTenant(async () => {
74
+ listOfDirs.push(await getDirs());
75
+ });
76
+ return [...new Set(listOfDirs.flat(1))];
77
+ };
78
+
79
+ const projectRoot = getProjectRoot();
80
+
81
+ const watchCfg = {
82
+ recursive: true,
83
+ filter(file, skip) {
84
+ for (const excludePattern of excludePatterns) {
85
+ if (excludePattern.test(file)) return skip;
86
+ }
87
+ return /(\.js|\.ts)$/.test(file);
88
+ },
89
+ };
90
+
91
+ let activeWatchers = [];
92
+
93
+ /**
94
+ * close all open file watchers
95
+ */
96
+ const closeWatchers = () => {
97
+ for (const activeWatcher of activeWatchers) {
98
+ if (!activeWatcher.isClosed()) {
99
+ activeWatcher.close();
100
+ }
101
+ }
102
+ };
103
+
104
+ /**
105
+ * register many file change listener and do re-starts on changes
106
+ * The listener calls process.exit() and assumes
107
+ * that pm2 does the actual re-start.
108
+ * @param {string[]} projectDirs package paths that should trigger re-starts.
109
+ * @param {string[]} pluginDirs plugin paths that should trigger re-starts.
110
+ */
111
+ const listenForChanges = (projectDirs, pluginDirs) => {
112
+ // watch project dirs
113
+ for (const projectDir of projectDirs) {
114
+ activeWatchers.push(
115
+ watch(
116
+ projectDir,
117
+ watchCfg,
118
+ // event is either 'update' or 'remove'
119
+ (event, file) => {
120
+ console.log("'%s' changed \n re-starting now", file);
121
+ closeWatchers();
122
+ spawnSync("npm", ["run", "tsc"], {
123
+ stdio: "inherit",
124
+ cwd: projectRoot,
125
+ });
126
+ process.exit();
127
+ }
128
+ )
129
+ );
130
+ }
131
+ // watch plugin dirs
132
+ for (const pluginDir of pluginDirs) {
133
+ activeWatchers.push(
134
+ watch(
135
+ pluginDir,
136
+ watchCfg,
137
+ // event is either 'update' or 'remove'
138
+ (event, file) => {
139
+ console.log("'%s' changed \n re-starting now", file);
140
+ closeWatchers();
141
+ process.exit();
142
+ }
143
+ )
144
+ );
145
+ }
146
+ };
147
+
148
+ module.exports = {
149
+ listenForChanges,
150
+ getProjectRoot,
151
+ getPackagesDirectory,
152
+ getRelevantPackages,
153
+ getPluginDirectories,
154
+ closeWatchers,
155
+ };
package/routes/actions.js CHANGED
@@ -5,12 +5,7 @@
5
5
  * @subcategory routes
6
6
  */
7
7
  const Router = require("express-promise-router");
8
- const {
9
- isAdmin,
10
- setTenant,
11
- error_catcher,
12
- get_base_url,
13
- } = require("./utils.js");
8
+ const { isAdmin, error_catcher, get_base_url } = require("./utils.js");
14
9
  const { getState } = require("@saltcorn/data/db/state");
15
10
  const Trigger = require("@saltcorn/data/models/trigger");
16
11
 
@@ -87,7 +82,6 @@ const getActions = async () => {
87
82
  */
88
83
  router.get(
89
84
  "/",
90
- setTenant,
91
85
  isAdmin,
92
86
  error_catcher(async (req, res) => {
93
87
  const triggers = await Trigger.findAllWithTableName();
@@ -288,7 +282,6 @@ const triggerForm = async (req, trigger) => {
288
282
  */
289
283
  router.get(
290
284
  "/new",
291
- setTenant,
292
285
  isAdmin,
293
286
  error_catcher(async (req, res) => {
294
287
  const form = await triggerForm(req);
@@ -314,7 +307,6 @@ router.get(
314
307
  */
315
308
  router.get(
316
309
  "/edit/:id",
317
- setTenant,
318
310
  isAdmin,
319
311
  error_catcher(async (req, res) => {
320
312
  const { id } = req.params;
@@ -344,7 +336,6 @@ router.get(
344
336
  */
345
337
  router.post(
346
338
  "/new",
347
- setTenant,
348
339
  isAdmin,
349
340
  error_catcher(async (req, res) => {
350
341
  const form = await triggerForm(req);
@@ -384,7 +375,6 @@ router.post(
384
375
  */
385
376
  router.post(
386
377
  "/edit/:id",
387
- setTenant,
388
378
  isAdmin,
389
379
  error_catcher(async (req, res) => {
390
380
  const { id } = req.params;
@@ -427,7 +417,6 @@ router.post(
427
417
  */
428
418
  router.get(
429
419
  "/configure/:id",
430
- setTenant,
431
420
  isAdmin,
432
421
  error_catcher(async (req, res) => {
433
422
  const { id } = req.params;
@@ -543,7 +532,6 @@ router.get(
543
532
  */
544
533
  router.post(
545
534
  "/configure/:id",
546
- setTenant,
547
535
  isAdmin,
548
536
  error_catcher(async (req, res) => {
549
537
  const { id } = req.params;
@@ -585,7 +573,6 @@ router.post(
585
573
  */
586
574
  router.post(
587
575
  "/delete/:id",
588
- setTenant,
589
576
  isAdmin,
590
577
  error_catcher(async (req, res) => {
591
578
  const { id } = req.params;
@@ -602,7 +589,6 @@ router.post(
602
589
  */
603
590
  router.get(
604
591
  "/testrun/:id",
605
- setTenant,
606
592
  isAdmin,
607
593
  error_catcher(async (req, res) => {
608
594
  const { id } = req.params;
package/routes/admin.js CHANGED
@@ -5,12 +5,7 @@
5
5
  */
6
6
  const Router = require("express-promise-router");
7
7
 
8
- const {
9
- setTenant,
10
- isAdmin,
11
- error_catcher,
12
- getGitRevision,
13
- } = require("./utils.js");
8
+ const { isAdmin, error_catcher, getGitRevision } = require("./utils.js");
14
9
  const Table = require("@saltcorn/data/models/table");
15
10
  const Plugin = require("@saltcorn/data/models/plugin");
16
11
  const File = require("@saltcorn/data/models/file");
@@ -52,6 +47,7 @@ const load_plugins = require("../load_plugins");
52
47
  const {
53
48
  restore_backup,
54
49
  send_admin_page,
50
+ send_files_page,
55
51
  config_fields_form,
56
52
  save_config_from_form,
57
53
  flash_restart_if_required,
@@ -66,6 +62,7 @@ const {
66
62
  is_hsts_tld,
67
63
  } = require("../markup/admin");
68
64
  const moment = require("moment");
65
+ const View = require("@saltcorn/data/models/view");
69
66
 
70
67
  /**
71
68
  * @type {object}
@@ -78,7 +75,7 @@ const router = new Router();
78
75
  module.exports = router;
79
76
 
80
77
  /**
81
- * @param {object} req
78
+ * @param {object} req
82
79
  * @returns {Promise<Form>}
83
80
  */
84
81
  const site_id_form = (req) =>
@@ -131,7 +128,6 @@ const email_form = async (req) => {
131
128
  */
132
129
  router.get(
133
130
  "/",
134
- setTenant,
135
131
  isAdmin,
136
132
  error_catcher(async (req, res) => {
137
133
  const isRoot = db.getTenantSchema() === db.connectObj.default_schema;
@@ -156,7 +152,6 @@ router.get(
156
152
  */
157
153
  router.post(
158
154
  "/",
159
- setTenant,
160
155
  isAdmin,
161
156
  error_catcher(async (req, res) => {
162
157
  const form = await site_id_form(req);
@@ -189,7 +184,6 @@ router.post(
189
184
  */
190
185
  router.get(
191
186
  "/email",
192
- setTenant,
193
187
  isAdmin,
194
188
  error_catcher(async (req, res) => {
195
189
  const form = await email_form(req);
@@ -223,7 +217,6 @@ router.get(
223
217
  */
224
218
  router.get(
225
219
  "/send-test-email",
226
- setTenant,
227
220
  isAdmin,
228
221
  error_catcher(async (req, res) => {
229
222
  const from = getState().getConfig("email_from");
@@ -254,7 +247,6 @@ router.get(
254
247
  */
255
248
  router.post(
256
249
  "/email",
257
- setTenant,
258
250
  isAdmin,
259
251
  error_catcher(async (req, res) => {
260
252
  const form = await email_form(req);
@@ -285,7 +277,6 @@ router.post(
285
277
  */
286
278
  router.get(
287
279
  "/backup",
288
- setTenant,
289
280
  isAdmin,
290
281
  error_catcher(async (req, res) => {
291
282
  send_admin_page({
@@ -330,7 +321,6 @@ router.get(
330
321
  */
331
322
  router.get(
332
323
  "/system",
333
- setTenant,
334
324
  isAdmin,
335
325
  error_catcher(async (req, res) => {
336
326
  const isRoot = db.getTenantSchema() === db.connectObj.default_schema;
@@ -450,7 +440,6 @@ router.get(
450
440
  */
451
441
  router.post(
452
442
  "/restart",
453
- setTenant,
454
443
  isAdmin,
455
444
  error_catcher(async (req, res) => {
456
445
  if (db.getTenantSchema() === db.connectObj.default_schema) {
@@ -473,7 +462,6 @@ router.post(
473
462
  */
474
463
  router.post(
475
464
  "/upgrade",
476
- setTenant,
477
465
  isAdmin,
478
466
  error_catcher(async (req, res) => {
479
467
  if (db.getTenantSchema() !== db.connectObj.default_schema) {
@@ -510,7 +498,6 @@ router.post(
510
498
  */
511
499
  router.post(
512
500
  "/backup",
513
- setTenant,
514
501
  isAdmin,
515
502
  error_catcher(async (req, res) => {
516
503
  const fileName = await create_backup();
@@ -531,7 +518,6 @@ router.post(
531
518
  */
532
519
  router.post(
533
520
  "/restore",
534
- setTenant,
535
521
  isAdmin,
536
522
  error_catcher(async (req, res) => {
537
523
  const newPath = File.get_new_path();
@@ -547,7 +533,7 @@ router.post(
547
533
  );
548
534
 
549
535
  /**
550
- * @param {object} req
536
+ * @param {object} req
551
537
  * @returns {Form}
552
538
  */
553
539
  const clearAllForm = (req) =>
@@ -628,7 +614,6 @@ const clearAllForm = (req) =>
628
614
  */
629
615
  router.post(
630
616
  "/enable-letsencrypt",
631
- setTenant,
632
617
  isAdmin,
633
618
  error_catcher(async (req, res) => {
634
619
  if (db.getTenantSchema() === db.connectObj.default_schema) {
@@ -706,7 +691,6 @@ router.post(
706
691
  */
707
692
  router.get(
708
693
  "/clear-all",
709
- setTenant,
710
694
  isAdmin,
711
695
  error_catcher(async (req, res) => {
712
696
  res.sendWrap(req.__(`Admin`), {
@@ -736,7 +720,6 @@ router.get(
736
720
  */
737
721
  router.post(
738
722
  "/clear-all",
739
- setTenant,
740
723
  isAdmin,
741
724
  error_catcher(async (req, res) => {
742
725
  const form = clearAllForm(req);
@@ -746,7 +729,7 @@ router.post(
746
729
  await db.deleteWhere("_sc_pages");
747
730
  }
748
731
  if (form.values.views) {
749
- await db.deleteWhere("_sc_views");
732
+ await View.delete({});
750
733
  }
751
734
  //user fields
752
735
  const users = await Table.findOne({ name: "users" });