@budibase/backend-core 2.13.14 → 2.13.16

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 (71) hide show
  1. package/dist/index.js +302 -242
  2. package/dist/index.js.map +3 -3
  3. package/dist/index.js.meta.json +1 -1
  4. package/dist/package.json +4 -4
  5. package/dist/plugins.js.meta.json +1 -1
  6. package/dist/src/auth/auth.js.map +1 -1
  7. package/dist/src/configs/configs.js +3 -4
  8. package/dist/src/configs/configs.js.map +1 -1
  9. package/dist/src/constants/db.js.map +1 -1
  10. package/dist/src/db/utils.js.map +1 -1
  11. package/dist/src/docIds/conversions.js.map +1 -1
  12. package/dist/src/events/processors/posthog/index.js.map +1 -1
  13. package/dist/src/features/index.js.map +1 -1
  14. package/dist/src/index.js.map +1 -1
  15. package/dist/src/installation.js +2 -3
  16. package/dist/src/installation.js.map +1 -1
  17. package/dist/src/logging/correlation/correlation.js.map +1 -1
  18. package/dist/src/logging/correlation/middleware.js.map +1 -1
  19. package/dist/src/logging/pino/middleware.js.map +1 -1
  20. package/dist/src/middleware/index.js.map +1 -1
  21. package/dist/src/middleware/passport/sso/google.js.map +1 -1
  22. package/dist/src/objectStore/objectStore.js.map +1 -1
  23. package/dist/src/security/permissions.d.ts +1 -0
  24. package/dist/src/security/permissions.js +2 -1
  25. package/dist/src/security/permissions.js.map +1 -1
  26. package/dist/src/security/roles.js +1 -2
  27. package/dist/src/security/roles.js.map +1 -1
  28. package/dist/src/security/sessions.js.map +1 -1
  29. package/dist/src/users/db.d.ts +6 -1
  30. package/dist/src/users/db.js +29 -8
  31. package/dist/src/users/db.js.map +1 -1
  32. package/dist/src/users/users.d.ts +14 -11
  33. package/dist/src/users/users.js +200 -144
  34. package/dist/src/users/users.js.map +1 -1
  35. package/dist/src/utils/hashing.js.map +1 -1
  36. package/dist/src/utils/utils.js.map +1 -1
  37. package/dist/tests/core/utilities/mocks/alerts.js.map +1 -1
  38. package/dist/tests/core/utilities/mocks/index.js.map +1 -1
  39. package/dist/tests/core/utilities/structures/generator.js.map +1 -1
  40. package/dist/tests/jestSetup.js.map +1 -1
  41. package/package.json +4 -4
  42. package/src/auth/auth.ts +2 -0
  43. package/src/configs/configs.ts +3 -4
  44. package/src/constants/db.ts +1 -0
  45. package/src/db/utils.ts +1 -0
  46. package/src/docIds/conversions.ts +1 -0
  47. package/src/events/processors/posthog/index.ts +1 -0
  48. package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +2 -0
  49. package/src/features/index.ts +1 -0
  50. package/src/index.ts +1 -0
  51. package/src/installation.ts +1 -2
  52. package/src/logging/correlation/correlation.ts +1 -0
  53. package/src/logging/correlation/middleware.ts +1 -0
  54. package/src/logging/pino/middleware.ts +3 -0
  55. package/src/middleware/index.ts +1 -0
  56. package/src/middleware/passport/sso/google.ts +1 -0
  57. package/src/middleware/passport/sso/tests/google.spec.ts +1 -0
  58. package/src/middleware/passport/sso/tests/sso.spec.ts +1 -0
  59. package/src/middleware/tests/builder.spec.ts +1 -0
  60. package/src/objectStore/objectStore.ts +1 -0
  61. package/src/security/permissions.ts +1 -0
  62. package/src/security/roles.ts +7 -2
  63. package/src/security/sessions.ts +1 -0
  64. package/src/users/db.ts +35 -14
  65. package/src/users/users.ts +46 -16
  66. package/src/utils/hashing.ts +1 -0
  67. package/src/utils/utils.ts +1 -0
  68. package/tests/core/utilities/mocks/alerts.ts +1 -0
  69. package/tests/core/utilities/mocks/index.ts +1 -0
  70. package/tests/core/utilities/structures/generator.ts +1 -0
  71. package/tests/jestSetup.ts +1 -0
package/dist/index.js CHANGED
@@ -691,6 +691,7 @@ var init_permissions = __esm({
691
691
  PermissionType2["AUTOMATION"] = "automation";
692
692
  PermissionType2["WEBHOOK"] = "webhook";
693
693
  PermissionType2["BUILDER"] = "builder";
694
+ PermissionType2["CREATOR"] = "creator";
694
695
  PermissionType2["GLOBAL_BUILDER"] = "globalBuilder";
695
696
  PermissionType2["QUERY"] = "query";
696
697
  PermissionType2["VIEW"] = "view";
@@ -6672,9 +6673,11 @@ var getStatus = async () => {
6672
6673
  var users_exports3 = {};
6673
6674
  __export(users_exports3, {
6674
6675
  UserDB: () => UserDB,
6676
+ addAppBuilder: () => addAppBuilder,
6675
6677
  bulkGetGlobalUsersById: () => bulkGetGlobalUsersById,
6676
6678
  bulkUpdateGlobalUsers: () => bulkUpdateGlobalUsers,
6677
6679
  cleanseUserObject: () => cleanseUserObject,
6680
+ doesUserExist: () => doesUserExist,
6678
6681
  getAccountHolderFromUserIds: () => getAccountHolderFromUserIds,
6679
6682
  getAllUserIds: () => getAllUserIds,
6680
6683
  getById: () => getById,
@@ -6696,6 +6699,7 @@ __export(users_exports3, {
6696
6699
  isGlobalBuilder: () => isGlobalBuilder2,
6697
6700
  isSupportedUserSearch: () => isSupportedUserSearch,
6698
6701
  paginatedUsers: () => paginatedUsers,
6702
+ removeAppBuilder: () => removeAppBuilder,
6699
6703
  removePortalUserPermissions: () => removePortalUserPermissions,
6700
6704
  searchExistingEmails: () => searchExistingEmails,
6701
6705
  searchGlobalUsersByApp: () => searchGlobalUsersByApp,
@@ -7306,12 +7310,14 @@ function getProdAppID2(appId) {
7306
7310
  // ../shared-core/src/sdk/documents/users.ts
7307
7311
  var users_exports2 = {};
7308
7312
  __export(users_exports2, {
7313
+ canCreateApps: () => canCreateApps,
7309
7314
  containsUserID: () => containsUserID,
7310
7315
  getGlobalUserID: () => getGlobalUserID,
7311
7316
  hasAdminPermissions: () => hasAdminPermissions,
7312
7317
  hasAppBuilderPermissions: () => hasAppBuilderPermissions,
7313
7318
  hasAppCreatorPermissions: () => hasAppCreatorPermissions,
7314
7319
  hasBuilderPermissions: () => hasBuilderPermissions,
7320
+ hasCreatorPermissions: () => hasCreatorPermissions,
7315
7321
  isAdmin: () => isAdmin,
7316
7322
  isAdminOrBuilder: () => isAdminOrBuilder,
7317
7323
  isAdminOrGlobalBuilder: () => isAdminOrGlobalBuilder,
@@ -7335,6 +7341,9 @@ function isBuilder(user, appId) {
7335
7341
  function isGlobalBuilder(user) {
7336
7342
  return isBuilder(user) && !hasAppBuilderPermissions(user) || isAdmin(user);
7337
7343
  }
7344
+ function canCreateApps(user) {
7345
+ return isGlobalBuilder(user) || hasCreatorPermissions(user);
7346
+ }
7338
7347
  function isAdmin(user) {
7339
7348
  if (!user) {
7340
7349
  return false;
@@ -7362,7 +7371,7 @@ function hasAppCreatorPermissions(user) {
7362
7371
  return _.flow(
7363
7372
  _.get("roles"),
7364
7373
  _.values,
7365
- _.find((x) => ["CREATOR", "ADMIN"].includes(x)),
7374
+ _.find((x) => x === "CREATOR"),
7366
7375
  (x) => !!x
7367
7376
  )(user);
7368
7377
  }
@@ -7370,7 +7379,7 @@ function hasBuilderPermissions(user) {
7370
7379
  if (!user) {
7371
7380
  return false;
7372
7381
  }
7373
- return user.builder?.global || hasAppBuilderPermissions(user);
7382
+ return user.builder?.global || hasAppBuilderPermissions(user) || hasCreatorPermissions(user);
7374
7383
  }
7375
7384
  function hasAdminPermissions(user) {
7376
7385
  if (!user) {
@@ -7378,11 +7387,17 @@ function hasAdminPermissions(user) {
7378
7387
  }
7379
7388
  return !!user.admin?.global;
7380
7389
  }
7390
+ function hasCreatorPermissions(user) {
7391
+ if (!user) {
7392
+ return false;
7393
+ }
7394
+ return !!user.builder?.creator;
7395
+ }
7381
7396
  function isCreator(user) {
7382
7397
  if (!user) {
7383
7398
  return false;
7384
7399
  }
7385
- return isGlobalBuilder(user) || hasAdminPermissions(user) || hasAppBuilderPermissions(user) || hasAppCreatorPermissions(user);
7400
+ return isGlobalBuilder(user) || hasAdminPermissions(user) || hasCreatorPermissions(user) || hasAppBuilderPermissions(user) || hasAppCreatorPermissions(user);
7386
7401
  }
7387
7402
  function getGlobalUserID(userId) {
7388
7403
  if (typeof userId !== "string") {
@@ -7477,239 +7492,6 @@ async function getAccountHolderFromUserIds(userIds) {
7477
7492
  }
7478
7493
  }
7479
7494
 
7480
- // src/users/users.ts
7481
- function removeUserPassword(users) {
7482
- if (Array.isArray(users)) {
7483
- return users.map((user) => {
7484
- if (user) {
7485
- delete user.password;
7486
- return user;
7487
- }
7488
- });
7489
- } else if (users) {
7490
- delete users.password;
7491
- return users;
7492
- }
7493
- return users;
7494
- }
7495
- var isSupportedUserSearch = (query) => {
7496
- const allowed = [
7497
- { op: "string" /* STRING */, key: "email" },
7498
- { op: "equal" /* EQUAL */, key: "_id" }
7499
- ];
7500
- for (let [key, operation] of Object.entries(query)) {
7501
- if (typeof operation !== "object") {
7502
- return false;
7503
- }
7504
- const fields = Object.keys(operation || {});
7505
- if (fields.length === 0) {
7506
- continue;
7507
- }
7508
- const allowedOperation = allowed.find(
7509
- (allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
7510
- );
7511
- if (!allowedOperation) {
7512
- return false;
7513
- }
7514
- }
7515
- return true;
7516
- };
7517
- var bulkGetGlobalUsersById = async (userIds, opts) => {
7518
- const db = getGlobalDB();
7519
- let users = (await db.allDocs({
7520
- keys: userIds,
7521
- include_docs: true
7522
- })).rows.map((row) => row.doc);
7523
- if (opts?.cleanup) {
7524
- users = removeUserPassword(users);
7525
- }
7526
- return users;
7527
- };
7528
- var getAllUserIds = async () => {
7529
- const db = getGlobalDB();
7530
- const startKey = `${"us" /* USER */}${SEPARATOR}`;
7531
- const response = await db.allDocs({
7532
- startkey: startKey,
7533
- endkey: `${startKey}${UNICODE_MAX}`
7534
- });
7535
- return response.rows.map((row) => row.id);
7536
- };
7537
- var bulkUpdateGlobalUsers = async (users) => {
7538
- const db = getGlobalDB();
7539
- return await db.bulkDocs(users);
7540
- };
7541
- async function getById(id, opts) {
7542
- const db = getGlobalDB();
7543
- let user = await db.get(id);
7544
- if (opts?.cleanup) {
7545
- user = removeUserPassword(user);
7546
- }
7547
- return user;
7548
- }
7549
- var getGlobalUserByEmail = async (email, opts) => {
7550
- if (email == null) {
7551
- throw "Must supply an email address to view";
7552
- }
7553
- const response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
7554
- key: email.toLowerCase(),
7555
- include_docs: true
7556
- });
7557
- if (Array.isArray(response)) {
7558
- throw new Error(`Multiple users found with email address: ${email}`);
7559
- }
7560
- let user = response;
7561
- if (opts?.cleanup) {
7562
- user = removeUserPassword(user);
7563
- }
7564
- return user;
7565
- };
7566
- var searchGlobalUsersByApp = async (appId, opts, getOpts) => {
7567
- if (typeof appId !== "string") {
7568
- throw new Error("Must provide a string based app ID");
7569
- }
7570
- const params2 = getUsersByAppParams(appId, {
7571
- include_docs: true
7572
- });
7573
- params2.startkey = opts && opts.startkey ? opts.startkey : params2.startkey;
7574
- let response = await queryGlobalView("by_app" /* USER_BY_APP */, params2);
7575
- if (!response) {
7576
- response = [];
7577
- }
7578
- let users = Array.isArray(response) ? response : [response];
7579
- if (getOpts?.cleanup) {
7580
- users = removeUserPassword(users);
7581
- }
7582
- return users;
7583
- };
7584
- var searchGlobalUsersByAppAccess = async (appId, opts) => {
7585
- const roleSelector = `roles.${appId}`;
7586
- let orQuery = [
7587
- {
7588
- "builder.global": true
7589
- },
7590
- {
7591
- "admin.global": true
7592
- }
7593
- ];
7594
- if (appId) {
7595
- const roleCheck = {
7596
- [roleSelector]: {
7597
- $exists: true
7598
- }
7599
- };
7600
- orQuery.push(roleCheck);
7601
- }
7602
- let searchOptions = {
7603
- selector: {
7604
- $or: orQuery,
7605
- _id: {
7606
- $regex: "^us_"
7607
- }
7608
- },
7609
- limit: opts?.limit || 50
7610
- };
7611
- const resp = await directCouchFind(getGlobalDBName(), searchOptions);
7612
- return resp.rows;
7613
- };
7614
- var getGlobalUserByAppPage = (appId, user) => {
7615
- if (!user) {
7616
- return;
7617
- }
7618
- return generateAppUserID(getProdAppID(appId), user._id);
7619
- };
7620
- var searchGlobalUsersByEmail = async (email, opts, getOpts) => {
7621
- if (typeof email !== "string") {
7622
- throw new Error("Must provide a string to search by");
7623
- }
7624
- const lcEmail = email.toLowerCase();
7625
- const startkey = opts && opts.startkey ? opts.startkey : lcEmail;
7626
- let response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
7627
- ...opts,
7628
- startkey,
7629
- endkey: `${lcEmail}${UNICODE_MAX}`
7630
- });
7631
- if (!response) {
7632
- response = [];
7633
- }
7634
- let users = Array.isArray(response) ? response : [response];
7635
- if (getOpts?.cleanup) {
7636
- users = removeUserPassword(users);
7637
- }
7638
- return users;
7639
- };
7640
- var PAGE_LIMIT = 8;
7641
- var paginatedUsers = async ({
7642
- bookmark,
7643
- query,
7644
- appId,
7645
- limit
7646
- } = {}) => {
7647
- const db = getGlobalDB();
7648
- const pageSize = limit ?? PAGE_LIMIT;
7649
- const pageLimit = pageSize + 1;
7650
- const opts = {
7651
- include_docs: true,
7652
- limit: pageLimit
7653
- };
7654
- if (bookmark) {
7655
- opts.startkey = bookmark;
7656
- }
7657
- let userList, property = "_id", getKey;
7658
- if (query?.equal?._id) {
7659
- userList = [await getById(query.equal._id)];
7660
- } else if (appId) {
7661
- userList = await searchGlobalUsersByApp(appId, opts);
7662
- getKey = (doc) => getGlobalUserByAppPage(appId, doc);
7663
- } else if (query?.string?.email) {
7664
- userList = await searchGlobalUsersByEmail(query?.string?.email, opts);
7665
- property = "email";
7666
- } else {
7667
- const response = await db.allDocs(getGlobalUserParams(null, opts));
7668
- userList = response.rows.map((row) => row.doc);
7669
- }
7670
- return pagination(userList, pageSize, {
7671
- paginate: true,
7672
- property,
7673
- getKey
7674
- });
7675
- };
7676
- async function getUserCount() {
7677
- const response = await queryGlobalViewRaw("by_email2" /* USER_BY_EMAIL */, {
7678
- limit: 0,
7679
- // to be as fast as possible - we just want the total rows count
7680
- include_docs: false
7681
- });
7682
- return response.total_rows;
7683
- }
7684
- async function getCreatorCount() {
7685
- let creators = 0;
7686
- async function iterate(startPage) {
7687
- const page = await paginatedUsers({ bookmark: startPage });
7688
- creators += page.data.filter(isCreator2).length;
7689
- if (page.hasNextPage) {
7690
- await iterate(page.nextPage);
7691
- }
7692
- }
7693
- await iterate();
7694
- return creators;
7695
- }
7696
- function removePortalUserPermissions(user) {
7697
- delete user.admin;
7698
- delete user.builder;
7699
- return user;
7700
- }
7701
- function cleanseUserObject(user, base) {
7702
- delete user.admin;
7703
- delete user.builder;
7704
- delete user.roles;
7705
- if (base) {
7706
- user.admin = base.admin;
7707
- user.builder = base.builder;
7708
- user.roles = base.roles;
7709
- }
7710
- return user;
7711
- }
7712
-
7713
7495
  // src/users/db.ts
7714
7496
  init_environment2();
7715
7497
 
@@ -8425,7 +8207,6 @@ __export(installation_exports, {
8425
8207
  getInstallFromDB: () => getInstallFromDB
8426
8208
  });
8427
8209
  init_db4();
8428
- init_db4();
8429
8210
  init_src();
8430
8211
  init_context2();
8431
8212
  var import_semver = __toESM(require("semver"));
@@ -10486,9 +10267,6 @@ var UserDB = class _UserDB {
10486
10267
  if (!email && !_id) {
10487
10268
  throw new Error("_id or email is required");
10488
10269
  }
10489
- if (user.builder?.apps?.length && !await _UserDB.features.isAppBuildersEnabled()) {
10490
- throw new Error("Unable to update app builders, please check license");
10491
- }
10492
10270
  let dbUser;
10493
10271
  if (_id) {
10494
10272
  try {
@@ -10697,6 +10475,29 @@ var UserDB = class _UserDB {
10697
10475
  await user_exports.invalidateUser(userId);
10698
10476
  await invalidateSessions(userId, { reason: "deletion" });
10699
10477
  }
10478
+ static async createAdminUser(email, password, tenantId, opts) {
10479
+ const user = {
10480
+ email,
10481
+ password,
10482
+ createdAt: Date.now(),
10483
+ roles: {},
10484
+ builder: {
10485
+ global: true
10486
+ },
10487
+ admin: {
10488
+ global: true
10489
+ },
10490
+ tenantId
10491
+ };
10492
+ if (opts?.ssoId) {
10493
+ user.ssoId = opts.ssoId;
10494
+ }
10495
+ await bustCache("checklist" /* CHECKLIST */);
10496
+ return await _UserDB.save(user, {
10497
+ hashPassword: opts?.hashPassword,
10498
+ requirePassword: opts?.requirePassword
10499
+ });
10500
+ }
10700
10501
  static async getGroups(groupIds) {
10701
10502
  return await this.groups.getBulk(groupIds);
10702
10503
  }
@@ -10705,6 +10506,265 @@ var UserDB = class _UserDB {
10705
10506
  }
10706
10507
  };
10707
10508
 
10509
+ // src/users/users.ts
10510
+ function removeUserPassword(users) {
10511
+ if (Array.isArray(users)) {
10512
+ return users.map((user) => {
10513
+ if (user) {
10514
+ delete user.password;
10515
+ return user;
10516
+ }
10517
+ });
10518
+ } else if (users) {
10519
+ delete users.password;
10520
+ return users;
10521
+ }
10522
+ return users;
10523
+ }
10524
+ function isSupportedUserSearch(query) {
10525
+ const allowed = [
10526
+ { op: "string" /* STRING */, key: "email" },
10527
+ { op: "equal" /* EQUAL */, key: "_id" }
10528
+ ];
10529
+ for (let [key, operation] of Object.entries(query)) {
10530
+ if (typeof operation !== "object") {
10531
+ return false;
10532
+ }
10533
+ const fields = Object.keys(operation || {});
10534
+ if (fields.length === 0) {
10535
+ continue;
10536
+ }
10537
+ const allowedOperation = allowed.find(
10538
+ (allow) => allow.op === key && fields.length === 1 && fields[0] === allow.key
10539
+ );
10540
+ if (!allowedOperation) {
10541
+ return false;
10542
+ }
10543
+ }
10544
+ return true;
10545
+ }
10546
+ async function bulkGetGlobalUsersById(userIds, opts) {
10547
+ const db = getGlobalDB();
10548
+ let users = (await db.allDocs({
10549
+ keys: userIds,
10550
+ include_docs: true
10551
+ })).rows.map((row) => row.doc);
10552
+ if (opts?.cleanup) {
10553
+ users = removeUserPassword(users);
10554
+ }
10555
+ return users;
10556
+ }
10557
+ async function getAllUserIds() {
10558
+ const db = getGlobalDB();
10559
+ const startKey = `${"us" /* USER */}${SEPARATOR}`;
10560
+ const response = await db.allDocs({
10561
+ startkey: startKey,
10562
+ endkey: `${startKey}${UNICODE_MAX}`
10563
+ });
10564
+ return response.rows.map((row) => row.id);
10565
+ }
10566
+ async function bulkUpdateGlobalUsers(users) {
10567
+ const db = getGlobalDB();
10568
+ return await db.bulkDocs(users);
10569
+ }
10570
+ async function getById(id, opts) {
10571
+ const db = getGlobalDB();
10572
+ let user = await db.get(id);
10573
+ if (opts?.cleanup) {
10574
+ user = removeUserPassword(user);
10575
+ }
10576
+ return user;
10577
+ }
10578
+ async function getGlobalUserByEmail(email, opts) {
10579
+ if (email == null) {
10580
+ throw "Must supply an email address to view";
10581
+ }
10582
+ const response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
10583
+ key: email.toLowerCase(),
10584
+ include_docs: true
10585
+ });
10586
+ if (Array.isArray(response)) {
10587
+ throw new Error(`Multiple users found with email address: ${email}`);
10588
+ }
10589
+ let user = response;
10590
+ if (opts?.cleanup) {
10591
+ user = removeUserPassword(user);
10592
+ }
10593
+ return user;
10594
+ }
10595
+ async function doesUserExist(email) {
10596
+ try {
10597
+ const user = await getGlobalUserByEmail(email);
10598
+ if (Array.isArray(user) || user != null) {
10599
+ return true;
10600
+ }
10601
+ } catch (err) {
10602
+ return false;
10603
+ }
10604
+ return false;
10605
+ }
10606
+ async function searchGlobalUsersByApp(appId, opts, getOpts) {
10607
+ if (typeof appId !== "string") {
10608
+ throw new Error("Must provide a string based app ID");
10609
+ }
10610
+ const params2 = getUsersByAppParams(appId, {
10611
+ include_docs: true
10612
+ });
10613
+ params2.startkey = opts && opts.startkey ? opts.startkey : params2.startkey;
10614
+ let response = await queryGlobalView("by_app" /* USER_BY_APP */, params2);
10615
+ if (!response) {
10616
+ response = [];
10617
+ }
10618
+ let users = Array.isArray(response) ? response : [response];
10619
+ if (getOpts?.cleanup) {
10620
+ users = removeUserPassword(users);
10621
+ }
10622
+ return users;
10623
+ }
10624
+ async function searchGlobalUsersByAppAccess(appId, opts) {
10625
+ const roleSelector = `roles.${appId}`;
10626
+ let orQuery = [
10627
+ {
10628
+ "builder.global": true
10629
+ },
10630
+ {
10631
+ "admin.global": true
10632
+ }
10633
+ ];
10634
+ if (appId) {
10635
+ const roleCheck = {
10636
+ [roleSelector]: {
10637
+ $exists: true
10638
+ }
10639
+ };
10640
+ orQuery.push(roleCheck);
10641
+ }
10642
+ let searchOptions = {
10643
+ selector: {
10644
+ $or: orQuery,
10645
+ _id: {
10646
+ $regex: "^us_"
10647
+ }
10648
+ },
10649
+ limit: opts?.limit || 50
10650
+ };
10651
+ const resp = await directCouchFind(getGlobalDBName(), searchOptions);
10652
+ return resp.rows;
10653
+ }
10654
+ function getGlobalUserByAppPage(appId, user) {
10655
+ if (!user) {
10656
+ return;
10657
+ }
10658
+ return generateAppUserID(getProdAppID(appId), user._id);
10659
+ }
10660
+ async function searchGlobalUsersByEmail(email, opts, getOpts) {
10661
+ if (typeof email !== "string") {
10662
+ throw new Error("Must provide a string to search by");
10663
+ }
10664
+ const lcEmail = email.toLowerCase();
10665
+ const startkey = opts && opts.startkey ? opts.startkey : lcEmail;
10666
+ let response = await queryGlobalView("by_email2" /* USER_BY_EMAIL */, {
10667
+ ...opts,
10668
+ startkey,
10669
+ endkey: `${lcEmail}${UNICODE_MAX}`
10670
+ });
10671
+ if (!response) {
10672
+ response = [];
10673
+ }
10674
+ let users = Array.isArray(response) ? response : [response];
10675
+ if (getOpts?.cleanup) {
10676
+ users = removeUserPassword(users);
10677
+ }
10678
+ return users;
10679
+ }
10680
+ var PAGE_LIMIT = 8;
10681
+ async function paginatedUsers({
10682
+ bookmark,
10683
+ query,
10684
+ appId,
10685
+ limit
10686
+ } = {}) {
10687
+ const db = getGlobalDB();
10688
+ const pageSize = limit ?? PAGE_LIMIT;
10689
+ const pageLimit = pageSize + 1;
10690
+ const opts = {
10691
+ include_docs: true,
10692
+ limit: pageLimit
10693
+ };
10694
+ if (bookmark) {
10695
+ opts.startkey = bookmark;
10696
+ }
10697
+ let userList, property = "_id", getKey;
10698
+ if (query?.equal?._id) {
10699
+ userList = [await getById(query.equal._id)];
10700
+ } else if (appId) {
10701
+ userList = await searchGlobalUsersByApp(appId, opts);
10702
+ getKey = (doc) => getGlobalUserByAppPage(appId, doc);
10703
+ } else if (query?.string?.email) {
10704
+ userList = await searchGlobalUsersByEmail(query?.string?.email, opts);
10705
+ property = "email";
10706
+ } else {
10707
+ const response = await db.allDocs(getGlobalUserParams(null, opts));
10708
+ userList = response.rows.map((row) => row.doc);
10709
+ }
10710
+ return pagination(userList, pageSize, {
10711
+ paginate: true,
10712
+ property,
10713
+ getKey
10714
+ });
10715
+ }
10716
+ async function getUserCount() {
10717
+ const response = await queryGlobalViewRaw("by_email2" /* USER_BY_EMAIL */, {
10718
+ limit: 0,
10719
+ // to be as fast as possible - we just want the total rows count
10720
+ include_docs: false
10721
+ });
10722
+ return response.total_rows;
10723
+ }
10724
+ async function getCreatorCount() {
10725
+ let creators = 0;
10726
+ async function iterate(startPage) {
10727
+ const page = await paginatedUsers({ bookmark: startPage });
10728
+ creators += page.data.filter(isCreator2).length;
10729
+ if (page.hasNextPage) {
10730
+ await iterate(page.nextPage);
10731
+ }
10732
+ }
10733
+ await iterate();
10734
+ return creators;
10735
+ }
10736
+ function removePortalUserPermissions(user) {
10737
+ delete user.admin;
10738
+ delete user.builder;
10739
+ return user;
10740
+ }
10741
+ function cleanseUserObject(user, base) {
10742
+ delete user.admin;
10743
+ delete user.builder;
10744
+ delete user.roles;
10745
+ if (base) {
10746
+ user.admin = base.admin;
10747
+ user.builder = base.builder;
10748
+ user.roles = base.roles;
10749
+ }
10750
+ return user;
10751
+ }
10752
+ async function addAppBuilder(user, appId) {
10753
+ const prodAppId = getProdAppID(appId);
10754
+ user.builder ??= {};
10755
+ user.builder.creator = true;
10756
+ user.builder.apps ??= [];
10757
+ user.builder.apps.push(prodAppId);
10758
+ await UserDB.save(user, { hashPassword: false });
10759
+ }
10760
+ async function removeAppBuilder(user, appId) {
10761
+ const prodAppId = getProdAppID(appId);
10762
+ if (user.builder && user.builder.apps?.includes(prodAppId)) {
10763
+ user.builder.apps = user.builder.apps.filter((id) => id !== prodAppId);
10764
+ }
10765
+ await UserDB.save(user, { hashPassword: false });
10766
+ }
10767
+
10708
10768
  // src/cache/user.ts
10709
10769
  var EXPIRY_SECONDS3 = 3600;
10710
10770
  async function populateFromDB2(userId, tenantId) {
@@ -10934,7 +10994,6 @@ async function getCode2(code) {
10934
10994
  // src/configs/configs.ts
10935
10995
  init_context2();
10936
10996
  init_environment2();
10937
- init_environment2();
10938
10997
  function generateConfigID(type) {
10939
10998
  return `${"config" /* CONFIG */}${SEPARATOR}${type}`;
10940
10999
  }
@@ -11301,6 +11360,7 @@ __export(permissions_exports, {
11301
11360
  BUILDER: () => BUILDER,
11302
11361
  BUILTIN_PERMISSIONS: () => BUILTIN_PERMISSIONS,
11303
11362
  BuiltinPermissionID: () => BuiltinPermissionID,
11363
+ CREATOR: () => CREATOR,
11304
11364
  GLOBAL_BUILDER: () => GLOBAL_BUILDER,
11305
11365
  Permission: () => Permission,
11306
11366
  PermissionLevel: () => PermissionLevel,
@@ -11441,12 +11501,12 @@ function isPermissionLevelHigherThanRead(level) {
11441
11501
  return levelToNumber(level) > 1;
11442
11502
  }
11443
11503
  var BUILDER = "builder" /* BUILDER */;
11504
+ var CREATOR = "creator" /* CREATOR */;
11444
11505
  var GLOBAL_BUILDER = "globalBuilder" /* GLOBAL_BUILDER */;
11445
11506
 
11446
11507
  // src/security/roles.ts
11447
11508
  init_db4();
11448
11509
  init_context2();
11449
- init_db4();
11450
11510
  var import_cloneDeep2 = __toESM(require("lodash/fp/cloneDeep"));
11451
11511
  var BUILTIN_ROLE_IDS = {
11452
11512
  ADMIN: "ADMIN",