@saltcorn/server 0.7.4-beta.3 → 0.7.4

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/utils.js CHANGED
@@ -113,37 +113,62 @@ const get_tenant_from_req = (req) => {
113
113
  };
114
114
 
115
115
  /**
116
+ * middleware to extract the tenant domain and call runWithtenant()
116
117
  * @param {object} req
117
118
  * @param {object} res
118
119
  * @param {function} next
119
120
  */
120
121
  const setTenant = (req, res, next) => {
121
122
  if (db.is_it_multi_tenant()) {
122
- const other_domain = get_other_domain_tenant(req.hostname);
123
- if (other_domain) {
124
- const state = getTenant(other_domain);
125
- if (!state) {
126
- setLanguage(req, res);
127
- next();
128
- } else {
129
- db.runWithTenant(other_domain, () => {
130
- setLanguage(req, res, state);
131
- state.log(5, `${req.method} ${req.originalUrl}`);
123
+ // for a saltcorn mobile request use 'req.user.tenant'
124
+ if (req.smr) {
125
+ if (
126
+ req.user?.tenant &&
127
+ req.user.tenant !== db.connectObj.default_schema
128
+ ) {
129
+ const state = getTenant(req.user.tenant);
130
+ if (!state) {
131
+ setLanguage(req, res);
132
132
  next();
133
- });
133
+ } else {
134
+ db.runWithTenant(req.user.tenant, () => {
135
+ setLanguage(req, res, state);
136
+ state.log(5, `${req.method} ${req.originalUrl}`);
137
+ next();
138
+ });
139
+ }
134
140
  }
135
- } else {
136
- const ten = get_tenant_from_req(req);
137
- const state = getTenant(ten);
138
- if (!state) {
141
+ else {
139
142
  setLanguage(req, res);
140
143
  next();
144
+ }
145
+ } else {
146
+ const other_domain = get_other_domain_tenant(req.hostname);
147
+ if (other_domain) {
148
+ const state = getTenant(other_domain);
149
+ if (!state) {
150
+ setLanguage(req, res);
151
+ next();
152
+ } else {
153
+ db.runWithTenant(other_domain, () => {
154
+ setLanguage(req, res, state);
155
+ state.log(5, `${req.method} ${req.originalUrl}`);
156
+ next();
157
+ });
158
+ }
141
159
  } else {
142
- db.runWithTenant(ten, () => {
143
- setLanguage(req, res, state);
144
- state.log(5, `${req.method} ${req.originalUrl}`);
160
+ const ten = get_tenant_from_req(req);
161
+ const state = getTenant(ten);
162
+ if (!state) {
163
+ setLanguage(req, res);
145
164
  next();
146
- });
165
+ } else {
166
+ db.runWithTenant(ten, () => {
167
+ setLanguage(req, res, state);
168
+ state.log(5, `${req.method} ${req.originalUrl}`);
169
+ next();
170
+ });
171
+ }
147
172
  }
148
173
  }
149
174
  } else {
@@ -232,6 +257,20 @@ const getSessionStore = () => {
232
257
  }
233
258
  };
234
259
 
260
+ /**
261
+ * appends 'req.query.on_done_redirect' to 'oldPath' if it exists
262
+ * @param {string} oldPath path without 'on_done_redirect'
263
+ * @param {any} req express request
264
+ * @returns a new string with or without on_done_redirect=...
265
+ */
266
+ const addOnDoneRedirect = (oldPath, req) => {
267
+ const separator = oldPath.indexOf("?") > -1 ? "&" : "?";
268
+ if (req.query.on_done_redirect) {
269
+ return `${oldPath}${separator}on_done_redirect=${req.query.on_done_redirect}`;
270
+ }
271
+ return oldPath;
272
+ };
273
+
235
274
  module.exports = {
236
275
  sqlsanitize,
237
276
  csrfField,
@@ -243,5 +282,6 @@ module.exports = {
243
282
  getGitRevision,
244
283
  getSessionStore,
245
284
  setTenant,
246
- get_tenant_from_req
285
+ get_tenant_from_req,
286
+ addOnDoneRedirect,
247
287
  };
@@ -16,6 +16,7 @@ const {
16
16
  post_dropdown_item,
17
17
  renderBuilder,
18
18
  settingsDropdown,
19
+ alert
19
20
  } = require("@saltcorn/markup");
20
21
  const {
21
22
  //span,
@@ -30,7 +31,7 @@ const {
30
31
  } = require("@saltcorn/markup/tags");
31
32
 
32
33
  const { getState } = require("@saltcorn/data/db/state");
33
- const { isAdmin, error_catcher } = require("./utils.js");
34
+ const { isAdmin, error_catcher, addOnDoneRedirect } = require("./utils.js");
34
35
  const { setTableRefs, viewsList } = require("./common_lists");
35
36
  const Form = require("@saltcorn/data/models/form");
36
37
  const Field = require("@saltcorn/data/models/field");
@@ -76,6 +77,20 @@ router.get(
76
77
 
77
78
  const viewMarkup = await viewsList(views, req);
78
79
  const tables = await Table.find();
80
+ const viewAccessWarning = view => {
81
+ const table = tables.find(t => t.name === view.table)
82
+ if (!table) return false
83
+ if (table.ownership_field_id || table.ownership_formula) return false
84
+
85
+ return table.min_role_read < view.min_role
86
+ }
87
+ const hasAccessWarning = views.filter(viewAccessWarning)
88
+ const accessWarning = hasAccessWarning.length > 0
89
+ ? alert("danger", `<p>You have views with a role to access lower than the table role to read,
90
+ with no table ownership. In the next version of Saltcorn, this may cause a
91
+ denial of access. Users will need to have table read access to any data displayed.</p>
92
+ Views potentially affected: ${hasAccessWarning.map(v => v.name).join(", ")}`)
93
+ : ''
79
94
  res.sendWrap(req.__(`Views`), {
80
95
  above: [
81
96
  {
@@ -87,17 +102,18 @@ router.get(
87
102
  class: "mt-0",
88
103
  title: req.__("Your views"),
89
104
  contents: [
105
+ accessWarning,
90
106
  viewMarkup,
91
107
  tables.length > 0
92
108
  ? a(
93
- { href: `/viewedit/new`, class: "btn btn-primary" },
94
- req.__("Create view")
95
- )
109
+ { href: `/viewedit/new`, class: "btn btn-primary" },
110
+ req.__("Create view")
111
+ )
96
112
  : p(
97
- req.__(
98
- "You must create at least one table before you can create views."
99
- )
100
- ),
113
+ req.__(
114
+ "You must create at least one table before you can create views."
115
+ )
116
+ ),
101
117
  ],
102
118
  },
103
119
  ],
@@ -129,7 +145,7 @@ const viewForm = async (req, tableOptions, roles, pages, values) => {
129
145
  .map(([k, v]) => k);
130
146
  const slugOptions = await Table.allSlugOptions();
131
147
  return new Form({
132
- action: "/viewedit/save",
148
+ action: addOnDoneRedirect("/viewedit/save", req),
133
149
  submitLabel: req.__("Configure") + " &raquo;",
134
150
  blurb: req.__("First, please give some basic information about the view."),
135
151
  fields: [
@@ -209,15 +225,15 @@ const viewForm = async (req, tableOptions, roles, pages, values) => {
209
225
  }),
210
226
  ...(isEdit
211
227
  ? [
212
- new Field({
213
- name: "viewtemplate",
214
- input_type: "hidden",
215
- }),
216
- new Field({
217
- name: "table_name",
218
- input_type: "hidden",
219
- }),
220
- ]
228
+ new Field({
229
+ name: "viewtemplate",
230
+ input_type: "hidden",
231
+ }),
232
+ new Field({
233
+ name: "table_name",
234
+ input_type: "hidden",
235
+ }),
236
+ ]
221
237
  : []),
222
238
  ],
223
239
  values,
@@ -337,7 +353,6 @@ router.post(
337
353
  const pages = await Page.find();
338
354
  const form = await viewForm(req, tableOptions, roles, pages);
339
355
  const result = form.validate(req.body);
340
-
341
356
  const sendForm = (form) => {
342
357
  res.sendWrap(req.__(`Edit view`), {
343
358
  above: [
@@ -397,7 +412,12 @@ router.post(
397
412
  else v.configuration = {};
398
413
  await View.create(v);
399
414
  }
400
- res.redirect(`/viewedit/config/${encodeURIComponent(v.name)}`);
415
+ res.redirect(
416
+ addOnDoneRedirect(
417
+ `/viewedit/config/${encodeURIComponent(v.name)}`,
418
+ req
419
+ )
420
+ );
401
421
  }
402
422
  } else {
403
423
  sendForm(form);