@saltcorn/server 0.8.0-beta.4 → 0.8.1-beta.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.
Files changed (46) hide show
  1. package/app.js +7 -6
  2. package/auth/admin.js +260 -217
  3. package/auth/index.js +20 -20
  4. package/auth/roleadmin.js +2 -9
  5. package/auth/routes.js +193 -139
  6. package/auth/testhelp.js +62 -55
  7. package/fixture_persons.js +1 -1
  8. package/index.js +22 -22
  9. package/locales/en.json +13 -1
  10. package/locales/fr.json +14 -2
  11. package/locales/ru.json +25 -19
  12. package/markup/admin.js +22 -15
  13. package/markup/blockly.js +1 -1
  14. package/markup/expression_blurb.js +15 -15
  15. package/markup/forms.js +21 -22
  16. package/markup/index.js +20 -20
  17. package/markup/plugin-store.js +4 -4
  18. package/package.json +8 -8
  19. package/public/diagram_utils.js +22 -9
  20. package/public/saltcorn-common.js +128 -68
  21. package/public/saltcorn.css +6 -0
  22. package/public/saltcorn.js +68 -20
  23. package/restart_watcher.js +157 -157
  24. package/routes/actions.js +4 -11
  25. package/routes/admin.js +14 -6
  26. package/routes/api.js +11 -18
  27. package/routes/common_lists.js +127 -130
  28. package/routes/delete.js +2 -2
  29. package/routes/edit.js +1 -1
  30. package/routes/fields.js +48 -2
  31. package/routes/files.js +112 -94
  32. package/routes/homepage.js +1 -1
  33. package/routes/infoarch.js +1 -1
  34. package/routes/list.js +6 -5
  35. package/routes/packs.js +1 -2
  36. package/routes/pageedit.js +1 -1
  37. package/routes/tag_entries.js +1 -1
  38. package/routes/tenant.js +2 -1
  39. package/routes/utils.js +3 -1
  40. package/routes/view.js +14 -2
  41. package/routes/viewedit.js +35 -0
  42. package/s3storage.js +13 -11
  43. package/serve.js +35 -31
  44. package/systemd.js +23 -21
  45. package/tests/fields.test.js +23 -0
  46. package/wrapper.js +46 -45
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
  }
@@ -154,38 +163,43 @@ const user_dropdown = (user, req, can_reset) =>
154
163
  '<i class="fas fa-edit"></i>&nbsp;' + req.__("Edit")
155
164
  ),
156
165
  post_dropdown_item(
157
- `/useradmin/set-random-password/${user.id}`,
158
- '<i class="fas fa-random"></i>&nbsp;' + req.__("Set random password"),
166
+ `/useradmin/become-user/${user.id}`,
167
+ '<i class="fas fa-ghost"></i>&nbsp;' + req.__("Become user"),
159
168
  req
160
169
  ),
161
- can_reset &&
162
170
  post_dropdown_item(
163
- `/useradmin/reset-password/${user.id}`,
164
- '<i class="fas fa-envelope"></i>&nbsp;' +
165
- req.__("Send password reset email"),
171
+ `/useradmin/set-random-password/${user.id}`,
172
+ '<i class="fas fa-random"></i>&nbsp;' + req.__("Set random password"),
166
173
  req
167
174
  ),
168
175
  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
- ),
176
+ post_dropdown_item(
177
+ `/useradmin/reset-password/${user.id}`,
178
+ '<i class="fas fa-envelope"></i>&nbsp;' +
179
+ req.__("Send password reset email"),
180
+ req
181
+ ),
182
+ can_reset &&
183
+ !user.verified_on &&
184
+ getState().getConfig("verification_view", "") &&
185
+ post_dropdown_item(
186
+ `/useradmin/send-verification/${user.id}`,
187
+ '<i class="fas fa-envelope"></i>&nbsp;' +
188
+ req.__("Send verification email"),
189
+ req
190
+ ),
177
191
  user.disabled &&
178
- post_dropdown_item(
179
- `/useradmin/enable/${user.id}`,
180
- '<i class="fas fa-play"></i>&nbsp;' + req.__("Enable"),
181
- req
182
- ),
192
+ post_dropdown_item(
193
+ `/useradmin/enable/${user.id}`,
194
+ '<i class="fas fa-play"></i>&nbsp;' + req.__("Enable"),
195
+ req
196
+ ),
183
197
  !user.disabled &&
184
- post_dropdown_item(
185
- `/useradmin/disable/${user.id}`,
186
- '<i class="fas fa-pause"></i>&nbsp;' + req.__("Disable"),
187
- req
188
- ),
198
+ post_dropdown_item(
199
+ `/useradmin/disable/${user.id}`,
200
+ '<i class="fas fa-pause"></i>&nbsp;' + req.__("Disable"),
201
+ req
202
+ ),
189
203
  div({ class: "dropdown-divider" }),
190
204
  post_dropdown_item(
191
205
  `/useradmin/delete/${user.id}`,
@@ -209,7 +223,7 @@ router.get(
209
223
  const users = await User.find({}, { orderBy: "id" });
210
224
  const roles = await User.get_roles();
211
225
  let roleMap = {};
212
- roles.forEach(r => {
226
+ roles.forEach((r) => {
213
227
  roleMap[r.id] = r.role;
214
228
  });
215
229
  const can_reset = getState().getConfig("smtp_host", "") !== "";
@@ -238,10 +252,10 @@ router.get(
238
252
  {
239
253
  label: req.__("Verified"),
240
254
  key: (r) =>
241
- !!r.verified_on
255
+ r.verified_on
242
256
  ? i({
243
- class: "fas fa-check-circle text-success",
244
- })
257
+ class: "fas fa-check-circle text-success",
258
+ })
245
259
  : "",
246
260
  },
247
261
  { label: req.__("Role"), key: (r) => roleMap[r.role_id] },
@@ -291,23 +305,23 @@ router.get(
291
305
  * @returns {Form}
292
306
  */
293
307
  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
- });
308
+ await config_fields_form({
309
+ req,
310
+ field_names: [
311
+ "allow_signup",
312
+ "login_menu",
313
+ "allow_forgot",
314
+ "new_user_form",
315
+ "login_form",
316
+ "signup_form",
317
+ "user_settings_form",
318
+ "verification_view",
319
+ "elevate_verified",
320
+ "email_mask",
321
+ ],
322
+ action: "/useradmin/settings",
323
+ submitLabel: req.__("Save"),
324
+ });
311
325
 
312
326
  /**
313
327
  * HTTP Settings Form
@@ -315,19 +329,18 @@ const auth_settings_form = async (req) =>
315
329
  * @returns {Form}
316
330
  */
317
331
  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
-
332
+ await config_fields_form({
333
+ req,
334
+ field_names: [
335
+ "timeout",
336
+ "cookie_duration",
337
+ "cookie_duration_remember",
338
+ "cookie_sessions",
339
+ "custom_http_headers",
340
+ ],
341
+ action: "/useradmin/http",
342
+ submitLabel: req.__("Save"),
343
+ });
331
344
 
332
345
  /**
333
346
  * Permissions Setting Form
@@ -335,16 +348,16 @@ const http_settings_form = async (req) =>
335
348
  * @returns {Form}
336
349
  */
337
350
  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
- });
351
+ await config_fields_form({
352
+ req,
353
+ field_names: [
354
+ "min_role_upload",
355
+ "min_role_apikeygen",
356
+ //hidden "exttables_min_role_read",
357
+ ],
358
+ action: "/useradmin/permissions",
359
+ submitLabel: req.__("Save"),
360
+ });
348
361
 
349
362
  /**
350
363
  * HTTP GET for /useradmin/settings
@@ -360,7 +373,7 @@ router.get(
360
373
  send_users_page({
361
374
  res,
362
375
  req,
363
- active_sub: "Settings",
376
+ active_sub: "Login and Signup",
364
377
  contents: {
365
378
  type: "card",
366
379
  title: req.__("Authentication settings"),
@@ -409,21 +422,21 @@ router.post(
409
422
  * @memberof module:auth/admin~auth/adminRouter
410
423
  */
411
424
  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
- })
425
+ "/http",
426
+ isAdmin,
427
+ error_catcher(async (req, res) => {
428
+ const form = await http_settings_form(req);
429
+ send_users_page({
430
+ res,
431
+ req,
432
+ active_sub: "HTTP",
433
+ contents: {
434
+ type: "card",
435
+ title: req.__("HTTP settings"),
436
+ contents: [renderForm(form, req.csrfToken())],
437
+ },
438
+ });
439
+ })
427
440
  );
428
441
 
429
442
  /**
@@ -433,29 +446,29 @@ router.get(
433
446
  * @memberof module:auth/admin~auth/adminRouter
434
447
  */
435
448
  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
- })
449
+ "/http",
450
+ isAdmin,
451
+ error_catcher(async (req, res) => {
452
+ const form = await http_settings_form(req);
453
+ form.validate(req.body);
454
+ if (form.hasErrors) {
455
+ send_users_page({
456
+ res,
457
+ req,
458
+ active_sub: "HTTP",
459
+ contents: {
460
+ type: "card",
461
+ title: req.__("HTTP settings"),
462
+ contents: [renderForm(form, req.csrfToken())],
463
+ },
464
+ });
465
+ } else {
466
+ await save_config_from_form(form);
467
+ req.flash("success", req.__("HTTP settings updated"));
468
+ if (!req.xhr) res.redirect("/useradmin/http");
469
+ else res.json({ success: "ok" });
470
+ }
471
+ })
459
472
  );
460
473
 
461
474
  /**
@@ -465,21 +478,21 @@ router.post(
465
478
  * @memberof module:auth/admin~auth/adminRouter
466
479
  */
467
480
  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
- })
481
+ "/permissions",
482
+ isAdmin,
483
+ error_catcher(async (req, res) => {
484
+ const form = await permissions_settings_form(req);
485
+ send_users_page({
486
+ res,
487
+ req,
488
+ active_sub: "Permissions",
489
+ contents: {
490
+ type: "card",
491
+ title: req.__("Permissions settings"),
492
+ contents: [renderForm(form, req.csrfToken())],
493
+ },
494
+ });
495
+ })
483
496
  );
484
497
 
485
498
  /**
@@ -489,29 +502,29 @@ router.get(
489
502
  * @memberof module:auth/admin~auth/adminRouter
490
503
  */
491
504
  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
- })
505
+ "/permissions",
506
+ isAdmin,
507
+ error_catcher(async (req, res) => {
508
+ const form = await permissions_settings_form(req);
509
+ form.validate(req.body);
510
+ if (form.hasErrors) {
511
+ send_users_page({
512
+ res,
513
+ req,
514
+ active_sub: "Permissions",
515
+ contents: {
516
+ type: "card",
517
+ title: req.__("Permissions settings"),
518
+ contents: [renderForm(form, req.csrfToken())],
519
+ },
520
+ });
521
+ } else {
522
+ await save_config_from_form(form);
523
+ req.flash("success", req.__("Permissions settings updated"));
524
+ if (!req.xhr) res.redirect("/useradmin/permissions");
525
+ else res.json({ success: "ok" });
526
+ }
527
+ })
515
528
  );
516
529
 
517
530
  /**
@@ -549,15 +562,15 @@ router.get(
549
562
  above: [
550
563
  ...(letsencrypt && has_custom
551
564
  ? [
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
- ]
565
+ {
566
+ type: "card",
567
+ contents: p(
568
+ req.__(
569
+ "You have enabled both Let's Encrypt certificates and custom SSL certificates. Let's Encrypt takes priority and the custom certificates will be ignored."
570
+ )
571
+ ),
572
+ },
573
+ ]
561
574
  : []),
562
575
  {
563
576
  type: "card",
@@ -578,33 +591,33 @@ router.get(
578
591
  ),
579
592
  letsencrypt
580
593
  ? post_btn(
581
- "/config/delete/letsencrypt",
582
- req.__("Disable LetsEncrypt HTTPS"),
583
- req.csrfToken(),
584
- { btnClass: "btn-danger", req }
585
- )
594
+ "/config/delete/letsencrypt",
595
+ req.__("Disable LetsEncrypt HTTPS"),
596
+ req.csrfToken(),
597
+ { btnClass: "btn-danger", req }
598
+ )
586
599
  : post_btn(
587
- "/admin/enable-letsencrypt",
588
- req.__("Enable LetsEncrypt HTTPS"),
589
- req.csrfToken(),
590
- { confirm: true, req }
591
- ),
600
+ "/admin/enable-letsencrypt",
601
+ req.__("Enable LetsEncrypt HTTPS"),
602
+ req.csrfToken(),
603
+ { confirm: true, req }
604
+ ),
592
605
  !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."
606
+ show_warning &&
607
+ !has_custom &&
608
+ div(
609
+ { class: "mt-3 alert alert-danger" },
610
+ p(
611
+ req.__(
612
+ "The address you are using to reach Saltcorn does not match the Base URL."
613
+ )
614
+ ),
615
+ p(
616
+ req.__(
617
+ "The DNS A records (for * and @, or a subdomain) should point to this server's IP address before enabling LetsEncrypt"
618
+ )
600
619
  )
601
620
  ),
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
621
  ],
609
622
  },
610
623
  {
@@ -641,11 +654,11 @@ router.get(
641
654
  * @returns {Form}
642
655
  */
643
656
  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
- });
657
+ await config_fields_form({
658
+ req,
659
+ field_names: ["custom_ssl_certificate", "custom_ssl_private_key"],
660
+ action: "/useradmin/ssl/custom",
661
+ });
649
662
 
650
663
  /**
651
664
  * HTTP GET for /useradmin/ssl/custom
@@ -701,8 +714,8 @@ router.post(
701
714
  req.flash(
702
715
  "success",
703
716
  req.__("Custom SSL enabled. Restart for changes to take effect.") +
704
- " " +
705
- a({ href: "/admin/system" }, req.__("Restart here"))
717
+ " " +
718
+ a({ href: "/admin/system" }, req.__("Restart here"))
706
719
  );
707
720
  if (!req.xhr) {
708
721
  res.redirect("/useradmin/ssl");
@@ -721,15 +734,15 @@ router.get(
721
734
  "/table-access",
722
735
  isAdmin,
723
736
  error_catcher(async (req, res) => {
724
- const tables = await Table.find()
737
+ const tables = await Table.find();
725
738
  const roleOptions = (await User.get_roles()).map((r) => ({
726
739
  value: r.id,
727
740
  label: r.role,
728
741
  }));
729
742
 
730
- const contents = []
743
+ const contents = [];
731
744
  for (const table of tables) {
732
- if (table.external) continue
745
+ if (table.external) continue;
733
746
  const fields = await table.getFields();
734
747
  const userFields = fields
735
748
  .filter((f) => f.reftable_name === "users")
@@ -773,7 +786,7 @@ router.get(
773
786
  name: "min_role_read",
774
787
  input_type: "select",
775
788
  options: roleOptions,
776
- attributes: { asideNext: true }
789
+ attributes: { asideNext: true },
777
790
  },
778
791
  {
779
792
  label: req.__("Minimum role to write"),
@@ -784,16 +797,18 @@ router.get(
784
797
  ),
785
798
  options: roleOptions,
786
799
  },
787
- ]
788
- })
800
+ ],
801
+ });
789
802
  form.hidden("id", "name");
790
- form.values = table
803
+ form.values = table;
791
804
  if (table.ownership_formula && !table.ownership_field_id)
792
805
  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
- ))
806
+ contents.push(
807
+ div(
808
+ h5(a({ href: `/table/${table.id}` }, table.name)),
809
+ renderForm(form, req.csrfToken())
810
+ )
811
+ );
797
812
  }
798
813
  send_users_page({
799
814
  res,
@@ -802,13 +817,12 @@ router.get(
802
817
  contents: {
803
818
  type: "card",
804
819
  title: req.__("Table access"),
805
- contents
820
+ contents,
806
821
  },
807
822
  });
808
823
  })
809
824
  );
810
825
 
811
-
812
826
  /**
813
827
  * @name get/:id
814
828
  * @function
@@ -842,9 +856,9 @@ router.get(
842
856
  div(
843
857
  user.api_token
844
858
  ? span(
845
- { class: "me-1" },
846
- req.__("API token for this user: ")
847
- ) + code(user.api_token)
859
+ { class: "me-1" },
860
+ req.__("API token for this user: ")
861
+ ) + code(user.api_token)
848
862
  : req.__("No API token issued")
849
863
  ),
850
864
  // button for reset or generate api token
@@ -858,16 +872,16 @@ router.get(
858
872
  ),
859
873
  // button for remove api token
860
874
  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
- ),
875
+ div(
876
+ { class: "mt-4 ms-2 d-inline-block" },
877
+ post_btn(
878
+ `/useradmin/remove-api-token/${user.id}`,
879
+ // TBD localization
880
+ user.api_token ? req.__("Remove") : req.__("Generate"),
881
+ req.csrfToken(),
882
+ { req: req, confirm: true }
883
+ )
884
+ ),
871
885
  ],
872
886
  },
873
887
  ],
@@ -989,10 +1003,10 @@ router.post(
989
1003
  // todo add test case
990
1004
  const result = await send_verification_email(u, req);
991
1005
  if (result.error)
992
- req.flash(
993
- "danger",
994
- req.__(`Verification email sender error:`, result.error)
995
- );
1006
+ req.flash(
1007
+ "danger",
1008
+ req.__(`Verification email sender error:`, result.error)
1009
+ );
996
1010
  else
997
1011
  req.flash(
998
1012
  "success",
@@ -1065,6 +1079,35 @@ router.post(
1065
1079
  })
1066
1080
  );
1067
1081
 
1082
+ /**
1083
+ * Become user
1084
+ * @name post/become-user/:id
1085
+ * @function
1086
+ * @memberof module:auth/admin~auth/adminRouter
1087
+ */
1088
+ router.post(
1089
+ "/become-user/:id",
1090
+ isAdmin,
1091
+ error_catcher(async (req, res) => {
1092
+ const { id } = req.params;
1093
+ const u = await User.findOne({ id });
1094
+ if (u) {
1095
+ u.relogin(req);
1096
+ req.flash(
1097
+ "success",
1098
+ req.__(
1099
+ `Your are now logged in as %s. Logout and login again to assume your usual identity`,
1100
+ u.email
1101
+ )
1102
+ );
1103
+ res.redirect(`/`);
1104
+ } else {
1105
+ req.flash("error", req.__(`User not found`));
1106
+ res.redirect(`/useradmin`);
1107
+ }
1108
+ })
1109
+ );
1110
+
1068
1111
  /**
1069
1112
  * @name post/disable/:id
1070
1113
  * @function