@saltcorn/server 1.1.1-beta.5 → 1.1.1-beta.6
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/CHANGELOG.md +6 -0
- package/auth/admin.js +8 -0
- package/locales/en.json +16 -1
- package/markup/admin.js +8 -3
- package/package.json +9 -9
- package/public/saltcorn-common.js +8 -1
- package/public/saltcorn.js +12 -0
- package/routes/actions.js +20 -18
- package/routes/admin.js +90 -63
- package/routes/common_lists.js +40 -20
- package/routes/fields.js +31 -9
- package/routes/list.js +17 -4
- package/routes/notifications.js +27 -20
- package/routes/pageedit.js +14 -13
- package/routes/tables.js +171 -92
- package/routes/utils.js +27 -0
- package/routes/view.js +2 -1
- package/routes/viewedit.js +14 -13
- package/tests/api.test.js +0 -18
- package/wrapper.js +80 -42
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## 1.1.1 - In beta
|
|
4
4
|
|
|
5
|
+
* You can now permit to non-admin (role ID > 1) users to edit or inspect tables, or
|
|
6
|
+
edit views, pages or triggers. In the permissions tab of the Users and security
|
|
7
|
+
settings, minimum roles can be set for these capabilities. The appropriate
|
|
8
|
+
menu items will be added to any users with the roles that match these permissions.
|
|
9
|
+
|
|
5
10
|
* Stored calculated fields that contain joinfields in the expression are now automatically
|
|
6
11
|
updated when the values they reference are changed, i.e. changes occur in the tables they
|
|
7
12
|
reference. This is limited to single (expression contains x.y) and double joinfields
|
|
@@ -34,6 +39,7 @@
|
|
|
34
39
|
|
|
35
40
|
### Fixes
|
|
36
41
|
|
|
42
|
+
* fix workflows on SQLite
|
|
37
43
|
* fix query string build on check_state_field (#2948). Author: St0rml
|
|
38
44
|
|
|
39
45
|
### Translations
|
package/auth/admin.js
CHANGED
|
@@ -414,6 +414,14 @@ const permissions_settings_form = async (req) =>
|
|
|
414
414
|
"min_role_upload",
|
|
415
415
|
"min_role_apikeygen",
|
|
416
416
|
"min_role_search",
|
|
417
|
+
{
|
|
418
|
+
section_header: req.__("Development permissions"),
|
|
419
|
+
},
|
|
420
|
+
"min_role_inspect_tables",
|
|
421
|
+
"min_role_edit_tables",
|
|
422
|
+
"min_role_edit_views",
|
|
423
|
+
"min_role_edit_pages",
|
|
424
|
+
"min_role_edit_triggers",
|
|
417
425
|
//hidden "exttables_min_role_read",
|
|
418
426
|
],
|
|
419
427
|
action: "/useradmin/permissions",
|
package/locales/en.json
CHANGED
|
@@ -1528,5 +1528,20 @@
|
|
|
1528
1528
|
"Finished": "Finished",
|
|
1529
1529
|
"Error": "Error",
|
|
1530
1530
|
"Waiting": "Waiting",
|
|
1531
|
-
"Running": "Running"
|
|
1531
|
+
"Running": "Running",
|
|
1532
|
+
"Minimum role to access search page": "Minimum role to access search page",
|
|
1533
|
+
"Edit tables": "Edit tables",
|
|
1534
|
+
"Minimum role to edit tables": "Minimum role to edit tables",
|
|
1535
|
+
"Edit views": "Edit views",
|
|
1536
|
+
"Minimum role to edit views": "Minimum role to edit views",
|
|
1537
|
+
"Edit pages": "Edit pages",
|
|
1538
|
+
"Minimum role to edit pages": "Minimum role to edit pages",
|
|
1539
|
+
"Edit triggers": "Edit triggers",
|
|
1540
|
+
"Minimum role to edit triggers": "Minimum role to edit triggers",
|
|
1541
|
+
"Development permissions": "Development permissions",
|
|
1542
|
+
"Inspect tables": "Inspect tables",
|
|
1543
|
+
"Minimum role to inspect (see, without editing) tables": "Minimum role to inspect (see, without editing) tables",
|
|
1544
|
+
"Home pages": "Home pages",
|
|
1545
|
+
"The home page is the page that is served when the user visits the home location (/). This can be set for each user role.": "The home page is the page that is served when the user visits the home location (/). This can be set for each user role.",
|
|
1546
|
+
"Trigger %s deleted": "Trigger %s deleted"
|
|
1532
1547
|
}
|
package/markup/admin.js
CHANGED
|
@@ -302,14 +302,19 @@ const send_tags_page = (args) => {
|
|
|
302
302
|
*/
|
|
303
303
|
const send_events_page = (args) => {
|
|
304
304
|
const isRoot = db.getTenantSchema() === db.connectObj.default_schema;
|
|
305
|
+
const isUserAdmin = args.req?.user.role_id === 1;
|
|
305
306
|
return send_settings_page({
|
|
306
307
|
main_section: "Events",
|
|
307
308
|
main_section_href: "/events",
|
|
308
309
|
sub_sections: [
|
|
309
310
|
{ text: "Triggers", href: "/actions" },
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
...(isUserAdmin
|
|
312
|
+
? [
|
|
313
|
+
{ text: "Custom", href: "/eventlog/custom" },
|
|
314
|
+
{ text: "Settings", href: "/eventlog/settings" },
|
|
315
|
+
{ text: "Event log", href: "/eventlog" },
|
|
316
|
+
]
|
|
317
|
+
: []),
|
|
313
318
|
{ text: "Workflow runs", href: "/actions/runs" },
|
|
314
319
|
...(isRoot ? [{ text: "Crash log", href: "/crashlog" }] : []),
|
|
315
320
|
],
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "1.1.1-beta.
|
|
3
|
+
"version": "1.1.1-beta.6",
|
|
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
9
|
"@aws-sdk/client-s3": "^3.451.0",
|
|
10
|
-
"@saltcorn/base-plugin": "1.1.1-beta.
|
|
11
|
-
"@saltcorn/builder": "1.1.1-beta.
|
|
12
|
-
"@saltcorn/data": "1.1.1-beta.
|
|
13
|
-
"@saltcorn/admin-models": "1.1.1-beta.
|
|
14
|
-
"@saltcorn/filemanager": "1.1.1-beta.
|
|
15
|
-
"@saltcorn/markup": "1.1.1-beta.
|
|
16
|
-
"@saltcorn/plugins-loader": "1.1.1-beta.
|
|
17
|
-
"@saltcorn/sbadmin2": "1.1.1-beta.
|
|
10
|
+
"@saltcorn/base-plugin": "1.1.1-beta.6",
|
|
11
|
+
"@saltcorn/builder": "1.1.1-beta.6",
|
|
12
|
+
"@saltcorn/data": "1.1.1-beta.6",
|
|
13
|
+
"@saltcorn/admin-models": "1.1.1-beta.6",
|
|
14
|
+
"@saltcorn/filemanager": "1.1.1-beta.6",
|
|
15
|
+
"@saltcorn/markup": "1.1.1-beta.6",
|
|
16
|
+
"@saltcorn/plugins-loader": "1.1.1-beta.6",
|
|
17
|
+
"@saltcorn/sbadmin2": "1.1.1-beta.6",
|
|
18
18
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
19
19
|
"@socket.io/sticky": "^1.0.1",
|
|
20
20
|
"adm-zip": "0.5.10",
|
|
@@ -139,6 +139,9 @@ function valid_js_var_name(s) {
|
|
|
139
139
|
if (!s) return false;
|
|
140
140
|
return !!s.match(/^[a-zA-Z_$][a-zA-Z_$0-9]*$/);
|
|
141
141
|
}
|
|
142
|
+
|
|
143
|
+
const apply_showif_fetching_urls = new Set();
|
|
144
|
+
|
|
142
145
|
function apply_showif() {
|
|
143
146
|
const isNode = getIsNode();
|
|
144
147
|
$("[data-show-if]").each(function (ix, element) {
|
|
@@ -358,6 +361,7 @@ function apply_showif() {
|
|
|
358
361
|
...cache,
|
|
359
362
|
[qs]: "fetching",
|
|
360
363
|
});
|
|
364
|
+
apply_showif_fetching_urls.add(`/api/${dynwhere.table}?${qs}`);
|
|
361
365
|
$.ajax(`/api/${dynwhere.table}?${qs}`)
|
|
362
366
|
.then((resp) => {
|
|
363
367
|
if (resp.success) {
|
|
@@ -378,7 +382,10 @@ function apply_showif() {
|
|
|
378
382
|
});
|
|
379
383
|
}
|
|
380
384
|
})
|
|
381
|
-
.fail(checkNetworkError)
|
|
385
|
+
.fail(checkNetworkError)
|
|
386
|
+
.always(() => {
|
|
387
|
+
apply_showif_fetching_urls.delete(`/api/${dynwhere.table}?${qs}`);
|
|
388
|
+
});
|
|
382
389
|
}
|
|
383
390
|
});
|
|
384
391
|
$("[data-filter-table]").each(function (ix, element) {
|
package/public/saltcorn.js
CHANGED
|
@@ -459,6 +459,18 @@ function saveAndContinueIfValid(e, k, event) {
|
|
|
459
459
|
});
|
|
460
460
|
}
|
|
461
461
|
|
|
462
|
+
function saveAndContinueDelayed(e, k, event, retries = 1) {
|
|
463
|
+
//wait for applyShowIf
|
|
464
|
+
setTimeout(() => {
|
|
465
|
+
if (apply_showif_fetching_urls.size > 0 && retries < 5) {
|
|
466
|
+
setTimeout(() => {
|
|
467
|
+
saveAndContinueDelayed(e, k, event, retries + 1);
|
|
468
|
+
}, 200);
|
|
469
|
+
} else saveAndContinue(e, k, event);
|
|
470
|
+
});
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
|
|
462
474
|
function saveAndContinue(e, k, event) {
|
|
463
475
|
if (
|
|
464
476
|
event &&
|
package/routes/actions.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
const Router = require("express-promise-router");
|
|
8
8
|
const {
|
|
9
9
|
isAdmin,
|
|
10
|
+
isAdminOrHasConfigMinRole,
|
|
10
11
|
error_catcher,
|
|
11
12
|
addOnDoneRedirect,
|
|
12
13
|
is_relative_url,
|
|
@@ -85,7 +86,7 @@ const {
|
|
|
85
86
|
*/
|
|
86
87
|
router.get(
|
|
87
88
|
"/",
|
|
88
|
-
|
|
89
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
89
90
|
error_catcher(async (req, res) => {
|
|
90
91
|
let triggers = await Trigger.findAllWithTableName();
|
|
91
92
|
let filterOnTag;
|
|
@@ -347,7 +348,7 @@ const triggerForm = async (req, trigger) => {
|
|
|
347
348
|
*/
|
|
348
349
|
router.get(
|
|
349
350
|
"/new",
|
|
350
|
-
|
|
351
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
351
352
|
error_catcher(async (req, res) => {
|
|
352
353
|
const form = await triggerForm(req);
|
|
353
354
|
if (req.query.table) {
|
|
@@ -388,7 +389,7 @@ router.get(
|
|
|
388
389
|
*/
|
|
389
390
|
router.get(
|
|
390
391
|
"/edit/:id",
|
|
391
|
-
|
|
392
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
392
393
|
error_catcher(async (req, res) => {
|
|
393
394
|
const { id } = req.params;
|
|
394
395
|
const trigger = await Trigger.findOne({ id });
|
|
@@ -419,7 +420,7 @@ router.get(
|
|
|
419
420
|
*/
|
|
420
421
|
router.post(
|
|
421
422
|
"/new",
|
|
422
|
-
|
|
423
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
423
424
|
error_catcher(async (req, res) => {
|
|
424
425
|
const form = await triggerForm(req);
|
|
425
426
|
|
|
@@ -462,7 +463,7 @@ router.post(
|
|
|
462
463
|
*/
|
|
463
464
|
router.post(
|
|
464
465
|
"/edit/:id",
|
|
465
|
-
|
|
466
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
466
467
|
error_catcher(async (req, res) => {
|
|
467
468
|
const { id } = req.params;
|
|
468
469
|
const trigger = await Trigger.findOne({ id });
|
|
@@ -928,7 +929,7 @@ const getMultiStepForm = async (req, id, table) => {
|
|
|
928
929
|
*/
|
|
929
930
|
router.get(
|
|
930
931
|
"/configure/:idorname",
|
|
931
|
-
|
|
932
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
932
933
|
error_catcher(async (req, res) => {
|
|
933
934
|
const { idorname } = req.params;
|
|
934
935
|
let trigger;
|
|
@@ -1130,7 +1131,7 @@ router.get(
|
|
|
1130
1131
|
*/
|
|
1131
1132
|
router.post(
|
|
1132
1133
|
"/configure/:id",
|
|
1133
|
-
|
|
1134
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1134
1135
|
error_catcher(async (req, res) => {
|
|
1135
1136
|
const { id } = req.params;
|
|
1136
1137
|
const trigger = await Trigger.findOne({ id });
|
|
@@ -1202,7 +1203,7 @@ router.post(
|
|
|
1202
1203
|
*/
|
|
1203
1204
|
router.post(
|
|
1204
1205
|
"/delete/:id",
|
|
1205
|
-
|
|
1206
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1206
1207
|
error_catcher(async (req, res) => {
|
|
1207
1208
|
const { id } = req.params;
|
|
1208
1209
|
const trigger = await Trigger.findOne({ id });
|
|
@@ -1211,6 +1212,7 @@ router.post(
|
|
|
1211
1212
|
entity_name: trigger.name,
|
|
1212
1213
|
});
|
|
1213
1214
|
await trigger.delete();
|
|
1215
|
+
req.flash("success", req.__(`Trigger %s deleted`, trigger.name));
|
|
1214
1216
|
res.redirect(`/actions/`);
|
|
1215
1217
|
})
|
|
1216
1218
|
);
|
|
@@ -1222,7 +1224,7 @@ router.post(
|
|
|
1222
1224
|
*/
|
|
1223
1225
|
router.get(
|
|
1224
1226
|
"/testrun/:id",
|
|
1225
|
-
|
|
1227
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1226
1228
|
error_catcher(async (req, res) => {
|
|
1227
1229
|
const { id } = req.params;
|
|
1228
1230
|
const trigger = await Trigger.findOne({ id });
|
|
@@ -1333,7 +1335,7 @@ router.get(
|
|
|
1333
1335
|
*/
|
|
1334
1336
|
router.post(
|
|
1335
1337
|
"/clone/:id",
|
|
1336
|
-
|
|
1338
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1337
1339
|
error_catcher(async (req, res) => {
|
|
1338
1340
|
const { id } = req.params;
|
|
1339
1341
|
const trig = await Trigger.findOne({ id });
|
|
@@ -1358,7 +1360,7 @@ router.post(
|
|
|
1358
1360
|
*/
|
|
1359
1361
|
router.get(
|
|
1360
1362
|
"/stepedit/:trigger_id/:step_id?",
|
|
1361
|
-
|
|
1363
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1362
1364
|
error_catcher(async (req, res) => {
|
|
1363
1365
|
const { trigger_id, step_id } = req.params;
|
|
1364
1366
|
const { initial_step, after_step, before_step } = req.query;
|
|
@@ -1400,7 +1402,7 @@ router.get(
|
|
|
1400
1402
|
|
|
1401
1403
|
router.post(
|
|
1402
1404
|
"/stepedit/:trigger_id",
|
|
1403
|
-
|
|
1405
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1404
1406
|
error_catcher(async (req, res) => {
|
|
1405
1407
|
const { trigger_id } = req.params;
|
|
1406
1408
|
const trigger = await Trigger.findOne({ id: trigger_id });
|
|
@@ -1499,7 +1501,7 @@ router.post(
|
|
|
1499
1501
|
|
|
1500
1502
|
router.post(
|
|
1501
1503
|
"/gen-copilot/:trigger_id",
|
|
1502
|
-
|
|
1504
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1503
1505
|
error_catcher(async (req, res) => {
|
|
1504
1506
|
const { trigger_id } = req.params;
|
|
1505
1507
|
const trigger = await Trigger.findOne({ id: trigger_id });
|
|
@@ -1525,18 +1527,18 @@ router.post(
|
|
|
1525
1527
|
|
|
1526
1528
|
router.post(
|
|
1527
1529
|
"/delete-step/:step_id",
|
|
1528
|
-
|
|
1530
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1529
1531
|
error_catcher(async (req, res) => {
|
|
1530
1532
|
const { step_id } = req.params;
|
|
1531
1533
|
const step = await WorkflowStep.findOne({ id: step_id });
|
|
1532
|
-
await step.delete();
|
|
1534
|
+
await step.delete(true);
|
|
1533
1535
|
res.json({ goto: `/actions/configure/${step.trigger_id}` });
|
|
1534
1536
|
})
|
|
1535
1537
|
);
|
|
1536
1538
|
|
|
1537
1539
|
router.get(
|
|
1538
1540
|
"/runs",
|
|
1539
|
-
|
|
1541
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1540
1542
|
error_catcher(async (req, res) => {
|
|
1541
1543
|
const trNames = {};
|
|
1542
1544
|
const { _page, trigger } = req.query;
|
|
@@ -1607,7 +1609,7 @@ router.get(
|
|
|
1607
1609
|
|
|
1608
1610
|
router.get(
|
|
1609
1611
|
"/run/:id",
|
|
1610
|
-
|
|
1612
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1611
1613
|
error_catcher(async (req, res) => {
|
|
1612
1614
|
const { id } = req.params;
|
|
1613
1615
|
|
|
@@ -1730,7 +1732,7 @@ router.get(
|
|
|
1730
1732
|
|
|
1731
1733
|
router.post(
|
|
1732
1734
|
"/delete-run/:id",
|
|
1733
|
-
|
|
1735
|
+
isAdminOrHasConfigMinRole("min_role_edit_triggers"),
|
|
1734
1736
|
error_catcher(async (req, res) => {
|
|
1735
1737
|
const { id } = req.params;
|
|
1736
1738
|
|
package/routes/admin.js
CHANGED
|
@@ -13,6 +13,7 @@ const {
|
|
|
13
13
|
admin_config_route,
|
|
14
14
|
get_sys_info,
|
|
15
15
|
tenant_letsencrypt_name,
|
|
16
|
+
isAdminOrHasConfigMinRole,
|
|
16
17
|
} = require("./utils.js");
|
|
17
18
|
const Table = require("@saltcorn/data/models/table");
|
|
18
19
|
const Plugin = require("@saltcorn/data/models/plugin");
|
|
@@ -295,7 +296,7 @@ router.get(
|
|
|
295
296
|
error_catcher(async (req, res) => {
|
|
296
297
|
const fp = path.join(__dirname, "..", "CHANGELOG.md");
|
|
297
298
|
const fileBuf = await fs.promises.readFile(fp);
|
|
298
|
-
const mdContents = fileBuf.toString().replace("# Notable changes\n","");
|
|
299
|
+
const mdContents = fileBuf.toString().replace("# Notable changes\n", "");
|
|
299
300
|
const markup = md.render(mdContents);
|
|
300
301
|
res.sendWrap(`What's new in Saltcorn`, { above: [markup] });
|
|
301
302
|
})
|
|
@@ -626,13 +627,36 @@ router.get(
|
|
|
626
627
|
})
|
|
627
628
|
);
|
|
628
629
|
|
|
630
|
+
const checkEditPermission = (type, user) => {
|
|
631
|
+
if (user.role_id === 1) return true;
|
|
632
|
+
switch (type) {
|
|
633
|
+
case "view":
|
|
634
|
+
return getState().getConfig("min_role_edit_views", 1) >= user.role_id;
|
|
635
|
+
case "page":
|
|
636
|
+
return getState().getConfig("min_role_edit_pages", 1) >= user.role_id;
|
|
637
|
+
case "trigger":
|
|
638
|
+
return getState().getConfig("min_role_edit_triggers", 1) >= user.role_id;
|
|
639
|
+
default:
|
|
640
|
+
return false;
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
|
|
629
644
|
router.get(
|
|
630
645
|
"/snapshot-restore/:type/:name",
|
|
631
|
-
|
|
646
|
+
isAdminOrHasConfigMinRole([
|
|
647
|
+
"min_role_edit_views",
|
|
648
|
+
"min_role_edit_pages",
|
|
649
|
+
"min_role_edit_triggers",
|
|
650
|
+
]),
|
|
632
651
|
error_catcher(async (req, res) => {
|
|
633
652
|
const { type, name } = req.params;
|
|
634
653
|
const snaps = await Snapshot.entity_history(type, name);
|
|
635
654
|
const locale = getState().getConfig("default_locale", "en");
|
|
655
|
+
const auth = checkEditPermission(type, req.user);
|
|
656
|
+
if (!auth) {
|
|
657
|
+
res.send("Not authorized");
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
636
660
|
res.set("Page-Title", `Restore ${text(name)}`);
|
|
637
661
|
res.send(
|
|
638
662
|
mkTable(
|
|
@@ -663,17 +687,26 @@ router.get(
|
|
|
663
687
|
|
|
664
688
|
router.post(
|
|
665
689
|
"/snapshot-restore/:type/:name/:id",
|
|
666
|
-
|
|
690
|
+
isAdminOrHasConfigMinRole([
|
|
691
|
+
"min_role_edit_views",
|
|
692
|
+
"min_role_edit_pages",
|
|
693
|
+
"min_role_edit_triggers",
|
|
694
|
+
]),
|
|
667
695
|
error_catcher(async (req, res) => {
|
|
668
696
|
const { type, name, id } = req.params;
|
|
669
|
-
const
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
697
|
+
const auth = checkEditPermission(type, req.user);
|
|
698
|
+
if (!auth) {
|
|
699
|
+
req.flash("error", "Not authorized");
|
|
700
|
+
} else {
|
|
701
|
+
const snap = await Snapshot.findOne({ id });
|
|
702
|
+
await snap.restore_entity(type, name);
|
|
703
|
+
req.flash(
|
|
704
|
+
"success",
|
|
705
|
+
`${type} ${name} restored to snapshot saved ${moment(
|
|
706
|
+
snap.created
|
|
707
|
+
).fromNow()}`
|
|
708
|
+
);
|
|
709
|
+
}
|
|
677
710
|
res.redirect(
|
|
678
711
|
type === "trigger"
|
|
679
712
|
? `/actions`
|
|
@@ -2414,7 +2447,7 @@ router.get(
|
|
|
2414
2447
|
class: "form-control",
|
|
2415
2448
|
name: "appId",
|
|
2416
2449
|
id: "appIdInputId",
|
|
2417
|
-
placeholder: "com.saltcorn.app",
|
|
2450
|
+
placeholder: "com.saltcorn.mobile.app",
|
|
2418
2451
|
value: builderSettings.appId || "",
|
|
2419
2452
|
})
|
|
2420
2453
|
)
|
|
@@ -3114,49 +3147,48 @@ router.get(
|
|
|
3114
3147
|
].join("")
|
|
3115
3148
|
)
|
|
3116
3149
|
)
|
|
3117
|
-
)
|
|
3150
|
+
),
|
|
3118
3151
|
// Share Extension provisioning profile
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
// )
|
|
3152
|
+
div(
|
|
3153
|
+
{ class: "row pb-3" },
|
|
3154
|
+
div(
|
|
3155
|
+
{ class: "col-sm-8" },
|
|
3156
|
+
label(
|
|
3157
|
+
{
|
|
3158
|
+
for: "shareProvisioningProfileInputId",
|
|
3159
|
+
class: "form-label fw-bold",
|
|
3160
|
+
},
|
|
3161
|
+
req.__("Share Extension Provisioning Profile"),
|
|
3162
|
+
a(
|
|
3163
|
+
{
|
|
3164
|
+
href: "javascript:ajax_modal('/admin/help/Provisioning Profile?')",
|
|
3165
|
+
},
|
|
3166
|
+
i({ class: "fas fa-question-circle ps-1" })
|
|
3167
|
+
)
|
|
3168
|
+
),
|
|
3169
|
+
select(
|
|
3170
|
+
{
|
|
3171
|
+
class: "form-select",
|
|
3172
|
+
name: "shareProvisioningProfile",
|
|
3173
|
+
id: "shareProvisioningProfileInputId",
|
|
3174
|
+
},
|
|
3175
|
+
[
|
|
3176
|
+
option({ value: "" }, ""),
|
|
3177
|
+
...provisioningFiles.map((file) =>
|
|
3178
|
+
option(
|
|
3179
|
+
{
|
|
3180
|
+
value: file.location,
|
|
3181
|
+
selected:
|
|
3182
|
+
builderSettings.shareProvisioningProfile ===
|
|
3183
|
+
file.location,
|
|
3184
|
+
},
|
|
3185
|
+
file.filename
|
|
3186
|
+
)
|
|
3187
|
+
),
|
|
3188
|
+
].join("")
|
|
3189
|
+
)
|
|
3190
|
+
)
|
|
3191
|
+
)
|
|
3160
3192
|
)
|
|
3161
3193
|
)
|
|
3162
3194
|
),
|
|
@@ -3425,11 +3457,10 @@ router.post(
|
|
|
3425
3457
|
keystoreAlias,
|
|
3426
3458
|
keystorePassword,
|
|
3427
3459
|
} = req.body;
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
let allowShareTo = false; // receiveShareTriggers.length > 0;
|
|
3460
|
+
const receiveShareTriggers = Trigger.find({
|
|
3461
|
+
when_trigger: "ReceiveMobileShareData",
|
|
3462
|
+
});
|
|
3463
|
+
let allowShareTo = receiveShareTriggers.length > 0;
|
|
3433
3464
|
if (allowShareTo && iOSPlatform && !shareProvisioningProfile) {
|
|
3434
3465
|
allowShareTo = false;
|
|
3435
3466
|
msgs.push({
|
|
@@ -4191,10 +4222,6 @@ admin_config_route({
|
|
|
4191
4222
|
{ section_header: "Progressive Web Application" },
|
|
4192
4223
|
"pwa_enabled",
|
|
4193
4224
|
{ name: "pwa_display", showIf: { pwa_enabled: true } },
|
|
4194
|
-
{
|
|
4195
|
-
name: "pwa_share_to_enabled",
|
|
4196
|
-
showIf: { pwa_enabled: true },
|
|
4197
|
-
},
|
|
4198
4225
|
{ name: "pwa_set_colors", showIf: { pwa_enabled: true } },
|
|
4199
4226
|
{
|
|
4200
4227
|
name: "pwa_theme_color",
|
package/routes/common_lists.js
CHANGED
|
@@ -12,6 +12,7 @@ const {
|
|
|
12
12
|
badge,
|
|
13
13
|
} = require("@saltcorn/markup");
|
|
14
14
|
const { get_base_url } = require("./utils.js");
|
|
15
|
+
const { getState } = require("@saltcorn/data/db/state");
|
|
15
16
|
const { h4, p, div, a, i, text, span, nbsp } = require("@saltcorn/markup/tags");
|
|
16
17
|
|
|
17
18
|
/**
|
|
@@ -57,7 +58,9 @@ const tablesList = async (
|
|
|
57
58
|
});
|
|
58
59
|
const tagsById = {};
|
|
59
60
|
tags.forEach((t) => (tagsById[t.id] = t));
|
|
60
|
-
|
|
61
|
+
const user_can_edit_tables =
|
|
62
|
+
req.user.role_id === 1 ||
|
|
63
|
+
getState().getConfig("min_role_edit_tables", 1) >= req.user.role_id;
|
|
61
64
|
const tagBadges = (table) => {
|
|
62
65
|
const myTags = tag_entries.filter((te) => te.table_id === table.id);
|
|
63
66
|
return myTags
|
|
@@ -95,23 +98,27 @@ const tablesList = async (
|
|
|
95
98
|
? `${getRole(t.min_role_read)} (read only)`
|
|
96
99
|
: `${getRole(t.min_role_read)}/${getRole(t.min_role_write)}`,
|
|
97
100
|
},
|
|
98
|
-
|
|
99
|
-
?
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
101
|
+
...(user_can_edit_tables
|
|
102
|
+
? [
|
|
103
|
+
!tagId
|
|
104
|
+
? {
|
|
105
|
+
label: req.__("Delete"),
|
|
106
|
+
key: (r) =>
|
|
107
|
+
r.name === "users" || r.external
|
|
108
|
+
? ""
|
|
109
|
+
: post_delete_btn(`/table/delete/${r.id}`, req, r.name),
|
|
110
|
+
}
|
|
111
|
+
: {
|
|
112
|
+
label: req.__("Remove From Tag"),
|
|
113
|
+
key: (r) =>
|
|
114
|
+
post_delete_btn(
|
|
115
|
+
`/tag-entries/remove/tables/${r.id}/${tagId}`,
|
|
116
|
+
req,
|
|
117
|
+
`${r.name} from this tag`
|
|
118
|
+
),
|
|
119
|
+
},
|
|
120
|
+
]
|
|
121
|
+
: []),
|
|
115
122
|
],
|
|
116
123
|
tables,
|
|
117
124
|
{
|
|
@@ -286,6 +293,10 @@ const viewsList = async (
|
|
|
286
293
|
});
|
|
287
294
|
const tagsById = {};
|
|
288
295
|
tags.forEach((t) => (tagsById[t.id] = t));
|
|
296
|
+
const user_can_inspect_tables =
|
|
297
|
+
req.user.role_id === 1 ||
|
|
298
|
+
getState().getConfig("min_role_edit_tables", 1) >= req.user.role_id ||
|
|
299
|
+
getState().getConfig("min_role_inspect_tables", 1) >= req.user.role_id;
|
|
289
300
|
|
|
290
301
|
const tagBadges = (view) => {
|
|
291
302
|
const myTags = tag_entries.filter((te) => te.view_id === view.id);
|
|
@@ -339,7 +350,10 @@ const viewsList = async (
|
|
|
339
350
|
: [
|
|
340
351
|
{
|
|
341
352
|
label: req.__("Table"),
|
|
342
|
-
key: (r) =>
|
|
353
|
+
key: (r) =>
|
|
354
|
+
user_can_inspect_tables
|
|
355
|
+
? link(`/table/${r.table}`, r.table)
|
|
356
|
+
: r.table,
|
|
343
357
|
sortlink: !tagId
|
|
344
358
|
? `set_state_field('_sortby', 'table', this)`
|
|
345
359
|
: undefined,
|
|
@@ -634,6 +648,10 @@ const getTriggerList = async (
|
|
|
634
648
|
});
|
|
635
649
|
const tagsById = {};
|
|
636
650
|
tags.forEach((t) => (tagsById[t.id] = t));
|
|
651
|
+
const user_can_inspect_tables =
|
|
652
|
+
req.user.role_id === 1 ||
|
|
653
|
+
getState().getConfig("min_role_edit_tables", 1) >= req.user.role_id ||
|
|
654
|
+
getState().getConfig("min_role_inspect_tables", 1) >= req.user.role_id;
|
|
637
655
|
|
|
638
656
|
const tagBadges = (trigger) => {
|
|
639
657
|
const myTags = tag_entries.filter((te) => te.trigger_id === trigger.id);
|
|
@@ -682,7 +700,9 @@ const getTriggerList = async (
|
|
|
682
700
|
label: req.__("Table or Channel"),
|
|
683
701
|
key: (r) =>
|
|
684
702
|
r.table_name
|
|
685
|
-
?
|
|
703
|
+
? user_can_inspect_tables
|
|
704
|
+
? a({ href: `/table/${r.table_name}` }, r.table_name)
|
|
705
|
+
: r.table_name
|
|
686
706
|
: r.channel,
|
|
687
707
|
},
|
|
688
708
|
!tagId
|