@saltcorn/server 1.1.1-beta.5 → 1.1.1-beta.7

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.
Files changed (153) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/auth/admin.js +8 -0
  3. package/locales/en.json +16 -1
  4. package/markup/admin.js +8 -3
  5. package/markup/blockly.js +4 -4
  6. package/package.json +9 -9
  7. package/public/blockly/blockly_compressed.js +2016 -0
  8. package/public/blockly/blockly_compressed.js.map +1 -0
  9. package/public/blockly/blocks_compressed.js +212 -0
  10. package/public/blockly/blocks_compressed.js.map +1 -0
  11. package/public/blockly/javascript_compressed.js +121 -0
  12. package/public/blockly/javascript_compressed.js.map +1 -0
  13. package/public/blockly/msg/ab.js +440 -0
  14. package/public/blockly/msg/ace.js +440 -0
  15. package/public/blockly/msg/af.js +440 -0
  16. package/public/blockly/msg/am.js +440 -0
  17. package/public/blockly/msg/ar.js +440 -0
  18. package/public/blockly/msg/ast.js +440 -0
  19. package/public/blockly/msg/az.js +440 -0
  20. package/public/blockly/msg/ba.js +440 -0
  21. package/public/blockly/msg/bcc.js +440 -0
  22. package/public/blockly/msg/be-tarask.js +440 -0
  23. package/public/blockly/msg/be.js +440 -0
  24. package/public/blockly/msg/bg.js +440 -0
  25. package/public/blockly/msg/bn.js +440 -0
  26. package/public/blockly/msg/br.js +440 -0
  27. package/public/blockly/msg/bs.js +440 -0
  28. package/public/blockly/msg/ca.js +440 -0
  29. package/public/blockly/msg/cdo.js +440 -0
  30. package/public/blockly/msg/cs.js +440 -0
  31. package/public/blockly/msg/da.js +440 -0
  32. package/public/blockly/msg/de.js +440 -0
  33. package/public/blockly/msg/diq.js +440 -0
  34. package/public/blockly/msg/dty.js +440 -0
  35. package/public/blockly/msg/ee.js +440 -0
  36. package/public/blockly/msg/el.js +440 -0
  37. package/public/blockly/msg/en-gb.js +440 -0
  38. package/public/blockly/msg/en.js +440 -0
  39. package/public/blockly/msg/eo.js +440 -0
  40. package/public/blockly/msg/es.js +440 -0
  41. package/public/blockly/msg/et.js +440 -0
  42. package/public/blockly/msg/eu.js +440 -0
  43. package/public/blockly/msg/fa.js +440 -0
  44. package/public/blockly/msg/fi.js +440 -0
  45. package/public/blockly/msg/fo.js +440 -0
  46. package/public/blockly/msg/fr.js +440 -0
  47. package/public/blockly/msg/frr.js +440 -0
  48. package/public/blockly/msg/gl.js +440 -0
  49. package/public/blockly/msg/gn.js +440 -0
  50. package/public/blockly/msg/gor.js +440 -0
  51. package/public/blockly/msg/ha.js +440 -0
  52. package/public/blockly/msg/hak.js +440 -0
  53. package/public/blockly/msg/he.js +440 -0
  54. package/public/blockly/msg/hi.js +440 -0
  55. package/public/blockly/msg/hr.js +440 -0
  56. package/public/blockly/msg/hrx.js +440 -0
  57. package/public/blockly/msg/hu.js +440 -0
  58. package/public/blockly/msg/hy.js +440 -0
  59. package/public/blockly/msg/ia.js +440 -0
  60. package/public/blockly/msg/id.js +440 -0
  61. package/public/blockly/msg/ig.js +440 -0
  62. package/public/blockly/msg/inh.js +440 -0
  63. package/public/blockly/msg/is.js +440 -0
  64. package/public/blockly/msg/it.js +440 -0
  65. package/public/blockly/msg/ja.js +440 -0
  66. package/public/blockly/msg/ka.js +440 -0
  67. package/public/blockly/msg/kab.js +440 -0
  68. package/public/blockly/msg/kbd-cyrl.js +440 -0
  69. package/public/blockly/msg/km.js +440 -0
  70. package/public/blockly/msg/kn.js +440 -0
  71. package/public/blockly/msg/ko.js +440 -0
  72. package/public/blockly/msg/ksh.js +440 -0
  73. package/public/blockly/msg/ku-latn.js +440 -0
  74. package/public/blockly/msg/ky.js +440 -0
  75. package/public/blockly/msg/la.js +440 -0
  76. package/public/blockly/msg/lb.js +440 -0
  77. package/public/blockly/msg/lki.js +440 -0
  78. package/public/blockly/msg/lo.js +440 -0
  79. package/public/blockly/msg/lrc.js +440 -0
  80. package/public/blockly/msg/lt.js +440 -0
  81. package/public/blockly/msg/lv.js +440 -0
  82. package/public/blockly/msg/mg.js +440 -0
  83. package/public/blockly/msg/mk.js +440 -0
  84. package/public/blockly/msg/ml.js +440 -0
  85. package/public/blockly/msg/mnw.js +440 -0
  86. package/public/blockly/msg/ms.js +440 -0
  87. package/public/blockly/msg/msg.d.ts +444 -0
  88. package/public/blockly/msg/my.js +440 -0
  89. package/public/blockly/msg/mzn.js +440 -0
  90. package/public/blockly/msg/nb.js +440 -0
  91. package/public/blockly/msg/ne.js +440 -0
  92. package/public/blockly/msg/nl.js +440 -0
  93. package/public/blockly/msg/oc.js +440 -0
  94. package/public/blockly/msg/olo.js +440 -0
  95. package/public/blockly/msg/pa.js +440 -0
  96. package/public/blockly/msg/pl.js +440 -0
  97. package/public/blockly/msg/pms.js +440 -0
  98. package/public/blockly/msg/ps.js +440 -0
  99. package/public/blockly/msg/pt-br.js +440 -0
  100. package/public/blockly/msg/pt.js +440 -0
  101. package/public/blockly/msg/ro.js +440 -0
  102. package/public/blockly/msg/ru.js +440 -0
  103. package/public/blockly/msg/sc.js +440 -0
  104. package/public/blockly/msg/sco.js +440 -0
  105. package/public/blockly/msg/sd.js +440 -0
  106. package/public/blockly/msg/shn.js +440 -0
  107. package/public/blockly/msg/si.js +440 -0
  108. package/public/blockly/msg/sk.js +440 -0
  109. package/public/blockly/msg/skr-arab.js +440 -0
  110. package/public/blockly/msg/sl.js +440 -0
  111. package/public/blockly/msg/smn.js +440 -0
  112. package/public/blockly/msg/sq.js +440 -0
  113. package/public/blockly/msg/sr-latn.js +440 -0
  114. package/public/blockly/msg/sr.js +440 -0
  115. package/public/blockly/msg/sv.js +440 -0
  116. package/public/blockly/msg/sw.js +440 -0
  117. package/public/blockly/msg/ta.js +440 -0
  118. package/public/blockly/msg/tcy.js +440 -0
  119. package/public/blockly/msg/te.js +440 -0
  120. package/public/blockly/msg/th.js +440 -0
  121. package/public/blockly/msg/ti.js +440 -0
  122. package/public/blockly/msg/tl.js +440 -0
  123. package/public/blockly/msg/tlh.js +440 -0
  124. package/public/blockly/msg/tr.js +440 -0
  125. package/public/blockly/msg/ug-arab.js +440 -0
  126. package/public/blockly/msg/uk.js +440 -0
  127. package/public/blockly/msg/ur.js +440 -0
  128. package/public/blockly/msg/uz.js +440 -0
  129. package/public/blockly/msg/vi.js +440 -0
  130. package/public/blockly/msg/xmf.js +440 -0
  131. package/public/blockly/msg/yo.js +440 -0
  132. package/public/blockly/msg/yue.js +440 -0
  133. package/public/blockly/msg/zgh.js +440 -0
  134. package/public/blockly/msg/zh-hans.js +440 -0
  135. package/public/blockly/msg/zh-hant.js +440 -0
  136. package/public/saltcorn-common.js +8 -1
  137. package/public/saltcorn.js +12 -0
  138. package/routes/actions.js +32 -25
  139. package/routes/admin.js +90 -63
  140. package/routes/common_lists.js +46 -24
  141. package/routes/fields.js +31 -9
  142. package/routes/list.js +17 -4
  143. package/routes/notifications.js +27 -20
  144. package/routes/pageedit.js +14 -13
  145. package/routes/plugins.js +0 -32
  146. package/routes/tables.js +173 -92
  147. package/routes/utils.js +27 -0
  148. package/routes/view.js +2 -1
  149. package/routes/viewedit.js +14 -13
  150. package/serve.js +52 -1
  151. package/tests/api.test.js +0 -18
  152. package/tests/plugins.test.js +2 -2
  153. package/wrapper.js +80 -42
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
- isAdmin,
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
- isAdmin,
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
- isAdmin,
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
- isAdmin,
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
- isAdmin,
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 });
@@ -523,7 +524,7 @@ function genWorkflowDiagram(steps) {
523
524
  );
524
525
  if (stepNames.includes(step.next_step)) {
525
526
  linkLines.push(
526
- ` ${step.mmname}-- <i class="fas fa-plus add-btw-nodes btw-nodes-${step.id}-${step.next_step}"></i> ---${step.mmnext}`
527
+ ` ${step.mmname} -- <i class="fas fa-plus add-btw-nodes btw-nodes-${step.id}-${step.next_step}"></i> --- ${step.mmnext}`
527
528
  );
528
529
  } else if (step.next_step) {
529
530
  let found = false;
@@ -928,7 +929,7 @@ const getMultiStepForm = async (req, id, table) => {
928
929
  */
929
930
  router.get(
930
931
  "/configure/:idorname",
931
- isAdmin,
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
- isAdmin,
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
- isAdmin,
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,7 +1212,13 @@ router.post(
1211
1212
  entity_name: trigger.name,
1212
1213
  });
1213
1214
  await trigger.delete();
1214
- res.redirect(`/actions/`);
1215
+ req.flash("success", req.__(`Trigger %s deleted`, trigger.name));
1216
+ let redirectTarget =
1217
+ req.query.on_done_redirect &&
1218
+ is_relative_url("/" + req.query.on_done_redirect)
1219
+ ? `/${req.query.on_done_redirect}`
1220
+ : "/actions/";
1221
+ res.redirect(redirectTarget);
1215
1222
  })
1216
1223
  );
1217
1224
 
@@ -1222,7 +1229,7 @@ router.post(
1222
1229
  */
1223
1230
  router.get(
1224
1231
  "/testrun/:id",
1225
- isAdmin,
1232
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1226
1233
  error_catcher(async (req, res) => {
1227
1234
  const { id } = req.params;
1228
1235
  const trigger = await Trigger.findOne({ id });
@@ -1333,7 +1340,7 @@ router.get(
1333
1340
  */
1334
1341
  router.post(
1335
1342
  "/clone/:id",
1336
- isAdmin,
1343
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1337
1344
  error_catcher(async (req, res) => {
1338
1345
  const { id } = req.params;
1339
1346
  const trig = await Trigger.findOne({ id });
@@ -1358,7 +1365,7 @@ router.post(
1358
1365
  */
1359
1366
  router.get(
1360
1367
  "/stepedit/:trigger_id/:step_id?",
1361
- isAdmin,
1368
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1362
1369
  error_catcher(async (req, res) => {
1363
1370
  const { trigger_id, step_id } = req.params;
1364
1371
  const { initial_step, after_step, before_step } = req.query;
@@ -1400,7 +1407,7 @@ router.get(
1400
1407
 
1401
1408
  router.post(
1402
1409
  "/stepedit/:trigger_id",
1403
- isAdmin,
1410
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1404
1411
  error_catcher(async (req, res) => {
1405
1412
  const { trigger_id } = req.params;
1406
1413
  const trigger = await Trigger.findOne({ id: trigger_id });
@@ -1499,7 +1506,7 @@ router.post(
1499
1506
 
1500
1507
  router.post(
1501
1508
  "/gen-copilot/:trigger_id",
1502
- isAdmin,
1509
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1503
1510
  error_catcher(async (req, res) => {
1504
1511
  const { trigger_id } = req.params;
1505
1512
  const trigger = await Trigger.findOne({ id: trigger_id });
@@ -1525,18 +1532,18 @@ router.post(
1525
1532
 
1526
1533
  router.post(
1527
1534
  "/delete-step/:step_id",
1528
- isAdmin,
1535
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1529
1536
  error_catcher(async (req, res) => {
1530
1537
  const { step_id } = req.params;
1531
1538
  const step = await WorkflowStep.findOne({ id: step_id });
1532
- await step.delete();
1539
+ await step.delete(true);
1533
1540
  res.json({ goto: `/actions/configure/${step.trigger_id}` });
1534
1541
  })
1535
1542
  );
1536
1543
 
1537
1544
  router.get(
1538
1545
  "/runs",
1539
- isAdmin,
1546
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1540
1547
  error_catcher(async (req, res) => {
1541
1548
  const trNames = {};
1542
1549
  const { _page, trigger } = req.query;
@@ -1563,7 +1570,7 @@ router.get(
1563
1570
  key: (run) => {
1564
1571
  switch (run.status) {
1565
1572
  case "Running":
1566
- return run.current_step;
1573
+ return run.current_step_name;
1567
1574
  case "Error":
1568
1575
  return run.error;
1569
1576
  case "Waiting":
@@ -1571,9 +1578,9 @@ router.get(
1571
1578
  return a(
1572
1579
  { href: `/actions/fill-workflow-form/${run.id}` },
1573
1580
  run.wait_info.output ? "Show " : "Fill ",
1574
- run.current_step
1581
+ run.current_step_name
1575
1582
  );
1576
- return run.current_step;
1583
+ return run.current_step_name;
1577
1584
  default:
1578
1585
  return "";
1579
1586
  }
@@ -1607,7 +1614,7 @@ router.get(
1607
1614
 
1608
1615
  router.get(
1609
1616
  "/run/:id",
1610
- isAdmin,
1617
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1611
1618
  error_catcher(async (req, res) => {
1612
1619
  const { id } = req.params;
1613
1620
 
@@ -1730,7 +1737,7 @@ router.get(
1730
1737
 
1731
1738
  router.post(
1732
1739
  "/delete-run/:id",
1733
- isAdmin,
1740
+ isAdminOrHasConfigMinRole("min_role_edit_triggers"),
1734
1741
  error_catcher(async (req, res) => {
1735
1742
  const { id } = req.params;
1736
1743
 
@@ -1794,7 +1801,7 @@ router.get(
1794
1801
  const trigger = await Trigger.findOne({ id: run.trigger_id });
1795
1802
  const step = await WorkflowStep.findOne({
1796
1803
  trigger_id: trigger.id,
1797
- name: run.current_step,
1804
+ name: run.current_step_name,
1798
1805
  });
1799
1806
 
1800
1807
  const form = await getWorkflowStepUserForm(run, trigger, step, req);
@@ -1822,7 +1829,7 @@ router.post(
1822
1829
  const trigger = await Trigger.findOne({ id: run.trigger_id });
1823
1830
  const step = await WorkflowStep.findOne({
1824
1831
  trigger_id: trigger.id,
1825
- name: run.current_step,
1832
+ name: run.current_step_name,
1826
1833
  });
1827
1834
 
1828
1835
  const form = await getWorkflowStepUserForm(run, trigger, step, req);
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
- isAdmin,
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
- isAdmin,
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 snap = await Snapshot.findOne({ id });
670
- await snap.restore_entity(type, name);
671
- req.flash(
672
- "success",
673
- `${type} ${name} restored to snapshot saved ${moment(
674
- snap.created
675
- ).fromNow()}`
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
- // disabled for now
3120
- // div(
3121
- // { class: "row pb-3" },
3122
- // div(
3123
- // { class: "col-sm-8" },
3124
- // label(
3125
- // {
3126
- // for: "shareProvisioningProfileInputId",
3127
- // class: "form-label fw-bold",
3128
- // },
3129
- // req.__("Share Extension Provisioning Profile"),
3130
- // a(
3131
- // {
3132
- // href: "javascript:ajax_modal('/admin/help/Provisioning Profile?')",
3133
- // },
3134
- // i({ class: "fas fa-question-circle ps-1" })
3135
- // )
3136
- // ),
3137
- // select(
3138
- // {
3139
- // class: "form-select",
3140
- // name: "shareProvisioningProfile",
3141
- // id: "shareProvisioningProfileInputId",
3142
- // },
3143
- // [
3144
- // option({ value: "" }, ""),
3145
- // ...provisioningFiles.map((file) =>
3146
- // option(
3147
- // {
3148
- // value: file.location,
3149
- // selected:
3150
- // builderSettings.shareProvisioningProfile ===
3151
- // file.location,
3152
- // },
3153
- // file.filename
3154
- // )
3155
- // ),
3156
- // ].join("")
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
- // const receiveShareTriggers = Trigger.find({
3429
- // when_trigger: "ReceiveMobileShareData",
3430
- // });
3431
- // disabeling share to support for now
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",
@@ -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
- !tagId
99
- ? {
100
- label: req.__("Delete"),
101
- key: (r) =>
102
- r.name === "users" || r.external
103
- ? ""
104
- : post_delete_btn(`/table/delete/${r.id}`, req, r.name),
105
- }
106
- : {
107
- label: req.__("Remove From Tag"),
108
- key: (r) =>
109
- post_delete_btn(
110
- `/tag-entries/remove/tables/${r.id}/${tagId}`,
111
- req,
112
- `${r.name} from this tag`
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) => link(`/table/${r.table}`, r.table),
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,
@@ -588,7 +602,7 @@ const getPageGroupList = (rows, roles, req) => {
588
602
  );
589
603
  };
590
604
 
591
- const trigger_dropdown = (trigger, req, on_done_redirect_str = "") =>
605
+ const trigger_dropdown = (trigger, req, on_done_redirect_str = "") =>
592
606
  settingsDropdown(`dropdownMenuButton${trigger.id}`, [
593
607
  a(
594
608
  {
@@ -624,16 +638,22 @@ const trigger_dropdown = (trigger, req, on_done_redirect_str = "") =>
624
638
  const getTriggerList = async (
625
639
  triggers,
626
640
  req,
627
- { tagId, domId, showList, filterOnTag } = {}
641
+ { tagId, domId, showList, filterOnTag, on_done_redirect } = {}
628
642
  ) => {
629
643
  const base_url = get_base_url(req);
630
644
  const tags = await Tag.find();
631
-
645
+ const on_done_redirect_str = on_done_redirect
646
+ ? `?on_done_redirect=${on_done_redirect}`
647
+ : "";
632
648
  const tag_entries = await TagEntry.find({
633
649
  not: { trigger_id: null },
634
650
  });
635
651
  const tagsById = {};
636
652
  tags.forEach((t) => (tagsById[t.id] = t));
653
+ const user_can_inspect_tables =
654
+ req.user.role_id === 1 ||
655
+ getState().getConfig("min_role_edit_tables", 1) >= req.user.role_id ||
656
+ getState().getConfig("min_role_inspect_tables", 1) >= req.user.role_id;
637
657
 
638
658
  const tagBadges = (trigger) => {
639
659
  const myTags = tag_entries.filter((te) => te.trigger_id === trigger.id);
@@ -682,13 +702,15 @@ const getTriggerList = async (
682
702
  label: req.__("Table or Channel"),
683
703
  key: (r) =>
684
704
  r.table_name
685
- ? a({ href: `/table/${r.table_name}` }, r.table_name)
705
+ ? user_can_inspect_tables
706
+ ? a({ href: `/table/${r.table_name}` }, r.table_name)
707
+ : r.table_name
686
708
  : r.channel,
687
709
  },
688
710
  !tagId
689
711
  ? {
690
712
  label: "",
691
- key: (r) => trigger_dropdown(r, req),
713
+ key: (r) => trigger_dropdown(r, req, on_done_redirect_str),
692
714
  }
693
715
  : {
694
716
  label: req.__("Remove From Tag"),
package/routes/fields.js CHANGED
@@ -24,7 +24,11 @@ const {
24
24
  } = require("@saltcorn/data/models/expression");
25
25
  const db = require("@saltcorn/data/db");
26
26
 
27
- const { isAdmin, error_catcher } = require("./utils.js");
27
+ const {
28
+ isAdmin,
29
+ error_catcher,
30
+ isAdminOrHasConfigMinRole,
31
+ } = require("./utils.js");
28
32
  const expressionBlurb = require("../markup/expression_blurb");
29
33
  const {
30
34
  readState,
@@ -774,7 +778,10 @@ const fieldFlow = (req) =>
774
778
  */
775
779
  router.get(
776
780
  "/:id",
777
- isAdmin,
781
+ isAdminOrHasConfigMinRole([
782
+ "min_role_edit_tables",
783
+ "min_role_inspect_tables",
784
+ ]),
778
785
  error_catcher(async (req, res) => {
779
786
  const { id } = req.params;
780
787
  const field = await Field.findOne({ id });
@@ -830,7 +837,7 @@ router.get(
830
837
  */
831
838
  router.get(
832
839
  "/new/:table_id",
833
- isAdmin,
840
+ isAdminOrHasConfigMinRole("min_role_edit_tables"),
834
841
  error_catcher(async (req, res) => {
835
842
  const { table_id } = req.params;
836
843
  const table = Table.findOne({ id: table_id });
@@ -867,7 +874,7 @@ router.get(
867
874
  */
868
875
  router.post(
869
876
  "/delete/:id",
870
- isAdmin,
877
+ isAdminOrHasConfigMinRole("min_role_edit_tables"),
871
878
  error_catcher(async (req, res) => {
872
879
  const { id } = req.params;
873
880
  const f = await Field.findOne({ id });
@@ -892,7 +899,7 @@ router.post(
892
899
  */
893
900
  router.post(
894
901
  "/",
895
- isAdmin,
902
+ isAdminOrHasConfigMinRole("min_role_edit_tables"),
896
903
  error_catcher(async (req, res) => {
897
904
  const wf = fieldFlow(req);
898
905
  const wfres = await wf.run(req.body, req);
@@ -941,7 +948,10 @@ router.post(
941
948
  */
942
949
  router.post(
943
950
  "/test-formula",
944
- isAdmin,
951
+ isAdminOrHasConfigMinRole([
952
+ "min_role_edit_tables",
953
+ "min_role_inspect_tables",
954
+ ]),
945
955
  error_catcher(async (req, res) => {
946
956
  let { formula, tablename, stored } = req.body;
947
957
  if (stored === "false") stored = false;
@@ -1231,7 +1241,11 @@ router.post(
1231
1241
  */
1232
1242
  router.post(
1233
1243
  "/preview/:tableName/:fieldName/:fieldview",
1234
- isAdmin,
1244
+ isAdminOrHasConfigMinRole([
1245
+ "min_role_edit_tables",
1246
+ "min_role_edit_views",
1247
+ "min_role_inspect_tables",
1248
+ ]),
1235
1249
  error_catcher(async (req, res) => {
1236
1250
  const { tableName, fieldName, fieldview } = req.params;
1237
1251
  const table = Table.findOne({ name: tableName });
@@ -1323,7 +1337,11 @@ router.post(
1323
1337
  */
1324
1338
  router.post(
1325
1339
  "/preview/:tableName/:fieldName/",
1326
- isAdmin,
1340
+ isAdminOrHasConfigMinRole([
1341
+ "min_role_edit_tables",
1342
+ "min_role_edit_views",
1343
+ "min_role_inspect_tables",
1344
+ ]),
1327
1345
  error_catcher(async (req, res) => {
1328
1346
  res.send("");
1329
1347
  })
@@ -1331,7 +1349,11 @@ router.post(
1331
1349
 
1332
1350
  router.post(
1333
1351
  "/fieldviewcfgform/:tableName",
1334
- isAdmin,
1352
+ isAdminOrHasConfigMinRole([
1353
+ "min_role_edit_tables",
1354
+ "min_role_edit_views",
1355
+ "min_role_inspect_tables",
1356
+ ]),
1335
1357
  error_catcher(async (req, res) => {
1336
1358
  const { tableName } = req.params;
1337
1359
  let {