@saltcorn/server 0.8.0-beta.3 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.js +7 -6
- package/auth/admin.js +226 -217
- package/auth/index.js +20 -20
- package/auth/roleadmin.js +2 -9
- package/auth/routes.js +193 -139
- package/auth/testhelp.js +62 -55
- package/fixture_persons.js +1 -1
- package/index.js +22 -22
- package/locales/en.json +3 -1
- package/locales/ru.json +25 -19
- package/markup/admin.js +86 -53
- package/markup/blockly.js +1 -1
- package/markup/expression_blurb.js +15 -15
- package/markup/forms.js +21 -22
- package/markup/index.js +20 -20
- package/markup/plugin-store.js +4 -4
- package/package.json +8 -8
- package/public/diagram_utils.js +22 -9
- package/public/saltcorn.css +6 -0
- package/restart_watcher.js +157 -157
- package/routes/actions.js +4 -11
- package/routes/admin.js +8 -5
- package/routes/api.js +9 -9
- package/routes/common_lists.js +127 -130
- package/routes/delete.js +2 -2
- package/routes/edit.js +1 -1
- package/routes/fields.js +4 -2
- package/routes/files.js +112 -94
- package/routes/homepage.js +1 -1
- package/routes/infoarch.js +1 -1
- package/routes/list.js +6 -5
- package/routes/packs.js +1 -2
- package/routes/pageedit.js +1 -1
- package/routes/tables.js +172 -165
- package/routes/tag_entries.js +1 -1
- package/routes/utils.js +3 -1
- package/routes/view.js +9 -2
- package/s3storage.js +6 -7
- package/serve.js +35 -31
- package/systemd.js +23 -21
- package/wrapper.js +44 -45
package/routes/tables.js
CHANGED
|
@@ -83,33 +83,33 @@ const tableForm = async (table, req) => {
|
|
|
83
83
|
fields: [
|
|
84
84
|
...(!table.external
|
|
85
85
|
? [
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
86
|
+
{
|
|
87
|
+
label: req.__("Ownership field"),
|
|
88
|
+
name: "ownership_field_id",
|
|
89
|
+
sublabel: req.__(
|
|
90
|
+
"The user referred to in this field will be the owner of the row"
|
|
91
|
+
),
|
|
92
|
+
input_type: "select",
|
|
93
|
+
options: [
|
|
94
|
+
{ value: "", label: req.__("None") },
|
|
95
|
+
...userFields,
|
|
96
|
+
{ value: "_formula", label: req.__("Formula") },
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: "ownership_formula",
|
|
101
|
+
label: req.__("Ownership formula"),
|
|
102
|
+
validator: expressionValidator,
|
|
103
|
+
type: "String",
|
|
104
|
+
class: "validate-expression",
|
|
105
|
+
sublabel:
|
|
106
|
+
req.__("User is treated as owner if true. In scope: ") +
|
|
107
|
+
["user", ...fields.map((f) => f.name)]
|
|
108
|
+
.map((fn) => code(fn))
|
|
109
|
+
.join(", "),
|
|
110
|
+
showIf: { ownership_field_id: "_formula" },
|
|
111
|
+
},
|
|
112
|
+
]
|
|
113
113
|
: []),
|
|
114
114
|
// description of table
|
|
115
115
|
{
|
|
@@ -129,29 +129,29 @@ const tableForm = async (table, req) => {
|
|
|
129
129
|
name: "min_role_read",
|
|
130
130
|
input_type: "select",
|
|
131
131
|
options: roleOptions,
|
|
132
|
-
attributes: { asideNext: !table.external }
|
|
132
|
+
attributes: { asideNext: !table.external },
|
|
133
133
|
},
|
|
134
134
|
...(table.external
|
|
135
135
|
? []
|
|
136
136
|
: [
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
137
|
+
{
|
|
138
|
+
label: req.__("Minimum role to write"),
|
|
139
|
+
name: "min_role_write",
|
|
140
|
+
input_type: "select",
|
|
141
|
+
sublabel: req.__(
|
|
142
|
+
"User must have this role or higher to edit or create new rows in the table, unless they are the owner"
|
|
143
|
+
),
|
|
144
|
+
options: roleOptions,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
label: req.__("Version history"),
|
|
148
|
+
sublabel: req.__(
|
|
149
|
+
"Version history allows to track table data changes"
|
|
150
|
+
),
|
|
151
|
+
name: "versioned",
|
|
152
|
+
type: "Bool",
|
|
153
|
+
},
|
|
154
|
+
]),
|
|
155
155
|
],
|
|
156
156
|
});
|
|
157
157
|
if (table) {
|
|
@@ -218,11 +218,11 @@ const discoverForm = (tables, req) => {
|
|
|
218
218
|
blurb:
|
|
219
219
|
tables.length > 0
|
|
220
220
|
? req.__(
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
"The following tables in your database can be imported into Saltcorn:"
|
|
222
|
+
)
|
|
223
223
|
: req.__(
|
|
224
|
-
|
|
225
|
-
|
|
224
|
+
"There are no tables in the database that can be imported into Saltcorn."
|
|
225
|
+
),
|
|
226
226
|
submitLabel: req.__("Import"),
|
|
227
227
|
fields: tables.map((t) => ({
|
|
228
228
|
name: t.table_name,
|
|
@@ -328,7 +328,7 @@ router.get(
|
|
|
328
328
|
name: "name",
|
|
329
329
|
input_type: "text",
|
|
330
330
|
},
|
|
331
|
-
|
|
331
|
+
// todo implement file mask filter like , accept: "text/csv"
|
|
332
332
|
{ label: req.__("File"), name: "file", input_type: "file" },
|
|
333
333
|
],
|
|
334
334
|
}),
|
|
@@ -516,7 +516,12 @@ const attribBadges = (f) => {
|
|
|
516
516
|
let s = "";
|
|
517
517
|
if (f.attributes) {
|
|
518
518
|
Object.entries(f.attributes).forEach(([k, v]) => {
|
|
519
|
-
if (
|
|
519
|
+
if (
|
|
520
|
+
["summary_field", "default", "on_delete_cascade", "on_delete"].includes(
|
|
521
|
+
k
|
|
522
|
+
)
|
|
523
|
+
)
|
|
524
|
+
return;
|
|
520
525
|
if (v || v === 0) s += badge("secondary", k);
|
|
521
526
|
});
|
|
522
527
|
}
|
|
@@ -575,11 +580,11 @@ router.get(
|
|
|
575
580
|
key: (r) =>
|
|
576
581
|
r.type === "Key"
|
|
577
582
|
? `Key to ` +
|
|
578
|
-
|
|
583
|
+
a({ href: `/table/${r.reftable_name}` }, r.reftable_name)
|
|
579
584
|
: (r.type && r.type.name) ||
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
585
|
+
r.type ||
|
|
586
|
+
r.typename +
|
|
587
|
+
span({ class: "badge bg-danger ms-1" }, "Unknown type"),
|
|
583
588
|
},
|
|
584
589
|
{
|
|
585
590
|
label: "",
|
|
@@ -593,23 +598,23 @@ router.get(
|
|
|
593
598
|
...(table.external
|
|
594
599
|
? []
|
|
595
600
|
: [
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
+
{
|
|
602
|
+
label: req.__("Edit"),
|
|
603
|
+
key: (r) => link(`/field/${r.id}`, req.__("Edit")),
|
|
604
|
+
},
|
|
605
|
+
]),
|
|
601
606
|
...(table.external || db.isSQLite
|
|
602
607
|
? []
|
|
603
608
|
: [
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
609
|
+
{
|
|
610
|
+
label: req.__("Delete"),
|
|
611
|
+
key: (r) =>
|
|
612
|
+
(table.name === "users" && r.name === "email") ||
|
|
608
613
|
r.primary_key
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
614
|
+
? ""
|
|
615
|
+
: post_delete_btn(`/field/delete/${r.id}`, req, r.name),
|
|
616
|
+
},
|
|
617
|
+
]),
|
|
613
618
|
],
|
|
614
619
|
fields,
|
|
615
620
|
{ hover: true }
|
|
@@ -618,17 +623,17 @@ router.get(
|
|
|
618
623
|
tableHtml,
|
|
619
624
|
inbound_refs.length > 0
|
|
620
625
|
? req.__("Inbound keys: ") +
|
|
621
|
-
|
|
622
|
-
|
|
626
|
+
inbound_refs.map((tnm) => link(`/table/${tnm}`, tnm)).join(", ") +
|
|
627
|
+
"<br>"
|
|
623
628
|
: "",
|
|
624
629
|
!table.external &&
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
630
|
+
a(
|
|
631
|
+
{
|
|
632
|
+
href: `/field/new/${table.id}`,
|
|
633
|
+
class: "btn btn-primary add-field mt-2",
|
|
634
|
+
},
|
|
635
|
+
req.__("Add field")
|
|
636
|
+
),
|
|
632
637
|
];
|
|
633
638
|
}
|
|
634
639
|
var viewCard;
|
|
@@ -700,8 +705,8 @@ router.get(
|
|
|
700
705
|
table.name === "users"
|
|
701
706
|
? `/useradmin/`
|
|
702
707
|
: fields.length === 1
|
|
703
|
-
|
|
704
|
-
|
|
708
|
+
? `javascript:;` // Fix problem with edition of table with only one column ID / Primary Key
|
|
709
|
+
: `/list/${table.name}`,
|
|
705
710
|
},
|
|
706
711
|
i({ class: "fas fa-2x fa-edit" }),
|
|
707
712
|
"<br/>",
|
|
@@ -721,75 +726,75 @@ router.get(
|
|
|
721
726
|
)
|
|
722
727
|
),
|
|
723
728
|
!table.external &&
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
{
|
|
728
|
-
method: "post",
|
|
729
|
-
action: `/table/upload_to_table/${table.name}`,
|
|
730
|
-
encType: "multipart/form-data",
|
|
731
|
-
acceptCharset: "UTF-8",
|
|
732
|
-
},
|
|
733
|
-
input({ type: "hidden", name: "_csrf", value: req.csrfToken() }),
|
|
734
|
-
label(
|
|
735
|
-
{ class: "btn-link", for: "upload_to_table" },
|
|
736
|
-
i({ class: "fas fa-2x fa-upload" }),
|
|
737
|
-
"<br/>",
|
|
738
|
-
req.__("Upload CSV")
|
|
739
|
-
),
|
|
740
|
-
input({
|
|
741
|
-
id: "upload_to_table",
|
|
742
|
-
name: "file",
|
|
743
|
-
type: "file",
|
|
744
|
-
accept: "text/csv,.csv",
|
|
745
|
-
onchange: "this.form.submit();",
|
|
746
|
-
})
|
|
747
|
-
)
|
|
748
|
-
),
|
|
749
|
-
// only if table is not external
|
|
750
|
-
!table.external &&
|
|
751
|
-
div(
|
|
752
|
-
{ class: "mx-auto" },
|
|
753
|
-
settingsDropdown(`dataMenuButton`, [
|
|
754
|
-
a(
|
|
729
|
+
div(
|
|
730
|
+
{ class: "mx-auto" },
|
|
731
|
+
form(
|
|
755
732
|
{
|
|
756
|
-
|
|
757
|
-
|
|
733
|
+
method: "post",
|
|
734
|
+
action: `/table/upload_to_table/${table.name}`,
|
|
735
|
+
encType: "multipart/form-data",
|
|
736
|
+
acceptCharset: "UTF-8",
|
|
758
737
|
},
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
738
|
+
input({ type: "hidden", name: "_csrf", value: req.csrfToken() }),
|
|
739
|
+
label(
|
|
740
|
+
{ class: "btn-link", for: "upload_to_table" },
|
|
741
|
+
i({ class: "fas fa-2x fa-upload" }),
|
|
742
|
+
"<br/>",
|
|
743
|
+
req.__("Upload CSV")
|
|
744
|
+
),
|
|
745
|
+
input({
|
|
746
|
+
id: "upload_to_table",
|
|
747
|
+
name: "file",
|
|
748
|
+
type: "file",
|
|
749
|
+
accept: "text/csv,.csv",
|
|
750
|
+
onchange: "this.form.submit();",
|
|
751
|
+
})
|
|
752
|
+
)
|
|
753
|
+
),
|
|
754
|
+
// only if table is not external
|
|
755
|
+
!table.external &&
|
|
756
|
+
div(
|
|
757
|
+
{ class: "mx-auto" },
|
|
758
|
+
settingsDropdown(`dataMenuButton`, [
|
|
759
|
+
a(
|
|
760
|
+
{
|
|
761
|
+
class: "dropdown-item",
|
|
762
|
+
href: `/table/constraints/${table.id}`,
|
|
763
|
+
},
|
|
764
|
+
'<i class="fas fa-ban"></i> ' + req.__("Constraints")
|
|
765
|
+
),
|
|
766
|
+
// rename table doesnt supported for sqlite
|
|
767
|
+
!db.isSQLite &&
|
|
768
|
+
table.name !== "users" &&
|
|
769
|
+
a(
|
|
770
|
+
{
|
|
771
|
+
class: "dropdown-item",
|
|
772
|
+
href: `/table/rename/${table.id}`,
|
|
773
|
+
},
|
|
774
|
+
'<i class="fas fa-edit"></i> ' + req.__("Rename table")
|
|
775
|
+
),
|
|
776
|
+
post_dropdown_item(
|
|
777
|
+
`/table/recalc-stored/${table.name}`,
|
|
778
|
+
'<i class="fas fa-sync"></i> ' +
|
|
779
|
+
req.__("Recalculate stored fields"),
|
|
780
|
+
req
|
|
781
|
+
),
|
|
782
|
+
post_dropdown_item(
|
|
783
|
+
`/table/delete-all-rows/${table.name}`,
|
|
784
|
+
'<i class="far fa-trash-alt"></i> ' +
|
|
785
|
+
req.__("Delete all rows"),
|
|
786
|
+
req,
|
|
787
|
+
true
|
|
788
|
+
),
|
|
789
|
+
table.name !== "users" &&
|
|
790
|
+
post_dropdown_item(
|
|
791
|
+
`/table/forget-table/${table.id}`,
|
|
792
|
+
'<i class="fas fa-recycle"></i> ' + req.__("Forget table"),
|
|
793
|
+
req,
|
|
794
|
+
true
|
|
795
|
+
),
|
|
796
|
+
])
|
|
797
|
+
)
|
|
793
798
|
);
|
|
794
799
|
// add table form
|
|
795
800
|
if (table.ownership_formula && !table.ownership_field_id)
|
|
@@ -812,12 +817,12 @@ router.get(
|
|
|
812
817
|
},
|
|
813
818
|
...(fields.length > 0
|
|
814
819
|
? [
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
820
|
+
{
|
|
821
|
+
type: "card",
|
|
822
|
+
title: req.__("Table data"),
|
|
823
|
+
contents: dataCard,
|
|
824
|
+
},
|
|
825
|
+
]
|
|
821
826
|
: []),
|
|
822
827
|
...(viewCard ? [viewCard] : []),
|
|
823
828
|
{
|
|
@@ -864,7 +869,7 @@ router.post(
|
|
|
864
869
|
// todo check that works after where change
|
|
865
870
|
// todo findOne can be have parameter for external table here
|
|
866
871
|
//we can only save min role
|
|
867
|
-
const table = await Table.findOne(
|
|
872
|
+
const table = await Table.findOne({ name: v.name });
|
|
868
873
|
if (table) {
|
|
869
874
|
const exttables_min_role_read = getState().getConfigCopy(
|
|
870
875
|
"exttables_min_role_read",
|
|
@@ -883,13 +888,13 @@ router.post(
|
|
|
883
888
|
const table = await Table.findOne({ id: parseInt(id) });
|
|
884
889
|
const old_versioned = table.versioned;
|
|
885
890
|
let hasError = false;
|
|
886
|
-
let notify = ""
|
|
891
|
+
let notify = "";
|
|
887
892
|
if (!rest.versioned) rest.versioned = false;
|
|
888
893
|
if (rest.ownership_field_id === "_formula") {
|
|
889
894
|
rest.ownership_field_id = null;
|
|
890
895
|
const fmlValidRes = expressionValidator(rest.ownership_formula);
|
|
891
896
|
if (typeof fmlValidRes === "string") {
|
|
892
|
-
notify = req.__(`Invalid ownership formula: %s`, fmlValidRes)
|
|
897
|
+
notify = req.__(`Invalid ownership formula: %s`, fmlValidRes);
|
|
893
898
|
hasError = true;
|
|
894
899
|
}
|
|
895
900
|
} else rest.ownership_formula = null;
|
|
@@ -1023,16 +1028,18 @@ router.get(
|
|
|
1023
1028
|
req.__("Create from CSV upload")
|
|
1024
1029
|
),
|
|
1025
1030
|
!db.isSQLite &&
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1031
|
+
a(
|
|
1032
|
+
{
|
|
1033
|
+
href: `/table/discover`,
|
|
1034
|
+
class: "btn btn-secondary mt-1",
|
|
1035
|
+
title: req.__(
|
|
1036
|
+
"Discover tables that are already in the Database, but not known to Saltcorn"
|
|
1037
|
+
),
|
|
1038
|
+
},
|
|
1039
|
+
i({ class: "fas fa-map-signs me-1" }),
|
|
1033
1040
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1041
|
+
req.__("Discover tables")
|
|
1042
|
+
)
|
|
1036
1043
|
);
|
|
1037
1044
|
res.sendWrap(req.__("Tables"), {
|
|
1038
1045
|
above: [
|
package/routes/tag_entries.js
CHANGED
package/routes/utils.js
CHANGED
|
@@ -218,7 +218,9 @@ const scan_for_page_title = (contents, viewname) => {
|
|
|
218
218
|
try {
|
|
219
219
|
scanstr =
|
|
220
220
|
typeof contents === "string" ? contents : JSON.stringify(contents);
|
|
221
|
-
} catch {
|
|
221
|
+
} catch {
|
|
222
|
+
//ignore
|
|
223
|
+
}
|
|
222
224
|
if (scanstr.includes("<!--SCPT:")) {
|
|
223
225
|
const start = scanstr.indexOf("<!--SCPT:");
|
|
224
226
|
const end = scanstr.indexOf("-->", start);
|
package/routes/view.js
CHANGED
|
@@ -71,8 +71,11 @@ router.get(
|
|
|
71
71
|
title: view.name,
|
|
72
72
|
what: req.__("View"),
|
|
73
73
|
url: `/viewedit/edit/${encodeURIComponent(view.name)}`,
|
|
74
|
+
cfgUrl: `/viewedit/config/${encodeURIComponent(view.name)}`,
|
|
74
75
|
contents,
|
|
75
76
|
req,
|
|
77
|
+
viewtemplate: view.viewtemplate,
|
|
78
|
+
table: view.table_id || view.exttable_name,
|
|
76
79
|
})
|
|
77
80
|
);
|
|
78
81
|
})
|
|
@@ -104,13 +107,17 @@ router.post(
|
|
|
104
107
|
if (!row) {
|
|
105
108
|
if (!table)
|
|
106
109
|
// todo check after where change
|
|
107
|
-
table = await Table.findOne(
|
|
110
|
+
table = await Table.findOne(
|
|
111
|
+
view.table_id
|
|
112
|
+
? { id: view.table_id }
|
|
113
|
+
: { name: view.exttable_name }
|
|
114
|
+
);
|
|
108
115
|
row = await table.getRow({});
|
|
109
116
|
}
|
|
110
117
|
if (row) query[sf.name] = row[sf.name];
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
|
-
const contents = await view.run(query, { req, res });
|
|
120
|
+
const contents = await view.run(query, { req, res, isPreview: true });
|
|
114
121
|
|
|
115
122
|
res.send(contents);
|
|
116
123
|
})
|
package/s3storage.js
CHANGED
|
@@ -5,7 +5,7 @@ const { getState } = require("@saltcorn/data/db/state");
|
|
|
5
5
|
const fileUpload = require("express-fileupload");
|
|
6
6
|
const { v4: uuidv4 } = require("uuid");
|
|
7
7
|
const contentDisposition = require("content-disposition");
|
|
8
|
-
|
|
8
|
+
const fs = require("fs");
|
|
9
9
|
function createS3Client() {
|
|
10
10
|
return new aws.S3({
|
|
11
11
|
secretAccessKey: getState().getConfig("storage_s3_access_secret"),
|
|
@@ -52,19 +52,18 @@ module.exports = {
|
|
|
52
52
|
createParentPath: true,
|
|
53
53
|
tempFileDir: "/tmp/",
|
|
54
54
|
// set to true - if you want to have debug
|
|
55
|
-
debug: getState().getConfig("file_upload_debug",false),
|
|
55
|
+
debug: getState().getConfig("file_upload_debug", false),
|
|
56
56
|
//uriDecodeFileNames: true,
|
|
57
57
|
//safeFileNames: true,
|
|
58
|
-
defCharset:
|
|
59
|
-
defParamCharset:
|
|
58
|
+
defCharset: "utf8",
|
|
59
|
+
defParamCharset: "utf8",
|
|
60
60
|
// 0 - means no upload limit check
|
|
61
61
|
limits: {
|
|
62
62
|
fileSize: fileSizeLimit,
|
|
63
63
|
},
|
|
64
64
|
abortOnLimit: fileSizeLimit !== 0,
|
|
65
65
|
// 0 - means no upload limit check
|
|
66
|
-
uploadTimeout: getState().getConfig("file_upload_timeout",0),
|
|
67
|
-
|
|
66
|
+
uploadTimeout: getState().getConfig("file_upload_timeout", 0),
|
|
68
67
|
})(req, res, next);
|
|
69
68
|
}
|
|
70
69
|
},
|
|
@@ -146,7 +145,7 @@ module.exports = {
|
|
|
146
145
|
// Forward the object
|
|
147
146
|
s3.getObject(params)
|
|
148
147
|
.on("httpHeaders", function (statusCode, headers) {
|
|
149
|
-
if (
|
|
148
|
+
if (download)
|
|
150
149
|
res.set("Content-Disposition", contentDisposition(file.filename));
|
|
151
150
|
res.set("Content-Length", headers["content-length"]);
|
|
152
151
|
this.response.httpResponse.createUnbufferedStream().pipe(res);
|
package/serve.js
CHANGED
|
@@ -30,7 +30,11 @@ const { getConfig } = require("@saltcorn/data/models/config");
|
|
|
30
30
|
const { migrate } = require("@saltcorn/data/migrate");
|
|
31
31
|
const socketio = require("socket.io");
|
|
32
32
|
const { createAdapter, setupPrimary } = require("@socket.io/cluster-adapter");
|
|
33
|
-
const {
|
|
33
|
+
const {
|
|
34
|
+
setTenant,
|
|
35
|
+
getSessionStore,
|
|
36
|
+
get_tenant_from_req,
|
|
37
|
+
} = require("./routes/utils");
|
|
34
38
|
const passport = require("passport");
|
|
35
39
|
const { authenticate } = require("passport");
|
|
36
40
|
const View = require("@saltcorn/data/models/view");
|
|
@@ -106,8 +110,8 @@ const workerDispatchMsg = ({ tenant, ...msg }) => {
|
|
|
106
110
|
});
|
|
107
111
|
}
|
|
108
112
|
if (!getState()) {
|
|
109
|
-
console.error("no State for tenant", tenant)
|
|
110
|
-
return
|
|
113
|
+
console.error("no State for tenant", tenant);
|
|
114
|
+
return;
|
|
111
115
|
}
|
|
112
116
|
if (msg.refresh) getState()[`refresh_${msg.refresh}`](true);
|
|
113
117
|
if (msg.createTenant) {
|
|
@@ -142,33 +146,33 @@ const workerDispatchMsg = ({ tenant, ...msg }) => {
|
|
|
142
146
|
*/
|
|
143
147
|
const onMessageFromWorker =
|
|
144
148
|
(masterState, { port, watchReaper, disableScheduler, pid }) =>
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
149
|
+
(msg) => {
|
|
150
|
+
//console.log("worker msg", typeof msg, msg);
|
|
151
|
+
if (msg === "Start" && !masterState.started) {
|
|
152
|
+
masterState.started = true;
|
|
153
|
+
runScheduler({
|
|
154
|
+
port,
|
|
155
|
+
watchReaper,
|
|
156
|
+
disableScheduler,
|
|
157
|
+
eachTenant,
|
|
158
|
+
auto_backup_now,
|
|
159
|
+
take_snapshot,
|
|
160
|
+
});
|
|
161
|
+
require("./systemd")({ port });
|
|
162
|
+
return true;
|
|
163
|
+
} else if (msg === "RestartServer") {
|
|
164
|
+
process.exit(0);
|
|
165
|
+
return true;
|
|
166
|
+
} else if (msg.tenant || msg.createTenant) {
|
|
167
|
+
///ie from saltcorn
|
|
168
|
+
//broadcast
|
|
169
|
+
Object.entries(cluster.workers).forEach(([wpid, w]) => {
|
|
170
|
+
if (wpid !== pid) w.send(msg);
|
|
171
|
+
});
|
|
172
|
+
workerDispatchMsg(msg); //also master
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
172
176
|
|
|
173
177
|
module.exports =
|
|
174
178
|
/**
|
|
@@ -381,7 +385,7 @@ const setupSocket = (...servers) => {
|
|
|
381
385
|
} catch (err) {
|
|
382
386
|
getState().log(1, `Socket join_room error: ${err.stack}`);
|
|
383
387
|
}
|
|
384
|
-
}
|
|
388
|
+
};
|
|
385
389
|
if (ten && ten !== "public") db.runWithTenant(ten, f);
|
|
386
390
|
else f();
|
|
387
391
|
});
|