@saltcorn/server 0.9.6-beta.2 → 0.9.6-beta.20
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 +6 -1
- package/auth/admin.js +55 -53
- package/auth/routes.js +28 -10
- package/auth/testhelp.js +86 -0
- package/help/Field label.tmd +11 -0
- package/help/Field types.tmd +39 -0
- package/help/Ownership field.tmd +76 -0
- package/help/Ownership formula.tmd +75 -0
- package/help/Table roles.tmd +20 -0
- package/help/User groups.tmd +35 -0
- package/load_plugins.js +33 -5
- package/locales/en.json +29 -1
- package/locales/it.json +3 -2
- package/markup/admin.js +1 -0
- package/markup/forms.js +5 -1
- package/package.json +9 -9
- package/public/log_viewer_utils.js +32 -0
- package/public/mermaid.min.js +705 -306
- package/public/saltcorn-builder.css +23 -0
- package/public/saltcorn-common.js +248 -80
- package/public/saltcorn.css +80 -0
- package/public/saltcorn.js +86 -2
- package/restart_watcher.js +1 -0
- package/routes/actions.js +27 -0
- package/routes/admin.js +175 -64
- package/routes/api.js +6 -0
- package/routes/common_lists.js +42 -32
- package/routes/fields.js +70 -42
- package/routes/homepage.js +2 -0
- package/routes/index.js +2 -0
- package/routes/menu.js +69 -4
- package/routes/notifications.js +90 -10
- package/routes/pageedit.js +18 -13
- package/routes/plugins.js +11 -2
- package/routes/registry.js +289 -0
- package/routes/search.js +10 -4
- package/routes/tables.js +51 -27
- package/routes/tenant.js +4 -15
- package/routes/utils.js +25 -8
- package/routes/view.js +1 -1
- package/routes/viewedit.js +11 -7
- package/serve.js +27 -5
- package/tests/edit.test.js +426 -0
- package/tests/fields.test.js +21 -0
- package/tests/filter.test.js +68 -0
- package/tests/page.test.js +2 -2
- package/tests/plugins.test.js +2 -0
- package/tests/sync.test.js +59 -0
- package/wrapper.js +4 -1
package/load_plugins.js
CHANGED
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
const db = require("@saltcorn/data/db");
|
|
9
9
|
const { getState, getRootState } = require("@saltcorn/data/db/state");
|
|
10
10
|
const Plugin = require("@saltcorn/data/models/plugin");
|
|
11
|
+
const { isRoot } = require("@saltcorn/data/utils");
|
|
12
|
+
const { eachTenant } = require("@saltcorn/admin-models/models/tenant");
|
|
11
13
|
|
|
12
14
|
const PluginInstaller = require("@saltcorn/plugins-loader/plugin_installer");
|
|
13
15
|
|
|
@@ -60,9 +62,23 @@ const loadPlugin = async (plugin, force) => {
|
|
|
60
62
|
console.error(error); // todo i think that situation is not resolved
|
|
61
63
|
}
|
|
62
64
|
}
|
|
65
|
+
|
|
66
|
+
if (isRoot() && res.plugin_module.authentication)
|
|
67
|
+
await eachTenant(reloadAuthFromRoot);
|
|
63
68
|
return res;
|
|
64
69
|
};
|
|
65
70
|
|
|
71
|
+
const reloadAuthFromRoot = () => {
|
|
72
|
+
if (isRoot()) return;
|
|
73
|
+
const rootState = getRootState();
|
|
74
|
+
const tenantState = getState();
|
|
75
|
+
if (!rootState || !tenantState || rootState === tenantState) return;
|
|
76
|
+
tenantState.auth_methods = {};
|
|
77
|
+
for (const [k, v] of Object.entries(rootState.auth_methods)) {
|
|
78
|
+
if (v.shareWithTenants) tenantState.auth_methods[k] = v;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
66
82
|
/**
|
|
67
83
|
* Install plugin
|
|
68
84
|
* @param plugin - plugin name
|
|
@@ -90,6 +106,7 @@ const loadAllPlugins = async (force) => {
|
|
|
90
106
|
}
|
|
91
107
|
await getState().refreshUserLayouts();
|
|
92
108
|
await getState().refresh(true);
|
|
109
|
+
if (!isRoot()) reloadAuthFromRoot();
|
|
93
110
|
};
|
|
94
111
|
|
|
95
112
|
/**
|
|
@@ -104,14 +121,14 @@ const loadAndSaveNewPlugin = async (
|
|
|
104
121
|
plugin,
|
|
105
122
|
force,
|
|
106
123
|
noSignalOrDB,
|
|
107
|
-
__ = (str) => str
|
|
124
|
+
__ = (str) => str,
|
|
125
|
+
allowUnsafeOnTenantsWithoutConfigSetting
|
|
108
126
|
) => {
|
|
109
127
|
const tenants_unsafe_plugins = getRootState().getConfig(
|
|
110
128
|
"tenants_unsafe_plugins",
|
|
111
129
|
false
|
|
112
130
|
);
|
|
113
|
-
|
|
114
|
-
if (!isRoot && !tenants_unsafe_plugins) {
|
|
131
|
+
if (!isRoot() && !tenants_unsafe_plugins) {
|
|
115
132
|
if (plugin.source !== "npm") {
|
|
116
133
|
console.error("\nWARNING: Skipping unsafe plugin ", plugin.name);
|
|
117
134
|
return;
|
|
@@ -126,7 +143,10 @@ const loadAndSaveNewPlugin = async (
|
|
|
126
143
|
|
|
127
144
|
const instore = getRootState().getConfig("available_plugins", []);
|
|
128
145
|
const safes = instore.filter((p) => !p.unsafe).map((p) => p.location);
|
|
129
|
-
if (
|
|
146
|
+
if (
|
|
147
|
+
!safes.includes(plugin.location) &&
|
|
148
|
+
!allowUnsafeOnTenantsWithoutConfigSetting
|
|
149
|
+
) {
|
|
130
150
|
console.error("\nWARNING: Skipping unsafe plugin ", plugin.name);
|
|
131
151
|
return;
|
|
132
152
|
}
|
|
@@ -141,7 +161,11 @@ const loadAndSaveNewPlugin = async (
|
|
|
141
161
|
const existing = await Plugin.findOne({ location: loc });
|
|
142
162
|
if (!existing && loc !== plugin.location) {
|
|
143
163
|
await loadAndSaveNewPlugin(
|
|
144
|
-
new Plugin({
|
|
164
|
+
new Plugin({
|
|
165
|
+
name: loc.replace("@saltcorn/", ""),
|
|
166
|
+
location: loc,
|
|
167
|
+
source: "npm",
|
|
168
|
+
}),
|
|
145
169
|
force,
|
|
146
170
|
noSignalOrDB
|
|
147
171
|
);
|
|
@@ -192,6 +216,10 @@ const loadAndSaveNewPlugin = async (
|
|
|
192
216
|
}
|
|
193
217
|
}
|
|
194
218
|
if (version) plugin.version = version;
|
|
219
|
+
|
|
220
|
+
if (isRoot() && plugin_module.authentication)
|
|
221
|
+
await eachTenant(reloadAuthFromRoot);
|
|
222
|
+
|
|
195
223
|
if (!noSignalOrDB) {
|
|
196
224
|
await plugin.upsert();
|
|
197
225
|
getState().processSend({
|
package/locales/en.json
CHANGED
|
@@ -1425,5 +1425,33 @@
|
|
|
1425
1425
|
"Keystore Alias": "Keystore Alias",
|
|
1426
1426
|
"Keystore Password": "Keystore Password",
|
|
1427
1427
|
"xcodebuild": "xcodebuild",
|
|
1428
|
-
"Provisioning Profile": "Provisioning Profile"
|
|
1428
|
+
"Provisioning Profile": "Provisioning Profile",
|
|
1429
|
+
"Registry editor": "Registry editor",
|
|
1430
|
+
"Mobile HTML": "Mobile HTML",
|
|
1431
|
+
"HTML for the item in the bottom navigation bar. Currently, only supported by the metronic theme.": "HTML for the item in the bottom navigation bar. Currently, only supported by the metronic theme.",
|
|
1432
|
+
"A short name that will be in the page URL": "A short name that will be in the page URL",
|
|
1433
|
+
"A longer description that is not visible but appears in the page header and is indexed by search engines": "A longer description that is not visible but appears in the page header and is indexed by search engines",
|
|
1434
|
+
"User role required to access page": "User role required to access page",
|
|
1435
|
+
"Example: <code>`/view/TheOtherView?id=${id}`</code>": "Example: <code>`/view/TheOtherView?id=${id}`</code>",
|
|
1436
|
+
"Older": "Older",
|
|
1437
|
+
"Newest": "Newest",
|
|
1438
|
+
"Delete all read": "Delete all read",
|
|
1439
|
+
"Trigger %s duplicated as %s": "Trigger %s duplicated as %s",
|
|
1440
|
+
"Tooltip": "Tooltip",
|
|
1441
|
+
"Tooltip formula": "Tooltip formula",
|
|
1442
|
+
"Install a different version": "Install a different version",
|
|
1443
|
+
"Page group": "Page group",
|
|
1444
|
+
"Starting upgrade, please wait...\n": "Starting upgrade, please wait...\n",
|
|
1445
|
+
"Upgrade done (if it was available) with code 0.\n\nPress the BACK button in your browser, then RELOAD the page.": "Upgrade done (if it was available) with code 0.\n\nPress the BACK button in your browser, then RELOAD the page.",
|
|
1446
|
+
"Installing %s, please wait...\n": "Installing %s, please wait...\n",
|
|
1447
|
+
"Install done with code 0.\n\nPress the BACK button in your browser, then RELOAD the page.": "Install done with code 0.\n\nPress the BACK button in your browser, then RELOAD the page.",
|
|
1448
|
+
"Pulling the cordova-builder docker image...": "Pulling the cordova-builder docker image...",
|
|
1449
|
+
"Check updates": "Check updates",
|
|
1450
|
+
"Choose version": "Choose version",
|
|
1451
|
+
"Unknown authentication method %s": "Unknown authentication method %s",
|
|
1452
|
+
"Card rows": "Card rows",
|
|
1453
|
+
"Each row in a card. Not supported by all themes": "Each row in a card. Not supported by all themes",
|
|
1454
|
+
"Prune session interval (seconds)": "Prune session interval (seconds)",
|
|
1455
|
+
"Interval in seconds to check for expred sessions in the postgres db. 0, empty or a negative number to disable": "Interval in seconds to check for expred sessions in the postgres db. 0, empty or a negative number to disable",
|
|
1456
|
+
"Progressive Web Application is not enabled": "Progressive Web Application is not enabled"
|
|
1429
1457
|
}
|
package/locales/it.json
CHANGED
|
@@ -518,5 +518,6 @@
|
|
|
518
518
|
"Save before going back": "Save before going back",
|
|
519
519
|
"Reload after going back": "Reload after going back",
|
|
520
520
|
"Steps to go back": "Steps to go back",
|
|
521
|
-
"%s configuration": "%s configuration"
|
|
522
|
-
|
|
521
|
+
"%s configuration": "%s configuration",
|
|
522
|
+
"The current theme has no user specific settings": "The current theme has no user specific settings"
|
|
523
|
+
}
|
package/markup/admin.js
CHANGED
|
@@ -241,6 +241,7 @@ const send_infoarch_page = (args) => {
|
|
|
241
241
|
{ text: "Pagegroups", href: "/page_group/settings" },
|
|
242
242
|
{ text: "Tags", href: "/tag" },
|
|
243
243
|
{ text: "Diagram", href: "/diagram" },
|
|
244
|
+
{ text: "Registry editor", href: "/registry-editor" },
|
|
244
245
|
],
|
|
245
246
|
...args,
|
|
246
247
|
});
|
package/markup/forms.js
CHANGED
|
@@ -28,10 +28,14 @@ const editRoleForm = ({ url, current_role, roles, req }) =>
|
|
|
28
28
|
{
|
|
29
29
|
action: url,
|
|
30
30
|
method: "post",
|
|
31
|
+
onchange: "saveAndContinue(this)",
|
|
31
32
|
},
|
|
32
33
|
csrfField(req),
|
|
33
34
|
select(
|
|
34
|
-
{
|
|
35
|
+
{
|
|
36
|
+
name: "role",
|
|
37
|
+
class: "w-unset form-select form-select-sm",
|
|
38
|
+
},
|
|
35
39
|
roles.map((role) =>
|
|
36
40
|
option(
|
|
37
41
|
{
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/server",
|
|
3
|
-
"version": "0.9.6-beta.
|
|
3
|
+
"version": "0.9.6-beta.20",
|
|
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": "0.9.6-beta.
|
|
11
|
-
"@saltcorn/builder": "0.9.6-beta.
|
|
12
|
-
"@saltcorn/data": "0.9.6-beta.
|
|
13
|
-
"@saltcorn/admin-models": "0.9.6-beta.
|
|
14
|
-
"@saltcorn/filemanager": "0.9.6-beta.
|
|
15
|
-
"@saltcorn/markup": "0.9.6-beta.
|
|
16
|
-
"@saltcorn/plugins-loader": "0.9.6-beta.
|
|
17
|
-
"@saltcorn/sbadmin2": "0.9.6-beta.
|
|
10
|
+
"@saltcorn/base-plugin": "0.9.6-beta.20",
|
|
11
|
+
"@saltcorn/builder": "0.9.6-beta.20",
|
|
12
|
+
"@saltcorn/data": "0.9.6-beta.20",
|
|
13
|
+
"@saltcorn/admin-models": "0.9.6-beta.20",
|
|
14
|
+
"@saltcorn/filemanager": "0.9.6-beta.20",
|
|
15
|
+
"@saltcorn/markup": "0.9.6-beta.20",
|
|
16
|
+
"@saltcorn/plugins-loader": "0.9.6-beta.20",
|
|
17
|
+
"@saltcorn/sbadmin2": "0.9.6-beta.20",
|
|
18
18
|
"@socket.io/cluster-adapter": "^0.2.1",
|
|
19
19
|
"@socket.io/sticky": "^1.0.1",
|
|
20
20
|
"adm-zip": "0.5.10",
|
|
@@ -10,6 +10,9 @@ var logViewerHelpers = (() => {
|
|
|
10
10
|
second: "2-digit",
|
|
11
11
|
};
|
|
12
12
|
let lostConnection = false;
|
|
13
|
+
let waitingForTestMessage = false;
|
|
14
|
+
let startedWaitingAt = null;
|
|
15
|
+
let waitTimeout = false;
|
|
13
16
|
|
|
14
17
|
const logLevelColor = (level) => {
|
|
15
18
|
switch (parseInt(level)) {
|
|
@@ -94,6 +97,17 @@ var logViewerHelpers = (() => {
|
|
|
94
97
|
});
|
|
95
98
|
};
|
|
96
99
|
|
|
100
|
+
const testMsgWaiter = (waiterStartedAt) => () => {
|
|
101
|
+
if (waitingForTestMessage && waiterStartedAt === startedWaitingAt) {
|
|
102
|
+
emptyAlerts();
|
|
103
|
+
waitTimeout = true;
|
|
104
|
+
notifyAlert({
|
|
105
|
+
type: "danger",
|
|
106
|
+
text: "You are connected but not receiving any messages",
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
97
111
|
const handleConnect = (socket) => {
|
|
98
112
|
socket.emit("join_log_room", (ack) => {
|
|
99
113
|
if (ack) {
|
|
@@ -109,6 +123,10 @@ var logViewerHelpers = (() => {
|
|
|
109
123
|
text: "You are connected again",
|
|
110
124
|
});
|
|
111
125
|
}
|
|
126
|
+
waitingForTestMessage = true;
|
|
127
|
+
waitTimeout = false;
|
|
128
|
+
startedWaitingAt = new Date().valueOf();
|
|
129
|
+
setTimeout(testMsgWaiter(startedWaitingAt), 5000);
|
|
112
130
|
} else if (ack.status === "error" && ack.msg) {
|
|
113
131
|
notifyAlert({
|
|
114
132
|
type: "danger",
|
|
@@ -129,6 +147,19 @@ var logViewerHelpers = (() => {
|
|
|
129
147
|
});
|
|
130
148
|
};
|
|
131
149
|
|
|
150
|
+
const handleTestConnMsg = () => {
|
|
151
|
+
waitingForTestMessage = false;
|
|
152
|
+
startedWaitingAt = null;
|
|
153
|
+
if (waitTimeout) {
|
|
154
|
+
emptyAlerts();
|
|
155
|
+
notifyAlert({
|
|
156
|
+
type: "success",
|
|
157
|
+
text: "You are connected and receiving messages",
|
|
158
|
+
});
|
|
159
|
+
waitTimeout = false;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
132
163
|
return {
|
|
133
164
|
init_log_socket: () => {
|
|
134
165
|
let socket = null;
|
|
@@ -152,6 +183,7 @@ var logViewerHelpers = (() => {
|
|
|
152
183
|
socket.on("connect", () => handleConnect(socket));
|
|
153
184
|
socket.on("disconnect", handleDisconnect);
|
|
154
185
|
socket.on("log_msg", handleLogMsg);
|
|
186
|
+
socket.on("test_conn_msg", handleTestConnMsg);
|
|
155
187
|
},
|
|
156
188
|
goToLogsPage: (n) => {
|
|
157
189
|
currentPage = n;
|