@saltcorn/server 0.8.0-beta.3 → 0.8.0

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 CHANGED
@@ -125,7 +125,7 @@ const getApp = async (opts = {}) => {
125
125
  // no jwt and session id at the same time
126
126
  if (!(jwt_extractor(req) && req.cookies && req.cookies["connect.sid"]))
127
127
  next();
128
- });
128
+ });
129
129
  app.use(flash());
130
130
 
131
131
  //static serving
@@ -171,7 +171,8 @@ const getApp = async (opts = {}) => {
171
171
  app.use(
172
172
  `/static_assets/${version_tag}`,
173
173
  express.static(
174
- path.dirname(require.resolve("@saltcorn/filemanager/package.json")) + "/public/build",
174
+ path.dirname(require.resolve("@saltcorn/filemanager/package.json")) +
175
+ "/public/build",
175
176
  {
176
177
  maxAge: development_mode ? 0 : "100d",
177
178
  }
@@ -348,13 +349,13 @@ Sitemap: ${base}sitemap.xml
348
349
  <urlset
349
350
  xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
350
351
  ${urls
351
- .map(
352
- (url) => `<url>
352
+ .map(
353
+ (url) => `<url>
353
354
  <loc>${url}</loc>
354
355
  <lastmod>${now}</lastmod>
355
356
  </url>`
356
- )
357
- .join("")}
357
+ )
358
+ .join("")}
358
359
 
359
360
  </urlset>`);
360
361
  })
package/auth/admin.js CHANGED
@@ -12,7 +12,14 @@ const User = require("@saltcorn/data/models/user");
12
12
  const View = require("@saltcorn/data/models/view");
13
13
  const Field = require("@saltcorn/data/models/field");
14
14
  const Form = require("@saltcorn/data/models/form");
15
- const { mkTable, renderForm, link, post_btn, settingsDropdown, post_dropdown_item } = require("@saltcorn/markup");
15
+ const {
16
+ mkTable,
17
+ renderForm,
18
+ link,
19
+ post_btn,
20
+ settingsDropdown,
21
+ post_dropdown_item,
22
+ } = require("@saltcorn/markup");
16
23
  const { isAdmin, error_catcher } = require("../routes/utils");
17
24
  const { send_reset_email } = require("./resetpw");
18
25
  const { getState } = require("@saltcorn/data/db/state");
@@ -50,8 +57,10 @@ const getUserFields = async (req) => {
50
57
  (signup_form.configuration.columns || []).forEach((f) => {
51
58
  const uf = userFields.find((uff) => uff.name === f.field_name);
52
59
  if (uf) {
53
- uf.fieldview = f.fieldview;
54
- uf.attributes = { ...f.configuration, ...uf.attributes };
60
+ if (!f?.fieldview?.unsuitableAsAdminDefault) {
61
+ uf.fieldview = f.fieldview;
62
+ uf.attributes = { ...f.configuration, ...uf.attributes };
63
+ }
55
64
  }
56
65
  });
57
66
  }
@@ -159,33 +168,33 @@ const user_dropdown = (user, req, can_reset) =>
159
168
  req
160
169
  ),
161
170
  can_reset &&
162
- post_dropdown_item(
163
- `/useradmin/reset-password/${user.id}`,
164
- '<i class="fas fa-envelope"></i>&nbsp;' +
165
- req.__("Send password reset email"),
166
- req
167
- ),
171
+ post_dropdown_item(
172
+ `/useradmin/reset-password/${user.id}`,
173
+ '<i class="fas fa-envelope"></i>&nbsp;' +
174
+ req.__("Send password reset email"),
175
+ req
176
+ ),
168
177
  can_reset &&
169
- !user.verified_on &&
170
- getState().getConfig("verification_view", "") &&
171
- post_dropdown_item(
172
- `/useradmin/send-verification/${user.id}`,
173
- '<i class="fas fa-envelope"></i>&nbsp;' +
174
- req.__("Send verification email"),
175
- req
176
- ),
178
+ !user.verified_on &&
179
+ getState().getConfig("verification_view", "") &&
180
+ post_dropdown_item(
181
+ `/useradmin/send-verification/${user.id}`,
182
+ '<i class="fas fa-envelope"></i>&nbsp;' +
183
+ req.__("Send verification email"),
184
+ req
185
+ ),
177
186
  user.disabled &&
178
- post_dropdown_item(
179
- `/useradmin/enable/${user.id}`,
180
- '<i class="fas fa-play"></i>&nbsp;' + req.__("Enable"),
181
- req
182
- ),
187
+ post_dropdown_item(
188
+ `/useradmin/enable/${user.id}`,
189
+ '<i class="fas fa-play"></i>&nbsp;' + req.__("Enable"),
190
+ req
191
+ ),
183
192
  !user.disabled &&
184
- post_dropdown_item(
185
- `/useradmin/disable/${user.id}`,
186
- '<i class="fas fa-pause"></i>&nbsp;' + req.__("Disable"),
187
- req
188
- ),
193
+ post_dropdown_item(
194
+ `/useradmin/disable/${user.id}`,
195
+ '<i class="fas fa-pause"></i>&nbsp;' + req.__("Disable"),
196
+ req
197
+ ),
189
198
  div({ class: "dropdown-divider" }),
190
199
  post_dropdown_item(
191
200
  `/useradmin/delete/${user.id}`,
@@ -209,7 +218,7 @@ router.get(
209
218
  const users = await User.find({}, { orderBy: "id" });
210
219
  const roles = await User.get_roles();
211
220
  let roleMap = {};
212
- roles.forEach(r => {
221
+ roles.forEach((r) => {
213
222
  roleMap[r.id] = r.role;
214
223
  });
215
224
  const can_reset = getState().getConfig("smtp_host", "") !== "";
@@ -238,10 +247,10 @@ router.get(
238
247
  {
239
248
  label: req.__("Verified"),
240
249
  key: (r) =>
241
- !!r.verified_on
250
+ r.verified_on
242
251
  ? i({
243
- class: "fas fa-check-circle text-success",
244
- })
252
+ class: "fas fa-check-circle text-success",
253
+ })
245
254
  : "",
246
255
  },
247
256
  { label: req.__("Role"), key: (r) => roleMap[r.role_id] },
@@ -291,23 +300,23 @@ router.get(
291
300
  * @returns {Form}
292
301
  */
293
302
  const auth_settings_form = async (req) =>
294
- await config_fields_form({
295
- req,
296
- field_names: [
297
- "allow_signup",
298
- "login_menu",
299
- "allow_forgot",
300
- "new_user_form",
301
- "login_form",
302
- "signup_form",
303
- "user_settings_form",
304
- "verification_view",
305
- "elevate_verified",
306
- "email_mask",
307
- ],
308
- action: "/useradmin/settings",
309
- submitLabel: req.__("Save"),
310
- });
303
+ await config_fields_form({
304
+ req,
305
+ field_names: [
306
+ "allow_signup",
307
+ "login_menu",
308
+ "allow_forgot",
309
+ "new_user_form",
310
+ "login_form",
311
+ "signup_form",
312
+ "user_settings_form",
313
+ "verification_view",
314
+ "elevate_verified",
315
+ "email_mask",
316
+ ],
317
+ action: "/useradmin/settings",
318
+ submitLabel: req.__("Save"),
319
+ });
311
320
 
312
321
  /**
313
322
  * HTTP Settings Form
@@ -315,19 +324,18 @@ const auth_settings_form = async (req) =>
315
324
  * @returns {Form}
316
325
  */
317
326
  const http_settings_form = async (req) =>
318
- await config_fields_form({
319
- req,
320
- field_names: [
321
- "timeout",
322
- "cookie_duration",
323
- "cookie_duration_remember",
324
- "cookie_sessions",
325
- "custom_http_headers",
326
- ],
327
- action: "/useradmin/http",
328
- submitLabel: req.__("Save"),
329
- });
330
-
327
+ await config_fields_form({
328
+ req,
329
+ field_names: [
330
+ "timeout",
331
+ "cookie_duration",
332
+ "cookie_duration_remember",
333
+ "cookie_sessions",
334
+ "custom_http_headers",
335
+ ],
336
+ action: "/useradmin/http",
337
+ submitLabel: req.__("Save"),
338
+ });
331
339
 
332
340
  /**
333
341
  * Permissions Setting Form
@@ -335,16 +343,16 @@ const http_settings_form = async (req) =>
335
343
  * @returns {Form}
336
344
  */
337
345
  const permissions_settings_form = async (req) =>
338
- await config_fields_form({
339
- req,
340
- field_names: [
341
- "min_role_upload",
342
- "min_role_apikeygen",
343
- //hidden "exttables_min_role_read",
344
- ],
345
- action: "/useradmin/permissions",
346
- submitLabel: req.__("Save"),
347
- });
346
+ await config_fields_form({
347
+ req,
348
+ field_names: [
349
+ "min_role_upload",
350
+ "min_role_apikeygen",
351
+ //hidden "exttables_min_role_read",
352
+ ],
353
+ action: "/useradmin/permissions",
354
+ submitLabel: req.__("Save"),
355
+ });
348
356
 
349
357
  /**
350
358
  * HTTP GET for /useradmin/settings
@@ -360,7 +368,7 @@ router.get(
360
368
  send_users_page({
361
369
  res,
362
370
  req,
363
- active_sub: "Settings",
371
+ active_sub: "Login and Signup",
364
372
  contents: {
365
373
  type: "card",
366
374
  title: req.__("Authentication settings"),
@@ -409,21 +417,21 @@ router.post(
409
417
  * @memberof module:auth/admin~auth/adminRouter
410
418
  */
411
419
  router.get(
412
- "/http",
413
- isAdmin,
414
- error_catcher(async (req, res) => {
415
- const form = await http_settings_form(req);
416
- send_users_page({
417
- res,
418
- req,
419
- active_sub: "HTTP",
420
- contents: {
421
- type: "card",
422
- title: req.__("HTTP settings"),
423
- contents: [renderForm(form, req.csrfToken())],
424
- },
425
- });
426
- })
420
+ "/http",
421
+ isAdmin,
422
+ error_catcher(async (req, res) => {
423
+ const form = await http_settings_form(req);
424
+ send_users_page({
425
+ res,
426
+ req,
427
+ active_sub: "HTTP",
428
+ contents: {
429
+ type: "card",
430
+ title: req.__("HTTP settings"),
431
+ contents: [renderForm(form, req.csrfToken())],
432
+ },
433
+ });
434
+ })
427
435
  );
428
436
 
429
437
  /**
@@ -433,29 +441,29 @@ router.get(
433
441
  * @memberof module:auth/admin~auth/adminRouter
434
442
  */
435
443
  router.post(
436
- "/http",
437
- isAdmin,
438
- error_catcher(async (req, res) => {
439
- const form = await http_settings_form(req);
440
- form.validate(req.body);
441
- if (form.hasErrors) {
442
- send_users_page({
443
- res,
444
- req,
445
- active_sub: "HTTP",
446
- contents: {
447
- type: "card",
448
- title: req.__("HTTP settings"),
449
- contents: [renderForm(form, req.csrfToken())],
450
- },
451
- });
452
- } else {
453
- await save_config_from_form(form);
454
- req.flash("success", req.__("HTTP settings updated"));
455
- if (!req.xhr) res.redirect("/useradmin/http");
456
- else res.json({ success: "ok" });
457
- }
458
- })
444
+ "/http",
445
+ isAdmin,
446
+ error_catcher(async (req, res) => {
447
+ const form = await http_settings_form(req);
448
+ form.validate(req.body);
449
+ if (form.hasErrors) {
450
+ send_users_page({
451
+ res,
452
+ req,
453
+ active_sub: "HTTP",
454
+ contents: {
455
+ type: "card",
456
+ title: req.__("HTTP settings"),
457
+ contents: [renderForm(form, req.csrfToken())],
458
+ },
459
+ });
460
+ } else {
461
+ await save_config_from_form(form);
462
+ req.flash("success", req.__("HTTP settings updated"));
463
+ if (!req.xhr) res.redirect("/useradmin/http");
464
+ else res.json({ success: "ok" });
465
+ }
466
+ })
459
467
  );
460
468
 
461
469
  /**
@@ -465,21 +473,21 @@ router.post(
465
473
  * @memberof module:auth/admin~auth/adminRouter
466
474
  */
467
475
  router.get(
468
- "/permissions",
469
- isAdmin,
470
- error_catcher(async (req, res) => {
471
- const form = await permissions_settings_form(req);
472
- send_users_page({
473
- res,
474
- req,
475
- active_sub: "Permissions",
476
- contents: {
477
- type: "card",
478
- title: req.__("Permissions settings"),
479
- contents: [renderForm(form, req.csrfToken())],
480
- },
481
- });
482
- })
476
+ "/permissions",
477
+ isAdmin,
478
+ error_catcher(async (req, res) => {
479
+ const form = await permissions_settings_form(req);
480
+ send_users_page({
481
+ res,
482
+ req,
483
+ active_sub: "Permissions",
484
+ contents: {
485
+ type: "card",
486
+ title: req.__("Permissions settings"),
487
+ contents: [renderForm(form, req.csrfToken())],
488
+ },
489
+ });
490
+ })
483
491
  );
484
492
 
485
493
  /**
@@ -489,29 +497,29 @@ router.get(
489
497
  * @memberof module:auth/admin~auth/adminRouter
490
498
  */
491
499
  router.post(
492
- "/permissions",
493
- isAdmin,
494
- error_catcher(async (req, res) => {
495
- const form = await permissions_settings_form(req);
496
- form.validate(req.body);
497
- if (form.hasErrors) {
498
- send_users_page({
499
- res,
500
- req,
501
- active_sub: "Permissions",
502
- contents: {
503
- type: "card",
504
- title: req.__("Permissions settings"),
505
- contents: [renderForm(form, req.csrfToken())],
506
- },
507
- });
508
- } else {
509
- await save_config_from_form(form);
510
- req.flash("success", req.__("Permissions settings updated"));
511
- if (!req.xhr) res.redirect("/useradmin/permissions");
512
- else res.json({ success: "ok" });
513
- }
514
- })
500
+ "/permissions",
501
+ isAdmin,
502
+ error_catcher(async (req, res) => {
503
+ const form = await permissions_settings_form(req);
504
+ form.validate(req.body);
505
+ if (form.hasErrors) {
506
+ send_users_page({
507
+ res,
508
+ req,
509
+ active_sub: "Permissions",
510
+ contents: {
511
+ type: "card",
512
+ title: req.__("Permissions settings"),
513
+ contents: [renderForm(form, req.csrfToken())],
514
+ },
515
+ });
516
+ } else {
517
+ await save_config_from_form(form);
518
+ req.flash("success", req.__("Permissions settings updated"));
519
+ if (!req.xhr) res.redirect("/useradmin/permissions");
520
+ else res.json({ success: "ok" });
521
+ }
522
+ })
515
523
  );
516
524
 
517
525
  /**
@@ -549,15 +557,15 @@ router.get(
549
557
  above: [
550
558
  ...(letsencrypt && has_custom
551
559
  ? [
552
- {
553
- type: "card",
554
- contents: p(
555
- req.__(
556
- "You have enabled both Let's Encrypt certificates and custom SSL certificates. Let's Encrypt takes priority and the custom certificates will be ignored."
557
- )
558
- ),
559
- },
560
- ]
560
+ {
561
+ type: "card",
562
+ contents: p(
563
+ req.__(
564
+ "You have enabled both Let's Encrypt certificates and custom SSL certificates. Let's Encrypt takes priority and the custom certificates will be ignored."
565
+ )
566
+ ),
567
+ },
568
+ ]
561
569
  : []),
562
570
  {
563
571
  type: "card",
@@ -578,33 +586,33 @@ router.get(
578
586
  ),
579
587
  letsencrypt
580
588
  ? post_btn(
581
- "/config/delete/letsencrypt",
582
- req.__("Disable LetsEncrypt HTTPS"),
583
- req.csrfToken(),
584
- { btnClass: "btn-danger", req }
585
- )
589
+ "/config/delete/letsencrypt",
590
+ req.__("Disable LetsEncrypt HTTPS"),
591
+ req.csrfToken(),
592
+ { btnClass: "btn-danger", req }
593
+ )
586
594
  : post_btn(
587
- "/admin/enable-letsencrypt",
588
- req.__("Enable LetsEncrypt HTTPS"),
589
- req.csrfToken(),
590
- { confirm: true, req }
591
- ),
595
+ "/admin/enable-letsencrypt",
596
+ req.__("Enable LetsEncrypt HTTPS"),
597
+ req.csrfToken(),
598
+ { confirm: true, req }
599
+ ),
592
600
  !letsencrypt &&
593
- show_warning &&
594
- !has_custom &&
595
- div(
596
- { class: "mt-3 alert alert-danger" },
597
- p(
598
- req.__(
599
- "The address you are using to reach Saltcorn does not match the Base URL."
601
+ show_warning &&
602
+ !has_custom &&
603
+ div(
604
+ { class: "mt-3 alert alert-danger" },
605
+ p(
606
+ req.__(
607
+ "The address you are using to reach Saltcorn does not match the Base URL."
608
+ )
609
+ ),
610
+ p(
611
+ req.__(
612
+ "The DNS A records (for * and @, or a subdomain) should point to this server's IP address before enabling LetsEncrypt"
613
+ )
600
614
  )
601
615
  ),
602
- p(
603
- req.__(
604
- "The DNS A records (for * and @, or a subdomain) should point to this server's IP address before enabling LetsEncrypt"
605
- )
606
- )
607
- ),
608
616
  ],
609
617
  },
610
618
  {
@@ -641,11 +649,11 @@ router.get(
641
649
  * @returns {Form}
642
650
  */
643
651
  const ssl_form = async (req) =>
644
- await config_fields_form({
645
- req,
646
- field_names: ["custom_ssl_certificate", "custom_ssl_private_key"],
647
- action: "/useradmin/ssl/custom",
648
- });
652
+ await config_fields_form({
653
+ req,
654
+ field_names: ["custom_ssl_certificate", "custom_ssl_private_key"],
655
+ action: "/useradmin/ssl/custom",
656
+ });
649
657
 
650
658
  /**
651
659
  * HTTP GET for /useradmin/ssl/custom
@@ -701,8 +709,8 @@ router.post(
701
709
  req.flash(
702
710
  "success",
703
711
  req.__("Custom SSL enabled. Restart for changes to take effect.") +
704
- " " +
705
- a({ href: "/admin/system" }, req.__("Restart here"))
712
+ " " +
713
+ a({ href: "/admin/system" }, req.__("Restart here"))
706
714
  );
707
715
  if (!req.xhr) {
708
716
  res.redirect("/useradmin/ssl");
@@ -721,15 +729,15 @@ router.get(
721
729
  "/table-access",
722
730
  isAdmin,
723
731
  error_catcher(async (req, res) => {
724
- const tables = await Table.find()
732
+ const tables = await Table.find();
725
733
  const roleOptions = (await User.get_roles()).map((r) => ({
726
734
  value: r.id,
727
735
  label: r.role,
728
736
  }));
729
737
 
730
- const contents = []
738
+ const contents = [];
731
739
  for (const table of tables) {
732
- if (table.external) continue
740
+ if (table.external) continue;
733
741
  const fields = await table.getFields();
734
742
  const userFields = fields
735
743
  .filter((f) => f.reftable_name === "users")
@@ -773,7 +781,7 @@ router.get(
773
781
  name: "min_role_read",
774
782
  input_type: "select",
775
783
  options: roleOptions,
776
- attributes: { asideNext: true }
784
+ attributes: { asideNext: true },
777
785
  },
778
786
  {
779
787
  label: req.__("Minimum role to write"),
@@ -784,16 +792,18 @@ router.get(
784
792
  ),
785
793
  options: roleOptions,
786
794
  },
787
- ]
788
- })
795
+ ],
796
+ });
789
797
  form.hidden("id", "name");
790
- form.values = table
798
+ form.values = table;
791
799
  if (table.ownership_formula && !table.ownership_field_id)
792
800
  form.values.ownership_field_id = "_formula";
793
- contents.push(div(
794
- h5(a({ href: `/table/${table.id}` }, table.name)),
795
- renderForm(form, req.csrfToken())
796
- ))
801
+ contents.push(
802
+ div(
803
+ h5(a({ href: `/table/${table.id}` }, table.name)),
804
+ renderForm(form, req.csrfToken())
805
+ )
806
+ );
797
807
  }
798
808
  send_users_page({
799
809
  res,
@@ -802,13 +812,12 @@ router.get(
802
812
  contents: {
803
813
  type: "card",
804
814
  title: req.__("Table access"),
805
- contents
815
+ contents,
806
816
  },
807
817
  });
808
818
  })
809
819
  );
810
820
 
811
-
812
821
  /**
813
822
  * @name get/:id
814
823
  * @function
@@ -842,9 +851,9 @@ router.get(
842
851
  div(
843
852
  user.api_token
844
853
  ? span(
845
- { class: "me-1" },
846
- req.__("API token for this user: ")
847
- ) + code(user.api_token)
854
+ { class: "me-1" },
855
+ req.__("API token for this user: ")
856
+ ) + code(user.api_token)
848
857
  : req.__("No API token issued")
849
858
  ),
850
859
  // button for reset or generate api token
@@ -858,16 +867,16 @@ router.get(
858
867
  ),
859
868
  // button for remove api token
860
869
  user.api_token &&
861
- div(
862
- { class: "mt-4 ms-2 d-inline-block" },
863
- post_btn(
864
- `/useradmin/remove-api-token/${user.id}`,
865
- // TBD localization
866
- user.api_token ? req.__("Remove") : req.__("Generate"),
867
- req.csrfToken(),
868
- { req: req, confirm: true }
869
- )
870
- ),
870
+ div(
871
+ { class: "mt-4 ms-2 d-inline-block" },
872
+ post_btn(
873
+ `/useradmin/remove-api-token/${user.id}`,
874
+ // TBD localization
875
+ user.api_token ? req.__("Remove") : req.__("Generate"),
876
+ req.csrfToken(),
877
+ { req: req, confirm: true }
878
+ )
879
+ ),
871
880
  ],
872
881
  },
873
882
  ],
@@ -989,10 +998,10 @@ router.post(
989
998
  // todo add test case
990
999
  const result = await send_verification_email(u, req);
991
1000
  if (result.error)
992
- req.flash(
993
- "danger",
994
- req.__(`Verification email sender error:`, result.error)
995
- );
1001
+ req.flash(
1002
+ "danger",
1003
+ req.__(`Verification email sender error:`, result.error)
1004
+ );
996
1005
  else
997
1006
  req.flash(
998
1007
  "success",