@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.
- package/CHANGELOG.md +6 -0
- package/auth/admin.js +8 -0
- package/locales/en.json +16 -1
- package/markup/admin.js +8 -3
- package/markup/blockly.js +4 -4
- package/package.json +9 -9
- package/public/blockly/blockly_compressed.js +2016 -0
- package/public/blockly/blockly_compressed.js.map +1 -0
- package/public/blockly/blocks_compressed.js +212 -0
- package/public/blockly/blocks_compressed.js.map +1 -0
- package/public/blockly/javascript_compressed.js +121 -0
- package/public/blockly/javascript_compressed.js.map +1 -0
- package/public/blockly/msg/ab.js +440 -0
- package/public/blockly/msg/ace.js +440 -0
- package/public/blockly/msg/af.js +440 -0
- package/public/blockly/msg/am.js +440 -0
- package/public/blockly/msg/ar.js +440 -0
- package/public/blockly/msg/ast.js +440 -0
- package/public/blockly/msg/az.js +440 -0
- package/public/blockly/msg/ba.js +440 -0
- package/public/blockly/msg/bcc.js +440 -0
- package/public/blockly/msg/be-tarask.js +440 -0
- package/public/blockly/msg/be.js +440 -0
- package/public/blockly/msg/bg.js +440 -0
- package/public/blockly/msg/bn.js +440 -0
- package/public/blockly/msg/br.js +440 -0
- package/public/blockly/msg/bs.js +440 -0
- package/public/blockly/msg/ca.js +440 -0
- package/public/blockly/msg/cdo.js +440 -0
- package/public/blockly/msg/cs.js +440 -0
- package/public/blockly/msg/da.js +440 -0
- package/public/blockly/msg/de.js +440 -0
- package/public/blockly/msg/diq.js +440 -0
- package/public/blockly/msg/dty.js +440 -0
- package/public/blockly/msg/ee.js +440 -0
- package/public/blockly/msg/el.js +440 -0
- package/public/blockly/msg/en-gb.js +440 -0
- package/public/blockly/msg/en.js +440 -0
- package/public/blockly/msg/eo.js +440 -0
- package/public/blockly/msg/es.js +440 -0
- package/public/blockly/msg/et.js +440 -0
- package/public/blockly/msg/eu.js +440 -0
- package/public/blockly/msg/fa.js +440 -0
- package/public/blockly/msg/fi.js +440 -0
- package/public/blockly/msg/fo.js +440 -0
- package/public/blockly/msg/fr.js +440 -0
- package/public/blockly/msg/frr.js +440 -0
- package/public/blockly/msg/gl.js +440 -0
- package/public/blockly/msg/gn.js +440 -0
- package/public/blockly/msg/gor.js +440 -0
- package/public/blockly/msg/ha.js +440 -0
- package/public/blockly/msg/hak.js +440 -0
- package/public/blockly/msg/he.js +440 -0
- package/public/blockly/msg/hi.js +440 -0
- package/public/blockly/msg/hr.js +440 -0
- package/public/blockly/msg/hrx.js +440 -0
- package/public/blockly/msg/hu.js +440 -0
- package/public/blockly/msg/hy.js +440 -0
- package/public/blockly/msg/ia.js +440 -0
- package/public/blockly/msg/id.js +440 -0
- package/public/blockly/msg/ig.js +440 -0
- package/public/blockly/msg/inh.js +440 -0
- package/public/blockly/msg/is.js +440 -0
- package/public/blockly/msg/it.js +440 -0
- package/public/blockly/msg/ja.js +440 -0
- package/public/blockly/msg/ka.js +440 -0
- package/public/blockly/msg/kab.js +440 -0
- package/public/blockly/msg/kbd-cyrl.js +440 -0
- package/public/blockly/msg/km.js +440 -0
- package/public/blockly/msg/kn.js +440 -0
- package/public/blockly/msg/ko.js +440 -0
- package/public/blockly/msg/ksh.js +440 -0
- package/public/blockly/msg/ku-latn.js +440 -0
- package/public/blockly/msg/ky.js +440 -0
- package/public/blockly/msg/la.js +440 -0
- package/public/blockly/msg/lb.js +440 -0
- package/public/blockly/msg/lki.js +440 -0
- package/public/blockly/msg/lo.js +440 -0
- package/public/blockly/msg/lrc.js +440 -0
- package/public/blockly/msg/lt.js +440 -0
- package/public/blockly/msg/lv.js +440 -0
- package/public/blockly/msg/mg.js +440 -0
- package/public/blockly/msg/mk.js +440 -0
- package/public/blockly/msg/ml.js +440 -0
- package/public/blockly/msg/mnw.js +440 -0
- package/public/blockly/msg/ms.js +440 -0
- package/public/blockly/msg/msg.d.ts +444 -0
- package/public/blockly/msg/my.js +440 -0
- package/public/blockly/msg/mzn.js +440 -0
- package/public/blockly/msg/nb.js +440 -0
- package/public/blockly/msg/ne.js +440 -0
- package/public/blockly/msg/nl.js +440 -0
- package/public/blockly/msg/oc.js +440 -0
- package/public/blockly/msg/olo.js +440 -0
- package/public/blockly/msg/pa.js +440 -0
- package/public/blockly/msg/pl.js +440 -0
- package/public/blockly/msg/pms.js +440 -0
- package/public/blockly/msg/ps.js +440 -0
- package/public/blockly/msg/pt-br.js +440 -0
- package/public/blockly/msg/pt.js +440 -0
- package/public/blockly/msg/ro.js +440 -0
- package/public/blockly/msg/ru.js +440 -0
- package/public/blockly/msg/sc.js +440 -0
- package/public/blockly/msg/sco.js +440 -0
- package/public/blockly/msg/sd.js +440 -0
- package/public/blockly/msg/shn.js +440 -0
- package/public/blockly/msg/si.js +440 -0
- package/public/blockly/msg/sk.js +440 -0
- package/public/blockly/msg/skr-arab.js +440 -0
- package/public/blockly/msg/sl.js +440 -0
- package/public/blockly/msg/smn.js +440 -0
- package/public/blockly/msg/sq.js +440 -0
- package/public/blockly/msg/sr-latn.js +440 -0
- package/public/blockly/msg/sr.js +440 -0
- package/public/blockly/msg/sv.js +440 -0
- package/public/blockly/msg/sw.js +440 -0
- package/public/blockly/msg/ta.js +440 -0
- package/public/blockly/msg/tcy.js +440 -0
- package/public/blockly/msg/te.js +440 -0
- package/public/blockly/msg/th.js +440 -0
- package/public/blockly/msg/ti.js +440 -0
- package/public/blockly/msg/tl.js +440 -0
- package/public/blockly/msg/tlh.js +440 -0
- package/public/blockly/msg/tr.js +440 -0
- package/public/blockly/msg/ug-arab.js +440 -0
- package/public/blockly/msg/uk.js +440 -0
- package/public/blockly/msg/ur.js +440 -0
- package/public/blockly/msg/uz.js +440 -0
- package/public/blockly/msg/vi.js +440 -0
- package/public/blockly/msg/xmf.js +440 -0
- package/public/blockly/msg/yo.js +440 -0
- package/public/blockly/msg/yue.js +440 -0
- package/public/blockly/msg/zgh.js +440 -0
- package/public/blockly/msg/zh-hans.js +440 -0
- package/public/blockly/msg/zh-hant.js +440 -0
- package/public/saltcorn-common.js +8 -1
- package/public/saltcorn.js +12 -0
- package/routes/actions.js +32 -25
- package/routes/admin.js +90 -63
- package/routes/common_lists.js +46 -24
- 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/plugins.js +0 -32
- package/routes/tables.js +173 -92
- package/routes/utils.js +27 -0
- package/routes/view.js +2 -1
- package/routes/viewedit.js +14 -13
- package/serve.js +52 -1
- package/tests/api.test.js +0 -18
- package/tests/plugins.test.js +2 -2
- 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,48 @@ 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
|
+
on_done_redirect: encodeURIComponent(`table/${table.name}`),
|
|
925
|
+
})
|
|
926
|
+
: p("Triggers run actions in response to events on this table")) +
|
|
927
|
+
a(
|
|
928
|
+
{
|
|
929
|
+
href: `/actions/new?table=${encodeURIComponent(
|
|
930
|
+
table.name
|
|
931
|
+
)}&on_done_redirect=${encodeURIComponent(
|
|
932
|
+
`table/${table.name}`
|
|
933
|
+
)}`,
|
|
934
|
+
class: "btn btn-primary",
|
|
935
|
+
},
|
|
936
|
+
req.__("Create trigger")
|
|
937
|
+
),
|
|
938
|
+
};
|
|
907
939
|
}
|
|
908
940
|
const models = await Model.find({ table_id: table.id });
|
|
909
941
|
const modelCard = div(
|
|
@@ -1025,6 +1057,7 @@ router.get(
|
|
|
1025
1057
|
settingsDropdown(`dataMenuButton`, [
|
|
1026
1058
|
// rename table doesnt supported for sqlite
|
|
1027
1059
|
!db.isSQLite &&
|
|
1060
|
+
user_can_edit_tables &&
|
|
1028
1061
|
table.name !== "users" &&
|
|
1029
1062
|
a(
|
|
1030
1063
|
{
|
|
@@ -1039,21 +1072,24 @@ router.get(
|
|
|
1039
1072
|
req.__("Recalculate stored fields"),
|
|
1040
1073
|
req
|
|
1041
1074
|
),
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1075
|
+
user_can_edit_tables &&
|
|
1076
|
+
post_dropdown_item(
|
|
1077
|
+
`/table/delete-all-rows/${encodeURIComponent(table.name)}`,
|
|
1078
|
+
'<i class="far fa-trash-alt"></i> ' +
|
|
1079
|
+
req.__("Delete all rows"),
|
|
1080
|
+
req,
|
|
1081
|
+
true
|
|
1082
|
+
),
|
|
1083
|
+
user_can_edit_tables &&
|
|
1084
|
+
table.name !== "users" &&
|
|
1050
1085
|
post_dropdown_item(
|
|
1051
1086
|
`/table/forget-table/${table.id}`,
|
|
1052
1087
|
'<i class="fas fa-recycle"></i> ' + req.__("Forget table"),
|
|
1053
1088
|
req,
|
|
1054
1089
|
true
|
|
1055
1090
|
),
|
|
1056
|
-
|
|
1091
|
+
user_can_edit_tables &&
|
|
1092
|
+
table.name !== "users" &&
|
|
1057
1093
|
post_dropdown_item(
|
|
1058
1094
|
`/table/delete/${table.id}`,
|
|
1059
1095
|
'<i class="fas fa-trash"></i> ' + req.__("Delete table"),
|
|
@@ -1067,6 +1103,9 @@ router.get(
|
|
|
1067
1103
|
if (table.ownership_formula && !table.ownership_field_id)
|
|
1068
1104
|
table.ownership_field_id = "_formula";
|
|
1069
1105
|
const tblForm = await tableForm(table, req);
|
|
1106
|
+
if (!user_can_edit_tables) {
|
|
1107
|
+
tblForm.fields.forEach((f) => (f.disabled = true));
|
|
1108
|
+
}
|
|
1070
1109
|
res.sendWrap(req.__(`%s table`, table.name), {
|
|
1071
1110
|
above: [
|
|
1072
1111
|
{
|
|
@@ -1105,7 +1144,7 @@ router.get(
|
|
|
1105
1144
|
titleAjaxIndicator: true,
|
|
1106
1145
|
contents: renderForm(tblForm, req.csrfToken()),
|
|
1107
1146
|
},
|
|
1108
|
-
...(Model.has_templates
|
|
1147
|
+
...(Model.has_templates && req.user.role_id === 1
|
|
1109
1148
|
? [
|
|
1110
1149
|
{
|
|
1111
1150
|
type: "card",
|
|
@@ -1127,7 +1166,7 @@ router.get(
|
|
|
1127
1166
|
*/
|
|
1128
1167
|
router.post(
|
|
1129
1168
|
"/",
|
|
1130
|
-
|
|
1169
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1131
1170
|
error_catcher(async (req, res) => {
|
|
1132
1171
|
const v = req.body;
|
|
1133
1172
|
if (typeof v.id === "undefined" && typeof v.external === "undefined") {
|
|
@@ -1228,7 +1267,7 @@ router.post(
|
|
|
1228
1267
|
*/
|
|
1229
1268
|
router.post(
|
|
1230
1269
|
"/delete/:id",
|
|
1231
|
-
|
|
1270
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1232
1271
|
error_catcher(async (req, res) => {
|
|
1233
1272
|
const { id } = req.params;
|
|
1234
1273
|
const t = Table.findOne({ id });
|
|
@@ -1280,7 +1319,7 @@ router.post(
|
|
|
1280
1319
|
);
|
|
1281
1320
|
router.post(
|
|
1282
1321
|
"/forget-table/:id",
|
|
1283
|
-
|
|
1322
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1284
1323
|
error_catcher(async (req, res) => {
|
|
1285
1324
|
const { id } = req.params;
|
|
1286
1325
|
const t = Table.findOne({ id });
|
|
@@ -1317,7 +1356,10 @@ router.post(
|
|
|
1317
1356
|
*/
|
|
1318
1357
|
router.get(
|
|
1319
1358
|
"/",
|
|
1320
|
-
|
|
1359
|
+
isAdminOrHasConfigMinRole([
|
|
1360
|
+
"min_role_edit_tables",
|
|
1361
|
+
"min_role_inspect_tables",
|
|
1362
|
+
]),
|
|
1321
1363
|
error_catcher(async (req, res) => {
|
|
1322
1364
|
const tblq = {};
|
|
1323
1365
|
let filterOnTag;
|
|
@@ -1329,6 +1371,11 @@ router.get(
|
|
|
1329
1371
|
tblq.id = { in: tagEntries.map((te) => te.table_id).filter(Boolean) };
|
|
1330
1372
|
filterOnTag = await Tag.findOne({ id: +req.query._tag });
|
|
1331
1373
|
}
|
|
1374
|
+
|
|
1375
|
+
const user_can_edit_tables =
|
|
1376
|
+
req.user.role_id === 1 ||
|
|
1377
|
+
getState().getConfig("min_role_edit_tables", 1) >= req.user.role_id;
|
|
1378
|
+
|
|
1332
1379
|
const rows = await Table.find_with_external(tblq, {
|
|
1333
1380
|
orderBy: "name",
|
|
1334
1381
|
nocase: true,
|
|
@@ -1337,20 +1384,23 @@ router.get(
|
|
|
1337
1384
|
const getRole = (rid) => roles.find((r) => r.id === rid).role;
|
|
1338
1385
|
const mainCard = await tablesList(rows, req, { filterOnTag });
|
|
1339
1386
|
const createCard = div(
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1387
|
+
user_can_edit_tables &&
|
|
1388
|
+
a(
|
|
1389
|
+
{ href: `/table/new`, class: "btn btn-primary mt-1 me-3" },
|
|
1390
|
+
i({ class: "fas fa-plus-square me-1" }),
|
|
1391
|
+
req.__("Create table")
|
|
1392
|
+
),
|
|
1393
|
+
user_can_edit_tables &&
|
|
1394
|
+
a(
|
|
1395
|
+
{
|
|
1396
|
+
href: `/table/create-from-csv`,
|
|
1397
|
+
class: "btn btn-secondary me-3 mt-1",
|
|
1398
|
+
},
|
|
1399
|
+
i({ class: "fas fa-upload me-1" }),
|
|
1400
|
+
req.__("Create from CSV upload")
|
|
1401
|
+
),
|
|
1402
|
+
req.user.role_id === 1 &&
|
|
1403
|
+
!db.isSQLite &&
|
|
1354
1404
|
a(
|
|
1355
1405
|
{
|
|
1356
1406
|
href: `/table/discover`,
|
|
@@ -1396,10 +1446,18 @@ router.get(
|
|
|
1396
1446
|
*/
|
|
1397
1447
|
router.get(
|
|
1398
1448
|
"/download/:name",
|
|
1399
|
-
|
|
1449
|
+
isAdminOrHasConfigMinRole([
|
|
1450
|
+
"min_role_edit_tables",
|
|
1451
|
+
"min_role_inspect_tables",
|
|
1452
|
+
]),
|
|
1400
1453
|
error_catcher(async (req, res) => {
|
|
1401
1454
|
const { name } = req.params;
|
|
1402
1455
|
const table = Table.findOne({ name });
|
|
1456
|
+
if (table.min_role_read < req.user.role_id) {
|
|
1457
|
+
req.flash("error", "Not authorized to read table");
|
|
1458
|
+
res.redirect(`/table/${table.id}`);
|
|
1459
|
+
return;
|
|
1460
|
+
}
|
|
1403
1461
|
const rows = await table.getRows({}, { orderBy: "id", forUser: req.user });
|
|
1404
1462
|
res.setHeader("Content-Type", "text/csv");
|
|
1405
1463
|
res.setHeader("Content-Disposition", `attachment; filename="${name}.csv"`);
|
|
@@ -1440,7 +1498,10 @@ router.get(
|
|
|
1440
1498
|
*/
|
|
1441
1499
|
router.get(
|
|
1442
1500
|
"/constraints/:id",
|
|
1443
|
-
|
|
1501
|
+
isAdminOrHasConfigMinRole([
|
|
1502
|
+
"min_role_edit_tables",
|
|
1503
|
+
"min_role_inspect_tables",
|
|
1504
|
+
]),
|
|
1444
1505
|
error_catcher(async (req, res) => {
|
|
1445
1506
|
const { id } = req.params;
|
|
1446
1507
|
const table = Table.findOne({ id });
|
|
@@ -1642,7 +1703,7 @@ router.get(
|
|
|
1642
1703
|
*/
|
|
1643
1704
|
router.post(
|
|
1644
1705
|
"/add-constraint/:id/:type",
|
|
1645
|
-
|
|
1706
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1646
1707
|
error_catcher(async (req, res) => {
|
|
1647
1708
|
const { id, type } = req.params;
|
|
1648
1709
|
const table = Table.findOne({ id });
|
|
@@ -1738,7 +1799,7 @@ router.get(
|
|
|
1738
1799
|
*/
|
|
1739
1800
|
router.post(
|
|
1740
1801
|
"/rename/:id",
|
|
1741
|
-
|
|
1802
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1742
1803
|
error_catcher(async (req, res) => {
|
|
1743
1804
|
const { id } = req.params;
|
|
1744
1805
|
const table = Table.findOne({ id });
|
|
@@ -1762,7 +1823,7 @@ router.post(
|
|
|
1762
1823
|
*/
|
|
1763
1824
|
router.post(
|
|
1764
1825
|
"/delete-constraint/:id",
|
|
1765
|
-
|
|
1826
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1766
1827
|
error_catcher(async (req, res) => {
|
|
1767
1828
|
const { id } = req.params;
|
|
1768
1829
|
const cons = await TableConstraint.findOne({ id });
|
|
@@ -1879,7 +1940,10 @@ const previewCSV = async ({ newPath, table, req, res, full }) => {
|
|
|
1879
1940
|
router.post(
|
|
1880
1941
|
"/upload_to_table/:name",
|
|
1881
1942
|
setTenant, // TODO why is this needed?????
|
|
1882
|
-
|
|
1943
|
+
isAdminOrHasConfigMinRole([
|
|
1944
|
+
"min_role_edit_tables",
|
|
1945
|
+
"min_role_inspect_tables",
|
|
1946
|
+
]),
|
|
1883
1947
|
error_catcher(async (req, res) => {
|
|
1884
1948
|
const { name } = req.params;
|
|
1885
1949
|
const table = Table.findOne({ name });
|
|
@@ -1888,6 +1952,11 @@ router.post(
|
|
|
1888
1952
|
res.redirect(`/table/${table.id}`);
|
|
1889
1953
|
return;
|
|
1890
1954
|
}
|
|
1955
|
+
if (table.min_role_write < req.user.role_id) {
|
|
1956
|
+
req.flash("error", "Not authorized to write to table");
|
|
1957
|
+
res.redirect(`/table/${table.id}`);
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1891
1960
|
|
|
1892
1961
|
const newPath = File.get_new_path();
|
|
1893
1962
|
await req.files.file.mv(newPath);
|
|
@@ -1898,7 +1967,10 @@ router.post(
|
|
|
1898
1967
|
|
|
1899
1968
|
router.get(
|
|
1900
1969
|
"/preview_full_csv_file/:name/:filename",
|
|
1901
|
-
|
|
1970
|
+
isAdminOrHasConfigMinRole([
|
|
1971
|
+
"min_role_edit_tables",
|
|
1972
|
+
"min_role_inspect_tables",
|
|
1973
|
+
]),
|
|
1902
1974
|
error_catcher(async (req, res) => {
|
|
1903
1975
|
const { name, filename } = req.params;
|
|
1904
1976
|
const table = Table.findOne({ name });
|
|
@@ -1909,7 +1981,10 @@ router.get(
|
|
|
1909
1981
|
|
|
1910
1982
|
router.post(
|
|
1911
1983
|
"/finish_upload_to_table/:name/:filename",
|
|
1912
|
-
|
|
1984
|
+
isAdminOrHasConfigMinRole([
|
|
1985
|
+
"min_role_edit_tables",
|
|
1986
|
+
"min_role_inspect_tables",
|
|
1987
|
+
]),
|
|
1913
1988
|
error_catcher(async (req, res) => {
|
|
1914
1989
|
const { name, filename } = req.params;
|
|
1915
1990
|
const table = Table.findOne({ name });
|
|
@@ -1938,7 +2013,7 @@ router.post(
|
|
|
1938
2013
|
*/
|
|
1939
2014
|
router.post(
|
|
1940
2015
|
"/delete-all-rows/:name",
|
|
1941
|
-
|
|
2016
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
1942
2017
|
error_catcher(async (req, res) => {
|
|
1943
2018
|
const { name } = req.params;
|
|
1944
2019
|
const table = Table.findOne({ name });
|
|
@@ -1963,7 +2038,10 @@ router.post(
|
|
|
1963
2038
|
*/
|
|
1964
2039
|
router.post(
|
|
1965
2040
|
"/recalc-stored/:name",
|
|
1966
|
-
|
|
2041
|
+
isAdminOrHasConfigMinRole([
|
|
2042
|
+
"min_role_edit_tables",
|
|
2043
|
+
"min_role_inspect_tables",
|
|
2044
|
+
]),
|
|
1967
2045
|
error_catcher(async (req, res) => {
|
|
1968
2046
|
const { name } = req.params;
|
|
1969
2047
|
const table = Table.findOne({ name });
|
|
@@ -2054,7 +2132,10 @@ const get_provider_workflow = (table, req) => {
|
|
|
2054
2132
|
|
|
2055
2133
|
router.get(
|
|
2056
2134
|
"/provider-cfg/:id",
|
|
2057
|
-
|
|
2135
|
+
isAdminOrHasConfigMinRole([
|
|
2136
|
+
"min_role_edit_tables",
|
|
2137
|
+
"min_role_inspect_tables",
|
|
2138
|
+
]),
|
|
2058
2139
|
error_catcher(async (req, res) => {
|
|
2059
2140
|
const { id } = req.params;
|
|
2060
2141
|
const { step } = req.query;
|
|
@@ -2080,7 +2161,7 @@ router.get(
|
|
|
2080
2161
|
|
|
2081
2162
|
router.post(
|
|
2082
2163
|
"/provider-cfg/:id",
|
|
2083
|
-
|
|
2164
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
2084
2165
|
error_catcher(async (req, res) => {
|
|
2085
2166
|
const { id } = req.params;
|
|
2086
2167
|
const { step } = req.query;
|
|
@@ -2099,7 +2180,7 @@ router.post(
|
|
|
2099
2180
|
|
|
2100
2181
|
router.post(
|
|
2101
2182
|
"/repair-composite-primary/:id",
|
|
2102
|
-
|
|
2183
|
+
isAdminOrHasConfigMinRole("min_role_edit_tables"),
|
|
2103
2184
|
error_catcher(async (req, res) => {
|
|
2104
2185
|
const { id } = req.params;
|
|
2105
2186
|
|
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
|
|