@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.
- package/app.js +7 -6
- package/auth/admin.js +260 -217
- package/auth/index.js +20 -20
- package/auth/roleadmin.js +2 -9
- package/auth/routes.js +193 -139
- package/auth/testhelp.js +62 -55
- package/fixture_persons.js +1 -1
- package/index.js +22 -22
- package/locales/en.json +13 -1
- package/locales/fr.json +14 -2
- package/locales/ru.json +25 -19
- package/markup/admin.js +22 -15
- package/markup/blockly.js +1 -1
- package/markup/expression_blurb.js +15 -15
- package/markup/forms.js +21 -22
- package/markup/index.js +20 -20
- package/markup/plugin-store.js +4 -4
- package/package.json +8 -8
- package/public/diagram_utils.js +22 -9
- package/public/saltcorn-common.js +128 -68
- package/public/saltcorn.css +6 -0
- package/public/saltcorn.js +68 -20
- package/restart_watcher.js +157 -157
- package/routes/actions.js +4 -11
- package/routes/admin.js +14 -6
- package/routes/api.js +11 -18
- package/routes/common_lists.js +127 -130
- package/routes/delete.js +2 -2
- package/routes/edit.js +1 -1
- package/routes/fields.js +48 -2
- package/routes/files.js +112 -94
- package/routes/homepage.js +1 -1
- package/routes/infoarch.js +1 -1
- package/routes/list.js +6 -5
- package/routes/packs.js +1 -2
- package/routes/pageedit.js +1 -1
- package/routes/tag_entries.js +1 -1
- package/routes/tenant.js +2 -1
- package/routes/utils.js +3 -1
- package/routes/view.js +14 -2
- package/routes/viewedit.js +35 -0
- package/s3storage.js +13 -11
- package/serve.js +35 -31
- package/systemd.js +23 -21
- package/tests/fields.test.js +23 -0
- 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 {
|
|
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
|
-
|
|
54
|
-
|
|
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> ' + req.__("Edit")
|
|
155
164
|
),
|
|
156
165
|
post_dropdown_item(
|
|
157
|
-
`/useradmin/
|
|
158
|
-
'<i class="fas fa-
|
|
166
|
+
`/useradmin/become-user/${user.id}`,
|
|
167
|
+
'<i class="fas fa-ghost"></i> ' + req.__("Become user"),
|
|
159
168
|
req
|
|
160
169
|
),
|
|
161
|
-
can_reset &&
|
|
162
170
|
post_dropdown_item(
|
|
163
|
-
`/useradmin/
|
|
164
|
-
'<i class="fas fa-
|
|
165
|
-
req.__("Send password reset email"),
|
|
171
|
+
`/useradmin/set-random-password/${user.id}`,
|
|
172
|
+
'<i class="fas fa-random"></i> ' + req.__("Set random password"),
|
|
166
173
|
req
|
|
167
174
|
),
|
|
168
175
|
can_reset &&
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
post_dropdown_item(
|
|
177
|
+
`/useradmin/reset-password/${user.id}`,
|
|
178
|
+
'<i class="fas fa-envelope"></i> ' +
|
|
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> ' +
|
|
188
|
+
req.__("Send verification email"),
|
|
189
|
+
req
|
|
190
|
+
),
|
|
177
191
|
user.disabled &&
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
post_dropdown_item(
|
|
193
|
+
`/useradmin/enable/${user.id}`,
|
|
194
|
+
'<i class="fas fa-play"></i> ' + req.__("Enable"),
|
|
195
|
+
req
|
|
196
|
+
),
|
|
183
197
|
!user.disabled &&
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
198
|
+
post_dropdown_item(
|
|
199
|
+
`/useradmin/disable/${user.id}`,
|
|
200
|
+
'<i class="fas fa-pause"></i> ' + 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
|
-
|
|
255
|
+
r.verified_on
|
|
242
256
|
? i({
|
|
243
|
-
|
|
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
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
//hidden "exttables_min_role_read",
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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: "
|
|
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
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
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
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
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
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
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
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
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
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
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
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
594
|
+
"/config/delete/letsencrypt",
|
|
595
|
+
req.__("Disable LetsEncrypt HTTPS"),
|
|
596
|
+
req.csrfToken(),
|
|
597
|
+
{ btnClass: "btn-danger", req }
|
|
598
|
+
)
|
|
586
599
|
: post_btn(
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
600
|
+
"/admin/enable-letsencrypt",
|
|
601
|
+
req.__("Enable LetsEncrypt HTTPS"),
|
|
602
|
+
req.csrfToken(),
|
|
603
|
+
{ confirm: true, req }
|
|
604
|
+
),
|
|
592
605
|
!letsencrypt &&
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
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
|
-
|
|
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(
|
|
794
|
-
|
|
795
|
-
|
|
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
|
-
|
|
846
|
-
|
|
847
|
-
|
|
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
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
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
|
-
|
|
993
|
-
|
|
994
|
-
|
|
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
|