@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/routes/tables.js
CHANGED
|
@@ -27,7 +27,12 @@ const {
|
|
|
27
27
|
recalculate_for_stored,
|
|
28
28
|
expressionValidator,
|
|
29
29
|
} = require("@saltcorn/data/models/expression");
|
|
30
|
-
const {
|
|
30
|
+
const {
|
|
31
|
+
isAdmin,
|
|
32
|
+
error_catcher,
|
|
33
|
+
setTenant,
|
|
34
|
+
isAdminOrHasConfigMinRole,
|
|
35
|
+
} = require("./utils.js");
|
|
31
36
|
const Form = require("@saltcorn/data/models/form");
|
|
32
37
|
const {
|
|
33
38
|
span,
|
|
@@ -230,7 +235,7 @@ const tableForm = async (table, req) => {
|
|
|
230
235
|
*/
|
|
231
236
|
router.get(
|
|
232
237
|
"/new/",
|
|
233
|
-
|
|
238
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
234
239
|
error_catcher(async (req, res) => {
|
|
235
240
|
const table_provider_names = Object.keys(getState().table_providers);
|
|
236
241
|
res.sendWrap(req.__(`New table`), {
|
|
@@ -377,7 +382,7 @@ router.post(
|
|
|
377
382
|
*/
|
|
378
383
|
router.get(
|
|
379
384
|
"/create-from-csv",
|
|
380
|
-
|
|
385
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
381
386
|
error_catcher(async (req, res) => {
|
|
382
387
|
res.sendWrap(req.__(`Create table from CSV file`), {
|
|
383
388
|
above: [
|
|
@@ -430,7 +435,7 @@ router.get(
|
|
|
430
435
|
router.post(
|
|
431
436
|
"/create-from-csv",
|
|
432
437
|
setTenant,
|
|
433
|
-
|
|
438
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
434
439
|
error_catcher(async (req, res) => {
|
|
435
440
|
if (req.body.name && req.files && req.files.file) {
|
|
436
441
|
const name = req.body.name;
|
|
@@ -573,7 +578,10 @@ const screenshotPanel = () =>
|
|
|
573
578
|
*/
|
|
574
579
|
router.get(
|
|
575
580
|
"/relationship-diagram",
|
|
576
|
-
|
|
581
|
+
isAdminOrHasConfigMinRole([
|
|
582
|
+
"min_role_edit_tables",
|
|
583
|
+
"min_role_inspect_tables",
|
|
584
|
+
]),
|
|
577
585
|
error_catcher(async (req, res) => {
|
|
578
586
|
const tables = await Table.find_with_external({}, { orderBy: "name" });
|
|
579
587
|
res.sendWrap(
|
|
@@ -711,7 +719,7 @@ const attribBadges = (f) => {
|
|
|
711
719
|
"table",
|
|
712
720
|
"agg_field",
|
|
713
721
|
"agg_relation",
|
|
714
|
-
"calc_joinfields"
|
|
722
|
+
"calc_joinfields",
|
|
715
723
|
].includes(k)
|
|
716
724
|
)
|
|
717
725
|
return;
|
|
@@ -734,7 +742,10 @@ const attribBadges = (f) => {
|
|
|
734
742
|
*/
|
|
735
743
|
router.get(
|
|
736
744
|
"/:idorname",
|
|
737
|
-
|
|
745
|
+
isAdminOrHasConfigMinRole([
|
|
746
|
+
"min_role_edit_tables",
|
|
747
|
+
"min_role_inspect_tables",
|
|
748
|
+
]),
|
|
738
749
|
error_catcher(async (req, res) => {
|
|
739
750
|
const { idorname } = req.params;
|
|
740
751
|
let id = parseInt(idorname);
|
|
@@ -749,6 +760,18 @@ router.get(
|
|
|
749
760
|
res.redirect(`/table`);
|
|
750
761
|
return;
|
|
751
762
|
}
|
|
763
|
+
|
|
764
|
+
const user_can_edit_tables =
|
|
765
|
+
req.user.role_id === 1 ||
|
|
766
|
+
getState().getConfig("min_role_edit_tables", 1) >= req.user.role_id;
|
|
767
|
+
|
|
768
|
+
const user_can_edit_views =
|
|
769
|
+
req.user.role_id === 1 ||
|
|
770
|
+
getState().getConfig("min_role_edit_views", 1) >= req.user.role_id;
|
|
771
|
+
const user_can_edit_triggers =
|
|
772
|
+
req.user.role_id === 1 ||
|
|
773
|
+
getState().getConfig("min_role_edit_triggers", 1) >= req.user.role_id;
|
|
774
|
+
|
|
752
775
|
const nrows = await table.countRows({}, { forUser: req.user });
|
|
753
776
|
const fields = table.getFields();
|
|
754
777
|
const { child_relations } = await table.get_child_relations();
|
|
@@ -764,13 +787,14 @@ router.get(
|
|
|
764
787
|
fieldCard = [
|
|
765
788
|
h4(req.__(`No fields defined in %s table`, table.name)),
|
|
766
789
|
p(req.__("Fields define the columns in your table.")),
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
790
|
+
user_can_edit_tables &&
|
|
791
|
+
a(
|
|
792
|
+
{
|
|
793
|
+
href: `/field/new/${table.id}`,
|
|
794
|
+
class: "btn btn-primary add-field",
|
|
795
|
+
},
|
|
796
|
+
req.__("Add field to table")
|
|
797
|
+
),
|
|
774
798
|
];
|
|
775
799
|
} else {
|
|
776
800
|
const tableHtml = mkTable(
|
|
@@ -787,7 +811,7 @@ router.get(
|
|
|
787
811
|
r.typename +
|
|
788
812
|
span({ class: "badge bg-danger ms-1" }, "Unknown type"),
|
|
789
813
|
},
|
|
790
|
-
...(table.external
|
|
814
|
+
...(table.external || !user_can_edit_tables
|
|
791
815
|
? []
|
|
792
816
|
: [
|
|
793
817
|
{
|
|
@@ -804,7 +828,7 @@ router.get(
|
|
|
804
828
|
key: (r) => attribBadges(r),
|
|
805
829
|
},
|
|
806
830
|
{ label: req.__("Variable name"), key: (t) => code(t.name) },
|
|
807
|
-
...(table.external
|
|
831
|
+
...(table.external || !user_can_edit_tables
|
|
808
832
|
? []
|
|
809
833
|
: [
|
|
810
834
|
{
|
|
@@ -842,6 +866,7 @@ router.get(
|
|
|
842
866
|
: "",
|
|
843
867
|
!table.external &&
|
|
844
868
|
!table.provider_name &&
|
|
869
|
+
user_can_edit_tables &&
|
|
845
870
|
a(
|
|
846
871
|
{
|
|
847
872
|
href: `/field/new/${table.id}`,
|
|
@@ -869,41 +894,46 @@ router.get(
|
|
|
869
894
|
p(req.__("Views define how table rows are displayed to the user"))
|
|
870
895
|
);
|
|
871
896
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
table
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
897
|
+
if (user_can_edit_views)
|
|
898
|
+
viewCard = {
|
|
899
|
+
type: "card",
|
|
900
|
+
id: "table-views",
|
|
901
|
+
title: req.__("Views of this table"),
|
|
902
|
+
contents:
|
|
903
|
+
viewCardContents +
|
|
904
|
+
a(
|
|
905
|
+
{
|
|
906
|
+
href: `/viewedit/new?table=${encodeURIComponent(
|
|
907
|
+
table.name
|
|
908
|
+
)}&on_done_redirect=${encodeURIComponent(
|
|
909
|
+
`table/${table.name}`
|
|
910
|
+
)}`,
|
|
911
|
+
class: "btn btn-primary",
|
|
912
|
+
},
|
|
913
|
+
req.__("Create view")
|
|
914
|
+
),
|
|
915
|
+
};
|
|
916
|
+
if (user_can_edit_triggers)
|
|
917
|
+
triggerCard = {
|
|
918
|
+
type: "card",
|
|
919
|
+
id: "table-triggers",
|
|
920
|
+
title: req.__("Triggers on table"),
|
|
921
|
+
contents:
|
|
922
|
+
(triggers.length
|
|
923
|
+
? await getTriggerList(triggers, req)
|
|
924
|
+
: p("Triggers run actions in response to events on this table")) +
|
|
925
|
+
a(
|
|
926
|
+
{
|
|
927
|
+
href: `/actions/new?table=${encodeURIComponent(
|
|
928
|
+
table.name
|
|
929
|
+
)}&on_done_redirect=${encodeURIComponent(
|
|
930
|
+
`table/${table.name}`
|
|
931
|
+
)}`,
|
|
932
|
+
class: "btn btn-primary",
|
|
933
|
+
},
|
|
934
|
+
req.__("Create trigger")
|
|
935
|
+
),
|
|
936
|
+
};
|
|
907
937
|
}
|
|
908
938
|
const models = await Model.find({ table_id: table.id });
|
|
909
939
|
const modelCard = div(
|
|
@@ -1025,6 +1055,7 @@ router.get(
|
|
|
1025
1055
|
settingsDropdown(`dataMenuButton`, [
|
|
1026
1056
|
// rename table doesnt supported for sqlite
|
|
1027
1057
|
!db.isSQLite &&
|
|
1058
|
+
user_can_edit_tables &&
|
|
1028
1059
|
table.name !== "users" &&
|
|
1029
1060
|
a(
|
|
1030
1061
|
{
|
|
@@ -1039,21 +1070,24 @@ router.get(
|
|
|
1039
1070
|
req.__("Recalculate stored fields"),
|
|
1040
1071
|
req
|
|
1041
1072
|
),
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1073
|
+
user_can_edit_tables &&
|
|
1074
|
+
post_dropdown_item(
|
|
1075
|
+
`/table/delete-all-rows/${encodeURIComponent(table.name)}`,
|
|
1076
|
+
'<i class="far fa-trash-alt"></i> ' +
|
|
1077
|
+
req.__("Delete all rows"),
|
|
1078
|
+
req,
|
|
1079
|
+
true
|
|
1080
|
+
),
|
|
1081
|
+
user_can_edit_tables &&
|
|
1082
|
+
table.name !== "users" &&
|
|
1050
1083
|
post_dropdown_item(
|
|
1051
1084
|
`/table/forget-table/${table.id}`,
|
|
1052
1085
|
'<i class="fas fa-recycle"></i> ' + req.__("Forget table"),
|
|
1053
1086
|
req,
|
|
1054
1087
|
true
|
|
1055
1088
|
),
|
|
1056
|
-
|
|
1089
|
+
user_can_edit_tables &&
|
|
1090
|
+
table.name !== "users" &&
|
|
1057
1091
|
post_dropdown_item(
|
|
1058
1092
|
`/table/delete/${table.id}`,
|
|
1059
1093
|
'<i class="fas fa-trash"></i> ' + req.__("Delete table"),
|
|
@@ -1067,6 +1101,9 @@ router.get(
|
|
|
1067
1101
|
if (table.ownership_formula && !table.ownership_field_id)
|
|
1068
1102
|
table.ownership_field_id = "_formula";
|
|
1069
1103
|
const tblForm = await tableForm(table, req);
|
|
1104
|
+
if (!user_can_edit_tables) {
|
|
1105
|
+
tblForm.fields.forEach((f) => (f.disabled = true));
|
|
1106
|
+
}
|
|
1070
1107
|
res.sendWrap(req.__(`%s table`, table.name), {
|
|
1071
1108
|
above: [
|
|
1072
1109
|
{
|
|
@@ -1105,7 +1142,7 @@ router.get(
|
|
|
1105
1142
|
titleAjaxIndicator: true,
|
|
1106
1143
|
contents: renderForm(tblForm, req.csrfToken()),
|
|
1107
1144
|
},
|
|
1108
|
-
...(Model.has_templates
|
|
1145
|
+
...(Model.has_templates && req.user.role_id === 1
|
|
1109
1146
|
? [
|
|
1110
1147
|
{
|
|
1111
1148
|
type: "card",
|
|
@@ -1127,7 +1164,7 @@ router.get(
|
|
|
1127
1164
|
*/
|
|
1128
1165
|
router.post(
|
|
1129
1166
|
"/",
|
|
1130
|
-
|
|
1167
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1131
1168
|
error_catcher(async (req, res) => {
|
|
1132
1169
|
const v = req.body;
|
|
1133
1170
|
if (typeof v.id === "undefined" && typeof v.external === "undefined") {
|
|
@@ -1228,7 +1265,7 @@ router.post(
|
|
|
1228
1265
|
*/
|
|
1229
1266
|
router.post(
|
|
1230
1267
|
"/delete/:id",
|
|
1231
|
-
|
|
1268
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1232
1269
|
error_catcher(async (req, res) => {
|
|
1233
1270
|
const { id } = req.params;
|
|
1234
1271
|
const t = Table.findOne({ id });
|
|
@@ -1280,7 +1317,7 @@ router.post(
|
|
|
1280
1317
|
);
|
|
1281
1318
|
router.post(
|
|
1282
1319
|
"/forget-table/:id",
|
|
1283
|
-
|
|
1320
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1284
1321
|
error_catcher(async (req, res) => {
|
|
1285
1322
|
const { id } = req.params;
|
|
1286
1323
|
const t = Table.findOne({ id });
|
|
@@ -1317,7 +1354,10 @@ router.post(
|
|
|
1317
1354
|
*/
|
|
1318
1355
|
router.get(
|
|
1319
1356
|
"/",
|
|
1320
|
-
|
|
1357
|
+
isAdminOrHasConfigMinRole([
|
|
1358
|
+
"min_role_edit_tables",
|
|
1359
|
+
"min_role_inspect_tables",
|
|
1360
|
+
]),
|
|
1321
1361
|
error_catcher(async (req, res) => {
|
|
1322
1362
|
const tblq = {};
|
|
1323
1363
|
let filterOnTag;
|
|
@@ -1329,6 +1369,11 @@ router.get(
|
|
|
1329
1369
|
tblq.id = { in: tagEntries.map((te) => te.table_id).filter(Boolean) };
|
|
1330
1370
|
filterOnTag = await Tag.findOne({ id: +req.query._tag });
|
|
1331
1371
|
}
|
|
1372
|
+
|
|
1373
|
+
const user_can_edit_tables =
|
|
1374
|
+
req.user.role_id === 1 ||
|
|
1375
|
+
getState().getConfig("min_role_edit_tables", 1) >= req.user.role_id;
|
|
1376
|
+
|
|
1332
1377
|
const rows = await Table.find_with_external(tblq, {
|
|
1333
1378
|
orderBy: "name",
|
|
1334
1379
|
nocase: true,
|
|
@@ -1337,20 +1382,23 @@ router.get(
|
|
|
1337
1382
|
const getRole = (rid) => roles.find((r) => r.id === rid).role;
|
|
1338
1383
|
const mainCard = await tablesList(rows, req, { filterOnTag });
|
|
1339
1384
|
const createCard = div(
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1385
|
+
user_can_edit_tables &&
|
|
1386
|
+
a(
|
|
1387
|
+
{ href: `/table/new`, class: "btn btn-primary mt-1 me-3" },
|
|
1388
|
+
i({ class: "fas fa-plus-square me-1" }),
|
|
1389
|
+
req.__("Create table")
|
|
1390
|
+
),
|
|
1391
|
+
user_can_edit_tables &&
|
|
1392
|
+
a(
|
|
1393
|
+
{
|
|
1394
|
+
href: `/table/create-from-csv`,
|
|
1395
|
+
class: "btn btn-secondary me-3 mt-1",
|
|
1396
|
+
},
|
|
1397
|
+
i({ class: "fas fa-upload me-1" }),
|
|
1398
|
+
req.__("Create from CSV upload")
|
|
1399
|
+
),
|
|
1400
|
+
req.user.role_id === 1 &&
|
|
1401
|
+
!db.isSQLite &&
|
|
1354
1402
|
a(
|
|
1355
1403
|
{
|
|
1356
1404
|
href: `/table/discover`,
|
|
@@ -1396,10 +1444,18 @@ router.get(
|
|
|
1396
1444
|
*/
|
|
1397
1445
|
router.get(
|
|
1398
1446
|
"/download/:name",
|
|
1399
|
-
|
|
1447
|
+
isAdminOrHasConfigMinRole([
|
|
1448
|
+
"min_role_edit_tables",
|
|
1449
|
+
"min_role_inspect_tables",
|
|
1450
|
+
]),
|
|
1400
1451
|
error_catcher(async (req, res) => {
|
|
1401
1452
|
const { name } = req.params;
|
|
1402
1453
|
const table = Table.findOne({ name });
|
|
1454
|
+
if (table.min_role_read < req.user.role_id) {
|
|
1455
|
+
req.flash("error", "Not authorized to read table");
|
|
1456
|
+
res.redirect(`/table/${table.id}`);
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1403
1459
|
const rows = await table.getRows({}, { orderBy: "id", forUser: req.user });
|
|
1404
1460
|
res.setHeader("Content-Type", "text/csv");
|
|
1405
1461
|
res.setHeader("Content-Disposition", `attachment; filename="${name}.csv"`);
|
|
@@ -1440,7 +1496,10 @@ router.get(
|
|
|
1440
1496
|
*/
|
|
1441
1497
|
router.get(
|
|
1442
1498
|
"/constraints/:id",
|
|
1443
|
-
|
|
1499
|
+
isAdminOrHasConfigMinRole([
|
|
1500
|
+
"min_role_edit_tables",
|
|
1501
|
+
"min_role_inspect_tables",
|
|
1502
|
+
]),
|
|
1444
1503
|
error_catcher(async (req, res) => {
|
|
1445
1504
|
const { id } = req.params;
|
|
1446
1505
|
const table = Table.findOne({ id });
|
|
@@ -1642,7 +1701,7 @@ router.get(
|
|
|
1642
1701
|
*/
|
|
1643
1702
|
router.post(
|
|
1644
1703
|
"/add-constraint/:id/:type",
|
|
1645
|
-
|
|
1704
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1646
1705
|
error_catcher(async (req, res) => {
|
|
1647
1706
|
const { id, type } = req.params;
|
|
1648
1707
|
const table = Table.findOne({ id });
|
|
@@ -1738,7 +1797,7 @@ router.get(
|
|
|
1738
1797
|
*/
|
|
1739
1798
|
router.post(
|
|
1740
1799
|
"/rename/:id",
|
|
1741
|
-
|
|
1800
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1742
1801
|
error_catcher(async (req, res) => {
|
|
1743
1802
|
const { id } = req.params;
|
|
1744
1803
|
const table = Table.findOne({ id });
|
|
@@ -1762,7 +1821,7 @@ router.post(
|
|
|
1762
1821
|
*/
|
|
1763
1822
|
router.post(
|
|
1764
1823
|
"/delete-constraint/:id",
|
|
1765
|
-
|
|
1824
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1766
1825
|
error_catcher(async (req, res) => {
|
|
1767
1826
|
const { id } = req.params;
|
|
1768
1827
|
const cons = await TableConstraint.findOne({ id });
|
|
@@ -1879,7 +1938,10 @@ const previewCSV = async ({ newPath, table, req, res, full }) => {
|
|
|
1879
1938
|
router.post(
|
|
1880
1939
|
"/upload_to_table/:name",
|
|
1881
1940
|
setTenant, // TODO why is this needed?????
|
|
1882
|
-
|
|
1941
|
+
isAdminOrHasConfigMinRole([
|
|
1942
|
+
"min_role_edit_tables",
|
|
1943
|
+
"min_role_inspect_tables",
|
|
1944
|
+
]),
|
|
1883
1945
|
error_catcher(async (req, res) => {
|
|
1884
1946
|
const { name } = req.params;
|
|
1885
1947
|
const table = Table.findOne({ name });
|
|
@@ -1888,6 +1950,11 @@ router.post(
|
|
|
1888
1950
|
res.redirect(`/table/${table.id}`);
|
|
1889
1951
|
return;
|
|
1890
1952
|
}
|
|
1953
|
+
if (table.min_role_write < req.user.role_id) {
|
|
1954
|
+
req.flash("error", "Not authorized to write to table");
|
|
1955
|
+
res.redirect(`/table/${table.id}`);
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1891
1958
|
|
|
1892
1959
|
const newPath = File.get_new_path();
|
|
1893
1960
|
await req.files.file.mv(newPath);
|
|
@@ -1898,7 +1965,10 @@ router.post(
|
|
|
1898
1965
|
|
|
1899
1966
|
router.get(
|
|
1900
1967
|
"/preview_full_csv_file/:name/:filename",
|
|
1901
|
-
|
|
1968
|
+
isAdminOrHasConfigMinRole([
|
|
1969
|
+
"min_role_edit_tables",
|
|
1970
|
+
"min_role_inspect_tables",
|
|
1971
|
+
]),
|
|
1902
1972
|
error_catcher(async (req, res) => {
|
|
1903
1973
|
const { name, filename } = req.params;
|
|
1904
1974
|
const table = Table.findOne({ name });
|
|
@@ -1909,7 +1979,10 @@ router.get(
|
|
|
1909
1979
|
|
|
1910
1980
|
router.post(
|
|
1911
1981
|
"/finish_upload_to_table/:name/:filename",
|
|
1912
|
-
|
|
1982
|
+
isAdminOrHasConfigMinRole([
|
|
1983
|
+
"min_role_edit_tables",
|
|
1984
|
+
"min_role_inspect_tables",
|
|
1985
|
+
]),
|
|
1913
1986
|
error_catcher(async (req, res) => {
|
|
1914
1987
|
const { name, filename } = req.params;
|
|
1915
1988
|
const table = Table.findOne({ name });
|
|
@@ -1938,7 +2011,7 @@ router.post(
|
|
|
1938
2011
|
*/
|
|
1939
2012
|
router.post(
|
|
1940
2013
|
"/delete-all-rows/:name",
|
|
1941
|
-
|
|
2014
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1942
2015
|
error_catcher(async (req, res) => {
|
|
1943
2016
|
const { name } = req.params;
|
|
1944
2017
|
const table = Table.findOne({ name });
|
|
@@ -1963,7 +2036,10 @@ router.post(
|
|
|
1963
2036
|
*/
|
|
1964
2037
|
router.post(
|
|
1965
2038
|
"/recalc-stored/:name",
|
|
1966
|
-
|
|
2039
|
+
isAdminOrHasConfigMinRole([
|
|
2040
|
+
"min_role_edit_tables",
|
|
2041
|
+
"min_role_inspect_tables",
|
|
2042
|
+
]),
|
|
1967
2043
|
error_catcher(async (req, res) => {
|
|
1968
2044
|
const { name } = req.params;
|
|
1969
2045
|
const table = Table.findOne({ name });
|
|
@@ -2054,7 +2130,10 @@ const get_provider_workflow = (table, req) => {
|
|
|
2054
2130
|
|
|
2055
2131
|
router.get(
|
|
2056
2132
|
"/provider-cfg/:id",
|
|
2057
|
-
|
|
2133
|
+
isAdminOrHasConfigMinRole([
|
|
2134
|
+
"min_role_edit_tables",
|
|
2135
|
+
"min_role_inspect_tables",
|
|
2136
|
+
]),
|
|
2058
2137
|
error_catcher(async (req, res) => {
|
|
2059
2138
|
const { id } = req.params;
|
|
2060
2139
|
const { step } = req.query;
|
|
@@ -2080,7 +2159,7 @@ router.get(
|
|
|
2080
2159
|
|
|
2081
2160
|
router.post(
|
|
2082
2161
|
"/provider-cfg/:id",
|
|
2083
|
-
|
|
2162
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
2084
2163
|
error_catcher(async (req, res) => {
|
|
2085
2164
|
const { id } = req.params;
|
|
2086
2165
|
const { step } = req.query;
|
|
@@ -2099,7 +2178,7 @@ router.post(
|
|
|
2099
2178
|
|
|
2100
2179
|
router.post(
|
|
2101
2180
|
"/repair-composite-primary/:id",
|
|
2102
|
-
|
|
2181
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
2103
2182
|
error_catcher(async (req, res) => {
|
|
2104
2183
|
const { id } = req.params;
|
|
2105
2184
|
|
package/routes/utils.js
CHANGED
|
@@ -95,6 +95,32 @@ function isAdmin(req, res, next) {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
const isAdminOrHasConfigMinRole = (cfg) => (req, res, next) => {
|
|
99
|
+
const cur_tenant = db.getTenantSchema();
|
|
100
|
+
//console.log({ cur_tenant, user: req.user });
|
|
101
|
+
if (
|
|
102
|
+
req.user &&
|
|
103
|
+
(req.user.role_id === 1 ||
|
|
104
|
+
(Array.isArray(cfg)
|
|
105
|
+
? cfg.some(
|
|
106
|
+
(one_cfg) => getState().getConfig(one_cfg, 1) >= req.user.role_id
|
|
107
|
+
)
|
|
108
|
+
: getState().getConfig(cfg, 1) >= req.user.role_id)) &&
|
|
109
|
+
req.user.tenant === cur_tenant
|
|
110
|
+
) {
|
|
111
|
+
next();
|
|
112
|
+
} else {
|
|
113
|
+
req.flash("danger", req.__("Must be admin"));
|
|
114
|
+
res.redirect(
|
|
115
|
+
req.user && req.user.pending_user
|
|
116
|
+
? "/auth/twofa/login/totp"
|
|
117
|
+
: req.user
|
|
118
|
+
? "/"
|
|
119
|
+
: `/auth/login?dest=${encodeURIComponent(req.originalUrl)}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
98
124
|
/**
|
|
99
125
|
* Sets language for HTTP Request / HTTP Responce
|
|
100
126
|
* @param {object} req
|
|
@@ -590,6 +616,7 @@ module.exports = {
|
|
|
590
616
|
csrfField,
|
|
591
617
|
loggedIn,
|
|
592
618
|
isAdmin,
|
|
619
|
+
isAdminOrHasConfigMinRole,
|
|
593
620
|
get_base_url,
|
|
594
621
|
error_catcher,
|
|
595
622
|
scan_for_page_title,
|
package/routes/view.js
CHANGED
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
error_catcher,
|
|
17
17
|
scan_for_page_title,
|
|
18
18
|
setTenant,
|
|
19
|
+
isAdminOrHasConfigMinRole,
|
|
19
20
|
} = require("../routes/utils.js");
|
|
20
21
|
const { add_edit_bar } = require("../markup/admin.js");
|
|
21
22
|
const { InvalidConfiguration, isTest } = require("@saltcorn/data/utils");
|
|
@@ -166,7 +167,7 @@ router.get(
|
|
|
166
167
|
*/
|
|
167
168
|
router.post(
|
|
168
169
|
"/:viewname/preview",
|
|
169
|
-
|
|
170
|
+
isAdminOrHasConfigMinRole("min_role_edit_views"),
|
|
170
171
|
error_catcher(async (req, res) => {
|
|
171
172
|
const { viewname } = req.params;
|
|
172
173
|
|