@saltcorn/server 0.6.3-beta.2 → 0.6.3-beta.3
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 +12 -2
- package/auth/roleadmin.js +50 -0
- package/auth/routes.js +228 -2
- package/locales/en.json +860 -850
- package/package.json +10 -6
- package/public/gridedit.js +6 -2
- package/restart_watcher.js +3 -0
- package/routes/admin.js +1 -0
- package/routes/api.js +18 -15
- package/routes/delete.js +1 -1
- package/routes/edit.js +1 -1
- package/routes/fields.js +11 -1
- package/routes/files.js +3 -3
- package/routes/homepage.js +2 -2
- package/routes/page.js +2 -2
- package/routes/scapi.js +6 -5
- package/routes/utils.js +7 -1
- package/routes/view.js +3 -4
- package/serve.js +0 -3
- package/wrapper.js +1 -1
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.6.3-beta.
|
|
3
|
+
"version": "0.6.3-beta.3",
|
|
4
4
|
"description": "Server app for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@saltcorn/base-plugin": "0.6.3-beta.
|
|
10
|
-
"@saltcorn/builder": "0.6.3-beta.
|
|
11
|
-
"@saltcorn/data": "0.6.3-beta.
|
|
9
|
+
"@saltcorn/base-plugin": "0.6.3-beta.3",
|
|
10
|
+
"@saltcorn/builder": "0.6.3-beta.3",
|
|
11
|
+
"@saltcorn/data": "0.6.3-beta.3",
|
|
12
12
|
"greenlock-express": "^4.0.3",
|
|
13
|
-
"@saltcorn/markup": "0.6.3-beta.
|
|
14
|
-
"@saltcorn/sbadmin2": "0.6.3-beta.
|
|
13
|
+
"@saltcorn/markup": "0.6.3-beta.3",
|
|
14
|
+
"@saltcorn/sbadmin2": "0.6.3-beta.3",
|
|
15
15
|
"@socket.io/cluster-adapter": "^0.1.0",
|
|
16
16
|
"@socket.io/sticky": "^1.0.1",
|
|
17
17
|
"connect-flash": "^0.1.1",
|
|
@@ -34,13 +34,17 @@
|
|
|
34
34
|
"moment": "^2.27.0",
|
|
35
35
|
"node-fetch": "2.6.2",
|
|
36
36
|
"node-watch": "^0.7.2",
|
|
37
|
+
"notp": "2.0.3",
|
|
37
38
|
"passport": "^0.4.1",
|
|
38
39
|
"passport-custom": "^1.1.1",
|
|
39
40
|
"passport-http-bearer": "^1.0.1",
|
|
41
|
+
"passport-totp": "0.0.2",
|
|
40
42
|
"pg": "^8.2.1",
|
|
41
43
|
"pluralize": "^8.0.0",
|
|
44
|
+
"qrcode": "1.5.0",
|
|
42
45
|
"socket.io": "4.2.0",
|
|
43
46
|
"tmp-promise": "^3.0.2",
|
|
47
|
+
"thirty-two": "1.0.2",
|
|
44
48
|
"multer-s3": "^2.10.0",
|
|
45
49
|
"multer": "^1.4.3",
|
|
46
50
|
"aws-sdk": "^2.1037.0",
|
package/public/gridedit.js
CHANGED
|
@@ -179,7 +179,9 @@ DateField.prototype = new jsGrid.Field({
|
|
|
179
179
|
setTimeout(function () {
|
|
180
180
|
flatpickr(insertPicker, {
|
|
181
181
|
enableTime: true,
|
|
182
|
-
dateFormat: "
|
|
182
|
+
dateFormat: "Z",
|
|
183
|
+
altInput: true,
|
|
184
|
+
altFormat: "Y-m-d h:i K",
|
|
183
185
|
});
|
|
184
186
|
});
|
|
185
187
|
return insertPicker;
|
|
@@ -192,7 +194,9 @@ DateField.prototype = new jsGrid.Field({
|
|
|
192
194
|
setTimeout(function () {
|
|
193
195
|
flatpickr(editPicker, {
|
|
194
196
|
enableTime: true,
|
|
195
|
-
dateFormat: "
|
|
197
|
+
dateFormat: "Z",
|
|
198
|
+
altInput: true,
|
|
199
|
+
altFormat: "Y-m-d h:i K",
|
|
196
200
|
});
|
|
197
201
|
});
|
|
198
202
|
return editPicker;
|
package/restart_watcher.js
CHANGED
|
@@ -120,6 +120,9 @@ const listenForChanges = (projectDirs, pluginDirs) => {
|
|
|
120
120
|
(event, file) => {
|
|
121
121
|
console.log("'%s' changed \n re-starting now", file);
|
|
122
122
|
closeWatchers();
|
|
123
|
+
spawnSync("npm", ["run", "tsc"], {
|
|
124
|
+
stdio: "inherit",
|
|
125
|
+
});
|
|
123
126
|
process.exit();
|
|
124
127
|
}
|
|
125
128
|
)
|
package/routes/admin.js
CHANGED
package/routes/api.js
CHANGED
|
@@ -65,11 +65,12 @@ const limitFields = (fields) => (r) => {
|
|
|
65
65
|
* @returns {boolean}
|
|
66
66
|
*/
|
|
67
67
|
function accessAllowedRead(req, user, table) {
|
|
68
|
-
const role =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
const role =
|
|
69
|
+
req.user && req.user.id
|
|
70
|
+
? req.user.role_id
|
|
71
|
+
: user && user.role_id
|
|
72
|
+
? user.role_id
|
|
73
|
+
: 10;
|
|
73
74
|
|
|
74
75
|
return role <= table.min_role_read;
|
|
75
76
|
}
|
|
@@ -82,11 +83,12 @@ function accessAllowedRead(req, user, table) {
|
|
|
82
83
|
* @returns {boolean}
|
|
83
84
|
*/
|
|
84
85
|
function accessAllowedWrite(req, user, table) {
|
|
85
|
-
const role =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
const role =
|
|
87
|
+
req.user && req.user.id
|
|
88
|
+
? req.user.role_id
|
|
89
|
+
: user && user.role_id
|
|
90
|
+
? user.role_id
|
|
91
|
+
: 10;
|
|
90
92
|
|
|
91
93
|
return role <= table.min_role_write;
|
|
92
94
|
}
|
|
@@ -98,11 +100,12 @@ function accessAllowedWrite(req, user, table) {
|
|
|
98
100
|
* @returns {boolean}
|
|
99
101
|
*/
|
|
100
102
|
function accessAllowed(req, user, trigger) {
|
|
101
|
-
const role =
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
103
|
+
const role =
|
|
104
|
+
req.user && req.user.id
|
|
105
|
+
? req.user.role_id
|
|
106
|
+
: user && user.role_id
|
|
107
|
+
? user.role_id
|
|
108
|
+
: 10;
|
|
106
109
|
|
|
107
110
|
return role <= trigger.min_role;
|
|
108
111
|
}
|
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,7 @@ 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");
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* @type {object}
|
|
@@ -161,8 +162,9 @@ const translateAttributes = (attrs, req) =>
|
|
|
161
162
|
* @returns {object}
|
|
162
163
|
*/
|
|
163
164
|
const translateAttribute = (attr, req) => {
|
|
164
|
-
|
|
165
|
+
let res = { ...attr };
|
|
165
166
|
if (res.sublabel) res.sublabel = req.__(res.sublabel);
|
|
167
|
+
if (res.isRepeat) res = new FieldRepeat(res);
|
|
166
168
|
return res;
|
|
167
169
|
};
|
|
168
170
|
|
|
@@ -660,7 +662,15 @@ router.post(
|
|
|
660
662
|
if (fieldName.includes(".")) {
|
|
661
663
|
const [refNm, targetNm] = fieldName.split(".");
|
|
662
664
|
const ref = fields.find((f) => f.name === refNm);
|
|
665
|
+
if (!ref) {
|
|
666
|
+
res.send("");
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
663
669
|
const reftable = await Table.findOne({ name: ref.reftable_name });
|
|
670
|
+
if (!reftable) {
|
|
671
|
+
res.send("");
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
664
674
|
const reffields = await reftable.getFields();
|
|
665
675
|
field = reffields.find((f) => f.name === targetNm);
|
|
666
676
|
row = await reftable.getRow({});
|
package/routes/files.js
CHANGED
|
@@ -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;
|
|
@@ -243,7 +243,7 @@ router.post(
|
|
|
243
243
|
error_catcher(async (req, res) => {
|
|
244
244
|
let jsonResp = {};
|
|
245
245
|
const min_role_upload = getState().getConfig("min_role_upload", 1);
|
|
246
|
-
const role = req.
|
|
246
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
247
247
|
if (role > +min_role_upload) {
|
|
248
248
|
if (!req.xhr) req.flash("warning", req.__("Not authorized"));
|
|
249
249
|
else jsonResp = { error: "Not authorized" };
|
package/routes/homepage.js
CHANGED
|
@@ -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/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/scapi.js
CHANGED
|
@@ -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/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
|
@@ -42,8 +42,7 @@ router.get(
|
|
|
42
42
|
const { viewname } = req.params;
|
|
43
43
|
const query = { ...req.query };
|
|
44
44
|
const view = await View.findOne({ name: viewname });
|
|
45
|
-
const role = req.
|
|
46
|
-
|
|
45
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
47
46
|
if (!view) {
|
|
48
47
|
req.flash("danger", req.__(`No such view: %s`, text(viewname)));
|
|
49
48
|
res.redirect("/");
|
|
@@ -122,7 +121,7 @@ router.post(
|
|
|
122
121
|
"/:viewname/:route",
|
|
123
122
|
error_catcher(async (req, res) => {
|
|
124
123
|
const { viewname, route } = req.params;
|
|
125
|
-
const role = req.
|
|
124
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
126
125
|
|
|
127
126
|
const view = await View.findOne({ name: viewname });
|
|
128
127
|
if (!view) {
|
|
@@ -147,7 +146,7 @@ router.post(
|
|
|
147
146
|
["/:viewname", "/:viewname/*"],
|
|
148
147
|
error_catcher(async (req, res) => {
|
|
149
148
|
const { viewname } = req.params;
|
|
150
|
-
const role = req.
|
|
149
|
+
const role = req.user && req.user.id ? req.user.role_id : 10;
|
|
151
150
|
const query = { ...req.query };
|
|
152
151
|
|
|
153
152
|
const view = await View.findOne({ name: viewname });
|
package/serve.js
CHANGED
|
@@ -163,9 +163,6 @@ module.exports =
|
|
|
163
163
|
...appargs
|
|
164
164
|
} = {}) => {
|
|
165
165
|
if (dev && cluster.isMaster) {
|
|
166
|
-
spawnSync("npm", ["run", "tsc"], {
|
|
167
|
-
stdio: "inherit",
|
|
168
|
-
});
|
|
169
166
|
listenForChanges(getRelevantPackages(), await getPluginDirectories());
|
|
170
167
|
}
|
|
171
168
|
const useNCpus = process.env.SALTCORN_NWORKERS
|
package/wrapper.js
CHANGED