@saltcorn/server 0.6.3-beta.2 → 0.6.4-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/app.js +15 -3
- package/auth/roleadmin.js +50 -0
- package/auth/routes.js +229 -3
- package/locales/en.json +19 -1
- package/package.json +14 -7
- package/public/gridedit.js +6 -2
- package/public/saltcorn.js +71 -9
- package/restart_watcher.js +4 -1
- package/routes/admin.js +10 -3
- package/routes/api.js +28 -20
- package/routes/delete.js +1 -1
- package/routes/edit.js +1 -1
- package/routes/fields.js +42 -3
- package/routes/files.js +5 -4
- package/routes/homepage.js +3 -3
- package/routes/list.js +4 -0
- package/routes/packs.js +1 -1
- package/routes/page.js +2 -2
- package/routes/pageedit.js +7 -4
- package/routes/plugins.js +1 -1
- package/routes/scapi.js +7 -6
- package/routes/tables.js +3 -1
- package/routes/tenant.js +19 -9
- package/routes/utils.js +7 -1
- package/routes/view.js +5 -4
- package/routes/viewedit.js +1 -1
- package/serve.js +38 -30
- package/wrapper.js +1 -1
package/routes/admin.js
CHANGED
|
@@ -5,14 +5,19 @@
|
|
|
5
5
|
*/
|
|
6
6
|
const Router = require("express-promise-router");
|
|
7
7
|
|
|
8
|
-
const {
|
|
8
|
+
const {
|
|
9
|
+
isAdmin,
|
|
10
|
+
error_catcher,
|
|
11
|
+
getGitRevision,
|
|
12
|
+
setTenant,
|
|
13
|
+
} = require("./utils.js");
|
|
9
14
|
const Table = require("@saltcorn/data/models/table");
|
|
10
15
|
const Plugin = require("@saltcorn/data/models/plugin");
|
|
11
16
|
const File = require("@saltcorn/data/models/file");
|
|
12
17
|
const { spawn } = require("child_process");
|
|
13
18
|
const User = require("@saltcorn/data/models/user");
|
|
14
19
|
const path = require("path");
|
|
15
|
-
const { getAllTenants } = require("@saltcorn/
|
|
20
|
+
const { getAllTenants } = require("@saltcorn/admin-models/models/tenant");
|
|
16
21
|
const { post_btn, renderForm } = require("@saltcorn/markup");
|
|
17
22
|
const {
|
|
18
23
|
div,
|
|
@@ -41,7 +46,7 @@ const {
|
|
|
41
46
|
get_process_init_time,
|
|
42
47
|
} = require("@saltcorn/data/db/state");
|
|
43
48
|
const { loadAllPlugins } = require("../load_plugins");
|
|
44
|
-
const { create_backup, restore } = require("@saltcorn/
|
|
49
|
+
const { create_backup, restore } = require("@saltcorn/admin-models/models/backup");
|
|
45
50
|
const fs = require("fs");
|
|
46
51
|
const load_plugins = require("../load_plugins");
|
|
47
52
|
const {
|
|
@@ -518,6 +523,7 @@ router.post(
|
|
|
518
523
|
*/
|
|
519
524
|
router.post(
|
|
520
525
|
"/restore",
|
|
526
|
+
setTenant, // TODO why is this needed?????
|
|
521
527
|
isAdmin,
|
|
522
528
|
error_catcher(async (req, res) => {
|
|
523
529
|
const newPath = File.get_new_path();
|
|
@@ -769,6 +775,7 @@ router.post(
|
|
|
769
775
|
for (const file of files) {
|
|
770
776
|
await file.delete();
|
|
771
777
|
}
|
|
778
|
+
if (db.reset_sequence) await db.reset_sequence("_sc_files");
|
|
772
779
|
}
|
|
773
780
|
if (form.values.plugins) {
|
|
774
781
|
const ps = await Plugin.find();
|
package/routes/api.js
CHANGED
|
@@ -28,6 +28,7 @@ const passport = require("passport");
|
|
|
28
28
|
const {
|
|
29
29
|
stateFieldsToWhere,
|
|
30
30
|
readState,
|
|
31
|
+
strictParseInt,
|
|
31
32
|
} = require("@saltcorn/data/plugin-helper");
|
|
32
33
|
|
|
33
34
|
/**
|
|
@@ -65,11 +66,12 @@ const limitFields = (fields) => (r) => {
|
|
|
65
66
|
* @returns {boolean}
|
|
66
67
|
*/
|
|
67
68
|
function accessAllowedRead(req, user, table) {
|
|
68
|
-
const role =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
const role =
|
|
70
|
+
req.user && req.user.id
|
|
71
|
+
? req.user.role_id
|
|
72
|
+
: user && user.role_id
|
|
73
|
+
? user.role_id
|
|
74
|
+
: 10;
|
|
73
75
|
|
|
74
76
|
return role <= table.min_role_read;
|
|
75
77
|
}
|
|
@@ -82,11 +84,12 @@ function accessAllowedRead(req, user, table) {
|
|
|
82
84
|
* @returns {boolean}
|
|
83
85
|
*/
|
|
84
86
|
function accessAllowedWrite(req, user, table) {
|
|
85
|
-
const role =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
const role =
|
|
88
|
+
req.user && req.user.id
|
|
89
|
+
? req.user.role_id
|
|
90
|
+
: user && user.role_id
|
|
91
|
+
? user.role_id
|
|
92
|
+
: 10;
|
|
90
93
|
|
|
91
94
|
return role <= table.min_role_write;
|
|
92
95
|
}
|
|
@@ -98,11 +101,12 @@ function accessAllowedWrite(req, user, table) {
|
|
|
98
101
|
* @returns {boolean}
|
|
99
102
|
*/
|
|
100
103
|
function accessAllowed(req, user, trigger) {
|
|
101
|
-
const role =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
const role =
|
|
105
|
+
req.user && req.user.id
|
|
106
|
+
? req.user.role_id
|
|
107
|
+
: user && user.role_id
|
|
108
|
+
? user.role_id
|
|
109
|
+
: 10;
|
|
106
110
|
|
|
107
111
|
return role <= trigger.min_role;
|
|
108
112
|
}
|
|
@@ -118,9 +122,13 @@ router.get(
|
|
|
118
122
|
"/:tableName/",
|
|
119
123
|
//passport.authenticate("api-bearer", { session: false }),
|
|
120
124
|
error_catcher(async (req, res, next) => {
|
|
121
|
-
|
|
122
|
-
const { fields, versioncount, ...req_query } = req.query;
|
|
123
|
-
const table = await Table.findOne(
|
|
125
|
+
let { tableName } = req.params;
|
|
126
|
+
const { fields, versioncount, approximate, ...req_query } = req.query;
|
|
127
|
+
const table = await Table.findOne(
|
|
128
|
+
strictParseInt(tableName)
|
|
129
|
+
? { id: strictParseInt(tableName) }
|
|
130
|
+
: { name: tableName }
|
|
131
|
+
);
|
|
124
132
|
if (!table) {
|
|
125
133
|
res.status(404).json({ error: req.__("Not found") });
|
|
126
134
|
return;
|
|
@@ -149,8 +157,8 @@ router.get(
|
|
|
149
157
|
const tbl_fields = await table.getFields();
|
|
150
158
|
const qstate = await stateFieldsToWhere({
|
|
151
159
|
fields: tbl_fields,
|
|
152
|
-
approximate:
|
|
153
|
-
state:
|
|
160
|
+
approximate: !!approximate,
|
|
161
|
+
state: req_query,
|
|
154
162
|
});
|
|
155
163
|
rows = await table.getRows(qstate);
|
|
156
164
|
} else {
|
package/routes/delete.js
CHANGED
|
@@ -33,7 +33,7 @@ router.post(
|
|
|
33
33
|
const { name, id } = req.params;
|
|
34
34
|
const { redirect } = req.query;
|
|
35
35
|
const table = await Table.findOne({ name });
|
|
36
|
-
const role = req.
|
|
36
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
37
37
|
try {
|
|
38
38
|
if (role <= table.min_role_write) await table.deleteRows({ id });
|
|
39
39
|
else if (table.ownership_field_id && req.user) {
|
package/routes/edit.js
CHANGED
|
@@ -37,7 +37,7 @@ router.post(
|
|
|
37
37
|
const { name, id, field_name } = req.params;
|
|
38
38
|
const { redirect } = req.query;
|
|
39
39
|
const table = await Table.findOne({ name });
|
|
40
|
-
const role = req.
|
|
40
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
41
41
|
if (role <= table.min_role_write) await table.toggleBool(+id, field_name);
|
|
42
42
|
else
|
|
43
43
|
req.flash(
|
package/routes/fields.js
CHANGED
|
@@ -26,6 +26,8 @@ const { isAdmin, error_catcher } = require("./utils.js");
|
|
|
26
26
|
const expressionBlurb = require("../markup/expression_blurb");
|
|
27
27
|
const { readState } = require("@saltcorn/data/plugin-helper");
|
|
28
28
|
const { wizardCardTitle } = require("../markup/forms.js");
|
|
29
|
+
const FieldRepeat = require("@saltcorn/data/models/fieldrepeat");
|
|
30
|
+
const { applyAsync } = require("@saltcorn/data/utils");
|
|
29
31
|
|
|
30
32
|
/**
|
|
31
33
|
* @type {object}
|
|
@@ -161,8 +163,9 @@ const translateAttributes = (attrs, req) =>
|
|
|
161
163
|
* @returns {object}
|
|
162
164
|
*/
|
|
163
165
|
const translateAttribute = (attr, req) => {
|
|
164
|
-
|
|
166
|
+
let res = { ...attr };
|
|
165
167
|
if (res.sublabel) res.sublabel = req.__(res.sublabel);
|
|
168
|
+
if (res.isRepeat) res = new FieldRepeat(res);
|
|
166
169
|
return res;
|
|
167
170
|
};
|
|
168
171
|
|
|
@@ -622,10 +625,38 @@ router.post(
|
|
|
622
625
|
const { tableName, fieldName, fieldview } = req.params;
|
|
623
626
|
const table = await Table.findOne({ name: tableName });
|
|
624
627
|
const fields = await table.getFields();
|
|
625
|
-
const field = fields.find((f) => f.name === fieldName);
|
|
626
|
-
const formula = field.expression;
|
|
627
628
|
const row = { ...req.body };
|
|
628
629
|
readState(row, fields);
|
|
630
|
+
|
|
631
|
+
if (fieldName.includes(".")) {
|
|
632
|
+
//join field
|
|
633
|
+
const kpath = fieldName.split(".");
|
|
634
|
+
|
|
635
|
+
if (kpath.length === 2 && row[kpath[0]]) {
|
|
636
|
+
const field = fields.find((f) => f.name === kpath[0]);
|
|
637
|
+
const reftable = await Table.findOne({ name: field.reftable_name });
|
|
638
|
+
const targetField = (await reftable.getFields()).find(
|
|
639
|
+
(f) => f.name === kpath[1]
|
|
640
|
+
);
|
|
641
|
+
const fv = targetField.type.fieldviews[fieldview];
|
|
642
|
+
const q = { [reftable.pk_name]: row[kpath[0]] };
|
|
643
|
+
const refRow = await reftable.getRow(q);
|
|
644
|
+
const configuration = req.query;
|
|
645
|
+
let configFields = [];
|
|
646
|
+
if (fv.configFields)
|
|
647
|
+
configFields = await applyAsync(fv.configFields, targetField);
|
|
648
|
+
readState(configuration, configFields);
|
|
649
|
+
res.send(fv.run(refRow[kpath[1]], req, configuration));
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
res.send("");
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
const field = fields.find((f) => f.name === fieldName);
|
|
657
|
+
|
|
658
|
+
const formula = field.expression;
|
|
659
|
+
|
|
629
660
|
let result;
|
|
630
661
|
try {
|
|
631
662
|
if (field.stored) {
|
|
@@ -660,7 +691,15 @@ router.post(
|
|
|
660
691
|
if (fieldName.includes(".")) {
|
|
661
692
|
const [refNm, targetNm] = fieldName.split(".");
|
|
662
693
|
const ref = fields.find((f) => f.name === refNm);
|
|
694
|
+
if (!ref) {
|
|
695
|
+
res.send("");
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
663
698
|
const reftable = await Table.findOne({ name: ref.reftable_name });
|
|
699
|
+
if (!reftable) {
|
|
700
|
+
res.send("");
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
664
703
|
const reffields = await reftable.getFields();
|
|
665
704
|
field = reffields.find((f) => f.name === targetNm);
|
|
666
705
|
row = await reftable.getRow({});
|
package/routes/files.js
CHANGED
|
@@ -17,7 +17,7 @@ const {
|
|
|
17
17
|
post_btn,
|
|
18
18
|
post_delete_btn,
|
|
19
19
|
} = require("@saltcorn/markup");
|
|
20
|
-
const { isAdmin, error_catcher } = require("./utils.js");
|
|
20
|
+
const { isAdmin, error_catcher, setTenant } = require("./utils.js");
|
|
21
21
|
const {
|
|
22
22
|
span,
|
|
23
23
|
h5,
|
|
@@ -136,7 +136,7 @@ router.get(
|
|
|
136
136
|
router.get(
|
|
137
137
|
"/download/:id",
|
|
138
138
|
error_catcher(async (req, res) => {
|
|
139
|
-
const role = req.
|
|
139
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
140
140
|
const user_id = req.user && req.user.id;
|
|
141
141
|
const { id } = req.params;
|
|
142
142
|
const file = await File.findOne({ id });
|
|
@@ -160,7 +160,7 @@ router.get(
|
|
|
160
160
|
router.get(
|
|
161
161
|
"/serve/:id",
|
|
162
162
|
error_catcher(async (req, res) => {
|
|
163
|
-
const role = req.
|
|
163
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
164
164
|
const user_id = req.user && req.user.id;
|
|
165
165
|
const { id } = req.params;
|
|
166
166
|
let file;
|
|
@@ -240,10 +240,11 @@ router.post(
|
|
|
240
240
|
*/
|
|
241
241
|
router.post(
|
|
242
242
|
"/upload",
|
|
243
|
+
setTenant, // TODO why is this needed?????
|
|
243
244
|
error_catcher(async (req, res) => {
|
|
244
245
|
let jsonResp = {};
|
|
245
246
|
const min_role_upload = getState().getConfig("min_role_upload", 1);
|
|
246
|
-
const role = req.
|
|
247
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
247
248
|
if (role > +min_role_upload) {
|
|
248
249
|
if (!req.xhr) req.flash("warning", req.__("Not authorized"));
|
|
249
250
|
else jsonResp = { error: "Not authorized" };
|
package/routes/homepage.js
CHANGED
|
@@ -13,7 +13,7 @@ const Page = require("@saltcorn/data/models/page");
|
|
|
13
13
|
const { link, renderForm, mkTable, post_btn } = require("@saltcorn/markup");
|
|
14
14
|
const { ul, li, div, small, a, h5, p, i } = require("@saltcorn/markup/tags");
|
|
15
15
|
const Table = require("@saltcorn/data/models/table");
|
|
16
|
-
const { fetch_available_packs } = require("@saltcorn/
|
|
16
|
+
const { fetch_available_packs } = require("@saltcorn/admin-models/models/pack");
|
|
17
17
|
const { restore_backup } = require("../markup/admin");
|
|
18
18
|
const { get_latest_npm_version } = require("@saltcorn/data/models/config");
|
|
19
19
|
const packagejson = require("../package.json");
|
|
@@ -398,7 +398,7 @@ const welcome_page = async (req) => {
|
|
|
398
398
|
* @returns {Promise<void>}
|
|
399
399
|
*/
|
|
400
400
|
const no_views_logged_in = async (req, res) => {
|
|
401
|
-
const role = req.
|
|
401
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
402
402
|
if (role > 1 || req.user.tenant !== db.getTenantSchema())
|
|
403
403
|
res.sendWrap(req.__("Hello"), req.__("Welcome to Saltcorn!"));
|
|
404
404
|
else {
|
|
@@ -463,7 +463,7 @@ module.exports =
|
|
|
463
463
|
* @returns {Promise<void>}
|
|
464
464
|
*/
|
|
465
465
|
async (req, res) => {
|
|
466
|
-
const isAuth = req.
|
|
466
|
+
const isAuth = req.user && req.user.id;
|
|
467
467
|
const role_id = req.user ? req.user.role_id : 10;
|
|
468
468
|
const cfgResp = await get_config_response(role_id, res, req);
|
|
469
469
|
if (cfgResp) return;
|
package/routes/list.js
CHANGED
package/routes/packs.js
CHANGED
|
@@ -30,7 +30,7 @@ const {
|
|
|
30
30
|
fetch_pack_by_name,
|
|
31
31
|
can_install_pack,
|
|
32
32
|
uninstall_pack,
|
|
33
|
-
} = require("@saltcorn/
|
|
33
|
+
} = require("@saltcorn/admin-models/models/pack");
|
|
34
34
|
const { h5, pre, code, p, text, text_attr } = require("@saltcorn/markup/tags");
|
|
35
35
|
const Library = require("@saltcorn/data/models/library");
|
|
36
36
|
const Trigger = require("@saltcorn/data/models/trigger");
|
package/routes/page.js
CHANGED
|
@@ -37,7 +37,7 @@ router.get(
|
|
|
37
37
|
error_catcher(async (req, res) => {
|
|
38
38
|
const { pagename } = req.params;
|
|
39
39
|
|
|
40
|
-
const role = req.
|
|
40
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
41
41
|
const db_page = await Page.findOne({ name: pagename });
|
|
42
42
|
if (db_page && role <= db_page.min_role) {
|
|
43
43
|
const contents = await db_page.run(req.query, { res, req });
|
|
@@ -73,7 +73,7 @@ router.post(
|
|
|
73
73
|
"/:pagename/action/:rndid",
|
|
74
74
|
error_catcher(async (req, res) => {
|
|
75
75
|
const { pagename, rndid } = req.params;
|
|
76
|
-
const role = req.
|
|
76
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
77
77
|
const db_page = await Page.findOne({ name: pagename });
|
|
78
78
|
if (db_page && role <= db_page.min_role) {
|
|
79
79
|
let col;
|
package/routes/pageedit.js
CHANGED
|
@@ -17,7 +17,7 @@ const Form = require("@saltcorn/data/models/form");
|
|
|
17
17
|
const File = require("@saltcorn/data/models/file");
|
|
18
18
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
19
19
|
const { getViews, traverseSync } = require("@saltcorn/data/models/layout");
|
|
20
|
-
const { add_to_menu } = require("@saltcorn/
|
|
20
|
+
const { add_to_menu } = require("@saltcorn/admin-models/models/pack");
|
|
21
21
|
const db = require("@saltcorn/data/db");
|
|
22
22
|
|
|
23
23
|
const { isAdmin, error_catcher } = require("./utils.js");
|
|
@@ -157,9 +157,12 @@ const pageBuilderData = async (req, context) => {
|
|
|
157
157
|
const images = await File.find({ mime_super: "image" });
|
|
158
158
|
const roles = await User.get_roles();
|
|
159
159
|
const stateActions = getState().actions;
|
|
160
|
-
const actions =
|
|
161
|
-
|
|
162
|
-
.
|
|
160
|
+
const actions = [
|
|
161
|
+
"GoBack",
|
|
162
|
+
...Object.entries(stateActions)
|
|
163
|
+
.filter(([k, v]) => !v.requireRow && !v.disableInBuilder)
|
|
164
|
+
.map(([k, v]) => k),
|
|
165
|
+
];
|
|
163
166
|
const triggers = await Trigger.find({
|
|
164
167
|
when_trigger: { or: ["API call", "Never"] },
|
|
165
168
|
});
|
package/routes/plugins.js
CHANGED
|
@@ -18,7 +18,7 @@ const { getState } = require("@saltcorn/data/db/state");
|
|
|
18
18
|
const Form = require("@saltcorn/data/models/form");
|
|
19
19
|
const Field = require("@saltcorn/data/models/field");
|
|
20
20
|
const Plugin = require("@saltcorn/data/models/plugin");
|
|
21
|
-
const { fetch_available_packs } = require("@saltcorn/
|
|
21
|
+
const { fetch_available_packs } = require("@saltcorn/admin-models/models/pack");
|
|
22
22
|
const { getConfig, setConfig } = require("@saltcorn/data/models/config");
|
|
23
23
|
const db = require("@saltcorn/data/db");
|
|
24
24
|
const {
|
package/routes/scapi.js
CHANGED
|
@@ -16,7 +16,7 @@ const Page = require("@saltcorn/data/models/page");
|
|
|
16
16
|
const File = require("@saltcorn/data/models/file");
|
|
17
17
|
const Trigger = require("@saltcorn/data/models/trigger");
|
|
18
18
|
const Role = require("@saltcorn/data/models/role");
|
|
19
|
-
const Tenant = require("@saltcorn/
|
|
19
|
+
const Tenant = require("@saltcorn/admin-models/models/tenant");
|
|
20
20
|
const Plugin = require("@saltcorn/data/models/plugin");
|
|
21
21
|
const Config = require("@saltcorn/data/models/config");
|
|
22
22
|
const passport = require("passport");
|
|
@@ -44,11 +44,12 @@ module.exports = router;
|
|
|
44
44
|
* @returns {boolean}
|
|
45
45
|
*/
|
|
46
46
|
function accessAllowedRead(req, user) {
|
|
47
|
-
const role =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
const role =
|
|
48
|
+
req.user && req.user.id
|
|
49
|
+
? req.user.role_id
|
|
50
|
+
: user && user.role_id
|
|
51
|
+
? user.role_id
|
|
52
|
+
: 10;
|
|
52
53
|
|
|
53
54
|
if (role === 1) return true;
|
|
54
55
|
return false;
|
package/routes/tables.js
CHANGED
|
@@ -22,7 +22,7 @@ const {
|
|
|
22
22
|
post_dropdown_item,
|
|
23
23
|
} = require("@saltcorn/markup");
|
|
24
24
|
const { recalculate_for_stored } = require("@saltcorn/data/models/expression");
|
|
25
|
-
const { isAdmin, error_catcher } = require("./utils.js");
|
|
25
|
+
const { isAdmin, error_catcher, setTenant } = require("./utils.js");
|
|
26
26
|
const Form = require("@saltcorn/data/models/form");
|
|
27
27
|
const {
|
|
28
28
|
span,
|
|
@@ -352,6 +352,7 @@ router.get(
|
|
|
352
352
|
*/
|
|
353
353
|
router.post(
|
|
354
354
|
"/create-from-csv",
|
|
355
|
+
setTenant, // TODO why is this needed?????
|
|
355
356
|
isAdmin,
|
|
356
357
|
error_catcher(async (req, res) => {
|
|
357
358
|
if (req.body.name && req.files && req.files.file) {
|
|
@@ -1367,6 +1368,7 @@ router.post(
|
|
|
1367
1368
|
*/
|
|
1368
1369
|
router.post(
|
|
1369
1370
|
"/upload_to_table/:name",
|
|
1371
|
+
setTenant, // TODO why is this needed?????
|
|
1370
1372
|
isAdmin,
|
|
1371
1373
|
error_catcher(async (req, res) => {
|
|
1372
1374
|
const { name } = req.params;
|
package/routes/tenant.js
CHANGED
|
@@ -6,12 +6,15 @@
|
|
|
6
6
|
|
|
7
7
|
const Router = require("express-promise-router");
|
|
8
8
|
const Form = require("@saltcorn/data/models/form");
|
|
9
|
-
const { getState,
|
|
9
|
+
const { getState, add_tenant } = require("@saltcorn/data/db/state");
|
|
10
|
+
const { create_tenant } = require("@saltcorn/admin-models/models/tenant");
|
|
10
11
|
const {
|
|
11
12
|
getAllTenants,
|
|
12
13
|
domain_sanitize,
|
|
13
14
|
deleteTenant,
|
|
14
|
-
|
|
15
|
+
switchToTenant,
|
|
16
|
+
insertTenant,
|
|
17
|
+
} = require("@saltcorn/admin-models/models/tenant");
|
|
15
18
|
const {
|
|
16
19
|
renderForm,
|
|
17
20
|
link,
|
|
@@ -45,6 +48,10 @@ const {
|
|
|
45
48
|
save_config_from_form,
|
|
46
49
|
} = require("../markup/admin.js");
|
|
47
50
|
const { getConfig } = require("@saltcorn/data/models/config");
|
|
51
|
+
const {
|
|
52
|
+
create_backup,
|
|
53
|
+
restore,
|
|
54
|
+
} = require("@saltcorn/admin-models/models/backup");
|
|
48
55
|
|
|
49
56
|
/**
|
|
50
57
|
* @type {object}
|
|
@@ -249,13 +256,16 @@ router.post(
|
|
|
249
256
|
);
|
|
250
257
|
} else {
|
|
251
258
|
const newurl = getNewURL(req, subdomain);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
+
const tenant_template = getState().getConfig("tenant_template");
|
|
260
|
+
await switchToTenant(await insertTenant(subdomain), newurl);
|
|
261
|
+
add_tenant(subdomain);
|
|
262
|
+
await create_tenant({
|
|
263
|
+
t: subdomain,
|
|
264
|
+
plugin_loader: loadAllPlugins,
|
|
265
|
+
noSignalOrDB: false,
|
|
266
|
+
loadAndSaveNewPlugin: loadAndSaveNewPlugin,
|
|
267
|
+
tenant_template,
|
|
268
|
+
});
|
|
259
269
|
let new_url_create = newurl;
|
|
260
270
|
const hasTemplate = getState().getConfig("tenant_template");
|
|
261
271
|
if (hasTemplate) {
|
package/routes/utils.js
CHANGED
|
@@ -49,7 +49,13 @@ function isAdmin(req, res, next) {
|
|
|
49
49
|
next();
|
|
50
50
|
} else {
|
|
51
51
|
req.flash("danger", req.__("Must be admin"));
|
|
52
|
-
res.redirect(
|
|
52
|
+
res.redirect(
|
|
53
|
+
req.user && req.user.pending_user
|
|
54
|
+
? "/auth/twofa/login/totp"
|
|
55
|
+
: req.user
|
|
56
|
+
? "/"
|
|
57
|
+
: "/auth/login"
|
|
58
|
+
);
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
61
|
|
package/routes/view.js
CHANGED
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
isAdmin,
|
|
17
17
|
error_catcher,
|
|
18
18
|
scan_for_page_title,
|
|
19
|
+
setTenant,
|
|
19
20
|
} = require("../routes/utils.js");
|
|
20
21
|
const { add_edit_bar } = require("../markup/admin.js");
|
|
21
22
|
const { InvalidConfiguration } = require("@saltcorn/data/utils");
|
|
@@ -42,8 +43,7 @@ router.get(
|
|
|
42
43
|
const { viewname } = req.params;
|
|
43
44
|
const query = { ...req.query };
|
|
44
45
|
const view = await View.findOne({ name: viewname });
|
|
45
|
-
const role = req.
|
|
46
|
-
|
|
46
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
47
47
|
if (!view) {
|
|
48
48
|
req.flash("danger", req.__(`No such view: %s`, text(viewname)));
|
|
49
49
|
res.redirect("/");
|
|
@@ -122,7 +122,7 @@ router.post(
|
|
|
122
122
|
"/:viewname/:route",
|
|
123
123
|
error_catcher(async (req, res) => {
|
|
124
124
|
const { viewname, route } = req.params;
|
|
125
|
-
const role = req.
|
|
125
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
126
126
|
|
|
127
127
|
const view = await View.findOne({ name: viewname });
|
|
128
128
|
if (!view) {
|
|
@@ -145,9 +145,10 @@ router.post(
|
|
|
145
145
|
*/
|
|
146
146
|
router.post(
|
|
147
147
|
["/:viewname", "/:viewname/*"],
|
|
148
|
+
setTenant,
|
|
148
149
|
error_catcher(async (req, res) => {
|
|
149
150
|
const { viewname } = req.params;
|
|
150
|
-
const role = req.
|
|
151
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
151
152
|
const query = { ...req.query };
|
|
152
153
|
|
|
153
154
|
const view = await View.findOne({ name: viewname });
|
package/routes/viewedit.js
CHANGED
|
@@ -39,7 +39,7 @@ const Workflow = require("@saltcorn/data/models/workflow");
|
|
|
39
39
|
const User = require("@saltcorn/data/models/user");
|
|
40
40
|
const Page = require("@saltcorn/data/models/page");
|
|
41
41
|
|
|
42
|
-
const { add_to_menu } = require("@saltcorn/
|
|
42
|
+
const { add_to_menu } = require("@saltcorn/admin-models/models/pack");
|
|
43
43
|
const { editRoleForm } = require("../markup/forms.js");
|
|
44
44
|
|
|
45
45
|
/**
|
package/serve.js
CHANGED
|
@@ -11,9 +11,10 @@ const db = require("@saltcorn/data/db");
|
|
|
11
11
|
const {
|
|
12
12
|
getState,
|
|
13
13
|
init_multi_tenant,
|
|
14
|
-
create_tenant,
|
|
15
14
|
restart_tenant,
|
|
15
|
+
add_tenant,
|
|
16
16
|
} = require("@saltcorn/data/db/state");
|
|
17
|
+
const { create_tenant } = require("@saltcorn/admin-models/models/tenant");
|
|
17
18
|
|
|
18
19
|
const path = require("path");
|
|
19
20
|
|
|
@@ -38,7 +39,10 @@ const {
|
|
|
38
39
|
getRelevantPackages,
|
|
39
40
|
getPluginDirectories,
|
|
40
41
|
} = require("./restart_watcher");
|
|
41
|
-
const {
|
|
42
|
+
const {
|
|
43
|
+
eachTenant,
|
|
44
|
+
getAllTenants,
|
|
45
|
+
} = require("@saltcorn/admin-models/models/tenant");
|
|
42
46
|
|
|
43
47
|
// helpful https://gist.github.com/jpoehls/2232358
|
|
44
48
|
/**
|
|
@@ -72,7 +76,8 @@ const initMaster = async ({ disableMigrate }, useClusterAdaptor = true) => {
|
|
|
72
76
|
// switch on sql logging - but it was initiated before???
|
|
73
77
|
if (getState().getConfig("log_sql", false)) db.set_sql_logging();
|
|
74
78
|
if (db.is_it_multi_tenant()) {
|
|
75
|
-
await
|
|
79
|
+
const tenants = await getAllTenants();
|
|
80
|
+
await init_multi_tenant(loadAllPlugins, disableMigrate, tenants);
|
|
76
81
|
}
|
|
77
82
|
if (useClusterAdaptor) setupPrimary();
|
|
78
83
|
};
|
|
@@ -95,7 +100,14 @@ const workerDispatchMsg = ({ tenant, ...msg }) => {
|
|
|
95
100
|
}
|
|
96
101
|
if (msg.refresh) getState()[`refresh_${msg.refresh}`](true);
|
|
97
102
|
if (msg.createTenant) {
|
|
98
|
-
|
|
103
|
+
const tenant_template = getState().getConfig("tenant_template");
|
|
104
|
+
add_tenant(msg.createTenant);
|
|
105
|
+
create_tenant({
|
|
106
|
+
t: msg.createTenant,
|
|
107
|
+
plugin_loader: loadAllPlugins,
|
|
108
|
+
noSignalOrDB: true,
|
|
109
|
+
tenant_template,
|
|
110
|
+
});
|
|
99
111
|
db.runWithTenant(msg.createTenant, async () => {
|
|
100
112
|
getState().refresh(true);
|
|
101
113
|
});
|
|
@@ -117,29 +129,28 @@ const workerDispatchMsg = ({ tenant, ...msg }) => {
|
|
|
117
129
|
* @param {number} opts.pid
|
|
118
130
|
* @returns {function}
|
|
119
131
|
*/
|
|
120
|
-
const onMessageFromWorker =
|
|
121
|
-
masterState,
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
};
|
|
132
|
+
const onMessageFromWorker =
|
|
133
|
+
(masterState, { port, watchReaper, disableScheduler, pid }) =>
|
|
134
|
+
(msg) => {
|
|
135
|
+
//console.log("worker msg", typeof msg, msg);
|
|
136
|
+
if (msg === "Start" && !masterState.started) {
|
|
137
|
+
masterState.started = true;
|
|
138
|
+
runScheduler({ port, watchReaper, disableScheduler, eachTenant });
|
|
139
|
+
require("./systemd")({ port });
|
|
140
|
+
return true;
|
|
141
|
+
} else if (msg === "RestartServer") {
|
|
142
|
+
process.exit(0);
|
|
143
|
+
return true;
|
|
144
|
+
} else if (msg.tenant || msg.createTenant) {
|
|
145
|
+
///ie from saltcorn
|
|
146
|
+
//broadcast
|
|
147
|
+
Object.entries(cluster.workers).forEach(([wpid, w]) => {
|
|
148
|
+
if (wpid !== pid) w.send(msg);
|
|
149
|
+
});
|
|
150
|
+
workerDispatchMsg(msg); //also master
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
143
154
|
|
|
144
155
|
module.exports =
|
|
145
156
|
/**
|
|
@@ -163,9 +174,6 @@ module.exports =
|
|
|
163
174
|
...appargs
|
|
164
175
|
} = {}) => {
|
|
165
176
|
if (dev && cluster.isMaster) {
|
|
166
|
-
spawnSync("npm", ["run", "tsc"], {
|
|
167
|
-
stdio: "inherit",
|
|
168
|
-
});
|
|
169
177
|
listenForChanges(getRelevantPackages(), await getPluginDirectories());
|
|
170
178
|
}
|
|
171
179
|
const useNCpus = process.env.SALTCORN_NWORKERS
|