@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/app.js +26 -12
- package/auth/routes.js +41 -27
- package/locales/en.json +10 -1
- package/package.json +7 -7
- package/public/saltcorn-common.js +86 -21
- package/public/saltcorn.css +16 -10
- package/public/saltcorn.js +13 -7
- package/routes/actions.js +15 -5
- package/routes/admin.js +21 -10
- package/routes/diagram.js +436 -35
- package/routes/pageedit.js +9 -6
- package/routes/tags.js +26 -22
- package/routes/utils.js +60 -20
- package/routes/viewedit.js +40 -20
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
|
-
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
setLanguage(req, res
|
|
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
|
-
|
|
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
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
};
|
package/routes/viewedit.js
CHANGED
|
@@ -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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
109
|
+
{ href: `/viewedit/new`, class: "btn btn-primary" },
|
|
110
|
+
req.__("Create view")
|
|
111
|
+
)
|
|
96
112
|
: p(
|
|
97
|
-
|
|
98
|
-
|
|
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") + " »",
|
|
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
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
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(
|
|
415
|
+
res.redirect(
|
|
416
|
+
addOnDoneRedirect(
|
|
417
|
+
`/viewedit/config/${encodeURIComponent(v.name)}`,
|
|
418
|
+
req
|
|
419
|
+
)
|
|
420
|
+
);
|
|
401
421
|
}
|
|
402
422
|
} else {
|
|
403
423
|
sendForm(form);
|