@saltcorn/server 1.1.0-beta.1 → 1.1.0-beta.10
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/auth/roleadmin.js +10 -2
- package/locales/en.json +2 -1
- package/package.json +9 -9
- package/public/codemirror.css +33 -0
- package/public/gridedit.js +1 -1
- package/public/saltcorn-common.js +5 -4
- package/public/saltcorn.css +1 -4
- package/routes/admin.js +18 -12
- package/routes/eventlog.js +5 -1
- package/routes/homepage.js +13 -3
- package/routes/list.js +9 -1
- package/routes/tenant.js +52 -3
- package/tests/plugin_install.test.js +10 -10
- package/tests/plugins.test.js +6 -6
- package/wrapper.js +3 -1
package/auth/roleadmin.js
CHANGED
|
@@ -56,7 +56,11 @@ const editRoleLayoutForm = (role, layouts, layout_by_role, req) => {
|
|
|
56
56
|
},
|
|
57
57
|
csrfField(req),
|
|
58
58
|
select(
|
|
59
|
-
{
|
|
59
|
+
{
|
|
60
|
+
name: "layout",
|
|
61
|
+
onchange: "form.submit()",
|
|
62
|
+
class: "form-select form-select-sm w-unset d-inline",
|
|
63
|
+
},
|
|
60
64
|
layouts.map((layout, ix) =>
|
|
61
65
|
option(
|
|
62
66
|
{
|
|
@@ -88,7 +92,11 @@ const editRole2FAPolicyForm = (role, twofa_policy_by_role, req) =>
|
|
|
88
92
|
},
|
|
89
93
|
csrfField(req),
|
|
90
94
|
select(
|
|
91
|
-
{
|
|
95
|
+
{
|
|
96
|
+
name: "policy",
|
|
97
|
+
onchange: "form.submit()",
|
|
98
|
+
class: "form-select form-select-sm w-unset d-inline",
|
|
99
|
+
},
|
|
92
100
|
["Optional", "Disabled", "Mandatory"].map((p) =>
|
|
93
101
|
option({ selected: twofa_policy_by_role[role.id] === p }, p)
|
|
94
102
|
)
|
package/locales/en.json
CHANGED
|
@@ -1493,5 +1493,6 @@
|
|
|
1493
1493
|
"You must be logged in to share": "You must be logged in to share",
|
|
1494
1494
|
"Fluid layout": "Fluid layout",
|
|
1495
1495
|
"Request fluid layout from theme for a wider display for this page": "Request fluid layout from theme for a wider display for this page",
|
|
1496
|
-
"Location of view to create new row": "Location of view to create new row"
|
|
1496
|
+
"Location of view to create new row": "Location of view to create new row",
|
|
1497
|
+
"Default locale": "Default locale"
|
|
1497
1498
|
}
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "1.1.0-beta.
|
|
3
|
+
"version": "1.1.0-beta.10",
|
|
4
4
|
"description": "Server app for Saltcorn, open-source no-code platform",
|
|
5
5
|
"homepage": "https://saltcorn.com",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@aws-sdk/client-s3": "^3.451.0",
|
|
10
|
-
"@saltcorn/base-plugin": "1.1.0-beta.
|
|
11
|
-
"@saltcorn/builder": "1.1.0-beta.
|
|
12
|
-
"@saltcorn/data": "1.1.0-beta.
|
|
13
|
-
"@saltcorn/admin-models": "1.1.0-beta.
|
|
14
|
-
"@saltcorn/filemanager": "1.1.0-beta.
|
|
15
|
-
"@saltcorn/markup": "1.1.0-beta.
|
|
16
|
-
"@saltcorn/plugins-loader": "1.1.0-beta.
|
|
17
|
-
"@saltcorn/sbadmin2": "1.1.0-beta.
|
|
10
|
+
"@saltcorn/base-plugin": "1.1.0-beta.10",
|
|
11
|
+
"@saltcorn/builder": "1.1.0-beta.10",
|
|
12
|
+
"@saltcorn/data": "1.1.0-beta.10",
|
|
13
|
+
"@saltcorn/admin-models": "1.1.0-beta.10",
|
|
14
|
+
"@saltcorn/filemanager": "1.1.0-beta.10",
|
|
15
|
+
"@saltcorn/markup": "1.1.0-beta.10",
|
|
16
|
+
"@saltcorn/plugins-loader": "1.1.0-beta.10",
|
|
17
|
+
"@saltcorn/sbadmin2": "1.1.0-beta.10",
|
|
18
18
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
19
19
|
"@socket.io/sticky": "^1.0.1",
|
|
20
20
|
"adm-zip": "0.5.10",
|
package/public/codemirror.css
CHANGED
|
@@ -348,3 +348,36 @@ div.CodeMirror-dragcursors {
|
|
|
348
348
|
|
|
349
349
|
/* Help users use markselection to safely style text background */
|
|
350
350
|
span.CodeMirror-selectedtext { background: none; }
|
|
351
|
+
|
|
352
|
+
/* Port of TextMate's Blackboard theme */
|
|
353
|
+
|
|
354
|
+
.cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; }
|
|
355
|
+
.cm-s-blackboard div.CodeMirror-selected { background: #253B76; }
|
|
356
|
+
.cm-s-blackboard .CodeMirror-line::selection, .cm-s-blackboard .CodeMirror-line > span::selection, .cm-s-blackboard .CodeMirror-line > span > span::selection { background: rgba(37, 59, 118, .99); }
|
|
357
|
+
.cm-s-blackboard .CodeMirror-line::-moz-selection, .cm-s-blackboard .CodeMirror-line > span::-moz-selection, .cm-s-blackboard .CodeMirror-line > span > span::-moz-selection { background: rgba(37, 59, 118, .99); }
|
|
358
|
+
.cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; }
|
|
359
|
+
.cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; }
|
|
360
|
+
.cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; }
|
|
361
|
+
.cm-s-blackboard .CodeMirror-linenumber { color: #888; }
|
|
362
|
+
.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7; }
|
|
363
|
+
|
|
364
|
+
.cm-s-blackboard .cm-keyword { color: #FBDE2D; }
|
|
365
|
+
.cm-s-blackboard .cm-atom { color: #D8FA3C; }
|
|
366
|
+
.cm-s-blackboard .cm-number { color: #D8FA3C; }
|
|
367
|
+
.cm-s-blackboard .cm-def { color: #8DA6CE; }
|
|
368
|
+
.cm-s-blackboard .cm-variable { color: #FF6400; }
|
|
369
|
+
.cm-s-blackboard .cm-operator { color: #FBDE2D; }
|
|
370
|
+
.cm-s-blackboard .cm-comment { color: #AEAEAE; }
|
|
371
|
+
.cm-s-blackboard .cm-string { color: #61CE3C; }
|
|
372
|
+
.cm-s-blackboard .cm-string-2 { color: #61CE3C; }
|
|
373
|
+
.cm-s-blackboard .cm-meta { color: #D8FA3C; }
|
|
374
|
+
.cm-s-blackboard .cm-builtin { color: #8DA6CE; }
|
|
375
|
+
.cm-s-blackboard .cm-tag { color: #8DA6CE; }
|
|
376
|
+
.cm-s-blackboard .cm-attribute { color: #8DA6CE; }
|
|
377
|
+
.cm-s-blackboard .cm-header { color: #FF6400; }
|
|
378
|
+
.cm-s-blackboard .cm-hr { color: #AEAEAE; }
|
|
379
|
+
.cm-s-blackboard .cm-link { color: #8DA6CE; }
|
|
380
|
+
.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
|
|
381
|
+
|
|
382
|
+
.cm-s-blackboard .CodeMirror-activeline-background { background: #3C3636; }
|
|
383
|
+
.cm-s-blackboard .CodeMirror-matchingbracket { outline:1px solid grey;color:white !important; }
|
package/public/gridedit.js
CHANGED
|
@@ -28,7 +28,7 @@ function flatpickerEditor(cell, onRendered, success, cancel, editorParams) {
|
|
|
28
28
|
enableTime: !dayOnly,
|
|
29
29
|
dateFormat: dayOnly ? "Y-m-d" : "Z",
|
|
30
30
|
time_24hr: true,
|
|
31
|
-
locale: "en",
|
|
31
|
+
locale: window._sc_locale || "en",
|
|
32
32
|
defaultDate,
|
|
33
33
|
onClose: function (selectedDates, dateStr, instance) {
|
|
34
34
|
evt = window.event;
|
|
@@ -1064,11 +1064,12 @@ function initialize_page() {
|
|
|
1064
1064
|
codes.forEach((el) => {
|
|
1065
1065
|
//console.log($(el).attr("mode"), el);
|
|
1066
1066
|
if ($(el).hasClass("codemirror-enabled")) return;
|
|
1067
|
-
|
|
1068
|
-
const cm = CodeMirror.fromTextArea(el, {
|
|
1067
|
+
const cmOpts = {
|
|
1069
1068
|
lineNumbers: true,
|
|
1070
1069
|
mode: $(el).attr("mode"),
|
|
1071
|
-
}
|
|
1070
|
+
};
|
|
1071
|
+
if (_sc_lightmode === "dark") cmOpts.theme = "blackboard";
|
|
1072
|
+
const cm = CodeMirror.fromTextArea(el, cmOpts);
|
|
1072
1073
|
$(el).addClass("codemirror-enabled");
|
|
1073
1074
|
cm.on(
|
|
1074
1075
|
"change",
|
|
@@ -1550,7 +1551,7 @@ async function common_done(res, viewnameOrElem, isWeb = true) {
|
|
|
1550
1551
|
});
|
|
1551
1552
|
}
|
|
1552
1553
|
if (res.eval_js) await handle(res.eval_js, eval_it);
|
|
1553
|
-
|
|
1554
|
+
if (res.goto) {
|
|
1554
1555
|
if (!isWeb) {
|
|
1555
1556
|
const next = new URL(res.goto, "http://localhost");
|
|
1556
1557
|
const pathname = next.pathname;
|
package/public/saltcorn.css
CHANGED
|
@@ -85,18 +85,15 @@ div[data-inline-edit-dest-url]:hover .editicon {
|
|
|
85
85
|
border-left: none;
|
|
86
86
|
border-color: #95a5a6;
|
|
87
87
|
padding-left: 0.3rem;
|
|
88
|
-
background-color: #ffffff;
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
.search-bar input[type="search"] {
|
|
92
91
|
border-color: #95a5a6;
|
|
93
92
|
padding-left: 0.3rem;
|
|
94
|
-
background-color: #ffffff;
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
.search-bar button.search-bar {
|
|
98
96
|
border-color: #95a5a6;
|
|
99
|
-
background-color: #ffffff;
|
|
100
97
|
border-left: 1px solid #95a5a6 !important;
|
|
101
98
|
border-top: 1px solid #95a5a6 !important;
|
|
102
99
|
border-bottom: 1px solid #95a5a6 !important;
|
|
@@ -358,7 +355,7 @@ table.table-inner-grid td {
|
|
|
358
355
|
}
|
|
359
356
|
|
|
360
357
|
.w-unset {
|
|
361
|
-
width: unset;
|
|
358
|
+
width: unset !important;
|
|
362
359
|
}
|
|
363
360
|
|
|
364
361
|
.preview-text {
|
package/routes/admin.js
CHANGED
|
@@ -155,6 +155,7 @@ admin_config_route({
|
|
|
155
155
|
field_names: [
|
|
156
156
|
"site_name",
|
|
157
157
|
"timezone",
|
|
158
|
+
"default_locale",
|
|
158
159
|
"base_url",
|
|
159
160
|
...(getConfigFile() ? ["multitenancy_enabled"] : []),
|
|
160
161
|
{ section_header: "Logo image" },
|
|
@@ -534,6 +535,7 @@ router.get(
|
|
|
534
535
|
{},
|
|
535
536
|
{ orderBy: "created", orderDesc: true, fields: ["id", "created", "hash"] }
|
|
536
537
|
);
|
|
538
|
+
const locale = getState().getConfig("default_locale", "en");
|
|
537
539
|
send_admin_page({
|
|
538
540
|
res,
|
|
539
541
|
req,
|
|
@@ -555,9 +557,11 @@ router.get(
|
|
|
555
557
|
)}`,
|
|
556
558
|
target: "_blank",
|
|
557
559
|
},
|
|
558
|
-
`${localeDateTime(
|
|
559
|
-
snap.created
|
|
560
|
-
|
|
560
|
+
`${localeDateTime(
|
|
561
|
+
snap.created,
|
|
562
|
+
{},
|
|
563
|
+
locale
|
|
564
|
+
)} (${moment(snap.created).fromNow()})`
|
|
561
565
|
)
|
|
562
566
|
)
|
|
563
567
|
)
|
|
@@ -595,6 +599,7 @@ router.get(
|
|
|
595
599
|
error_catcher(async (req, res) => {
|
|
596
600
|
const { type, name } = req.params;
|
|
597
601
|
const snaps = await Snapshot.entity_history(type, name);
|
|
602
|
+
const locale = getState().getConfig("default_locale", "en");
|
|
598
603
|
res.set("Page-Title", `Restore ${text(name)}`);
|
|
599
604
|
res.send(
|
|
600
605
|
mkTable(
|
|
@@ -602,7 +607,9 @@ router.get(
|
|
|
602
607
|
{
|
|
603
608
|
label: req.__("When"),
|
|
604
609
|
key: (r) =>
|
|
605
|
-
`${localeDateTime(r.created)} (${moment(
|
|
610
|
+
`${localeDateTime(r.created, {}, locale)} (${moment(
|
|
611
|
+
r.created
|
|
612
|
+
).fromNow()})`,
|
|
606
613
|
},
|
|
607
614
|
|
|
608
615
|
{
|
|
@@ -1741,8 +1748,8 @@ router.post(
|
|
|
1741
1748
|
|
|
1742
1749
|
let altname = await tenant_letsencrypt_name(subdomain);
|
|
1743
1750
|
|
|
1744
|
-
if (!altname || domain) {
|
|
1745
|
-
|
|
1751
|
+
if (!altname || !domain) {
|
|
1752
|
+
res.json({ error: "Set Base URL for both tenant and root first." });
|
|
1746
1753
|
return;
|
|
1747
1754
|
}
|
|
1748
1755
|
|
|
@@ -1759,13 +1766,14 @@ router.post(
|
|
|
1759
1766
|
|
|
1760
1767
|
await greenlock.sites.add({
|
|
1761
1768
|
subject: altname,
|
|
1769
|
+
altnames: [altname],
|
|
1762
1770
|
});
|
|
1763
1771
|
// letsencrypt
|
|
1764
1772
|
const tenant_letsencrypt_sites = getState().getConfig(
|
|
1765
1773
|
"tenant_letsencrypt_sites",
|
|
1766
1774
|
[]
|
|
1767
1775
|
);
|
|
1768
|
-
await getState().setConfig(tenant_letsencrypt_sites, [
|
|
1776
|
+
await getState().setConfig("tenant_letsencrypt_sites", [
|
|
1769
1777
|
altname,
|
|
1770
1778
|
...tenant_letsencrypt_sites,
|
|
1771
1779
|
]);
|
|
@@ -1775,12 +1783,10 @@ router.post(
|
|
|
1775
1783
|
notify: "Certificate added, please restart server",
|
|
1776
1784
|
});
|
|
1777
1785
|
} catch (e) {
|
|
1778
|
-
|
|
1779
|
-
res.redirect("/useradmin/ssl");
|
|
1786
|
+
res.json({ error: e.message });
|
|
1780
1787
|
}
|
|
1781
1788
|
} else {
|
|
1782
|
-
|
|
1783
|
-
res.redirect("/useradmin/ssl");
|
|
1789
|
+
res.json({ error: req.__("Not possible for tenant") });
|
|
1784
1790
|
}
|
|
1785
1791
|
})
|
|
1786
1792
|
);
|
|
@@ -1849,7 +1855,7 @@ router.post(
|
|
|
1849
1855
|
"tenant_letsencrypt_sites",
|
|
1850
1856
|
[]
|
|
1851
1857
|
);
|
|
1852
|
-
await getState().setConfig(tenant_letsencrypt_sites, [
|
|
1858
|
+
await getState().setConfig("tenant_letsencrypt_sites", [
|
|
1853
1859
|
...altnames,
|
|
1854
1860
|
...tenant_letsencrypt_sites,
|
|
1855
1861
|
]);
|
package/routes/eventlog.js
CHANGED
|
@@ -424,6 +424,7 @@ router.get(
|
|
|
424
424
|
error_catcher(async (req, res) => {
|
|
425
425
|
const { id } = req.params;
|
|
426
426
|
const ev = await EventLog.findOneWithUser(id);
|
|
427
|
+
const locale = getState().getConfig("default_locale", "en");
|
|
427
428
|
send_events_page({
|
|
428
429
|
res,
|
|
429
430
|
req,
|
|
@@ -435,7 +436,10 @@ router.get(
|
|
|
435
436
|
table(
|
|
436
437
|
{ class: "table eventlog" },
|
|
437
438
|
tbody(
|
|
438
|
-
tr(
|
|
439
|
+
tr(
|
|
440
|
+
th(req.__("When")),
|
|
441
|
+
td(localeDateTime(ev.occur_at, {}, locale))
|
|
442
|
+
),
|
|
439
443
|
tr(th(req.__("Type")), td(ev.event_type)),
|
|
440
444
|
tr(th(req.__("Channel")), td(ev.channel)),
|
|
441
445
|
tr(th(req.__("User")), td(ev.email))
|
package/routes/homepage.js
CHANGED
|
@@ -549,7 +549,14 @@ const no_views_logged_in = async (req, res) => {
|
|
|
549
549
|
* @returns {Promise<boolean>}
|
|
550
550
|
*/
|
|
551
551
|
const get_config_response = async (role_id, res, req) => {
|
|
552
|
-
const wrap = async (
|
|
552
|
+
const wrap = async (
|
|
553
|
+
contents,
|
|
554
|
+
homeCfg,
|
|
555
|
+
title,
|
|
556
|
+
description,
|
|
557
|
+
no_menu,
|
|
558
|
+
requestFluidLayout
|
|
559
|
+
) => {
|
|
553
560
|
if (contents.html_file) await sendHtmlFile(req, res, contents.html_file);
|
|
554
561
|
else
|
|
555
562
|
res.sendWrap(
|
|
@@ -558,6 +565,7 @@ const get_config_response = async (role_id, res, req) => {
|
|
|
558
565
|
description: description || "",
|
|
559
566
|
bodyClass: "page_" + db.sqlsanitize(homeCfg),
|
|
560
567
|
no_menu,
|
|
568
|
+
requestFluidLayout,
|
|
561
569
|
},
|
|
562
570
|
contents
|
|
563
571
|
);
|
|
@@ -578,7 +586,8 @@ const get_config_response = async (role_id, res, req) => {
|
|
|
578
586
|
homeCfg,
|
|
579
587
|
db_page.title,
|
|
580
588
|
db_page.description,
|
|
581
|
-
db_page.attributes?.no_menu
|
|
589
|
+
db_page.attributes?.no_menu,
|
|
590
|
+
db_page.attributes?.request_fluid_layout
|
|
582
591
|
);
|
|
583
592
|
else {
|
|
584
593
|
const group = PageGroup.findOne({ name: homeCfg });
|
|
@@ -592,7 +601,8 @@ const get_config_response = async (role_id, res, req) => {
|
|
|
592
601
|
homeCfg,
|
|
593
602
|
eligible.title,
|
|
594
603
|
eligible.description,
|
|
595
|
-
eligible.attributes?.no_menu
|
|
604
|
+
eligible.attributes?.no_menu,
|
|
605
|
+
eligible.attributes?.request_fluid_layout
|
|
596
606
|
);
|
|
597
607
|
} else wrap(req.__("%s has no eligible page", group.name), homeCfg);
|
|
598
608
|
} else res.redirect(homeCfg);
|
package/routes/list.js
CHANGED
|
@@ -26,6 +26,7 @@ const {
|
|
|
26
26
|
const Table = require("@saltcorn/data/models/table");
|
|
27
27
|
const { isAdmin, error_catcher } = require("./utils");
|
|
28
28
|
const moment = require("moment");
|
|
29
|
+
const { getState } = require("@saltcorn/data/db/state");
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* @type {object}
|
|
@@ -270,6 +271,7 @@ router.get(
|
|
|
270
271
|
res.sendWrap(
|
|
271
272
|
{
|
|
272
273
|
title: req.__(`%s data table`, table.name),
|
|
274
|
+
requestFluidLayout: true,
|
|
273
275
|
headers: [
|
|
274
276
|
//jsgrid - grid editor external component
|
|
275
277
|
{
|
|
@@ -426,7 +428,13 @@ router.get(
|
|
|
426
428
|
),
|
|
427
429
|
div({ id: "jsGridNotify" }),
|
|
428
430
|
|
|
429
|
-
div({
|
|
431
|
+
div({
|
|
432
|
+
id: "jsGrid",
|
|
433
|
+
class:
|
|
434
|
+
getState().getLightDarkMode() === "dark"
|
|
435
|
+
? "table-dark"
|
|
436
|
+
: undefined,
|
|
437
|
+
})
|
|
430
438
|
),
|
|
431
439
|
},
|
|
432
440
|
],
|
package/routes/tenant.js
CHANGED
|
@@ -58,6 +58,7 @@ const {
|
|
|
58
58
|
save_config_from_form,
|
|
59
59
|
} = require("../markup/admin.js");
|
|
60
60
|
const { getConfig } = require("@saltcorn/data/models/config");
|
|
61
|
+
const path = require("path");
|
|
61
62
|
//const {quote} = require("@saltcorn/db-common");
|
|
62
63
|
// todo add button backup / restore for particular tenant (available in admin tenants screens)
|
|
63
64
|
//const {
|
|
@@ -318,7 +319,53 @@ router.post(
|
|
|
318
319
|
if (hasTemplate) {
|
|
319
320
|
new_url_create += "auth/create_first_user";
|
|
320
321
|
}
|
|
321
|
-
|
|
322
|
+
const letsencrypt = getState().getConfig("letsencrypt", false);
|
|
323
|
+
if (letsencrypt) {
|
|
324
|
+
let altname = await tenant_letsencrypt_name(subdomain);
|
|
325
|
+
const tenant_letsencrypt_sites = getState().getConfig(
|
|
326
|
+
"tenant_letsencrypt_sites",
|
|
327
|
+
[]
|
|
328
|
+
);
|
|
329
|
+
const has_cert = tenant_letsencrypt_sites.includes(altname);
|
|
330
|
+
if (!has_cert) {
|
|
331
|
+
const file_store = db.connectObj.file_store;
|
|
332
|
+
const admin_users = await User.find(
|
|
333
|
+
{ role_id: 1 },
|
|
334
|
+
{ orderBy: "id" }
|
|
335
|
+
);
|
|
336
|
+
// greenlock logic
|
|
337
|
+
const Greenlock = require("greenlock");
|
|
338
|
+
const greenlock = Greenlock.create({
|
|
339
|
+
packageRoot: path.resolve(__dirname, ".."),
|
|
340
|
+
configDir: path.join(file_store, "greenlock.d"),
|
|
341
|
+
maintainerEmail: admin_users[0].email,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
await greenlock.sites.add({
|
|
345
|
+
subject: altname,
|
|
346
|
+
altnames: [altname],
|
|
347
|
+
});
|
|
348
|
+
// letsencrypt
|
|
349
|
+
const tenant_letsencrypt_sites = getState().getConfig(
|
|
350
|
+
"tenant_letsencrypt_sites",
|
|
351
|
+
[]
|
|
352
|
+
);
|
|
353
|
+
await getState().setConfig("tenant_letsencrypt_sites", [
|
|
354
|
+
altname,
|
|
355
|
+
...tenant_letsencrypt_sites,
|
|
356
|
+
]);
|
|
357
|
+
if (req.user?.role_id === 1) {
|
|
358
|
+
req.flash(
|
|
359
|
+
"success",
|
|
360
|
+
req.__(
|
|
361
|
+
"Tenant created. Certificate will be acquired on first visit."
|
|
362
|
+
)
|
|
363
|
+
);
|
|
364
|
+
res.redirect("/tenant/list");
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
322
369
|
res.sendWrap(
|
|
323
370
|
req.__("Create application"),
|
|
324
371
|
div(
|
|
@@ -374,6 +421,7 @@ router.get(
|
|
|
374
421
|
return;
|
|
375
422
|
}
|
|
376
423
|
const tens = await db.select("_sc_tenants");
|
|
424
|
+
const locale = getState().getConfig("default_locale", "en");
|
|
377
425
|
send_infoarch_page({
|
|
378
426
|
res,
|
|
379
427
|
req,
|
|
@@ -400,7 +448,8 @@ router.get(
|
|
|
400
448
|
},
|
|
401
449
|
{
|
|
402
450
|
label: req.__("Created"),
|
|
403
|
-
key: (r) =>
|
|
451
|
+
key: (r) =>
|
|
452
|
+
r.created ? localeDateTime(r.created, {}, locale) : "",
|
|
404
453
|
},
|
|
405
454
|
{
|
|
406
455
|
label: req.__("Information"),
|
|
@@ -628,7 +677,7 @@ router.get(
|
|
|
628
677
|
[]
|
|
629
678
|
);
|
|
630
679
|
const has_cert = tenant_letsencrypt_sites.includes(altname);
|
|
631
|
-
|
|
680
|
+
|
|
632
681
|
// get list of files
|
|
633
682
|
let files;
|
|
634
683
|
await db.runWithTenant(subdomain, async () => {
|
|
@@ -161,10 +161,10 @@ describe("Stable versioning install", () => {
|
|
|
161
161
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
162
162
|
});
|
|
163
163
|
expect(dbPlugin).not.toBe(null);
|
|
164
|
-
expect(dbPlugin.version).toBe("0.0
|
|
164
|
+
expect(dbPlugin.version).toBe("0.1.0");
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
it("installs a fixed version", async () => {
|
|
167
|
+
it("installs and upgrades a fixed version", async () => {
|
|
168
168
|
const loadAndSaveNewPlugin = load_plugins.loadAndSaveNewPlugin;
|
|
169
169
|
await loadAndSaveNewPlugin(
|
|
170
170
|
new Plugin({
|
|
@@ -178,7 +178,7 @@ describe("Stable versioning install", () => {
|
|
|
178
178
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
179
179
|
});
|
|
180
180
|
expect(dbPlugin).not.toBe(null);
|
|
181
|
-
expect(dbPlugin.version).toBe("0.0
|
|
181
|
+
expect(dbPlugin.version).toBe("0.1.0");
|
|
182
182
|
});
|
|
183
183
|
|
|
184
184
|
it("installs and downgrades a fixed version", async () => {
|
|
@@ -188,7 +188,7 @@ describe("Stable versioning install", () => {
|
|
|
188
188
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
189
189
|
location: "@christianhugoch/empty_sc_test_plugin",
|
|
190
190
|
source: "npm",
|
|
191
|
-
version: "0.0
|
|
191
|
+
version: "0.2.0",
|
|
192
192
|
}),
|
|
193
193
|
true
|
|
194
194
|
);
|
|
@@ -196,7 +196,7 @@ describe("Stable versioning install", () => {
|
|
|
196
196
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
197
197
|
});
|
|
198
198
|
expect(dbPlugin).not.toBe(null);
|
|
199
|
-
expect(dbPlugin.version).toBe("0.0
|
|
199
|
+
expect(dbPlugin.version).toBe("0.1.0");
|
|
200
200
|
});
|
|
201
201
|
});
|
|
202
202
|
|
|
@@ -245,7 +245,7 @@ describe("Stable versioning upgrade", () => {
|
|
|
245
245
|
expect(newPlugin.version).toBe("0.0.3");
|
|
246
246
|
});
|
|
247
247
|
|
|
248
|
-
it("upgrades to latest with downgrade", async () => {
|
|
248
|
+
it("upgrades to latest with downgrade to supported", async () => {
|
|
249
249
|
const loadAndSaveNewPlugin = load_plugins.loadAndSaveNewPlugin;
|
|
250
250
|
await loadAndSaveNewPlugin(
|
|
251
251
|
new Plugin({
|
|
@@ -276,7 +276,7 @@ describe("Stable versioning upgrade", () => {
|
|
|
276
276
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
277
277
|
});
|
|
278
278
|
expect(newPlugin).not.toBe(null);
|
|
279
|
-
expect(newPlugin.version).toBe("0.0
|
|
279
|
+
expect(newPlugin.version).toBe("0.1.0");
|
|
280
280
|
});
|
|
281
281
|
|
|
282
282
|
it("upgrades to fixed version", async () => {
|
|
@@ -313,7 +313,7 @@ describe("Stable versioning upgrade", () => {
|
|
|
313
313
|
expect(newPlugin.version).toBe("0.0.3");
|
|
314
314
|
});
|
|
315
315
|
|
|
316
|
-
it("upgrades to fixed version with downgrade", async () => {
|
|
316
|
+
it("upgrades to fixed version with downgrade to supported", async () => {
|
|
317
317
|
const loadAndSaveNewPlugin = load_plugins.loadAndSaveNewPlugin;
|
|
318
318
|
await loadAndSaveNewPlugin(
|
|
319
319
|
new Plugin({
|
|
@@ -336,7 +336,7 @@ describe("Stable versioning upgrade", () => {
|
|
|
336
336
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
337
337
|
location: "@christianhugoch/empty_sc_test_plugin",
|
|
338
338
|
source: "npm",
|
|
339
|
-
version: "0.0
|
|
339
|
+
version: "0.2.0",
|
|
340
340
|
}),
|
|
341
341
|
true
|
|
342
342
|
);
|
|
@@ -344,6 +344,6 @@ describe("Stable versioning upgrade", () => {
|
|
|
344
344
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
345
345
|
});
|
|
346
346
|
expect(newPlugin).not.toBe(null);
|
|
347
|
-
expect(newPlugin.version).toBe("0.0
|
|
347
|
+
expect(newPlugin.version).toBe("0.1.0");
|
|
348
348
|
});
|
|
349
349
|
});
|
package/tests/plugins.test.js
CHANGED
|
@@ -365,7 +365,7 @@ describe("Upgrade plugin to supported version", () => {
|
|
|
365
365
|
expect(upgradedPlugin.version).toBe("0.0.3");
|
|
366
366
|
});
|
|
367
367
|
|
|
368
|
-
it("upgrades to
|
|
368
|
+
it("upgrades to latest as fixed version", async () => {
|
|
369
369
|
const oldPlugin = await setupPluginVersion(
|
|
370
370
|
"@christianhugoch/empty_sc_test_plugin_two",
|
|
371
371
|
"0.0.1"
|
|
@@ -389,7 +389,7 @@ describe("Upgrade plugin to supported version", () => {
|
|
|
389
389
|
expect(upgradedPlugin.version).toBe("0.0.3");
|
|
390
390
|
});
|
|
391
391
|
|
|
392
|
-
it("upgrades with a downgrade of
|
|
392
|
+
it("upgrades with a downgrade of latest", async () => {
|
|
393
393
|
const oldPlugin = await setupPluginVersion(
|
|
394
394
|
"@christianhugoch/empty_sc_test_plugin",
|
|
395
395
|
"0.0.1"
|
|
@@ -404,10 +404,10 @@ describe("Upgrade plugin to supported version", () => {
|
|
|
404
404
|
const upgradedPlugin = await Plugin.findOne({
|
|
405
405
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
406
406
|
});
|
|
407
|
-
expect(upgradedPlugin.version).toBe("0.0
|
|
407
|
+
expect(upgradedPlugin.version).toBe("0.1.0");
|
|
408
408
|
});
|
|
409
409
|
|
|
410
|
-
it("upgrades with a downgrade of
|
|
410
|
+
it("upgrades with a downgrade of latest as fixed version", async () => {
|
|
411
411
|
const oldPlugin = await setupPluginVersion(
|
|
412
412
|
"@christianhugoch/empty_sc_test_plugin",
|
|
413
413
|
"0.0.1"
|
|
@@ -421,13 +421,13 @@ describe("Upgrade plugin to supported version", () => {
|
|
|
421
421
|
"@christianhugoch/empty_sc_test_plugin"
|
|
422
422
|
)}`
|
|
423
423
|
)
|
|
424
|
-
.send("version=0.
|
|
424
|
+
.send("version=0.2.0")
|
|
425
425
|
.set("Cookie", loginCookie)
|
|
426
426
|
.expect(toRedirect("/plugins"));
|
|
427
427
|
const upgradedPlugin = await Plugin.findOne({
|
|
428
428
|
name: "@christianhugoch/empty_sc_test_plugin",
|
|
429
429
|
});
|
|
430
|
-
expect(upgradedPlugin.version).toBe("0.0
|
|
430
|
+
expect(upgradedPlugin.version).toBe("0.1.0");
|
|
431
431
|
});
|
|
432
432
|
});
|
|
433
433
|
|
package/wrapper.js
CHANGED
|
@@ -193,7 +193,9 @@ const get_headers = (req, version_tag, description, extras = []) => {
|
|
|
193
193
|
state.logLevel
|
|
194
194
|
}, _sc_globalCsrf = "${req.csrfToken()}", _sc_version_tag = "${version_tag}"${
|
|
195
195
|
locale ? `, _sc_locale = "${locale}"` : ""
|
|
196
|
-
}
|
|
196
|
+
}, _sc_lightmode = ${JSON.stringify(
|
|
197
|
+
state.getLightDarkMode(req.user)
|
|
198
|
+
)};</script>`,
|
|
197
199
|
},
|
|
198
200
|
{ css: `/static_assets/${version_tag}/saltcorn.css` },
|
|
199
201
|
{ script: `/static_assets/${version_tag}/saltcorn-common.js` },
|