@saltcorn/server 1.1.1-beta.0 → 1.1.1-beta.2
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/help/Event types.tmd +2 -0
- package/locales/en.json +7 -1
- package/locales/pl.json +16 -1
- package/package.json +9 -9
- package/public/saltcorn.js +87 -17
- package/routes/actions.js +128 -183
- package/routes/admin.js +257 -46
- package/routes/fields.js +9 -0
- package/routes/menu.js +1 -0
- package/routes/notifications.js +20 -12
- package/routes/page.js +2 -2
- package/routes/pageedit.js +34 -1
- package/routes/utils.js +5 -0
- package/routes/view.js +14 -12
- package/routes/viewedit.js +26 -0
- package/tests/clientjs.test.js +19 -0
- package/tests/view.test.js +37 -0
package/routes/utils.js
CHANGED
|
@@ -23,6 +23,7 @@ const Crash = require("@saltcorn/data/models/crash");
|
|
|
23
23
|
const File = require("@saltcorn/data/models/file");
|
|
24
24
|
const User = require("@saltcorn/data/models/user");
|
|
25
25
|
const Page = require("@saltcorn/data/models/page");
|
|
26
|
+
const Trigger = require("@saltcorn/data/models/trigger");
|
|
26
27
|
const si = require("systeminformation");
|
|
27
28
|
const {
|
|
28
29
|
config_fields_form,
|
|
@@ -107,6 +108,7 @@ const setLanguage = (req, res, state) => {
|
|
|
107
108
|
} else if (req.cookies?.lang) {
|
|
108
109
|
req.setLocale(req.cookies?.lang);
|
|
109
110
|
}
|
|
111
|
+
if (req.user) Object.freeze(req.user);
|
|
110
112
|
set_custom_http_headers(res, req, state);
|
|
111
113
|
};
|
|
112
114
|
|
|
@@ -425,6 +427,9 @@ const admin_config_route = ({
|
|
|
425
427
|
const restart_required = check_if_restart_required(form, req);
|
|
426
428
|
|
|
427
429
|
await save_config_from_form(form);
|
|
430
|
+
Trigger.emitEvent("AppChange", `Config`, req.user, {
|
|
431
|
+
config_keys: Object.keys(form.values),
|
|
432
|
+
});
|
|
428
433
|
if (!req.xhr) {
|
|
429
434
|
if (restart_required) {
|
|
430
435
|
flash_restart(req);
|
package/routes/view.js
CHANGED
|
@@ -139,18 +139,20 @@ router.get(
|
|
|
139
139
|
: contents0;
|
|
140
140
|
res.sendWrap(
|
|
141
141
|
title,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
142
|
+
!req.smr
|
|
143
|
+
? add_edit_bar({
|
|
144
|
+
role,
|
|
145
|
+
title: view.name,
|
|
146
|
+
what: req.__("View"),
|
|
147
|
+
url: `/viewedit/edit/${encodeURIComponent(view.name)}`,
|
|
148
|
+
cfgUrl: `/viewedit/config/${encodeURIComponent(view.name)}`,
|
|
149
|
+
contents,
|
|
150
|
+
req,
|
|
151
|
+
view,
|
|
152
|
+
viewtemplate: view.viewtemplate,
|
|
153
|
+
table: view.table_id || view.exttable_name,
|
|
154
|
+
})
|
|
155
|
+
: contents
|
|
154
156
|
);
|
|
155
157
|
}
|
|
156
158
|
})
|
package/routes/viewedit.js
CHANGED
|
@@ -27,6 +27,7 @@ const Table = require("@saltcorn/data/models/table");
|
|
|
27
27
|
const View = require("@saltcorn/data/models/view");
|
|
28
28
|
const Workflow = require("@saltcorn/data/models/workflow");
|
|
29
29
|
const User = require("@saltcorn/data/models/user");
|
|
30
|
+
const Trigger = require("@saltcorn/data/models/trigger");
|
|
30
31
|
const Page = require("@saltcorn/data/models/page");
|
|
31
32
|
const File = require("@saltcorn/data/models/file");
|
|
32
33
|
const Tag = require("@saltcorn/data/models/tag");
|
|
@@ -551,6 +552,10 @@ router.post(
|
|
|
551
552
|
//console.log(v);
|
|
552
553
|
await View.create(v);
|
|
553
554
|
}
|
|
555
|
+
Trigger.emitEvent("AppChange", `View ${v.name}`, req.user, {
|
|
556
|
+
entity_type: "View",
|
|
557
|
+
entity_name: v.name,
|
|
558
|
+
});
|
|
554
559
|
if (req.xhr) res.json({ success: "ok" });
|
|
555
560
|
else
|
|
556
561
|
res.redirect(
|
|
@@ -733,6 +738,10 @@ router.post(
|
|
|
733
738
|
};
|
|
734
739
|
else newcfg = { ...view.configuration, ...context };
|
|
735
740
|
await View.update({ configuration: newcfg }, view.id);
|
|
741
|
+
Trigger.emitEvent("AppChange", `View ${view.name}`, req.user, {
|
|
742
|
+
entity_type: "View",
|
|
743
|
+
entity_name: view.name,
|
|
744
|
+
});
|
|
736
745
|
};
|
|
737
746
|
const wfres = await configFlow.run(req.body, req);
|
|
738
747
|
|
|
@@ -761,6 +770,7 @@ router.post(
|
|
|
761
770
|
min_role: view.min_role,
|
|
762
771
|
viewname: view.name,
|
|
763
772
|
});
|
|
773
|
+
Trigger.emitEvent("AppChange", `Menu`, req.user, {});
|
|
764
774
|
req.flash(
|
|
765
775
|
"success",
|
|
766
776
|
req.__(
|
|
@@ -790,6 +800,10 @@ router.post(
|
|
|
790
800
|
const { id } = req.params;
|
|
791
801
|
const view = await View.findOne({ id });
|
|
792
802
|
const newview = await view.clone();
|
|
803
|
+
Trigger.emitEvent("AppChange", `View ${newview.name}`, req.user, {
|
|
804
|
+
entity_type: "View",
|
|
805
|
+
entity_name: newview.name,
|
|
806
|
+
});
|
|
793
807
|
req.flash(
|
|
794
808
|
"success",
|
|
795
809
|
req.__("View %s duplicated as %s", view.name, newview.name)
|
|
@@ -841,6 +855,10 @@ router.post(
|
|
|
841
855
|
const exview = await View.findOne({ id });
|
|
842
856
|
let newcfg = { ...exview.configuration, ...req.body };
|
|
843
857
|
await View.update({ configuration: newcfg }, +id);
|
|
858
|
+
Trigger.emitEvent("AppChange", `View ${exview.name}`, req.user, {
|
|
859
|
+
entity_type: "View",
|
|
860
|
+
entity_name: exview.name,
|
|
861
|
+
});
|
|
844
862
|
res.json({ success: "ok" });
|
|
845
863
|
} else {
|
|
846
864
|
res.json({ error: req.__("Unable to save: No view") });
|
|
@@ -879,6 +897,10 @@ router.post(
|
|
|
879
897
|
};
|
|
880
898
|
else newcfg = { ...view.configuration, ...step.renderForm.values };
|
|
881
899
|
await View.update({ configuration: newcfg }, view.id);
|
|
900
|
+
Trigger.emitEvent("AppChange", `View ${view.name}`, req.user, {
|
|
901
|
+
entity_type: "View",
|
|
902
|
+
entity_name: view.name,
|
|
903
|
+
});
|
|
882
904
|
res.json({ success: "ok" });
|
|
883
905
|
} else {
|
|
884
906
|
res.json({ error: step.renderForm.errorSummary });
|
|
@@ -906,6 +928,10 @@ router.post(
|
|
|
906
928
|
const role = req.body.role;
|
|
907
929
|
await View.update({ min_role: role }, +id);
|
|
908
930
|
const view = await View.findOne({ id });
|
|
931
|
+
Trigger.emitEvent("AppChange", `View ${view.name}`, req.user, {
|
|
932
|
+
entity_type: "View",
|
|
933
|
+
entity_name: view.name,
|
|
934
|
+
});
|
|
909
935
|
const roles = await User.get_roles();
|
|
910
936
|
const roleRow = roles.find((r) => r.id === +role);
|
|
911
937
|
const message =
|
package/tests/clientjs.test.js
CHANGED
|
@@ -90,6 +90,25 @@ test("updateQueryStringParameter hash", () => {
|
|
|
90
90
|
"/foo?name=Bar#Baz"
|
|
91
91
|
);
|
|
92
92
|
});
|
|
93
|
+
test("addQueryStringParameter", () => {
|
|
94
|
+
expect(addQueryStringParameter("/foo", "age", 43)).toBe(
|
|
95
|
+
"/foo?age=43"
|
|
96
|
+
);
|
|
97
|
+
expect(addQueryStringParameter("/foo?age=43", "age", 44)).toBe(
|
|
98
|
+
"/foo?age=43&age=44"
|
|
99
|
+
);
|
|
100
|
+
expect(addQueryStringParameter("/foo?age=43", "age", 43)).toBe(
|
|
101
|
+
"/foo?age=43"
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
test("addQueryStringParameter hash", () => {
|
|
105
|
+
expect(addQueryStringParameter("/foo#baz", "age", 43)).toBe(
|
|
106
|
+
"/foo?age=43#baz"
|
|
107
|
+
);
|
|
108
|
+
expect(addQueryStringParameter("/foo?age=43#baz", "age", 44)).toBe(
|
|
109
|
+
"/foo?age=43&age=44#baz"
|
|
110
|
+
);
|
|
111
|
+
});
|
|
93
112
|
test("unique_field_from_rows test", () => {
|
|
94
113
|
$("body").append(`<input id="mkuniq6" value="bar"></div>`);
|
|
95
114
|
unique_field_from_rows(
|
package/tests/view.test.js
CHANGED
|
@@ -194,6 +194,43 @@ describe("render view with slug", () => {
|
|
|
194
194
|
});
|
|
195
195
|
});
|
|
196
196
|
|
|
197
|
+
describe("frozen user object", () => {
|
|
198
|
+
it("should create view writing to user object", async () => {
|
|
199
|
+
const table = Table.findOne({ name: "books" });
|
|
200
|
+
const configuration = {
|
|
201
|
+
layout: {
|
|
202
|
+
type: "container",
|
|
203
|
+
style: {},
|
|
204
|
+
contents: {
|
|
205
|
+
type: "blank",
|
|
206
|
+
contents: "'userid='+user.id",
|
|
207
|
+
isFormula: {
|
|
208
|
+
text: true,
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
showIfFormula: "user.id=1",
|
|
212
|
+
},
|
|
213
|
+
columns: [],
|
|
214
|
+
};
|
|
215
|
+
await View.create({
|
|
216
|
+
table_id: table.id,
|
|
217
|
+
name: "ShowBookWriteUser",
|
|
218
|
+
viewtemplate: "Show",
|
|
219
|
+
configuration,
|
|
220
|
+
min_role: 100,
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
it("should run view setting user", async () => {
|
|
224
|
+
const loginCookie = await getStaffLoginCookie();
|
|
225
|
+
|
|
226
|
+
const app = await getApp({ disableCsrf: true });
|
|
227
|
+
await request(app)
|
|
228
|
+
.get("/view/ShowBookWriteUser?id=1")
|
|
229
|
+
.set("Cookie", loginCookie)
|
|
230
|
+
.expect(toInclude(">userid=2</div>"));
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
197
234
|
describe("action row_variable", () => {
|
|
198
235
|
const createFilterView = async ({
|
|
199
236
|
configuration,
|