@saltcorn/server 0.6.4-beta.2 → 0.6.4-beta.3

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/resetpw.js CHANGED
@@ -8,9 +8,9 @@ const { getMailTransport } = require("@saltcorn/data/models/email");
8
8
  const { get_base_url } = require("../routes/utils");
9
9
 
10
10
  /**
11
- * @param {string} link
12
- * @param {object} user
13
- * @param {object} req
11
+ * @param {string} link
12
+ * @param {object} user
13
+ * @param {object} req
14
14
  * @returns {void}
15
15
  */
16
16
  const generate_email = (link, user, req) => ({
@@ -48,8 +48,8 @@ ${req.__(
48
48
  });
49
49
 
50
50
  /**
51
- * @param {object} user
52
- * @param {object} req
51
+ * @param {object} user
52
+ * @param {object} req
53
53
  * @returns {Promise<void>}
54
54
  */
55
55
  const send_reset_email = async (user, req) => {
@@ -59,8 +59,8 @@ const send_reset_email = async (user, req) => {
59
59
  };
60
60
 
61
61
  /**
62
- * @param {object} user
63
- * @param {object} req
62
+ * @param {object} user
63
+ * @param {object} req
64
64
  * @returns {Promise<string>}
65
65
  */
66
66
  const get_reset_link = async (user, req) => {
package/locales/en.json CHANGED
@@ -865,5 +865,7 @@
865
865
  "Vertical column width": "Vertical column width",
866
866
  "Vertical width units": "Vertical width units",
867
867
  "Save before going back": "Save before going back",
868
- "Reload after going back": "Reload after going back"
868
+ "Reload after going back": "Reload after going back",
869
+ "2FA policy": "2FA policy",
870
+ "Steps to go back": "Steps to go back"
869
871
  }
package/package.json CHANGED
@@ -1,23 +1,24 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "0.6.4-beta.2",
3
+ "version": "0.6.4-beta.3",
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
- "@saltcorn/base-plugin": "0.6.4-beta.2",
10
- "@saltcorn/builder": "0.6.4-beta.2",
11
- "@saltcorn/data": "0.6.4-beta.2",
12
- "@saltcorn/admin-models": "0.6.4-beta.2",
13
- "greenlock-express": "^4.0.3",
14
- "@saltcorn/markup": "0.6.4-beta.2",
15
- "@saltcorn/sbadmin2": "0.6.4-beta.2",
9
+ "@saltcorn/base-plugin": "0.6.4-beta.3",
10
+ "@saltcorn/builder": "0.6.4-beta.3",
11
+ "@saltcorn/data": "0.6.4-beta.3",
12
+ "@saltcorn/admin-models": "0.6.4-beta.3",
13
+ "@saltcorn/markup": "0.6.4-beta.3",
14
+ "@saltcorn/sbadmin2": "0.6.4-beta.3",
16
15
  "@socket.io/cluster-adapter": "^0.1.0",
17
16
  "@socket.io/sticky": "^1.0.1",
17
+ "aws-sdk": "^2.1037.0",
18
18
  "connect-flash": "^0.1.1",
19
19
  "connect-pg-simple": "^6.1.0",
20
20
  "connect-sqlite3": "^0.9.11",
21
+ "content-disposition": "^0.5.3",
21
22
  "contractis": "^0.1.0",
22
23
  "cookie-parser": "^1.4.4",
23
24
  "cookie-session": "^1.4.0",
@@ -29,10 +30,13 @@
29
30
  "express-rate-limit": "^5.1.3",
30
31
  "express-session": "^1.17.1",
31
32
  "greenlock": "^4.0.4",
33
+ "greenlock-express": "^4.0.3",
32
34
  "helmet": "^3.23.3",
33
35
  "i18n": "^0.13.2",
34
36
  "live-plugin-manager": "^0.16.0",
35
37
  "moment": "^2.27.0",
38
+ "multer": "^1.4.3",
39
+ "multer-s3": "^2.10.0",
36
40
  "node-fetch": "2.6.2",
37
41
  "node-watch": "^0.7.2",
38
42
  "notp": "2.0.3",
@@ -44,13 +48,9 @@
44
48
  "pluralize": "^8.0.0",
45
49
  "qrcode": "1.5.0",
46
50
  "socket.io": "4.2.0",
47
- "tmp-promise": "^3.0.2",
48
51
  "thirty-two": "1.0.2",
49
- "multer-s3": "^2.10.0",
50
- "multer": "^1.4.3",
51
- "aws-sdk": "^2.1037.0",
52
- "uuid": "^8.2.0",
53
- "content-disposition": "^0.5.3"
52
+ "tmp-promise": "^3.0.2",
53
+ "uuid": "^8.2.0"
54
54
  },
55
55
  "optionalDependencies": {
56
56
  "sd-notify": "^2.8.0"
@@ -1,228 +1,169 @@
1
- /**
2
- * jsgrid_controller
3
- * @param table_name -
4
- * @param vc -
5
- * @param keyfields -
6
- * @returns {{deleteItem: (function(*): *), loadData: (function(*=): *), updateItem: (function(*=): *), insertItem: (function(*=): *)}}
7
- */
8
-
9
- function jsgrid_controller(table_name, vc, keyfields) {
10
- var url = "/api/" + table_name + "/";
11
- //
12
- var fixKeys = function (item) {
13
- keyfields.forEach((kf) => {
14
- if (kf.type === "Integer") item[kf.name] = +item[kf.name];
15
- });
16
- return item;
1
+ function showHideCol(nm, e) {
2
+ if (e && e.checked) window.tabulator_table.showColumn(nm);
3
+ else window.tabulator_table.hideColumn(nm);
4
+ }
5
+
6
+ function lookupIntToString(cell, formatterParams, onRendered) {
7
+ const val = `${cell.getValue()}`;
8
+ const res = formatterParams.values[val];
9
+ return res;
10
+ }
11
+
12
+ function flatpickerEditor(cell, onRendered, success, cancel) {
13
+ var input = $("<input type='text'/>");
14
+
15
+ input.flatpickr({
16
+ enableTime: true,
17
+ dateFormat: "Y-m-d H:i",
18
+ time_24hr: true,
19
+ locale: "en", // global variable with locale 'en', 'fr', ...
20
+ defaultDate: cell.getValue(),
21
+ onClose: function (selectedDates, dateStr, instance) {
22
+ evt = window.event;
23
+ var isEscape = false;
24
+ if ("key" in evt) {
25
+ isEscape = evt.key === "Escape" || evt.key === "Esc";
26
+ } else {
27
+ isEscape = evt.keyCode === 27;
28
+ }
29
+ if (isEscape) {
30
+ // user hit escape
31
+ cancel();
32
+ } else {
33
+ success(dateStr);
34
+ }
35
+ },
36
+ });
37
+
38
+ input.css({
39
+ border: "1px",
40
+ background: "transparent",
41
+ padding: "4px",
42
+ width: "100%",
43
+ "box-sizing": "border-box",
44
+ });
45
+
46
+ input.val(cell.getValue());
47
+
48
+ var inputBlur = function (e) {
49
+ if (e.target !== input[0]) {
50
+ if ($(e.target).closest(".flatpicker-input").length === 0) {
51
+ $(document).off("mousedown", inputBlur);
52
+ }
53
+ }
17
54
  };
18
- var errorHandler = function (prom) {
19
- return function (request) {
20
- var errtxt =
21
- request.responseJSON && request.responseJSON.error
22
- ? request.responseJSON.error
23
- : request.responseText;
24
- $("#jsGridNotify").html(`<div class="alert alert-danger" role="alert">
55
+
56
+ $(document).on("mousedown", inputBlur);
57
+
58
+ onRendered(function () {
59
+ input.focus();
60
+ });
61
+
62
+ return input[0];
63
+ }
64
+
65
+ function isoDateTimeFormatter(cell, formatterParams, onRendered) {
66
+ const val = cell.getValue();
67
+ if (!val) return "";
68
+
69
+ return new Date(val).toLocaleString(window.detected_locale || "en");
70
+ }
71
+ function colorFormatter(cell, formatterParams, onRendered) {
72
+ const val = cell.getValue();
73
+ if (!val) return "";
74
+
75
+ return $(
76
+ `<div style="height: 15px; width: 30px; background-color: ${val}"></div>`
77
+ )[0];
78
+ }
79
+
80
+ function jsonFormatter(cell, formatterParams, onRendered) {
81
+ const val = cell.getValue();
82
+ if (val === null) return "";
83
+ return JSON.stringify(val, null, 1);
84
+ }
85
+
86
+ function versionsFormatter(cell, formatterParams, onRendered) {
87
+ const value = cell.getValue();
88
+ const row = cell.getRow().getData();
89
+ return $(`<a href="/list/_versions/${window.tabulator_table_name}/${row.id}">
90
+ ${value || 0}&nbsp;<i class="fa-sm fas fa-list"></i></a>`)[0];
91
+ }
92
+ function colorEditor(cell, onRendered, success, cancel) {
93
+ const editor = document.createElement("input");
94
+
95
+ editor.setAttribute("type", "color");
96
+ editor.value = cell.getValue();
97
+ //when the value has been set, trigger the cell to update
98
+ function successFunc() {
99
+ const val = editor.value;
100
+ success(val);
101
+ }
102
+
103
+ editor.addEventListener("change", successFunc);
104
+ editor.addEventListener("blur", successFunc);
105
+
106
+ //return the editor element
107
+ return editor;
108
+ }
109
+
110
+ function jsonEditor(cell, onRendered, success, cancel) {
111
+ const editor = document.createElement("textarea");
112
+
113
+ editor.value = JSON.stringify(cell.getValue());
114
+ //when the value has been set, trigger the cell to update
115
+ function successFunc() {
116
+ const val = editor.value;
117
+ try {
118
+ success(JSON.parse(val));
119
+ } catch (e) {
120
+ if (e) tabulator_show_error(e.message);
121
+ cancel();
122
+ }
123
+ }
124
+
125
+ editor.addEventListener("change", successFunc);
126
+ editor.addEventListener("blur", successFunc);
127
+
128
+ //return the editor element
129
+ return editor;
130
+ }
131
+ function add_tabulator_row() {
132
+ window.tabulator_table.addRow({}, true);
133
+ }
134
+
135
+ function delete_tabulator_row(e, cell) {
136
+ const row = cell.getRow().getData();
137
+ if (!row.id) {
138
+ cell.getRow().delete();
139
+ return;
140
+ }
141
+ $.ajax({
142
+ type: "DELETE",
143
+ url: `/api/${window.tabulator_table_name}/${row.id}`,
144
+ data: row, // to process primary keys different from id
145
+ headers: {
146
+ "CSRF-Token": _sc_globalCsrf,
147
+ },
148
+ success: () => cell.getRow().delete(),
149
+ error: tabulator_error_handler,
150
+ });
151
+ }
152
+
153
+ function tabulator_error_handler(request) {
154
+ let errtxt =
155
+ request.responseJSON && request.responseJSON.error
156
+ ? request.responseJSON.error
157
+ : request.responseText;
158
+ if (errtxt) {
159
+ tabulator_show_error(errtxt);
160
+ }
161
+ }
162
+ function tabulator_show_error(errtxt) {
163
+ $("#jsGridNotify").html(`<div class="alert alert-danger" role="alert">
25
164
  ${errtxt}
26
165
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
27
166
  <span aria-hidden="true">&times;</span>
28
167
  </button>
29
168
  </div>`);
30
- if (prom) prom.reject(errtxt);
31
- };
32
- };
33
- return {
34
- // load of data
35
- loadData: function (filter) {
36
- var data = $.Deferred();
37
- $.ajax({
38
- type: "GET",
39
- url: url + (vc ? "?versioncount=on" : ""),
40
- data: filter,
41
- error: errorHandler(data),
42
- }).done(function (resp) {
43
- data.resolve(resp.success);
44
- });
45
- return data.promise();
46
- },
47
- // insert row
48
- insertItem: function (item) {
49
- var data = $.Deferred();
50
- $.ajax({
51
- type: "POST",
52
- url: url,
53
- data: item,
54
- headers: {
55
- "CSRF-Token": _sc_globalCsrf,
56
- },
57
- error: errorHandler(data),
58
- }).done(function (resp) {
59
- item._versions = 1;
60
- if (resp.success) {
61
- item.id = resp.success;
62
- data.resolve(fixKeys(item));
63
- } else {
64
- data.resolve();
65
- }
66
- });
67
- return data.promise();
68
- },
69
- // update row
70
- updateItem: function (item) {
71
- var data = $.Deferred();
72
- $.ajax({
73
- type: "POST",
74
- url: url + item.id,
75
- data: item,
76
- headers: {
77
- "CSRF-Token": _sc_globalCsrf,
78
- },
79
- error: errorHandler(data),
80
- }).done(function (resp) {
81
- if (item._versions) item._versions = +item._versions + 1;
82
- data.resolve(fixKeys(item));
83
- });
84
- return data.promise();
85
- },
86
- // delete row
87
- deleteItem: function (item) {
88
- return $.ajax({
89
- type: "DELETE",
90
- url: url + item.id,
91
- data: item, // to process primary keys different from id
92
- headers: {
93
- "CSRF-Token": _sc_globalCsrf,
94
- },
95
- error: errorHandler(),
96
- });
97
- },
98
- };
99
- }
100
- function DecimalField(config) {
101
- jsGrid.fields.number.call(this, config);
102
169
  }
103
- DecimalField.prototype = new jsGrid.fields.number({
104
- filterValue: function () {
105
- return this.filterControl.val()
106
- ? parseFloat(this.filterControl.val() || 0, 10)
107
- : undefined;
108
- },
109
-
110
- insertValue: function () {
111
- return this.insertControl.val()
112
- ? parseFloat(this.insertControl.val() || 0, 10)
113
- : undefined;
114
- },
115
-
116
- editValue: function () {
117
- return this.editControl.val()
118
- ? parseFloat(this.editControl.val() || 0, 10)
119
- : undefined;
120
- },
121
- });
122
-
123
- jsGrid.fields.decimal = jsGrid.DecimalField = DecimalField;
124
-
125
- var ColorField = function (config) {
126
- jsGrid.Field.call(this, config);
127
- };
128
-
129
- ColorField.prototype = new jsGrid.Field({
130
- itemTemplate: function (value) {
131
- return $("<div>").css({
132
- display: "inline-block",
133
- background: value,
134
- width: "50px",
135
- height: "20px",
136
- });
137
- },
138
-
139
- insertTemplate: function (value) {
140
- var insertPicker = (this._insertPicker = $("<input>").attr(
141
- "type",
142
- "color"
143
- ));
144
-
145
- return insertPicker;
146
- },
147
-
148
- editTemplate: function (value) {
149
- var editPicker = (this._editPicker = $("<input>")
150
- .attr("type", "color")
151
- .val(value));
152
-
153
- return editPicker;
154
- },
155
-
156
- insertValue: function () {
157
- return this._insertPicker.val();
158
- },
159
-
160
- editValue: function () {
161
- return this._editPicker.val();
162
- },
163
- });
164
-
165
- jsGrid.fields.color = ColorField;
166
-
167
- var DateField = function (config) {
168
- jsGrid.Field.call(this, config);
169
- };
170
-
171
- DateField.prototype = new jsGrid.Field({
172
- itemTemplate: function (value) {
173
- var v = typeof value === "string" && value !== "" ? new Date(value) : value;
174
- return v && v.toLocaleString ? v.toLocaleString() : v;
175
- },
176
-
177
- insertTemplate: function (value) {
178
- var insertPicker = (this._insertPicker = $("<input>").attr("type", "text"));
179
- setTimeout(function () {
180
- flatpickr(insertPicker, {
181
- enableTime: true,
182
- dateFormat: "Z",
183
- altInput: true,
184
- altFormat: "Y-m-d h:i K",
185
- });
186
- });
187
- return insertPicker;
188
- },
189
-
190
- editTemplate: function (value) {
191
- var editPicker = (this._editPicker = $("<input>")
192
- .attr("type", "text")
193
- .val(value));
194
- setTimeout(function () {
195
- flatpickr(editPicker, {
196
- enableTime: true,
197
- dateFormat: "Z",
198
- altInput: true,
199
- altFormat: "Y-m-d h:i K",
200
- });
201
- });
202
- return editPicker;
203
- },
204
-
205
- insertValue: function () {
206
- return this._insertPicker.val();
207
- },
208
-
209
- editValue: function () {
210
- return this._editPicker.val();
211
- },
212
- });
213
-
214
- jsGrid.fields.date = DateField;
215
-
216
- var HtmlField = function (config) {
217
- jsGrid.Field.call(this, config);
218
- };
219
- HtmlField.prototype = new jsGrid.Field({
220
- align: "left",
221
- itemTemplate: function (value, item) {
222
- if (value) {
223
- //return +value+1;
224
- return value;
225
- } else return "";
226
- },
227
- });
228
- jsGrid.fields.html = HtmlField;
@@ -177,6 +177,14 @@ function rep_down(e) {
177
177
  apply_form_subset_record(theform, vals1);
178
178
  }
179
179
  }
180
+
181
+ function reload_on_init() {
182
+ localStorage.setItem("reload_on_init", true);
183
+ }
184
+ if (localStorage.getItem("reload_on_init")) {
185
+ localStorage.removeItem("reload_on_init");
186
+ location.reload();
187
+ }
180
188
  function initialize_page() {
181
189
  $("form").change(apply_showif);
182
190
  apply_showif();
@@ -247,6 +255,7 @@ function initialize_page() {
247
255
  navigator.browserLanguage ||
248
256
  navigator.systemLanguage ||
249
257
  "en";
258
+ window.detected_locale = locale;
250
259
  const parse = (s) => JSON.parse(decodeURIComponent(s));
251
260
  $("time[locale-time-options]").each(function () {
252
261
  var el = $(this);
@@ -266,6 +275,7 @@ function initialize_page() {
266
275
  const options = parse(el.attr("locale-date-options"));
267
276
  el.text(date.toLocaleDateString(locale, options));
268
277
  });
278
+ $('a[data-toggle="tab"]').historyTabs();
269
279
  }
270
280
 
271
281
  $(initialize_page);
@@ -610,7 +620,15 @@ function ajax_post_btn(e, reload_on_done, reload_delay) {
610
620
 
611
621
  return false;
612
622
  }
613
- function make_unique_field(id, table_id, field_name, value) {
623
+ function make_unique_field(
624
+ id,
625
+ table_id,
626
+ field_name,
627
+ value,
628
+ space,
629
+ start,
630
+ always_append
631
+ ) {
614
632
  if (!value) return;
615
633
  $.ajax(
616
634
  `/api/${table_id}?approximate=true&${encodeURIComponent(
@@ -623,9 +641,9 @@ function make_unique_field(id, table_id, field_name, value) {
623
641
  const vals = res.success
624
642
  .map((o) => o[field_name])
625
643
  .filter((s) => s.startsWith(value));
626
- if (vals.includes(value)) {
627
- for (let i = 1; i < vals.length + 1; i++) {
628
- const newname = `${value} ${i}`;
644
+ if (vals.includes(value) || always_append) {
645
+ for (let i = start || 0; i < vals.length + (start || 0) + 2; i++) {
646
+ const newname = `${value}${space ? " " : ""}${i}`;
629
647
  if (!vals.includes(newname)) {
630
648
  $("#" + id).val(newname);
631
649
  return;
@@ -702,6 +720,51 @@ function room_older(viewname, room_id, btn) {
702
720
  }
703
721
  );
704
722
  }
705
- function showHideCol(nm, e) {
706
- $("#jsGrid").jsGrid("fieldOption", nm, "visible", e.checked);
707
- }
723
+
724
+ /*
725
+ https://github.com/jeffdavidgreen/bootstrap-html5-history-tabs/blob/master/bootstrap-history-tabs.js
726
+ Copyright (c) 2015 Jeff Green
727
+ */
728
+
729
+ +(function ($) {
730
+ "use strict";
731
+ $.fn.historyTabs = function () {
732
+ var that = this;
733
+ window.addEventListener("popstate", function (event) {
734
+ if (event.state) {
735
+ $(that)
736
+ .filter('[href="' + event.state.url + '"]')
737
+ .tab("show");
738
+ }
739
+ });
740
+ return this.each(function (index, element) {
741
+ $(element).on("show.bs.tab", function () {
742
+ var stateObject = { url: $(this).attr("href") };
743
+
744
+ if (window.location.hash && stateObject.url !== window.location.hash) {
745
+ window.history.pushState(
746
+ stateObject,
747
+ document.title,
748
+ window.location.pathname +
749
+ window.location.search +
750
+ $(this).attr("href")
751
+ );
752
+ } else {
753
+ window.history.replaceState(
754
+ stateObject,
755
+ document.title,
756
+ window.location.pathname +
757
+ window.location.search +
758
+ $(this).attr("href")
759
+ );
760
+ }
761
+ });
762
+ if (!window.location.hash && $(element).is(".active")) {
763
+ // Shows the first element if there are no query parameters.
764
+ $(element).tab("show");
765
+ } else if ($(this).attr("href") === window.location.hash) {
766
+ $(element).tab("show");
767
+ }
768
+ });
769
+ };
770
+ })(jQuery);