@saltcorn/server 0.8.0-beta.4 → 0.8.1-beta.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.
Files changed (46) hide show
  1. package/app.js +7 -6
  2. package/auth/admin.js +260 -217
  3. package/auth/index.js +20 -20
  4. package/auth/roleadmin.js +2 -9
  5. package/auth/routes.js +193 -139
  6. package/auth/testhelp.js +62 -55
  7. package/fixture_persons.js +1 -1
  8. package/index.js +22 -22
  9. package/locales/en.json +13 -1
  10. package/locales/fr.json +14 -2
  11. package/locales/ru.json +25 -19
  12. package/markup/admin.js +22 -15
  13. package/markup/blockly.js +1 -1
  14. package/markup/expression_blurb.js +15 -15
  15. package/markup/forms.js +21 -22
  16. package/markup/index.js +20 -20
  17. package/markup/plugin-store.js +4 -4
  18. package/package.json +8 -8
  19. package/public/diagram_utils.js +22 -9
  20. package/public/saltcorn-common.js +128 -68
  21. package/public/saltcorn.css +6 -0
  22. package/public/saltcorn.js +68 -20
  23. package/restart_watcher.js +157 -157
  24. package/routes/actions.js +4 -11
  25. package/routes/admin.js +14 -6
  26. package/routes/api.js +11 -18
  27. package/routes/common_lists.js +127 -130
  28. package/routes/delete.js +2 -2
  29. package/routes/edit.js +1 -1
  30. package/routes/fields.js +48 -2
  31. package/routes/files.js +112 -94
  32. package/routes/homepage.js +1 -1
  33. package/routes/infoarch.js +1 -1
  34. package/routes/list.js +6 -5
  35. package/routes/packs.js +1 -2
  36. package/routes/pageedit.js +1 -1
  37. package/routes/tag_entries.js +1 -1
  38. package/routes/tenant.js +2 -1
  39. package/routes/utils.js +3 -1
  40. package/routes/view.js +14 -2
  41. package/routes/viewedit.js +35 -0
  42. package/s3storage.js +13 -11
  43. package/serve.js +35 -31
  44. package/systemd.js +23 -21
  45. package/tests/fields.test.js +23 -0
  46. package/wrapper.js +46 -45
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
+ };
@@ -367,3 +367,26 @@ describe("Field Endpoints", () => {
367
367
  .expect((r) => +r.body > 1);
368
368
  });
369
369
  });
370
+
371
+ describe("Fieldview config", () => {
372
+ //itShouldRedirectUnauthToLogin("/field/2");
373
+ it("should return fieldview options", async () => {
374
+ const loginCookie = await getAdminLoginCookie();
375
+
376
+ const app = await getApp({ disableCsrf: true });
377
+
378
+ await request(app)
379
+ .post("/field/fieldviewcfgform/books")
380
+ .set("Cookie", loginCookie)
381
+ .send({
382
+ type: "Field",
383
+ field_name: "pages",
384
+ fieldview: "progress_bar",
385
+ })
386
+ .expect(
387
+ toInclude(
388
+ `<div class="form-group"><div><label for="inputmax">max</label></div><div><input type="number" class="form-control item-menu" data-fieldname="max" name="max" id="inputmax" step="1" required></div></div><div class="form-group"><div><label for="inputbar_color">Bar color</label></div><div><input type="color" class="form-control item-menu" data-fieldname="bar_color" name="bar_color" id="inputbar_color"></div></div><div class="form-group"><div><label for="inputbg_color">Background color</label></div><div><input type="color" class="form-control item-menu" data-fieldname="bg_color" name="bg_color" id="inputbg_color"></div></div><div class="form-group"><div><label for="inputpx_height">Height in px</label></div><div><input type="number" class="form-control item-menu" data-fieldname="px_height" name="px_height" id="inputpx_height" step="1"></div></div>`
389
+ )
390
+ );
391
+ });
392
+ });
package/wrapper.js CHANGED
@@ -45,12 +45,12 @@ const get_extra_menu = (role, state, req) => {
45
45
  item.type === "Link"
46
46
  ? item.url
47
47
  : item.type === "Action"
48
- ? `javascript:ajax_post_json('/menu/runaction/${item.action_name}')`
49
- : item.type === "View"
50
- ? `/view/${encodeURIComponent(item.viewname)}`
51
- : item.type === "Page"
52
- ? `/page/${encodeURIComponent(item.pagename)}`
53
- : undefined,
48
+ ? `javascript:ajax_post_json('/menu/runaction/${item.action_name}')`
49
+ : item.type === "View"
50
+ ? `/view/${encodeURIComponent(item.viewname)}`
51
+ : item.type === "Page"
52
+ ? `/page/${encodeURIComponent(item.pagename)}`
53
+ : undefined,
54
54
  ...(item.subitems ? { subitems: transform(item.subitems) } : {}),
55
55
  }));
56
56
  return transform(cfg);
@@ -70,34 +70,34 @@ const get_menu = (req) => {
70
70
  const extra_menu = get_extra_menu(role, state, req);
71
71
  const authItems = isAuth
72
72
  ? [
73
- {
74
- label: req.__("User"),
75
- icon: "far fa-user",
76
- isUser: true,
77
- subitems: [
78
- { label: small((req.user.email || "").split("@")[0]) },
79
- {
80
- label: req.__("User Settings"),
81
- icon: "fas fa-user-cog",
73
+ {
74
+ label: req.__("User"),
75
+ icon: "far fa-user",
76
+ isUser: true,
77
+ subitems: [
78
+ { label: small((req.user.email || "").split("@")[0]) },
79
+ {
80
+ label: req.__("User Settings"),
81
+ icon: "fas fa-user-cog",
82
82
 
83
- link: "/auth/settings",
84
- },
85
- {
86
- link: "/auth/logout",
87
- icon: "fas fa-sign-out-alt",
88
- label: req.__("Logout"),
89
- },
90
- ],
91
- },
92
- ]
83
+ link: "/auth/settings",
84
+ },
85
+ {
86
+ link: "/auth/logout",
87
+ icon: "fas fa-sign-out-alt",
88
+ label: req.__("Logout"),
89
+ },
90
+ ],
91
+ },
92
+ ]
93
93
  : [
94
- ...(allow_signup
95
- ? [{ link: "/auth/signup", label: req.__("Sign up") }]
96
- : []),
97
- ...(login_menu
98
- ? [{ link: "/auth/login", label: req.__("Login") }]
99
- : []),
100
- ];
94
+ ...(allow_signup
95
+ ? [{ link: "/auth/signup", label: req.__("Sign up") }]
96
+ : []),
97
+ ...(login_menu
98
+ ? [{ link: "/auth/login", label: req.__("Login") }]
99
+ : []),
100
+ ];
101
101
  // const schema = db.getTenantSchema();
102
102
  // Admin role id (todo move to common constants)
103
103
  const isAdmin = role === 1;
@@ -163,7 +163,6 @@ const get_menu = (req) => {
163
163
  items: authItems,
164
164
  },
165
165
  ].filter((s) => s);
166
-
167
166
  };
168
167
  /**
169
168
  * Get Headers
@@ -179,17 +178,17 @@ const get_headers = (req, version_tag, description, extras = []) => {
179
178
 
180
179
  const iconHeader = favicon
181
180
  ? [
182
- {
183
- headerTag: `<link rel="icon" type="image/png" href="/files/serve/${favicon}">`,
184
- },
185
- ]
181
+ {
182
+ headerTag: `<link rel="icon" type="image/png" href="/files/serve/${favicon}">`,
183
+ },
184
+ ]
186
185
  : [];
187
186
  const meta_description = description
188
187
  ? [
189
- {
190
- headerTag: `<meta name="description" content="${description}">`,
191
- },
192
- ]
188
+ {
189
+ headerTag: `<meta name="description" content="${description}">`,
190
+ },
191
+ ]
193
192
  : [];
194
193
  const stdHeaders = [
195
194
  {
@@ -204,6 +203,8 @@ const get_headers = (req, version_tag, description, extras = []) => {
204
203
  from_cfg.push({ style: state.getConfig("page_custom_css", "") });
205
204
  if (state.getConfig("page_custom_html", ""))
206
205
  from_cfg.push({ headerTag: state.getConfig("page_custom_html", "") });
206
+ if (state.getConfig("log_client_errors", false))
207
+ from_cfg.push({ scriptBody: `enable_error_catcher()` });
207
208
  const state_headers = [];
208
209
  for (const hs of Object.values(state.headers)) {
209
210
  state_headers.push(...hs);
@@ -351,7 +352,7 @@ const defaultRenderToHtml = (s, role) =>
351
352
  typeof s === "string"
352
353
  ? s
353
354
  : renderLayout({
354
- blockDispatch: {},
355
- role,
356
- layout: s,
357
- });
355
+ blockDispatch: {},
356
+ role,
357
+ layout: s,
358
+ });