@saltcorn/server 0.7.4-beta.3 → 0.8.0-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.
- package/app.js +43 -22
- package/auth/admin.js +173 -74
- package/auth/routes.js +67 -28
- package/locales/en.json +54 -2
- package/locales/es.json +134 -134
- package/locales/ru.json +32 -5
- package/markup/admin.js +40 -38
- package/markup/forms.js +4 -3
- package/package.json +8 -7
- package/public/diagram_utils.js +530 -0
- package/public/gridedit.js +4 -1
- package/public/jquery-menu-editor.min.js +112 -112
- package/public/saltcorn-common.js +114 -26
- package/public/saltcorn.css +27 -10
- package/public/saltcorn.js +223 -76
- package/restart_watcher.js +1 -0
- package/routes/actions.js +20 -6
- package/routes/admin.js +243 -82
- package/routes/api.js +19 -2
- package/routes/common_lists.js +137 -134
- package/routes/diagram.js +362 -35
- package/routes/fields.js +4 -1
- package/routes/files.js +137 -101
- package/routes/homepage.js +2 -2
- package/routes/infoarch.js +2 -2
- package/routes/list.js +4 -4
- package/routes/page.js +16 -3
- package/routes/pageedit.js +22 -14
- package/routes/scapi.js +1 -1
- package/routes/search.js +1 -1
- package/routes/tables.js +4 -5
- package/routes/tag_entries.js +31 -10
- package/routes/tags.js +36 -32
- package/routes/tenant.js +98 -36
- package/routes/utils.js +72 -20
- package/routes/view.js +0 -1
- package/routes/viewedit.js +55 -22
- package/serve.js +5 -0
- package/tests/admin.test.js +2 -0
- package/tests/auth.test.js +20 -0
- package/tests/files.test.js +11 -20
- package/tests/tenant.test.js +4 -2
package/routes/tag_entries.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
const {
|
|
2
|
-
a,
|
|
3
2
|
div,
|
|
4
|
-
text,
|
|
5
3
|
button,
|
|
6
|
-
i,
|
|
7
4
|
form,
|
|
8
5
|
select,
|
|
9
6
|
option,
|
|
@@ -81,10 +78,10 @@ const formOptions = async (type, tag_id) => {
|
|
|
81
78
|
),
|
|
82
79
|
};
|
|
83
80
|
}
|
|
84
|
-
case "
|
|
81
|
+
case "triggers": {
|
|
85
82
|
const ids = await tag.getTriggerIds();
|
|
86
83
|
return {
|
|
87
|
-
|
|
84
|
+
triggers: (Trigger.find()).filter(
|
|
88
85
|
(value) => ids.indexOf(value.id) === -1
|
|
89
86
|
),
|
|
90
87
|
};
|
|
@@ -101,7 +98,7 @@ router.get(
|
|
|
101
98
|
above: [
|
|
102
99
|
{
|
|
103
100
|
type: "breadcrumbs",
|
|
104
|
-
crumbs: [{ text: `Tag entry` }],
|
|
101
|
+
crumbs: [{ text: req.__(`Tag entry`) }],
|
|
105
102
|
},
|
|
106
103
|
{
|
|
107
104
|
type: "card",
|
|
@@ -120,15 +117,19 @@ router.get(
|
|
|
120
117
|
|
|
121
118
|
const idField = (entryType) => {
|
|
122
119
|
switch (entryType) {
|
|
123
|
-
case "tables":
|
|
120
|
+
case "tables":
|
|
121
|
+
case "table": {
|
|
124
122
|
return "table_id";
|
|
125
123
|
}
|
|
126
|
-
case "views":
|
|
124
|
+
case "views":
|
|
125
|
+
case "view": {
|
|
127
126
|
return "view_id";
|
|
128
127
|
}
|
|
129
|
-
case "pages":
|
|
128
|
+
case "pages":
|
|
129
|
+
case "page": {
|
|
130
130
|
return "page_id";
|
|
131
131
|
}
|
|
132
|
+
case "triggers":
|
|
132
133
|
case "trigger": {
|
|
133
134
|
return "trigger_id";
|
|
134
135
|
}
|
|
@@ -136,6 +137,7 @@ const idField = (entryType) => {
|
|
|
136
137
|
return null;
|
|
137
138
|
};
|
|
138
139
|
|
|
140
|
+
// add multiple objects to one tag
|
|
139
141
|
router.post(
|
|
140
142
|
"/add/:entry_type/:tag_id",
|
|
141
143
|
isAdmin,
|
|
@@ -155,6 +157,24 @@ router.post(
|
|
|
155
157
|
})
|
|
156
158
|
);
|
|
157
159
|
|
|
160
|
+
// add one object to multiple tags
|
|
161
|
+
router.post(
|
|
162
|
+
"/add/multiple_tags/:entry_type/:object_id",
|
|
163
|
+
isAdmin,
|
|
164
|
+
error_catcher(async (req, res) => {
|
|
165
|
+
let { entry_type, object_id } = req.params;
|
|
166
|
+
let { tag_ids } = req.body;
|
|
167
|
+
object_id = parseInt(object_id);
|
|
168
|
+
tag_ids = tag_ids.map((id) => parseInt(id));
|
|
169
|
+
const tags = (await Tag.find()).filter((tag) => tag_ids.includes(tag.id));
|
|
170
|
+
const fieldName = idField(entry_type);
|
|
171
|
+
for (const tag of tags) {
|
|
172
|
+
await tag.addEntry({ [fieldName]: object_id });
|
|
173
|
+
}
|
|
174
|
+
res.json({ tags });
|
|
175
|
+
})
|
|
176
|
+
);
|
|
177
|
+
|
|
158
178
|
router.post(
|
|
159
179
|
"/remove/:entry_type/:entry_id/:tag_id",
|
|
160
180
|
isAdmin,
|
|
@@ -168,6 +188,7 @@ router.post(
|
|
|
168
188
|
} else {
|
|
169
189
|
await TagEntry.update(entry.id, { [fieldName]: null });
|
|
170
190
|
}
|
|
171
|
-
res.redirect(`/tag/${tag_id}?show_list=${entry_type}`);
|
|
191
|
+
if (!req.xhr) res.redirect(`/tag/${tag_id}?show_list=${entry_type}`);
|
|
192
|
+
else res.json({ okay: true });
|
|
172
193
|
})
|
|
173
194
|
);
|
package/routes/tags.js
CHANGED
|
@@ -35,30 +35,34 @@ router.get(
|
|
|
35
35
|
res,
|
|
36
36
|
req,
|
|
37
37
|
active_sub: "Tags",
|
|
38
|
-
contents:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
contents: {
|
|
39
|
+
type: "card",
|
|
40
|
+
title: req.__("Tags"),
|
|
41
|
+
contents: [
|
|
42
|
+
mkTable(
|
|
43
|
+
[
|
|
44
|
+
{
|
|
45
|
+
label: req.__("Tagname"),
|
|
46
|
+
key: (r) =>
|
|
47
|
+
link(`/tag/${r.id || r.name}?show_list=tables`, text(r.name)),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
label: req.__("Delete"),
|
|
51
|
+
key: (r) => post_delete_btn(`/tag/delete/${r.id}`, req, r.name),
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
rows,
|
|
55
|
+
{}
|
|
56
|
+
),
|
|
57
|
+
a(
|
|
46
58
|
{
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
href: `/tag/new`,
|
|
60
|
+
class: "btn btn-primary",
|
|
49
61
|
},
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
a(
|
|
55
|
-
{
|
|
56
|
-
href: `/tag/new`,
|
|
57
|
-
class: "btn btn-primary",
|
|
58
|
-
},
|
|
59
|
-
req.__("Create tag")
|
|
60
|
-
),
|
|
61
|
-
],
|
|
62
|
+
req.__("Create tag")
|
|
63
|
+
),
|
|
64
|
+
],
|
|
65
|
+
},
|
|
62
66
|
});
|
|
63
67
|
})
|
|
64
68
|
);
|
|
@@ -124,18 +128,18 @@ router.get(
|
|
|
124
128
|
const views = await tag.getViews();
|
|
125
129
|
await setTableRefs(views);
|
|
126
130
|
const pages = await tag.getPages();
|
|
127
|
-
const
|
|
131
|
+
const triggers = await tag.getTriggers();
|
|
128
132
|
const roles = await User.get_roles();
|
|
129
133
|
|
|
130
134
|
const tablesDomId = "tablesListId";
|
|
131
135
|
const viewsDomId = "viewsListId";
|
|
132
136
|
const pagesDomId = "pagesDomId";
|
|
133
|
-
const
|
|
137
|
+
const triggersDomId = "triggerDomId";
|
|
134
138
|
res.sendWrap(req.__("%s Tag", tag.name), {
|
|
135
139
|
above: [
|
|
136
140
|
{
|
|
137
141
|
type: "breadcrumbs",
|
|
138
|
-
crumbs: [{ text: `Tag:
|
|
142
|
+
crumbs: [{ text: req.__(`Tag: %s`, tag.name) }],
|
|
139
143
|
},
|
|
140
144
|
{
|
|
141
145
|
type: "card",
|
|
@@ -207,19 +211,19 @@ router.get(
|
|
|
207
211
|
type: "card",
|
|
208
212
|
bodyId: "collapseTriggerCard",
|
|
209
213
|
title: headerWithCollapser(
|
|
210
|
-
req.__("
|
|
211
|
-
|
|
212
|
-
isShowList(show_list, "
|
|
214
|
+
req.__("Triggers"),
|
|
215
|
+
triggersDomId,
|
|
216
|
+
isShowList(show_list, "triggers")
|
|
213
217
|
),
|
|
214
218
|
contents: [
|
|
215
|
-
getTriggerList(
|
|
219
|
+
getTriggerList(triggers, req, {
|
|
216
220
|
tagId: tag.id,
|
|
217
|
-
domId:
|
|
218
|
-
showList: isShowList(show_list, "
|
|
221
|
+
domId: triggersDomId,
|
|
222
|
+
showList: isShowList(show_list, "triggers"),
|
|
219
223
|
}),
|
|
220
224
|
a(
|
|
221
225
|
{
|
|
222
|
-
href: `/tag-entries/add/
|
|
226
|
+
href: `/tag-entries/add/triggers/${tag.id}`,
|
|
223
227
|
class: "btn btn-primary",
|
|
224
228
|
},
|
|
225
229
|
req.__("Add triggers")
|
package/routes/tenant.js
CHANGED
|
@@ -8,13 +8,14 @@
|
|
|
8
8
|
const Router = require("express-promise-router");
|
|
9
9
|
const Form = require("@saltcorn/data/models/form");
|
|
10
10
|
const { getState, add_tenant } = require("@saltcorn/data/db/state");
|
|
11
|
-
const { create_tenant } = require("@saltcorn/admin-models/models/tenant");
|
|
12
11
|
const {
|
|
12
|
+
create_tenant,
|
|
13
13
|
getAllTenants,
|
|
14
14
|
domain_sanitize,
|
|
15
15
|
deleteTenant,
|
|
16
16
|
switchToTenant,
|
|
17
17
|
insertTenant,
|
|
18
|
+
Tenant,
|
|
18
19
|
} = require("@saltcorn/admin-models/models/tenant");
|
|
19
20
|
const {
|
|
20
21
|
renderForm,
|
|
@@ -24,7 +25,6 @@ const {
|
|
|
24
25
|
} = require("@saltcorn/markup");
|
|
25
26
|
const {
|
|
26
27
|
div,
|
|
27
|
-
nbsp,
|
|
28
28
|
p,
|
|
29
29
|
a,
|
|
30
30
|
h4,
|
|
@@ -87,6 +87,11 @@ const tenant_form = (req) =>
|
|
|
87
87
|
input_type: "text",
|
|
88
88
|
postText: text(req.hostname),
|
|
89
89
|
},
|
|
90
|
+
{
|
|
91
|
+
name: "description",
|
|
92
|
+
label: req.__("Description"),
|
|
93
|
+
input_type: "text",
|
|
94
|
+
},
|
|
90
95
|
],
|
|
91
96
|
});
|
|
92
97
|
|
|
@@ -148,37 +153,49 @@ router.get(
|
|
|
148
153
|
"You are trying to create a tenant while connecting via an IP address rather than a domain. This will probably not work."
|
|
149
154
|
)
|
|
150
155
|
);
|
|
151
|
-
let
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
156
|
+
let create_tenant_warning_text = "";
|
|
157
|
+
if (getState().getConfig("create_tenant_warning")) {
|
|
158
|
+
create_tenant_warning_text = getState().getConfig("create_tenant_warning_text");
|
|
159
|
+
if (create_tenant_warning_text && create_tenant_warning_text.length > 0)
|
|
160
|
+
create_tenant_warning_text = div(
|
|
161
|
+
{
|
|
162
|
+
class: "alert alert-warning alert-dismissible fade show mt-5",
|
|
163
|
+
role: "alert",
|
|
164
|
+
},
|
|
165
|
+
h4(req.__("Warning")),
|
|
166
|
+
p( create_tenant_warning_text
|
|
167
|
+
)
|
|
168
|
+
);
|
|
169
|
+
else
|
|
170
|
+
create_tenant_warning_text = div(
|
|
171
|
+
{
|
|
172
|
+
class: "alert alert-warning alert-dismissible fade show mt-5",
|
|
173
|
+
role: "alert",
|
|
174
|
+
},
|
|
175
|
+
h4(req.__("Warning")),
|
|
176
|
+
p(
|
|
177
|
+
req.__(
|
|
178
|
+
"Hosting on this site is provided for free and with no guarantee of availability or security of your application. "
|
|
179
|
+
) +
|
|
180
|
+
" " +
|
|
181
|
+
req.__(
|
|
182
|
+
"This facility is intended solely for you to evaluate the suitability of Saltcorn. "
|
|
183
|
+
) +
|
|
184
|
+
" " +
|
|
185
|
+
req.__(
|
|
186
|
+
"If you would like to store private information that needs to be secure, please use self-hosted Saltcorn. "
|
|
187
|
+
) +
|
|
188
|
+
" " +
|
|
189
|
+
req.__(
|
|
190
|
+
'See <a href="https://github.com/saltcorn/saltcorn">GitHub repository</a> for instructions<p>'
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
);
|
|
194
|
+
}
|
|
178
195
|
|
|
179
196
|
res.sendWrap(
|
|
180
197
|
req.__("Create application"),
|
|
181
|
-
|
|
198
|
+
create_tenant_warning_text +
|
|
182
199
|
renderForm(tenant_form(req), req.csrfToken()) +
|
|
183
200
|
p(
|
|
184
201
|
{ class: "mt-2" },
|
|
@@ -246,6 +263,8 @@ router.post(
|
|
|
246
263
|
else {
|
|
247
264
|
// normalize domain name
|
|
248
265
|
const subdomain = domain_sanitize(valres.success.subdomain);
|
|
266
|
+
// get description
|
|
267
|
+
const description = valres.success.description;
|
|
249
268
|
// get list of tenants
|
|
250
269
|
const allTens = await getAllTenants();
|
|
251
270
|
if (allTens.includes(subdomain) || !subdomain) {
|
|
@@ -258,9 +277,15 @@ router.post(
|
|
|
258
277
|
renderForm(form, req.csrfToken())
|
|
259
278
|
);
|
|
260
279
|
} else {
|
|
280
|
+
// tenant url
|
|
261
281
|
const newurl = getNewURL(req, subdomain);
|
|
282
|
+
// tenant template
|
|
262
283
|
const tenant_template = getState().getConfig("tenant_template");
|
|
263
|
-
|
|
284
|
+
// tenant creator
|
|
285
|
+
const user_email = req.user && req.user.email;
|
|
286
|
+
// switch to tenant
|
|
287
|
+
await switchToTenant(await insertTenant(subdomain, user_email, description, tenant_template), newurl);
|
|
288
|
+
// add tenant to global state
|
|
264
289
|
add_tenant(subdomain);
|
|
265
290
|
await create_tenant({
|
|
266
291
|
t: subdomain,
|
|
@@ -348,6 +373,15 @@ router.get(
|
|
|
348
373
|
{
|
|
349
374
|
label: req.__("Description"),
|
|
350
375
|
key: (r) => text(r.description),
|
|
376
|
+
//blurb: req.__("Specify some description for tenant if need"),
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
label: req.__("Creator email"),
|
|
380
|
+
key: (r) => text(r.email),
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
label: req.__("Created"),
|
|
384
|
+
key: (r) => text(r.created),
|
|
351
385
|
},
|
|
352
386
|
{
|
|
353
387
|
label: req.__("Information"),
|
|
@@ -387,6 +421,7 @@ const tenant_settings_form = (req) =>
|
|
|
387
421
|
field_names: [
|
|
388
422
|
"role_to_create_tenant",
|
|
389
423
|
"create_tenant_warning",
|
|
424
|
+
"create_tenant_warning_text",
|
|
390
425
|
"tenant_template",
|
|
391
426
|
],
|
|
392
427
|
action: "/tenant/settings",
|
|
@@ -468,8 +503,19 @@ router.post(
|
|
|
468
503
|
const get_tenant_info = async (subdomain) => {
|
|
469
504
|
const saneDomain = domain_sanitize(subdomain);
|
|
470
505
|
|
|
506
|
+
let info = {};
|
|
507
|
+
|
|
508
|
+
// get tenant row
|
|
509
|
+
const ten = await Tenant.findOne({ subdomain: saneDomain });
|
|
510
|
+
if (ten) {
|
|
511
|
+
info.description = ten.description;
|
|
512
|
+
info.created = ten.created;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
// get data from tenant schema
|
|
471
517
|
return await db.runWithTenant(saneDomain, async () => {
|
|
472
|
-
|
|
518
|
+
|
|
473
519
|
// TBD fix the first user issue because not always firt user by id is creator of tenant
|
|
474
520
|
const firstUser = await User.find({}, { orderBy: "id", limit: 1 });
|
|
475
521
|
if (firstUser && firstUser.length > 0) {
|
|
@@ -497,7 +543,11 @@ const get_tenant_info = async (subdomain) => {
|
|
|
497
543
|
info.nconfigs = await db.count("_sc_config");
|
|
498
544
|
// plugins count
|
|
499
545
|
info.nplugins = await db.count("_sc_plugins");
|
|
500
|
-
//
|
|
546
|
+
// migration count
|
|
547
|
+
info.nmigrations = await db.count("_sc_migrations");
|
|
548
|
+
// library count
|
|
549
|
+
info.nlibrary = await db.count("_sc_library");
|
|
550
|
+
// TBD decide Do we need count tenants, table constraints
|
|
501
551
|
// base url
|
|
502
552
|
info.base_url = await getConfig("base_url");
|
|
503
553
|
return info;
|
|
@@ -525,6 +575,7 @@ router.get(
|
|
|
525
575
|
return;
|
|
526
576
|
}
|
|
527
577
|
const { subdomain } = req.params;
|
|
578
|
+
// get tenant info
|
|
528
579
|
const info = await get_tenant_info(subdomain);
|
|
529
580
|
// get list of files
|
|
530
581
|
let files;
|
|
@@ -545,7 +596,7 @@ router.get(
|
|
|
545
596
|
contents: [
|
|
546
597
|
table(
|
|
547
598
|
tr(
|
|
548
|
-
th(req.__("E-mail")),
|
|
599
|
+
th(req.__("First user E-mail")),
|
|
549
600
|
td(
|
|
550
601
|
a(
|
|
551
602
|
{ href: "mailto:" + info.first_user_email },
|
|
@@ -616,8 +667,13 @@ router.get(
|
|
|
616
667
|
label: req.__("Base URL"),
|
|
617
668
|
type: "String",
|
|
618
669
|
},
|
|
670
|
+
{
|
|
671
|
+
name: "description",
|
|
672
|
+
label: req.__("Description"),
|
|
673
|
+
type: "String",
|
|
674
|
+
},
|
|
619
675
|
],
|
|
620
|
-
values: { base_url: info.base_url },
|
|
676
|
+
values: { base_url: info.base_url, description: info.description },
|
|
621
677
|
}),
|
|
622
678
|
req.csrfToken()
|
|
623
679
|
),
|
|
@@ -673,6 +729,12 @@ router.post(
|
|
|
673
729
|
const { base_url } = req.body;
|
|
674
730
|
const saneDomain = domain_sanitize(subdomain);
|
|
675
731
|
|
|
732
|
+
// save description
|
|
733
|
+
const { description } = req.body;
|
|
734
|
+
await Tenant.update( saneDomain, {description: description});
|
|
735
|
+
|
|
736
|
+
|
|
737
|
+
|
|
676
738
|
await db.runWithTenant(saneDomain, async () => {
|
|
677
739
|
await getState().setConfig("base_url", base_url);
|
|
678
740
|
});
|
|
@@ -701,7 +763,7 @@ router.post(
|
|
|
701
763
|
return;
|
|
702
764
|
}
|
|
703
765
|
const { sub } = req.params;
|
|
704
|
-
|
|
766
|
+
// todo warning before deletion
|
|
705
767
|
await deleteTenant(sub);
|
|
706
768
|
res.redirect(`/tenant/list`);
|
|
707
769
|
})
|
package/routes/utils.js
CHANGED
|
@@ -20,6 +20,8 @@ const { validateHeaderName, validateHeaderValue } = require("http");
|
|
|
20
20
|
const Crash = require("@saltcorn/data/models/crash");
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
+
* Checks that user logged or not.
|
|
24
|
+
* If not shows than shows flash and redirects to login
|
|
23
25
|
* @param {object} req
|
|
24
26
|
* @param {object} res
|
|
25
27
|
* @param {function} next
|
|
@@ -35,6 +37,8 @@ function loggedIn(req, res, next) {
|
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
/**
|
|
40
|
+
* Checks that user has admin role or not.
|
|
41
|
+
* If user hasn't admin role shows flash and redirects user to login or totp
|
|
38
42
|
* @param {object} req
|
|
39
43
|
* @param {object} res
|
|
40
44
|
* @param {function} next
|
|
@@ -60,6 +64,7 @@ function isAdmin(req, res, next) {
|
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
/**
|
|
67
|
+
* Sets language for HTTP Request / HTTP Responce
|
|
63
68
|
* @param {object} req
|
|
64
69
|
* @param {object} res
|
|
65
70
|
* @param {string} state
|
|
@@ -73,6 +78,7 @@ const setLanguage = (req, res, state) => {
|
|
|
73
78
|
};
|
|
74
79
|
|
|
75
80
|
/**
|
|
81
|
+
* Sets Custom HTTP headers using data from "custom_http_headers" config variable
|
|
76
82
|
* @param {object} res
|
|
77
83
|
* @param {string} state
|
|
78
84
|
* @returns {void}
|
|
@@ -96,6 +102,7 @@ const set_custom_http_headers = (res, state) => {
|
|
|
96
102
|
};
|
|
97
103
|
|
|
98
104
|
/**
|
|
105
|
+
* Tries to recognize tenant from HTTP Request
|
|
99
106
|
* @param {object} req
|
|
100
107
|
* @returns {string}
|
|
101
108
|
*/
|
|
@@ -113,37 +120,62 @@ const get_tenant_from_req = (req) => {
|
|
|
113
120
|
};
|
|
114
121
|
|
|
115
122
|
/**
|
|
123
|
+
* middleware to extract the tenant domain and call runWithtenant()
|
|
116
124
|
* @param {object} req
|
|
117
125
|
* @param {object} res
|
|
118
126
|
* @param {function} next
|
|
119
127
|
*/
|
|
120
128
|
const setTenant = (req, res, next) => {
|
|
121
129
|
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}`);
|
|
130
|
+
// for a saltcorn mobile request use 'req.user.tenant'
|
|
131
|
+
if (req.smr) {
|
|
132
|
+
if (
|
|
133
|
+
req.user?.tenant &&
|
|
134
|
+
req.user.tenant !== db.connectObj.default_schema
|
|
135
|
+
) {
|
|
136
|
+
const state = getTenant(req.user.tenant);
|
|
137
|
+
if (!state) {
|
|
138
|
+
setLanguage(req, res);
|
|
132
139
|
next();
|
|
133
|
-
}
|
|
140
|
+
} else {
|
|
141
|
+
db.runWithTenant(req.user.tenant, () => {
|
|
142
|
+
setLanguage(req, res, state);
|
|
143
|
+
state.log(5, `${req.method} ${req.originalUrl}`);
|
|
144
|
+
next();
|
|
145
|
+
});
|
|
146
|
+
}
|
|
134
147
|
}
|
|
135
|
-
|
|
136
|
-
const ten = get_tenant_from_req(req);
|
|
137
|
-
const state = getTenant(ten);
|
|
138
|
-
if (!state) {
|
|
148
|
+
else {
|
|
139
149
|
setLanguage(req, res);
|
|
140
150
|
next();
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
const other_domain = get_other_domain_tenant(req.hostname);
|
|
154
|
+
if (other_domain) {
|
|
155
|
+
const state = getTenant(other_domain);
|
|
156
|
+
if (!state) {
|
|
157
|
+
setLanguage(req, res);
|
|
158
|
+
next();
|
|
159
|
+
} else {
|
|
160
|
+
db.runWithTenant(other_domain, () => {
|
|
161
|
+
setLanguage(req, res, state);
|
|
162
|
+
state.log(5, `${req.method} ${req.originalUrl}`);
|
|
163
|
+
next();
|
|
164
|
+
});
|
|
165
|
+
}
|
|
141
166
|
} else {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
167
|
+
const ten = get_tenant_from_req(req);
|
|
168
|
+
const state = getTenant(ten);
|
|
169
|
+
if (!state) {
|
|
170
|
+
setLanguage(req, res);
|
|
145
171
|
next();
|
|
146
|
-
}
|
|
172
|
+
} else {
|
|
173
|
+
db.runWithTenant(ten, () => {
|
|
174
|
+
setLanguage(req, res, state);
|
|
175
|
+
state.log(5, `${req.method} ${req.originalUrl}`);
|
|
176
|
+
next();
|
|
177
|
+
});
|
|
178
|
+
}
|
|
147
179
|
}
|
|
148
180
|
}
|
|
149
181
|
} else {
|
|
@@ -154,6 +186,7 @@ const setTenant = (req, res, next) => {
|
|
|
154
186
|
};
|
|
155
187
|
|
|
156
188
|
/**
|
|
189
|
+
* Injects hidden input "_csrf" for CSRF token
|
|
157
190
|
* @param {object} req
|
|
158
191
|
* @returns {input}
|
|
159
192
|
*/
|
|
@@ -165,6 +198,7 @@ const csrfField = (req) =>
|
|
|
165
198
|
});
|
|
166
199
|
|
|
167
200
|
/**
|
|
201
|
+
* Errors catcher
|
|
168
202
|
* @param {function} fn
|
|
169
203
|
* @returns {function}
|
|
170
204
|
*/
|
|
@@ -173,6 +207,7 @@ const error_catcher = (fn) => (request, response, next) => {
|
|
|
173
207
|
};
|
|
174
208
|
|
|
175
209
|
/**
|
|
210
|
+
* Scans for page title from contents
|
|
176
211
|
* @param {string|object} contents
|
|
177
212
|
* @param {string} viewname
|
|
178
213
|
* @returns {string}
|
|
@@ -193,11 +228,13 @@ const scan_for_page_title = (contents, viewname) => {
|
|
|
193
228
|
};
|
|
194
229
|
|
|
195
230
|
/**
|
|
231
|
+
* Gets gir revision
|
|
196
232
|
* @returns {string}
|
|
197
233
|
*/
|
|
198
234
|
const getGitRevision = () => db.connectObj.git_commit;
|
|
199
235
|
|
|
200
236
|
/**
|
|
237
|
+
* Gets session store
|
|
201
238
|
* @returns {session|cookieSession}
|
|
202
239
|
*/
|
|
203
240
|
const getSessionStore = () => {
|
|
@@ -232,6 +269,20 @@ const getSessionStore = () => {
|
|
|
232
269
|
}
|
|
233
270
|
};
|
|
234
271
|
|
|
272
|
+
/**
|
|
273
|
+
* appends 'req.query.on_done_redirect' to 'oldPath' if it exists
|
|
274
|
+
* @param {string} oldPath path without 'on_done_redirect'
|
|
275
|
+
* @param {any} req express request
|
|
276
|
+
* @returns a new string with or without on_done_redirect=...
|
|
277
|
+
*/
|
|
278
|
+
const addOnDoneRedirect = (oldPath, req) => {
|
|
279
|
+
const separator = oldPath.indexOf("?") > -1 ? "&" : "?";
|
|
280
|
+
if (req.query.on_done_redirect) {
|
|
281
|
+
return `${oldPath}${separator}on_done_redirect=${req.query.on_done_redirect}`;
|
|
282
|
+
}
|
|
283
|
+
return oldPath;
|
|
284
|
+
};
|
|
285
|
+
|
|
235
286
|
module.exports = {
|
|
236
287
|
sqlsanitize,
|
|
237
288
|
csrfField,
|
|
@@ -243,5 +294,6 @@ module.exports = {
|
|
|
243
294
|
getGitRevision,
|
|
244
295
|
getSessionStore,
|
|
245
296
|
setTenant,
|
|
246
|
-
get_tenant_from_req
|
|
297
|
+
get_tenant_from_req,
|
|
298
|
+
addOnDoneRedirect,
|
|
247
299
|
};
|
package/routes/view.js
CHANGED
|
@@ -8,7 +8,6 @@ const Router = require("express-promise-router");
|
|
|
8
8
|
|
|
9
9
|
const View = require("@saltcorn/data/models/view");
|
|
10
10
|
const Table = require("@saltcorn/data/models/table");
|
|
11
|
-
const Page = require("@saltcorn/data/models/page");
|
|
12
11
|
|
|
13
12
|
const { div, text, i, a } = require("@saltcorn/markup/tags");
|
|
14
13
|
const { renderForm, link } = require("@saltcorn/markup");
|