@budibase/backend-core 2.32.14 → 2.32.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 (45) hide show
  1. package/dist/index.js +96 -37
  2. package/dist/index.js.map +4 -4
  3. package/dist/index.js.meta.json +1 -1
  4. package/dist/package.json +4 -4
  5. package/dist/plugins.js +54 -0
  6. package/dist/plugins.js.map +4 -4
  7. package/dist/plugins.js.meta.json +1 -1
  8. package/dist/src/context/mainContext.d.ts +2 -0
  9. package/dist/src/context/mainContext.js +9 -0
  10. package/dist/src/context/mainContext.js.map +1 -1
  11. package/dist/src/context/types.d.ts +1 -0
  12. package/dist/src/db/couch/DatabaseImpl.d.ts +1 -0
  13. package/dist/src/db/couch/DatabaseImpl.js +13 -0
  14. package/dist/src/db/couch/DatabaseImpl.js.map +1 -1
  15. package/dist/src/db/instrumentation.d.ts +1 -0
  16. package/dist/src/db/instrumentation.js +6 -0
  17. package/dist/src/db/instrumentation.js.map +1 -1
  18. package/dist/src/features/features.d.ts +4 -4
  19. package/dist/src/features/features.js +24 -32
  20. package/dist/src/features/features.js.map +1 -1
  21. package/dist/src/index.d.ts +2 -0
  22. package/dist/src/middleware/index.d.ts +1 -0
  23. package/dist/src/middleware/index.js +3 -1
  24. package/dist/src/middleware/index.js.map +1 -1
  25. package/dist/src/middleware/ip.d.ts +3 -0
  26. package/dist/src/middleware/ip.js +23 -0
  27. package/dist/src/middleware/ip.js.map +1 -0
  28. package/dist/src/security/permissions.d.ts +17 -37
  29. package/dist/src/security/permissions.js.map +1 -1
  30. package/dist/src/security/roles.js +3 -1
  31. package/dist/src/security/roles.js.map +1 -1
  32. package/dist/src/sql/sql.js +6 -0
  33. package/dist/src/sql/sql.js.map +1 -1
  34. package/package.json +4 -4
  35. package/src/context/mainContext.ts +9 -0
  36. package/src/context/types.ts +1 -0
  37. package/src/db/couch/DatabaseImpl.ts +11 -0
  38. package/src/db/instrumentation.ts +7 -0
  39. package/src/features/features.ts +26 -47
  40. package/src/features/tests/features.spec.ts +59 -31
  41. package/src/middleware/index.ts +1 -0
  42. package/src/middleware/ip.ts +12 -0
  43. package/src/security/permissions.ts +7 -1
  44. package/src/security/roles.ts +3 -1
  45. package/src/sql/sql.ts +8 -1
package/dist/index.js CHANGED
@@ -61720,10 +61720,23 @@ var DocumentType = /* @__PURE__ */ ((DocumentType2) => {
61720
61720
  DocumentType2["ROW_ACTIONS"] = "ra";
61721
61721
  return DocumentType2;
61722
61722
  })(DocumentType || {});
61723
+ var sortedDocumentTypes = Object.values(DocumentType).sort(
61724
+ (a, b) => b.length - a.length
61725
+ // descending
61726
+ );
61723
61727
  var InternalTable = /* @__PURE__ */ ((InternalTable2) => {
61724
61728
  InternalTable2["USER_METADATA"] = "ta_users";
61725
61729
  return InternalTable2;
61726
61730
  })(InternalTable || {});
61731
+ var VirtualDocumentType = /* @__PURE__ */ ((VirtualDocumentType2) => {
61732
+ VirtualDocumentType2["VIEW"] = "view";
61733
+ VirtualDocumentType2["ROW_ACTION"] = "row_action";
61734
+ return VirtualDocumentType2;
61735
+ })(VirtualDocumentType || {});
61736
+ var sortedVirtualDocumentTypes = Object.values(VirtualDocumentType).sort(
61737
+ (a, b) => b.length - a.length
61738
+ // descending
61739
+ );
61727
61740
 
61728
61741
  // ../types/src/documents/global/user.ts
61729
61742
  function isSSOUser(user) {
@@ -62292,7 +62305,8 @@ __export(views_exports, {
62292
62305
  hasCalculationFields: () => hasCalculationFields,
62293
62306
  isBasicViewField: () => isBasicViewField,
62294
62307
  isCalculationField: () => isCalculationField,
62295
- isCalculationView: () => isCalculationView
62308
+ isCalculationView: () => isCalculationView,
62309
+ isVisible: () => isVisible
62296
62310
  });
62297
62311
  var import_lodash = require("lodash");
62298
62312
  function isCalculationField(field) {
@@ -62310,8 +62324,14 @@ function hasCalculationFields(view) {
62310
62324
  function calculationFields(view) {
62311
62325
  return (0, import_lodash.pickBy)(view.schema || {}, isCalculationField);
62312
62326
  }
62313
- function basicFields(view) {
62314
- return (0, import_lodash.pickBy)(view.schema || {}, (field) => !isCalculationField(field));
62327
+ function isVisible(field) {
62328
+ return field.visible !== false;
62329
+ }
62330
+ function basicFields(view, opts) {
62331
+ const { visible = true } = opts || {};
62332
+ return (0, import_lodash.pickBy)(view.schema || {}, (field) => {
62333
+ return !isCalculationField(field) && (!visible || isVisible(field));
62334
+ });
62315
62335
  }
62316
62336
 
62317
62337
  // ../shared-core/src/filters.ts
@@ -63421,6 +63441,7 @@ __export(context_exports, {
63421
63441
  doInAutomationContext: () => doInAutomationContext,
63422
63442
  doInContext: () => doInContext,
63423
63443
  doInEnvironmentContext: () => doInEnvironmentContext,
63444
+ doInIPContext: () => doInIPContext,
63424
63445
  doInIdentityContext: () => doInIdentityContext,
63425
63446
  doInScimContext: () => doInScimContext,
63426
63447
  doInTenant: () => doInTenant,
@@ -63436,6 +63457,7 @@ __export(context_exports, {
63436
63457
  getFeatureFlags: () => getFeatureFlags,
63437
63458
  getGlobalDB: () => getGlobalDB,
63438
63459
  getGlobalDBName: () => getGlobalDBName,
63460
+ getIP: () => getIP,
63439
63461
  getIdentity: () => getIdentity,
63440
63462
  getPlatformURL: () => getPlatformURL,
63441
63463
  getProdAppDB: () => getProdAppDB,
@@ -64002,6 +64024,12 @@ var DDInstrumentedDatabase = class {
64002
64024
  return this.db.get(id);
64003
64025
  });
64004
64026
  }
64027
+ tryGet(id) {
64028
+ return import_dd_trace.default.trace("db.tryGet", (span) => {
64029
+ span?.addTags({ db_name: this.name, doc_id: id });
64030
+ return this.db.tryGet(id);
64031
+ });
64032
+ }
64005
64033
  getMultiple(ids, opts) {
64006
64034
  return import_dd_trace.default.trace("db.getMultiple", (span) => {
64007
64035
  span?.addTags({
@@ -67134,6 +67162,7 @@ __export(features_exports, {
67134
67162
  });
67135
67163
 
67136
67164
  // src/features/features.ts
67165
+ var crypto = __toESM(require("crypto"));
67137
67166
  var import_posthog_node = require("posthog-node");
67138
67167
  var import_dd_trace3 = __toESM(require("dd-trace"));
67139
67168
 
@@ -67609,15 +67638,15 @@ var FlagSet = class {
67609
67638
  isFlagName(name) {
67610
67639
  return this.flagSchema[name] !== void 0;
67611
67640
  }
67612
- async get(key, ctx) {
67613
- const flags2 = await this.fetch(ctx);
67641
+ async get(key) {
67642
+ const flags2 = await this.fetch();
67614
67643
  return flags2[key];
67615
67644
  }
67616
- async isEnabled(key, ctx) {
67617
- const flags2 = await this.fetch(ctx);
67645
+ async isEnabled(key) {
67646
+ const flags2 = await this.fetch();
67618
67647
  return flags2[key];
67619
67648
  }
67620
- async fetch(ctx) {
67649
+ async fetch() {
67621
67650
  return await import_dd_trace3.default.trace("features.fetch", async (span) => {
67622
67651
  const cachedFlags = getFeatureFlags(this.setId);
67623
67652
  if (cachedFlags) {
@@ -67628,10 +67657,10 @@ var FlagSet = class {
67628
67657
  const flagValues = this.defaults();
67629
67658
  const currentTenantId = getTenantId();
67630
67659
  const specificallySetFalse = /* @__PURE__ */ new Set();
67631
- for (const { tenantId, key, value } of parseEnvFlags(
67660
+ for (const { tenantId: tenantId2, key, value } of parseEnvFlags(
67632
67661
  environment_default.TENANT_FEATURE_FLAGS || ""
67633
67662
  )) {
67634
- if (!tenantId || tenantId !== "*" && tenantId !== currentTenantId) {
67663
+ if (!tenantId2 || tenantId2 !== "*" && tenantId2 !== currentTenantId) {
67635
67664
  continue;
67636
67665
  }
67637
67666
  tags[`readFromEnvironmentVars`] = true;
@@ -67647,36 +67676,28 @@ var FlagSet = class {
67647
67676
  flagValues[key] = value;
67648
67677
  tags[`flags.${key}.source`] = "environment";
67649
67678
  }
67650
- const license = ctx?.user?.license;
67651
- if (license) {
67652
- tags[`readFromLicense`] = true;
67653
- for (const feature of license.features) {
67654
- if (!this.isFlagName(feature)) {
67655
- continue;
67656
- }
67657
- if (flagValues[feature] === true || specificallySetFalse.has(feature)) {
67658
- continue;
67659
- }
67660
- flagValues[feature] = true;
67661
- tags[`flags.${feature}.source`] = "license";
67679
+ const identity = getIdentity();
67680
+ let userId = identity?._id;
67681
+ if (!userId) {
67682
+ const ip = getIP();
67683
+ if (ip) {
67684
+ userId = crypto.createHash("sha512").update(ip).digest("hex");
67662
67685
  }
67663
67686
  }
67664
- const identity = getIdentity();
67687
+ let tenantId = identity?.tenantId;
67688
+ if (!tenantId) {
67689
+ tenantId = currentTenantId;
67690
+ }
67665
67691
  tags[`identity.type`] = identity?.type;
67666
- tags[`identity.tenantId`] = identity?.tenantId;
67667
67692
  tags[`identity._id`] = identity?._id;
67668
- if (posthog && identity?.type === "user" /* USER */) {
67693
+ tags[`tenantId`] = tenantId;
67694
+ tags[`userId`] = userId;
67695
+ if (posthog && userId) {
67669
67696
  tags[`readFromPostHog`] = true;
67670
- const personProperties = {};
67671
- if (identity.tenantId) {
67672
- personProperties.tenantId = identity.tenantId;
67673
- }
67674
- const posthogFlags = await posthog.getAllFlagsAndPayloads(
67675
- identity._id,
67676
- {
67677
- personProperties
67678
- }
67679
- );
67697
+ const personProperties = { tenantId };
67698
+ const posthogFlags = await posthog.getAllFlagsAndPayloads(userId, {
67699
+ personProperties
67700
+ });
67680
67701
  for (const [name, value] of Object.entries(posthogFlags.featureFlags)) {
67681
67702
  if (!this.isFlagName(name)) {
67682
67703
  console.warn(`Unexpected posthog flag "${name}": ${value}`);
@@ -67709,7 +67730,8 @@ var flags = new FlagSet({
67709
67730
  AUTOMATION_BRANCHING: Flag.boolean(environment_default.isDev()),
67710
67731
  SQS: Flag.boolean(environment_default.isDev()),
67711
67732
  ["AI_CUSTOM_CONFIGS" /* AI_CUSTOM_CONFIGS */]: Flag.boolean(environment_default.isDev()),
67712
- ["ENRICHED_RELATIONSHIPS" /* ENRICHED_RELATIONSHIPS */]: Flag.boolean(environment_default.isDev())
67733
+ ["ENRICHED_RELATIONSHIPS" /* ENRICHED_RELATIONSHIPS */]: Flag.boolean(environment_default.isDev()),
67734
+ ["TABLES_DEFAULT_ADMIN" /* TABLES_DEFAULT_ADMIN */]: Flag.boolean(environment_default.isDev())
67713
67735
  });
67714
67736
 
67715
67737
  // src/features/tests/utils.ts
@@ -67894,6 +67916,16 @@ var DatabaseImpl = class _DatabaseImpl {
67894
67916
  return () => db.get(id);
67895
67917
  });
67896
67918
  }
67919
+ async tryGet(id) {
67920
+ try {
67921
+ return await this.get(id);
67922
+ } catch (err) {
67923
+ if (err.statusCode === 404) {
67924
+ return void 0;
67925
+ }
67926
+ throw err;
67927
+ }
67928
+ }
67897
67929
  async getMultiple(ids, opts) {
67898
67930
  ids = [...new Set(ids)];
67899
67931
  const includeDocs = !opts?.excludeDocs;
@@ -68334,6 +68366,10 @@ function getAppId() {
68334
68366
  return foundId;
68335
68367
  }
68336
68368
  }
68369
+ function getIP() {
68370
+ const context = Context.get();
68371
+ return context?.ip;
68372
+ }
68337
68373
  var getProdAppId = () => {
68338
68374
  const appId = getAppId();
68339
68375
  if (!appId) {
@@ -68356,6 +68392,9 @@ function doInScimContext(task) {
68356
68392
  };
68357
68393
  return newContext(updates, task);
68358
68394
  }
68395
+ function doInIPContext(ip, task) {
68396
+ return newContext({ ip }, task);
68397
+ }
68359
68398
  async function ensureSnippetContext(enabled2 = !environment_default.isTest()) {
68360
68399
  const ctx = getCurrentContext();
68361
68400
  if (!ctx || ctx.snippets) {
@@ -69746,7 +69785,9 @@ function getDBRoleID(roleName) {
69746
69785
  }
69747
69786
  function getExternalRoleID(roleId, version) {
69748
69787
  if (roleId.startsWith("role" /* ROLE */) && (isBuiltin(roleId) || version === RoleIDVersion.NAME)) {
69749
- return roleId.split(`${"role" /* ROLE */}${SEPARATOR}`)[1];
69788
+ const parts = roleId.split(SEPARATOR);
69789
+ parts.shift();
69790
+ return parts.join(SEPARATOR);
69750
69791
  }
69751
69792
  return roleId;
69752
69793
  }
@@ -73828,6 +73869,7 @@ __export(middleware_exports, {
73828
73869
  errorHandling: () => errorHandling_default,
73829
73870
  google: () => google_exports,
73830
73871
  internalApi: () => internalApi_default,
73872
+ ip: () => ip_default,
73831
73873
  joiValidator: () => joi_validator_exports,
73832
73874
  local: () => local_exports,
73833
73875
  oidc: () => oidc_exports,
@@ -74818,6 +74860,17 @@ function params(schema, opts) {
74818
74860
  return validate2(schema, "params", opts);
74819
74861
  }
74820
74862
 
74863
+ // src/middleware/ip.ts
74864
+ var ip_default = async (ctx, next) => {
74865
+ if (ctx.ip) {
74866
+ return await doInIPContext(ctx.ip, () => {
74867
+ return next();
74868
+ });
74869
+ } else {
74870
+ return next();
74871
+ }
74872
+ };
74873
+
74821
74874
  // src/middleware/index.ts
74822
74875
  var datasource = {
74823
74876
  google: google_exports2
@@ -76419,6 +76472,9 @@ var InternalBuilder = class {
76419
76472
  }
76420
76473
  create(opts) {
76421
76474
  const { body: body2 } = this.query;
76475
+ if (!body2) {
76476
+ throw new Error("Cannot create without row body");
76477
+ }
76422
76478
  let query = this.qualifiedKnex({ alias: false });
76423
76479
  const parsedBody = this.parseBody(body2);
76424
76480
  if (this.client === "oracledb" /* ORACLE */) {
@@ -76526,6 +76582,9 @@ var InternalBuilder = class {
76526
76582
  }
76527
76583
  update(opts) {
76528
76584
  const { body: body2, filters } = this.query;
76585
+ if (!body2) {
76586
+ throw new Error("Cannot update without row body");
76587
+ }
76529
76588
  let query = this.qualifiedKnex();
76530
76589
  const parsedBody = this.parseBody(body2);
76531
76590
  query = this.addFilters(query, filters);