@saltcorn/server 0.8.6-beta.2 → 0.8.6-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/routes/sync.js ADDED
@@ -0,0 +1,170 @@
1
+ const { error_catcher } = require("./utils.js");
2
+ const Table = require("@saltcorn/data/models/table");
3
+ const Router = require("express-promise-router");
4
+ const db = require("@saltcorn/data/db");
5
+ const { getState } = require("@saltcorn/data/db/state");
6
+
7
+ const router = new Router();
8
+ module.exports = router;
9
+
10
+ /**
11
+ * Send all rows from a user, so that they can be used in an offline session with the mobile app
12
+ */
13
+ router.get(
14
+ "/table_data",
15
+ error_catcher(async (req, res) => {
16
+ // TODO optimsie: hash over all rows or dynamic user specific
17
+ // TODO public user
18
+ // TODO split large data 10 000 rows?
19
+ getState().log(
20
+ 4,
21
+ `GET /sync/table_data user: '${req.user ? req.user.id : "public"}'`
22
+ );
23
+ const allTables = await Table.find();
24
+ const result = {};
25
+ const selectOpts = req.user ? { forUser: req.user } : { forPublic: true };
26
+ for (const table of allTables) {
27
+ const rows = await table.getRows({}, selectOpts);
28
+ if (
29
+ req.user &&
30
+ table.name === "users" &&
31
+ !rows.find((row) => row.id === req.user.id)
32
+ ) {
33
+ rows.push(await table.getRow({ id: req.user.id }));
34
+ }
35
+ result[table.name] = {
36
+ rows:
37
+ table.name !== "users"
38
+ ? rows
39
+ : rows.map(({ id, email, role_id, language, disabled }) => {
40
+ return { id, email, role_id, language, disabled };
41
+ }),
42
+ };
43
+ }
44
+ res.json(result);
45
+ })
46
+ );
47
+
48
+ const pickFields = (table, row) => {
49
+ const result = {};
50
+ for (const { name, type } of table.getFields()) {
51
+ if (type?.name === "Date") {
52
+ result[name] = row[name] ? new Date(row[name]) : undefined;
53
+ } else {
54
+ result[name] = row[name];
55
+ }
56
+ }
57
+ return result;
58
+ };
59
+
60
+ const getChanges = (table, dbRow, appRow) => {
61
+ const changes = {};
62
+ for (const { name, type } of table.getFields()) {
63
+ if (name !== "id") {
64
+ const dbVal = dbRow[name];
65
+ const appVal = appRow[name];
66
+ let valHasChanged = false;
67
+ if (type?.name === "Date") {
68
+ valHasChanged = dbVal?.valueOf() !== appVal?.valueOf();
69
+ } else {
70
+ valHasChanged = dbVal !== appVal;
71
+ }
72
+ // TODO Float with decimal_places
73
+ if (valHasChanged) {
74
+ changes[name] = appRow[name];
75
+ }
76
+ }
77
+ }
78
+ return changes;
79
+ };
80
+
81
+ const allowUpdate = (table, row, user) => {
82
+ const role = user?.role_id || 100;
83
+ return table.min_role_write >= role || table.is_owner(user, row);
84
+ };
85
+
86
+ const allowInsert = (table, row, user) => {
87
+ const role = user?.role_id || 100;
88
+ return table.min_role_write >= role;
89
+ };
90
+
91
+ const syncRows = async (table, dbRows, appRows, user, dbClient) => {
92
+ const dbRowsLookup = {};
93
+ for (const row of dbRows) {
94
+ dbRowsLookup[row.id] = row;
95
+ }
96
+ const translatedIds = [];
97
+ for (const appRow of appRows.map((row) => pickFields(table, row))) {
98
+ if (!appRow.id) continue;
99
+ const dbRow = dbRowsLookup[appRow.id];
100
+ if (dbRow) {
101
+ const changes = getChanges(table, dbRow, appRow);
102
+ if (Object.keys(changes).length > 0 && allowUpdate(table, dbRow, user)) {
103
+ await db.update(table.name, changes, dbRow.id, { client: dbClient });
104
+ }
105
+ } else if (allowInsert(table, appRow, user)) {
106
+ const idFromApp = appRow.id;
107
+ delete appRow.id;
108
+ const newId = await db.insert(table.name, appRow, { client: dbClient });
109
+ if (newId !== idFromApp)
110
+ translatedIds.push({ from: idFromApp, to: newId });
111
+ } else {
112
+ getState().log(
113
+ 3,
114
+ `Skipping id: '${appRow.id}' from app of table '${table.name}'`
115
+ );
116
+ }
117
+ }
118
+ return translatedIds;
119
+ };
120
+
121
+ /**
122
+ * Sync the database to the state of an offline session with the mobile app
123
+ */
124
+ router.post(
125
+ "/table_data",
126
+ error_catcher(async (req, res) => {
127
+ // TODO public user
128
+ // TODO sqlite
129
+ getState().log(
130
+ 4,
131
+ `POST /sync/table_data user: '${req.user ? req.user.id : "public"}'`
132
+ );
133
+ const role = req.user ? req.user.role_id : 100;
134
+ const client = db.isSQLite ? db : await db.getClient();
135
+ const selectOpts = req.user ? { forUser: req.user } : { forPublic: true };
136
+ try {
137
+ await client.query("BEGIN");
138
+ await client.query("SET CONSTRAINTS ALL DEFERRED");
139
+ const translateIds = {};
140
+ for (const [tblName, appRows] of Object.entries(req.body.data) || []) {
141
+ if (tblName !== "users") {
142
+ const table = Table.findOne({ name: tblName });
143
+ if (table) {
144
+ const dbRows =
145
+ role <= table.min_role_write
146
+ ? await table.getRows({}, selectOpts)
147
+ : (await table.getRows({}, selectOpts)).filter((row) =>
148
+ table.is_owner(req.user, row)
149
+ );
150
+ const translated = await syncRows(
151
+ table,
152
+ dbRows,
153
+ appRows,
154
+ req.user,
155
+ client
156
+ );
157
+ if (translated.length > 0) translateIds[tblName] = translated;
158
+ }
159
+ }
160
+ }
161
+ await client.query("COMMIT");
162
+ if (!db.isSQLite) await client.release(true);
163
+ res.json({ translateIds });
164
+ } catch (error) {
165
+ await client.query("ROLLBACK");
166
+ getState().log(2, `POST /sync/table_data error: '${error.message}'`);
167
+ res.status(400).json({ error: error.message || error });
168
+ }
169
+ })
170
+ );
package/routes/tables.js CHANGED
@@ -53,6 +53,8 @@ const { getState } = require("@saltcorn/data/db/state");
53
53
  const { cardHeaderTabs } = require("@saltcorn/markup/layout_utils");
54
54
  const { tablesList } = require("./common_lists");
55
55
  const { InvalidConfiguration } = require("@saltcorn/data/utils");
56
+ const { sleep } = require("@saltcorn/data/utils");
57
+
56
58
  const path = require("path");
57
59
  /**
58
60
  * @type {object}
@@ -913,10 +915,12 @@ router.post(
913
915
  rest.provider_name !== "Database table"
914
916
  ) {
915
917
  const table = await Table.create(name, rest);
918
+ await sleep(500); // Allow other workers to load this view
916
919
  res.redirect(`/table/provider-cfg/${table.id}`);
917
920
  } else {
918
921
  delete rest.provider_name;
919
922
  const table = await Table.create(name, rest);
923
+ await sleep(500); // Allow other workers to load this view
920
924
  req.flash("success", req.__(`Table %s created`, name));
921
925
  res.redirect(`/table/${table.id}`);
922
926
  }
package/routes/tenant.js CHANGED
@@ -42,7 +42,7 @@ const {
42
42
  code,
43
43
  } = require("@saltcorn/markup/tags");
44
44
  const db = require("@saltcorn/data/db");
45
- //const url = require("url");
45
+
46
46
  const { loadAllPlugins, loadAndSaveNewPlugin } = require("../load_plugins");
47
47
  const { isAdmin, error_catcher } = require("./utils.js");
48
48
  const User = require("@saltcorn/data/models/user");
@@ -53,6 +53,7 @@ const {
53
53
  save_config_from_form,
54
54
  } = require("../markup/admin.js");
55
55
  const { getConfig } = require("@saltcorn/data/models/config");
56
+ //const {quote} = require("@saltcorn/db-common");
56
57
  // todo add button backup / restore for particular tenant (available in admin tenants screens)
57
58
  //const {
58
59
  // create_backup,
@@ -75,6 +76,7 @@ const remove_leading_chars = (cs, s) =>
75
76
  /**
76
77
  * Declare Form to create Tenant
77
78
  * @param {object} req - Request
79
+ * @param base_url - Base URL
78
80
  * @returns {Form} - Saltcorn Form Declaration
79
81
  * @category server
80
82
  */
@@ -109,8 +111,8 @@ const tenant_form = (req, base_url) =>
109
111
  // TBD To allow few roles to create tenants - currently only one role has such rights simultaneously
110
112
  const create_tenant_allowed = (req) => {
111
113
  const required_role =
112
- +getRootState().getConfig("role_to_create_tenant") || 10;
113
- const user_role = req.user ? req.user.role_id : 10;
114
+ +getRootState().getConfig("role_to_create_tenant") || 100;
115
+ const user_role = req.user ? req.user.role_id : 100;
114
116
  return user_role <= required_role;
115
117
  };
116
118
 
@@ -227,6 +229,7 @@ router.get(
227
229
  * Return URL of new Tenant
228
230
  * @param {object} req - Request
229
231
  * @param {string} subdomain - Tenant Subdomain name string
232
+ * @param base_url - Base URL
230
233
  * @returns {string}
231
234
  */
232
235
  const getNewURL = (req, subdomain, base_url) => {
@@ -280,7 +283,7 @@ router.post(
280
283
  const description = valres.success.description;
281
284
  // get list of tenants
282
285
  const allTens = await getAllTenants();
283
- if (allTens.includes(subdomain) || !subdomain) {
286
+ if (allTens.includes(subdomain) || !subdomain || subdomain === "public") {
284
287
  form.errors.subdomain = req.__(
285
288
  "A site with this subdomain already exists"
286
289
  );
@@ -446,7 +449,7 @@ const tenant_settings_form = (req) =>
446
449
  "tenant_template",
447
450
  "tenant_baseurl",
448
451
  "tenant_create_unauth_redirect",
449
- { section_header: "Tenant application capabilities" },
452
+ { section_header: req.__("Tenant application capabilities") },
450
453
  "tenants_install_git",
451
454
  "tenants_set_npm_modules",
452
455
  "tenants_unsafe_plugins",
@@ -536,8 +539,11 @@ const get_tenant_info = async (subdomain) => {
536
539
  // get tenant row
537
540
  const ten = await Tenant.findOne({ subdomain: saneDomain });
538
541
  if (ten) {
542
+ //info.ten = ten;
539
543
  info.description = ten.description;
540
544
  info.created = ten.created;
545
+ info.template = ten.template;
546
+ info.email = ten.email;
541
547
  }
542
548
 
543
549
  // get data from tenant schema
@@ -547,10 +553,19 @@ const get_tenant_info = async (subdomain) => {
547
553
  if (firstUser && firstUser.length > 0) {
548
554
  info.first_user_email = firstUser[0].email;
549
555
  }
556
+ // todo sort in alphabet order
557
+ // config items count
558
+ info.nconfigs = await db.count("_sc_config");
559
+ // error messages count
560
+ info.nerrors = await db.count("_sc_errors");
561
+ // event log
562
+ info.nevent_log = await db.count("_sc_event_log");
550
563
  // users count
551
564
  info.nusers = await db.count("users");
552
565
  // roles count
553
566
  info.nroles = await db.count("_sc_roles");
567
+ // table_constraints count
568
+ info.ntable_constraints = await db.count("_sc_table_constraints");
554
569
  // tables count
555
570
  info.ntables = await db.count("_sc_tables");
556
571
  // table fields count
@@ -561,19 +576,25 @@ const get_tenant_info = async (subdomain) => {
561
576
  info.nfiles = await db.count("_sc_files");
562
577
  // pages count
563
578
  info.npages = await db.count("_sc_pages");
564
- // triggers (actions) ccount
579
+ // triggers (actions) count
565
580
  info.nactions = await db.count("_sc_triggers");
566
- // error messages count
567
- info.nerrors = await db.count("_sc_errors");
568
- // config items count
569
- info.nconfigs = await db.count("_sc_config");
570
581
  // plugins count
571
582
  info.nplugins = await db.count("_sc_plugins");
572
583
  // migration count
573
584
  info.nmigrations = await db.count("_sc_migrations");
574
585
  // library count
575
586
  info.nlibrary = await db.count("_sc_library");
576
- // TBD decide Do we need count tenants, table constraints
587
+ // notifications
588
+ info.nnotifications = await db.count("_sc_notifications");
589
+ // tags
590
+ info.ntags = await db.count("_sc_tags");
591
+ // tag_entries
592
+ info.ntag_entries = await db.count("_sc_tag_entries");
593
+ // snapshots
594
+ info.nsnapshots = await db.count("_sc_snapshots");
595
+ // session - Only for main app?
596
+ //info.nsession = await db.count("_sc_session");
597
+
577
598
  // base url
578
599
  info.base_url = await getConfig("base_url");
579
600
  return info;
@@ -628,51 +649,76 @@ router.get(
628
649
  { href: "mailto:" + info.first_user_email },
629
650
  info.first_user_email
630
651
  )
631
- )
652
+ ),
653
+ th(req.__("Template")),
654
+ td(a({ href: info.base_url }, info.template))
632
655
  ),
633
656
  tr(
634
657
  th(req.__("Users")),
635
- td(a({ href: info.base_url + "useradmin" }, info.nusers))
636
- ),
637
- tr(
658
+ td(a({ href: info.base_url + "useradmin" }, info.nusers)),
638
659
  th(req.__("Roles")),
639
660
  td(a({ href: info.base_url + "roleadmin" }, info.nroles))
640
661
  ),
641
662
  tr(
642
663
  th(req.__("Tables")),
643
- td(a({ href: info.base_url + "table" }, info.ntables))
644
- ),
645
- tr(
664
+ td(a({ href: info.base_url + "table" }, info.ntables)),
646
665
  th(req.__("Table columns")),
647
666
  td(a({ href: info.base_url + "table" }, info.nfields))
648
667
  ),
649
668
  tr(
650
- th(req.__("Views")),
651
- td(a({ href: info.base_url + "viewedit" }, info.nviews))
669
+ th(req.__("Table constraints")),
670
+ td(
671
+ a(
672
+ { href: info.base_url + "table" },
673
+ info.ntable_constraints
674
+ )
675
+ ),
676
+ th(req.__("Library")),
677
+ td(a({ href: info.base_url + "library/list" }, info.nlibrary))
652
678
  ),
653
679
  tr(
680
+ th(req.__("Views")),
681
+ td(a({ href: info.base_url + "viewedit" }, info.nviews)),
654
682
  th(req.__("Pages")),
655
683
  td(a({ href: info.base_url + "pageedit" }, info.npages))
656
684
  ),
657
685
  tr(
658
686
  th(req.__("Files")),
659
- td(a({ href: info.base_url + "files" }, info.nfiles))
660
- ),
661
- tr(
687
+ td(a({ href: info.base_url + "files" }, info.nfiles)),
662
688
  th(req.__("Actions")),
663
689
  td(a({ href: info.base_url + "actions" }, info.nactions))
664
690
  ),
665
691
  tr(
666
692
  th(req.__("Modules")),
667
- td(a({ href: info.base_url + "plugins" }, info.nplugins))
668
- ),
669
- tr(
693
+ td(a({ href: info.base_url + "plugins" }, info.nplugins)),
670
694
  th(req.__("Configuration items")),
671
695
  td(a({ href: info.base_url + "admin" }, info.nconfigs))
672
696
  ),
673
697
  tr(
698
+ // Crashlogs only for main site?
674
699
  th(req.__("Crashlogs")),
675
- td(a({ href: info.base_url + "crashlog" }, info.nerrors))
700
+ td(a({ href: info.base_url + "crashlog" }, info.nerrors)),
701
+ //th(req.__("Sessions")),
702
+ //td(a({ href: info.base_url + "crashlog" }, info.nsessions)),
703
+ th(req.__("Event logs")),
704
+ td(a({ href: info.base_url + "eventlog" }, info.nevent_log))
705
+ // Notifications only for main site?
706
+ //th(req.__("Notifications")),
707
+ //td(a({ href: info.base_url + "???" }, info.nnotifications)),
708
+ ),
709
+ tr(
710
+ th(req.__("Snapshots")),
711
+ td(
712
+ a({ href: info.base_url + "admin/backup" }, info.nsnapshots)
713
+ ),
714
+ th(req.__("Migrations")),
715
+ td(a({ href: info.base_url + "admin" }, info.nmigrations))
716
+ ),
717
+ tr(
718
+ th(req.__("Tags")),
719
+ td(a({ href: info.base_url + "tag" }, info.ntags)),
720
+ th(req.__("Tag Entries")),
721
+ td(a({ href: info.base_url + "tag" }, info.ntag_entries))
676
722
  )
677
723
  ),
678
724
  ],
@@ -697,6 +743,7 @@ router.get(
697
743
  name: "description",
698
744
  label: req.__("Description"),
699
745
  type: "String",
746
+ fieldview: "textarea",
700
747
  },
701
748
  ],
702
749
  values: {
package/routes/view.js CHANGED
@@ -42,7 +42,7 @@ router.get(
42
42
  const { viewname } = req.params;
43
43
  const query = { ...req.query };
44
44
  const view = await View.findOne({ name: viewname });
45
- const role = req.user && req.user.id ? req.user.role_id : 10;
45
+ const role = req.user && req.user.id ? req.user.role_id : 100;
46
46
  const state = getState();
47
47
  state.log(3, `Route /view/${viewname} user=${req.user?.id}`);
48
48
  if (!view) {
@@ -157,7 +157,7 @@ router.post(
157
157
  "/:viewname/:route",
158
158
  error_catcher(async (req, res) => {
159
159
  const { viewname, route } = req.params;
160
- const role = req.user && req.user.id ? req.user.role_id : 10;
160
+ const role = req.user && req.user.id ? req.user.role_id : 100;
161
161
  const state = getState();
162
162
  state.log(
163
163
  3,
@@ -191,7 +191,7 @@ router.post(
191
191
  setTenant,
192
192
  error_catcher(async (req, res) => {
193
193
  const { viewname } = req.params;
194
- const role = req.user && req.user.id ? req.user.role_id : 10;
194
+ const role = req.user && req.user.id ? req.user.role_id : 100;
195
195
  const query = { ...req.query };
196
196
  const state = getState();
197
197
  state.log(3, `Route /view/${viewname} POST user=${req.user?.id}`);
@@ -8,16 +8,9 @@
8
8
  const Router = require("express-promise-router");
9
9
 
10
10
  const { renderForm, renderBuilder, alert } = require("@saltcorn/markup");
11
- const {
12
- p,
13
- a,
14
- div,
15
- script,
16
- text,
17
- domReady,
18
- code,
19
- pre,
20
- } = require("@saltcorn/markup/tags");
11
+ const tags = require("@saltcorn/markup/tags");
12
+ const { p, a, div, script, text, domReady, code, pre, tbody, tr, th, td } =
13
+ tags;
21
14
 
22
15
  const { getState } = require("@saltcorn/data/db/state");
23
16
  const { isAdmin, error_catcher, addOnDoneRedirect } = require("./utils.js");
@@ -30,6 +23,7 @@ const Workflow = require("@saltcorn/data/models/workflow");
30
23
  const User = require("@saltcorn/data/models/user");
31
24
  const Page = require("@saltcorn/data/models/page");
32
25
  const db = require("@saltcorn/data/db");
26
+ const { sleep } = require("@saltcorn/data/utils");
33
27
 
34
28
  const { add_to_menu } = require("@saltcorn/admin-models/models/pack");
35
29
 
@@ -305,6 +299,7 @@ router.get(
305
299
  const roles = await User.get_roles();
306
300
  const pages = await Page.find();
307
301
  const form = await viewForm(req, tableOptions, roles, pages, viewrow);
302
+ const inbound_connected = await viewrow.inbound_connected_objects();
308
303
  form.hidden("id");
309
304
  res.sendWrap(req.__(`Edit view`), {
310
305
  above: [
@@ -328,7 +323,6 @@ router.get(
328
323
  },
329
324
  {
330
325
  type: "card",
331
-
332
326
  title: req.__("View configuration"),
333
327
  contents: {
334
328
  type: "tabs",
@@ -340,6 +334,24 @@ router.get(
340
334
  titles: [req.__("Show configuration object")],
341
335
  },
342
336
  },
337
+ {
338
+ type: "card",
339
+ title: req.__("Connected views"),
340
+ contents: tags.table(
341
+ tbody(
342
+ tr(
343
+ th({ class: "me-2" }, req.__("Embedded in")),
344
+ td(
345
+ inbound_connected.embeddedViews.map((v) => v.name).join(", ")
346
+ )
347
+ ),
348
+ tr(
349
+ th({ class: "me-2" }, req.__("Linked from")),
350
+ td(inbound_connected.linkedViews.map((v) => v.name).join(", "))
351
+ )
352
+ )
353
+ ),
354
+ },
343
355
  ],
344
356
  });
345
357
  })
@@ -458,6 +470,7 @@ router.post(
458
470
  else v.configuration = {};
459
471
  //console.log(v);
460
472
  await View.create(v);
473
+ await sleep(500); // Allow other workers to load this view
461
474
  }
462
475
  res.redirect(
463
476
  addOnDoneRedirect(
@@ -29,7 +29,7 @@ beforeAll(async () => {
29
29
  await File.from_req_files(
30
30
  { mimetype: "image/png", name: "rick.png", mv, size: 245752 },
31
31
  1,
32
- 4
32
+ 40
33
33
  );
34
34
  });
35
35
 
@@ -272,7 +272,7 @@ describe("menu editor", () => {
272
272
  url: "",
273
273
  type: "View",
274
274
  label: "BarMenu",
275
- min_role: "10",
275
+ min_role: "100",
276
276
  pagename: null,
277
277
  viewname: "dqwdw",
278
278
  },
@@ -321,32 +321,32 @@ describe("roleadmin", () => {
321
321
  await request(app)
322
322
  .post("/roleadmin/edit")
323
323
  .set("Cookie", loginCookie)
324
- .send("id=5")
324
+ .send("id=50")
325
325
  .send("role=muppets")
326
326
  .expect(toRedirect("/roleadmin"));
327
327
  const roles = await User.get_roles();
328
- expect(roles).toContainEqual({ id: 5, role: "muppets" });
328
+ expect(roles).toContainEqual({ id: 50, role: "muppets" });
329
329
  });
330
330
  it("show set layout for role", async () => {
331
331
  const app = await getApp({ disableCsrf: true });
332
332
  const loginCookie = await getAdminLoginCookie();
333
333
  await request(app)
334
- .post("/roleadmin/setrolelayout/5")
334
+ .post("/roleadmin/setrolelayout/50")
335
335
  .set("Cookie", loginCookie)
336
336
  .send("layout=tabler")
337
337
  .expect(toRedirect("/roleadmin"));
338
338
  const roles = await User.get_roles();
339
- expect(roles).toContainEqual({ id: 5, role: "muppets" });
339
+ expect(roles).toContainEqual({ id: 50, role: "muppets" });
340
340
  });
341
341
  it("show delete role", async () => {
342
342
  const app = await getApp({ disableCsrf: true });
343
343
  const loginCookie = await getAdminLoginCookie();
344
344
  await request(app)
345
- .post("/roleadmin/delete/5")
345
+ .post("/roleadmin/delete/50")
346
346
  .set("Cookie", loginCookie)
347
347
  .expect(toRedirect("/roleadmin"));
348
348
  const roles = await User.get_roles();
349
- expect(roles).not.toContainEqual({ id: 5, role: "muppets" });
349
+ expect(roles).not.toContainEqual({ id: 50, role: "muppets" });
350
350
  });
351
351
  });
352
352
  /**
@@ -205,7 +205,7 @@ describe("user admin", () => {
205
205
  .post("/useradmin/save")
206
206
  .send("email=staff2@foo.com")
207
207
  .send("password=fideRGE54lio")
208
- .send("role_id=8")
208
+ .send("role_id=80")
209
209
  .set("Cookie", loginCookie)
210
210
  .expect(toRedirect("/useradmin"));
211
211
  });
@@ -223,7 +223,7 @@ describe("user admin", () => {
223
223
  const app = await getApp({ disableCsrf: true });
224
224
  const loginCookie = await getAdminLoginCookie();
225
225
  const user = await User.findOne({ email: "staff2@foo.com" });
226
- expect(user.role_id).toBe(8);
226
+ expect(user.role_id).toBe(80);
227
227
  await request(app)
228
228
  .get(`/useradmin/${user.id}`)
229
229
  .set("Cookie", loginCookie)
@@ -238,11 +238,11 @@ describe("user admin", () => {
238
238
  .post("/useradmin/save")
239
239
  .send("email=staff2@foo.com")
240
240
  .send(`id=${user.id}`)
241
- .send("role_id=4")
241
+ .send("role_id=40")
242
242
  .set("Cookie", loginCookie)
243
243
  .expect(toRedirect("/useradmin"));
244
244
  const edituser = await User.findOne({ email: "staff2@foo.com" });
245
- expect(edituser.role_id).toBe(4);
245
+ expect(edituser.role_id).toBe(40);
246
246
  });
247
247
  it("tries to create new user with existing email", async () => {
248
248
  const app = await getApp({ disableCsrf: true });
@@ -251,7 +251,7 @@ describe("user admin", () => {
251
251
  .post("/useradmin/save")
252
252
  .send("email=staff2@foo.com")
253
253
  .send("password=fideRGE54lio")
254
- .send("role_id=8")
254
+ .send("role_id=80")
255
255
  .set("Cookie", loginCookie)
256
256
  .expect(toRedirect("/useradmin"));
257
257
  const editusers = await User.find({ email: "staff2@foo.com" });
@@ -342,7 +342,7 @@ describe("User fields", () => {
342
342
  configuration: {
343
343
  columns: [
344
344
  { type: "Field", fieldview: "edit", field_name: "height" },
345
- { type: "Action", minRole: 10, action_name: "Save" },
345
+ { type: "Action", minRole: 100, action_name: "Save" },
346
346
  ],
347
347
  layout: {
348
348
  above: [
@@ -368,7 +368,7 @@ describe("User fields", () => {
368
368
  ],
369
369
  },
370
370
  { type: "line_break" },
371
- { type: "action", minRole: 10, action_name: "Save" },
371
+ { type: "action", minRole: 100, action_name: "Save" },
372
372
  ],
373
373
  },
374
374
  },
@@ -466,7 +466,7 @@ describe("signup with custom login form", () => {
466
466
  {
467
467
  type: "action",
468
468
  rndid: "63f01b",
469
- minRole: 10,
469
+ minRole: 100,
470
470
  isFormula: {},
471
471
  action_name: "Login",
472
472
  action_label: "Login",
@@ -476,7 +476,7 @@ describe("signup with custom login form", () => {
476
476
  {
477
477
  type: "action",
478
478
  rndid: "45dd57",
479
- minRole: 10,
479
+ minRole: 100,
480
480
  isFormula: {},
481
481
  action_name: "Login with github",
482
482
  configuration: {},
@@ -489,7 +489,7 @@ describe("signup with custom login form", () => {
489
489
  {
490
490
  type: "Action",
491
491
  rndid: "63f01b",
492
- minRole: 10,
492
+ minRole: 100,
493
493
  isFormula: {},
494
494
  action_name: "Login",
495
495
  action_label: "Login",
@@ -499,7 +499,7 @@ describe("signup with custom login form", () => {
499
499
  {
500
500
  type: "Action",
501
501
  rndid: "45dd57",
502
- minRole: 10,
502
+ minRole: 100,
503
503
  isFormula: {},
504
504
  action_name: "Login with github",
505
505
  configuration: {},
@@ -573,7 +573,7 @@ describe("signup with custom login form", () => {
573
573
  {
574
574
  type: "action",
575
575
  rndid: "63f01b",
576
- minRole: 10,
576
+ minRole: 100,
577
577
  isFormula: {},
578
578
  action_name: "Sign up",
579
579
  action_style: "btn-primary",
@@ -588,7 +588,7 @@ describe("signup with custom login form", () => {
588
588
  {
589
589
  type: "Action",
590
590
  rndid: "63f01b",
591
- minRole: 10,
591
+ minRole: 100,
592
592
  isFormula: {},
593
593
  action_name: "Sign up",
594
594
  action_style: "btn-primary",