@saltcorn/server 1.1.2-beta.17 → 1.1.2-beta.19

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/locales/en.json CHANGED
@@ -1554,5 +1554,8 @@
1554
1554
  "Search syntax": "Search syntax",
1555
1555
  "Maximum role": "Maximum role",
1556
1556
  "Module dependencies": "Module dependencies",
1557
- "Prompt": "Prompt"
1557
+ "Prompt": "Prompt",
1558
+ "Clean modules and restart": "Clean modules and restart",
1559
+ "Modules cleaned, server restarting...": "Modules cleaned, server restarting...",
1560
+ "Delete table+views+triggers": "Delete table+views+triggers"
1558
1561
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "1.1.2-beta.17",
3
+ "version": "1.1.2-beta.19",
4
4
  "description": "Server app for Saltcorn, open-source no-code platform",
5
5
  "homepage": "https://saltcorn.com",
6
6
  "main": "index.js",
@@ -8,14 +8,14 @@
8
8
  "dependencies": {
9
9
  "@aws-sdk/client-s3": "^3.735.0",
10
10
  "@dr.pogodin/csurf": "^1.14.1",
11
- "@saltcorn/base-plugin": "1.1.2-beta.17",
12
- "@saltcorn/builder": "1.1.2-beta.17",
13
- "@saltcorn/data": "1.1.2-beta.17",
14
- "@saltcorn/admin-models": "1.1.2-beta.17",
15
- "@saltcorn/filemanager": "1.1.2-beta.17",
16
- "@saltcorn/markup": "1.1.2-beta.17",
17
- "@saltcorn/plugins-loader": "1.1.2-beta.17",
18
- "@saltcorn/sbadmin2": "1.1.2-beta.17",
11
+ "@saltcorn/base-plugin": "1.1.2-beta.19",
12
+ "@saltcorn/builder": "1.1.2-beta.19",
13
+ "@saltcorn/data": "1.1.2-beta.19",
14
+ "@saltcorn/admin-models": "1.1.2-beta.19",
15
+ "@saltcorn/filemanager": "1.1.2-beta.19",
16
+ "@saltcorn/markup": "1.1.2-beta.19",
17
+ "@saltcorn/plugins-loader": "1.1.2-beta.19",
18
+ "@saltcorn/sbadmin2": "1.1.2-beta.19",
19
19
  "@socket.io/cluster-adapter": "^0.2.1",
20
20
  "@socket.io/sticky": "^1.0.1",
21
21
  "adm-zip": "0.5.16",
@@ -164,13 +164,15 @@ function delete_tabulator_row(e, cell) {
164
164
  def?.formatterParams?.tableName || window.tabulator_table_name;
165
165
 
166
166
  const row = cell.getRow().getData();
167
- if (!row.id) {
167
+
168
+ const pk_name = window.tabulator_table_primary_key || "id";
169
+ if (!row[pk_name]) {
168
170
  cell.getRow().delete();
169
171
  return;
170
172
  }
171
173
  $.ajax({
172
174
  type: "DELETE",
173
- url: `/api/${tableName}/${row.id}`,
175
+ url: `/api/${tableName}/${row[pk_name]}`,
174
176
  data: row, // to process primary keys different from id
175
177
  headers: {
176
178
  "CSRF-Token": _sc_globalCsrf,
package/routes/admin.js CHANGED
@@ -117,6 +117,7 @@ const { get_help_markup } = require("../help/index.js");
117
117
  const Docker = require("dockerode");
118
118
  const npmFetch = require("npm-registry-fetch");
119
119
  const Tag = require("@saltcorn/data/models/tag");
120
+ const PluginInstaller = require("@saltcorn/plugins-loader/plugin_installer.js");
120
121
  const MarkdownIt = require("markdown-it"),
121
122
  md = new MarkdownIt();
122
123
 
@@ -841,7 +842,8 @@ const autoBackupForm = (req) => {
841
842
  label: req.__("Backup now"),
842
843
  id: "btnBackupNow",
843
844
  class: "btn btn-outline-secondary",
844
- onclick: "ajax_post('/admin/auto-backup-now');press_store_button(this);",
845
+ onclick:
846
+ "ajax_post('/admin/auto-backup-now');press_store_button(this);",
845
847
  },
846
848
  ],
847
849
  fields: [
@@ -1565,6 +1567,7 @@ const cleanNodeModules = async () => {
1565
1567
  throw new Error(
1566
1568
  `'${topSaltcornDir}' is not a Saltcorn installation directory`
1567
1569
  );
1570
+ await PluginInstaller.cleanPluginsDirectory();
1568
1571
  };
1569
1572
 
1570
1573
  const doInstall = async (req, res, version, deepClean, runPull) => {
package/routes/api.js CHANGED
@@ -78,8 +78,8 @@ function accessAllowedRead(req, user, table, allow_ownership) {
78
78
  req.user && req.user.id
79
79
  ? req.user.role_id
80
80
  : user && user.role_id
81
- ? user.role_id
82
- : 100;
81
+ ? user.role_id
82
+ : 100;
83
83
 
84
84
  return (
85
85
  role <= table.min_role_read ||
@@ -101,8 +101,8 @@ function accessAllowedWrite(req, user, table) {
101
101
  req.user && req.user.id
102
102
  ? req.user.role_id
103
103
  : user && user.role_id
104
- ? user.role_id
105
- : 100;
104
+ ? user.role_id
105
+ : 100;
106
106
 
107
107
  return (
108
108
  role <= table.min_role_write ||
@@ -122,8 +122,8 @@ function accessAllowed(req, user, trigger) {
122
122
  req.user && req.user.id
123
123
  ? req.user.role_id
124
124
  : user && user.role_id
125
- ? user.role_id
126
- : 100;
125
+ ? user.role_id
126
+ : 100;
127
127
 
128
128
  return role <= trigger.min_role;
129
129
  }
@@ -397,8 +397,8 @@ router.get(
397
397
  const derefs = Array.isArray(dereference)
398
398
  ? dereference
399
399
  : !dereference
400
- ? []
401
- : [dereference];
400
+ ? []
401
+ : [dereference];
402
402
  derefs.forEach((f) => {
403
403
  const field = table.getField(f);
404
404
  if (field?.attributes?.summary_field)
@@ -701,7 +701,7 @@ router.delete(
701
701
  );
702
702
  } else
703
703
  await table.deleteRows(
704
- { id },
704
+ { [table.pk_name]: id },
705
705
  user || req.user || { role_id: 100 }
706
706
  );
707
707
  res.json({ success: true });
package/routes/list.js CHANGED
@@ -402,6 +402,7 @@ router.get(
402
402
  col[k] = window[v.substring(2)];
403
403
  })
404
404
  })
405
+ window.tabulator_table_primary_key = "${table.pk_name}";
405
406
  window.tabulator_table = new Tabulator("#jsGrid", {
406
407
  ajaxURL:"/api/${encodeURIComponent(
407
408
  table.name
@@ -421,7 +422,7 @@ router.get(
421
422
  ajaxContentType:"json",
422
423
  sortMode:"remote",
423
424
  initialSort:[
424
- {column:"id", dir:"asc"},
425
+ {column:"${table.pk_name}", dir:"asc"},
425
426
  ],
426
427
  });
427
428
  window.tabulator_table.on("cellEdited", function(cell){
package/routes/plugins.js CHANGED
@@ -495,6 +495,17 @@ const store_actions_dropdown = (req) => {
495
495
  '<i class="far fa-arrow-alt-circle-up"></i>&nbsp;' +
496
496
  req.__("Upgrade installed modules")
497
497
  ),
498
+ db.getTenantSchema() === db.connectObj.default_schema &&
499
+ a(
500
+ {
501
+ class: "dropdown-item",
502
+ href: `/plugins/reinstall-all`,
503
+ onClick: `notifyAlert('${req.__("Upgrading modules...")}', true)`,
504
+ },
505
+ '<i class="fas fa-pump-medical"></i>&nbsp;' +
506
+ req.__("Clean modules and restart")
507
+ ),
508
+
498
509
  (db.getTenantSchema() === db.connectObj.default_schema ||
499
510
  tenants_install_git) &&
500
511
  a(
@@ -558,7 +569,7 @@ const plugin_store_html = (items, req) => {
558
569
  },
559
570
  {
560
571
  besides: items.map(store_item_html(req)),
561
- gy:3,
572
+ gy: 3,
562
573
  widths: items.map(() => 4),
563
574
  },
564
575
  ],
@@ -1397,6 +1408,30 @@ router.get(
1397
1408
  })
1398
1409
  );
1399
1410
 
1411
+ /**
1412
+ * @name get/upgrade
1413
+ * @function
1414
+ * @memberof module:routes/plugins~pluginsRouter
1415
+ * @function
1416
+ */
1417
+ router.get(
1418
+ "/reinstall-all",
1419
+ isAdmin,
1420
+ error_catcher(async (req, res) => {
1421
+ //TODO make this post
1422
+ const schema = db.getTenantSchema();
1423
+ if (schema === db.connectObj.default_schema) {
1424
+ await PluginInstaller.cleanPluginsDirectory();
1425
+ req.flash("success", req.__(`Modules cleaned, server restarting...`));
1426
+ setTimeout(() => {
1427
+ if (process.send) getState().processSend("RestartServer");
1428
+ else process.exit(0);
1429
+ }, 1000);
1430
+ }
1431
+ res.redirect(`/plugins`);
1432
+ })
1433
+ );
1434
+
1400
1435
  /**
1401
1436
  * @name get/upgrade-plugin/:name
1402
1437
  * @function
package/routes/tables.js CHANGED
@@ -867,6 +867,8 @@ router.get(
867
867
  );
868
868
  fieldCard = [
869
869
  (nPrimaryKeys !== 1 || nonSerialPKS) &&
870
+ !table.external &&
871
+ !table.provider_name &&
870
872
  div(
871
873
  { class: "alert alert-danger", role: "alert" },
872
874
  i({ class: "fas fa-exclamation-triangle" }),
@@ -1117,6 +1119,15 @@ router.get(
1117
1119
  req,
1118
1120
  true
1119
1121
  ),
1122
+ req.user.role_id === 1 &&
1123
+ table.name !== "users" &&
1124
+ post_dropdown_item(
1125
+ `/table/delete-with-trig-views/${table.id}`,
1126
+ '<i class="fas fa-trash"></i>&nbsp;' +
1127
+ req.__("Delete table+views+triggers"),
1128
+ req,
1129
+ true
1130
+ ),
1120
1131
  ])
1121
1132
  )
1122
1133
  );
@@ -1278,6 +1289,50 @@ router.post(
1278
1289
  })
1279
1290
  );
1280
1291
 
1292
+ //delete-with-trig-views
1293
+ /**
1294
+ * Delete Table Route Handler definition
1295
+ * /delete:/id, where id is table id in _sc_tables
1296
+ * @name post/delete/:id
1297
+ * @function
1298
+ * @memberof module:routes/tables~tablesRouter
1299
+ * @function
1300
+ */
1301
+ router.post(
1302
+ "/delete-with-trig-views/:id",
1303
+ isAdmin,
1304
+ error_catcher(async (req, res) => {
1305
+ const { id } = req.params;
1306
+ const t = Table.findOne({ id });
1307
+ if (!t) {
1308
+ req.flash("error", `Table not found`);
1309
+ res.redirect(`/table`);
1310
+ return;
1311
+ }
1312
+ if (t.name === "users") {
1313
+ req.flash("error", req.__(`Cannot delete users table`));
1314
+ res.redirect(`/table`);
1315
+ return;
1316
+ }
1317
+ const views = await View.find(
1318
+ t.id ? { table_id: t.id } : { exttable_name: t.name }
1319
+ );
1320
+ for (const view of views) await view.delete();
1321
+ if (t.id) {
1322
+ const triggers = await Trigger.find({ table_id: t.id });
1323
+ for (const trig of triggers) await trig.delete();
1324
+ }
1325
+ try {
1326
+ await t.delete();
1327
+ req.flash("success", req.__(`Table %s deleted`, t.name));
1328
+ res.redirect(`/table`);
1329
+ } catch (err) {
1330
+ req.flash("error", err.message);
1331
+ res.redirect(`/table`);
1332
+ }
1333
+ })
1334
+ );
1335
+
1281
1336
  /**
1282
1337
  * Delete Table Route Handler definition
1283
1338
  * /delete:/id, where id is table id in _sc_tables