@budibase/backend-core 2.32.11 → 2.32.13

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 (37) hide show
  1. package/dist/index.js +504 -172
  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.meta.json +1 -1
  6. package/dist/src/db/couch/DatabaseImpl.js +10 -2
  7. package/dist/src/db/couch/DatabaseImpl.js.map +1 -1
  8. package/dist/src/features/features.d.ts +47 -0
  9. package/dist/src/features/features.js +269 -0
  10. package/dist/src/features/features.js.map +1 -0
  11. package/dist/src/features/index.d.ts +2 -39
  12. package/dist/src/features/index.js +6 -235
  13. package/dist/src/features/index.js.map +1 -1
  14. package/dist/src/features/tests/utils.d.ts +3 -0
  15. package/dist/src/features/tests/utils.js +56 -0
  16. package/dist/src/features/tests/utils.js.map +1 -0
  17. package/dist/src/middleware/passport/sso/sso.js +0 -25
  18. package/dist/src/middleware/passport/sso/sso.js.map +1 -1
  19. package/dist/src/sql/sql.js +93 -35
  20. package/dist/src/sql/sql.js.map +1 -1
  21. package/dist/src/users/users.js +8 -1
  22. package/dist/src/users/users.js.map +1 -1
  23. package/dist/tests/core/utilities/structures/accounts.d.ts +1 -6
  24. package/dist/tests/core/utilities/structures/accounts.js +4 -58
  25. package/dist/tests/core/utilities/structures/accounts.js.map +1 -1
  26. package/dist/tests/core/utilities/structures/users.js +2 -5
  27. package/dist/tests/core/utilities/structures/users.js.map +1 -1
  28. package/package.json +4 -4
  29. package/src/db/couch/DatabaseImpl.ts +12 -2
  30. package/src/features/features.ts +300 -0
  31. package/src/features/index.ts +2 -281
  32. package/src/features/tests/utils.ts +64 -0
  33. package/src/middleware/passport/sso/sso.ts +0 -24
  34. package/src/sql/sql.ts +107 -36
  35. package/src/users/users.ts +10 -2
  36. package/tests/core/utilities/structures/accounts.ts +1 -66
  37. package/tests/core/utilities/structures/users.ts +0 -5
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.selfSSOCreateAccount = exports.selfCreateAccount = exports.cloudVerifiableSSOCreateAccount = exports.cloudSSOCreateAccount = exports.cloudCreateAccount = exports.cloudAccount = exports.account = void 0;
6
+ exports.cloudAccount = exports.account = void 0;
7
7
  exports.selfHostAccount = selfHostAccount;
8
8
  exports.ssoAccount = ssoAccount;
9
9
  exports.verifiableSsoAccount = verifiableSsoAccount;
@@ -12,7 +12,7 @@ const docIds_1 = require("../../../../src/docIds");
12
12
  const types_1 = require("@budibase/types");
13
13
  const sample_1 = __importDefault(require("lodash/sample"));
14
14
  const account = (partial = {}) => {
15
- return Object.assign({ accountId: (0, _1.uuid)(), tenantId: _1.generator.word(), email: _1.generator.email({ domain: "example.com" }), tenantName: _1.generator.word(), hosting: types_1.Hosting.SELF, createdAt: Date.now(), verified: true, verificationSent: true, authType: types_1.AuthType.PASSWORD, name: _1.generator.name(), size: "10+", profession: "Software Engineer", quotaUsage: _1.quotas.usage() }, partial);
15
+ return Object.assign({ accountId: (0, _1.uuid)(), tenantId: _1.generator.word(), email: _1.generator.email({ domain: "example.com" }), accountName: _1.generator.word(), tenantName: _1.generator.word(), hosting: types_1.Hosting.SELF, createdAt: Date.now(), verified: true, verificationSent: true, authType: types_1.AuthType.PASSWORD, name: _1.generator.name(), size: "10+", profession: "Software Engineer", quotaUsage: _1.quotas.usage() }, partial);
16
16
  };
17
17
  exports.account = account;
18
18
  function selfHostAccount() {
@@ -32,66 +32,12 @@ function ssoAccount(account = (0, exports.cloudAccount)()) {
32
32
  return Object.assign(Object.assign({}, account), { authType: types_1.AuthType.SSO, oauth2: {
33
33
  accessToken: _1.generator.string(),
34
34
  refreshToken: _1.generator.string(),
35
- }, pictureUrl: _1.generator.url(), provider: provider(), providerType: providerType(), thirdPartyProfile: {} });
35
+ }, provider: provider(), providerType: providerType() });
36
36
  }
37
37
  function verifiableSsoAccount(account = (0, exports.cloudAccount)()) {
38
38
  return Object.assign(Object.assign({}, account), { authType: types_1.AuthType.SSO, oauth2: {
39
39
  accessToken: _1.generator.string(),
40
40
  refreshToken: _1.generator.string(),
41
- }, pictureUrl: _1.generator.url(), provider: types_1.AccountSSOProvider.MICROSOFT, providerType: types_1.AccountSSOProviderType.MICROSOFT, thirdPartyProfile: { id: "abc123" } });
41
+ }, provider: types_1.AccountSSOProvider.MICROSOFT, providerType: types_1.AccountSSOProviderType.MICROSOFT });
42
42
  }
43
- exports.cloudCreateAccount = {
44
- email: "cloud@budibase.com",
45
- tenantId: "cloud",
46
- hosting: types_1.Hosting.CLOUD,
47
- authType: types_1.AuthType.PASSWORD,
48
- password: "Password123!",
49
- tenantName: "cloud",
50
- name: "Budi Armstrong",
51
- size: "10+",
52
- profession: "Software Engineer",
53
- };
54
- exports.cloudSSOCreateAccount = {
55
- email: "cloud-sso@budibase.com",
56
- tenantId: "cloud-sso",
57
- hosting: types_1.Hosting.CLOUD,
58
- authType: types_1.AuthType.SSO,
59
- tenantName: "cloudsso",
60
- name: "Budi Armstrong",
61
- size: "10+",
62
- profession: "Software Engineer",
63
- };
64
- exports.cloudVerifiableSSOCreateAccount = {
65
- email: "cloud-sso@budibase.com",
66
- tenantId: "cloud-sso",
67
- hosting: types_1.Hosting.CLOUD,
68
- authType: types_1.AuthType.SSO,
69
- tenantName: "cloudsso",
70
- name: "Budi Armstrong",
71
- size: "10+",
72
- profession: "Software Engineer",
73
- provider: types_1.AccountSSOProvider.MICROSOFT,
74
- thirdPartyProfile: { id: "abc123" },
75
- };
76
- exports.selfCreateAccount = {
77
- email: "self@budibase.com",
78
- tenantId: "self",
79
- hosting: types_1.Hosting.SELF,
80
- authType: types_1.AuthType.PASSWORD,
81
- password: "Password123!",
82
- tenantName: "self",
83
- name: "Budi Armstrong",
84
- size: "10+",
85
- profession: "Software Engineer",
86
- };
87
- exports.selfSSOCreateAccount = {
88
- email: "self-sso@budibase.com",
89
- tenantId: "self-sso",
90
- hosting: types_1.Hosting.SELF,
91
- authType: types_1.AuthType.SSO,
92
- tenantName: "selfsso",
93
- name: "Budi Armstrong",
94
- size: "10+",
95
- profession: "Software Engineer",
96
- };
97
43
  //# sourceMappingURL=accounts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../../../tests/core/utilities/structures/accounts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../../../../../tests/core/utilities/structures/accounts.ts"],"names":[],"mappings":";;;;;;AAiCA,0CAEC;AAkBD,gCAWC;AAED,oDAaC;AA/ED,wBAA2C;AAC3C,mDAA6D;AAC7D,2CAQwB;AACxB,2DAAkC;AAE3B,MAAM,OAAO,GAAG,CAAC,UAA4B,EAAE,EAAW,EAAE;IACjE,uBACE,SAAS,EAAE,IAAA,OAAI,GAAE,EACjB,QAAQ,EAAE,YAAS,CAAC,IAAI,EAAE,EAC1B,KAAK,EAAE,YAAS,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,EACjD,WAAW,EAAE,YAAS,CAAC,IAAI,EAAE,EAC7B,UAAU,EAAE,YAAS,CAAC,IAAI,EAAE,EAC5B,OAAO,EAAE,eAAO,CAAC,IAAI,EACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EACrB,QAAQ,EAAE,IAAI,EACd,gBAAgB,EAAE,IAAI,EACtB,QAAQ,EAAE,gBAAQ,CAAC,QAAQ,EAC3B,IAAI,EAAE,YAAS,CAAC,IAAI,EAAE,EACtB,IAAI,EAAE,KAAK,EACX,UAAU,EAAE,mBAAmB,EAC/B,UAAU,EAAE,SAAM,CAAC,KAAK,EAAE,IACvB,OAAO,EACX;AACH,CAAC,CAAA;AAlBY,QAAA,OAAO,WAkBnB;AAED,SAAgB,eAAe;IAC7B,OAAO,IAAA,eAAO,GAAE,CAAA;AAClB,CAAC;AAEM,MAAM,YAAY,GAAG,GAAiB,EAAE;IAC7C,uCACK,IAAA,eAAO,GAAE,KACZ,OAAO,EAAE,eAAO,CAAC,KAAK,EACtB,cAAc,EAAE,IAAA,6BAAoB,GAAE,IACvC;AACH,CAAC,CAAA;AANY,QAAA,YAAY,gBAMxB;AAED,SAAS,YAAY;IACnB,OAAO,IAAA,gBAAM,EAAC,MAAM,CAAC,MAAM,CAAC,8BAAsB,CAAC,CAA2B,CAAA;AAChF,CAAC;AAED,SAAS,QAAQ;IACf,OAAO,IAAA,gBAAM,EAAC,MAAM,CAAC,MAAM,CAAC,0BAAkB,CAAC,CAAuB,CAAA;AACxE,CAAC;AAED,SAAgB,UAAU,CAAC,UAAmB,IAAA,oBAAY,GAAE;IAC1D,uCACK,OAAO,KACV,QAAQ,EAAE,gBAAQ,CAAC,GAAG,EACtB,MAAM,EAAE;YACN,WAAW,EAAE,YAAS,CAAC,MAAM,EAAE;YAC/B,YAAY,EAAE,YAAS,CAAC,MAAM,EAAE;SACjC,EACD,QAAQ,EAAE,QAAQ,EAAE,EACpB,YAAY,EAAE,YAAY,EAAE,IAC7B;AACH,CAAC;AAED,SAAgB,oBAAoB,CAClC,UAAmB,IAAA,oBAAY,GAAE;IAEjC,uCACK,OAAO,KACV,QAAQ,EAAE,gBAAQ,CAAC,GAAG,EACtB,MAAM,EAAE;YACN,WAAW,EAAE,YAAS,CAAC,MAAM,EAAE;YAC/B,YAAY,EAAE,YAAS,CAAC,MAAM,EAAE;SACjC,EACD,QAAQ,EAAE,0BAAkB,CAAC,SAAS,EACtC,YAAY,EAAE,8BAAsB,CAAC,SAAS,IAC/C;AACH,CAAC"}
@@ -12,7 +12,7 @@ const newEmail = () => {
12
12
  exports.newEmail = newEmail;
13
13
  const user = (userProps) => {
14
14
  const userId = userProps === null || userProps === void 0 ? void 0 : userProps._id;
15
- return Object.assign({ _id: userId, userId, email: (0, exports.newEmail)(), password: "password123!", roles: { app_test: "admin" }, firstName: generator_1.generator.first(), lastName: generator_1.generator.last(), pictureUrl: "http://example.com", tenantId: _1.tenant.id() }, userProps);
15
+ return Object.assign({ _id: userId, userId, email: (0, exports.newEmail)(), password: "password123!", roles: { app_test: "admin" }, firstName: generator_1.generator.first(), lastName: generator_1.generator.last(), tenantId: _1.tenant.id() }, userProps);
16
16
  };
17
17
  exports.user = user;
18
18
  const adminUser = (userProps) => {
@@ -48,9 +48,6 @@ function ssoUser(opts = {}) {
48
48
  if (!opts.details) {
49
49
  opts.details = (0, sso_1.authDetails)(base);
50
50
  }
51
- return Object.assign(Object.assign({}, base), { forceResetPassword: false, oauth2: (_a = opts.details) === null || _a === void 0 ? void 0 : _a.oauth2, provider: (_b = opts.details) === null || _b === void 0 ? void 0 : _b.provider, providerType: (_c = opts.details) === null || _c === void 0 ? void 0 : _c.providerType, thirdPartyProfile: {
52
- email: base.email,
53
- picture: base.pictureUrl,
54
- } });
51
+ return Object.assign(Object.assign({}, base), { forceResetPassword: false, oauth2: (_a = opts.details) === null || _a === void 0 ? void 0 : _a.oauth2, provider: (_b = opts.details) === null || _b === void 0 ? void 0 : _b.provider, providerType: (_c = opts.details) === null || _c === void 0 ? void 0 : _c.providerType });
55
52
  }
56
53
  //# sourceMappingURL=users.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"users.js","sourceRoot":"","sources":["../../../../../tests/core/utilities/structures/users.ts"],"names":[],"mappings":";;;AAwEA,0BAqBC;AArFD,+BAAmC;AACnC,qCAA+B;AAC/B,2CAAuC;AACvC,wBAA0B;AAEnB,MAAM,QAAQ,GAAG,GAAG,EAAE;IAC3B,OAAO,GAAG,IAAA,aAAI,GAAE,cAAc,CAAA;AAChC,CAAC,CAAA;AAFY,QAAA,QAAQ,YAEpB;AAEM,MAAM,IAAI,GAAG,CAAC,SAAyC,EAAQ,EAAE;IACtE,MAAM,MAAM,GAAG,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,GAAG,CAAA;IAC7B,uBACE,GAAG,EAAE,MAAM,EACX,MAAM,EACN,KAAK,EAAE,IAAA,gBAAQ,GAAE,EACjB,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAC5B,SAAS,EAAE,qBAAS,CAAC,KAAK,EAAE,EAC5B,QAAQ,EAAE,qBAAS,CAAC,IAAI,EAAE,EAC1B,UAAU,EAAE,oBAAoB,EAChC,QAAQ,EAAE,SAAM,CAAC,EAAE,EAAE,IAClB,SAAS,EACb;AACH,CAAC,CAAA;AAdY,QAAA,IAAI,QAchB;AAEM,MAAM,SAAS,GAAG,CAAC,SAAe,EAAa,EAAE;IACtD,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,KAAK,EAAE;YACL,MAAM,EAAE,IAAI;SACb,EACD,OAAO,EAAE;YACP,MAAM,EAAE,IAAI;SACb,IACF;AACH,CAAC,CAAA;AAVY,QAAA,SAAS,aAUrB;AAEM,MAAM,aAAa,GAAG,CAAC,SAAe,EAAiB,EAAE;IAC9D,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,KAAK,EAAE;YACL,MAAM,EAAE,IAAI;SACb,IACF;AACH,CAAC,CAAA;AAPY,QAAA,aAAa,iBAOzB;AAEM,MAAM,WAAW,GAAG,CAAC,SAAyB,EAAe,EAAE;IACpE,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,OAAO,EAAE;YACP,MAAM,EAAE,IAAI;SACb,IACF;AACH,CAAC,CAAA;AAPY,QAAA,WAAW,eAOvB;AAEM,MAAM,cAAc,GAAG,CAAC,KAAa,EAAE,SAAe,EAAe,EAAE;IAC5E,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,OAAO,EAAE;YACP,IAAI,EAAE,CAAC,KAAK,CAAC;SACd,IACF;AACH,CAAC,CAAA;AAPY,QAAA,cAAc,kBAO1B;AAED,SAAgB,OAAO,CACrB,OAAiD,EAAE;;IAEnD,MAAM,IAAI,GAAG,IAAA,YAAI,EAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,IAAI,CAAC,QAAQ,CAAA;IAEpB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,IAAA,iBAAW,EAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAED,uCACK,IAAI,KACP,kBAAkB,EAAE,KAAK,EACzB,MAAM,EAAE,MAAA,IAAI,CAAC,OAAO,0CAAE,MAAM,EAC5B,QAAQ,EAAE,MAAA,IAAI,CAAC,OAAO,0CAAE,QAAS,EACjC,YAAY,EAAE,MAAA,IAAI,CAAC,OAAO,0CAAE,YAAa,EACzC,iBAAiB,EAAE;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,UAAU;SACzB,IACF;AACH,CAAC"}
1
+ {"version":3,"file":"users.js","sourceRoot":"","sources":["../../../../../tests/core/utilities/structures/users.ts"],"names":[],"mappings":";;;AAuEA,0BAiBC;AAhFD,+BAAmC;AACnC,qCAA+B;AAC/B,2CAAuC;AACvC,wBAA0B;AAEnB,MAAM,QAAQ,GAAG,GAAG,EAAE;IAC3B,OAAO,GAAG,IAAA,aAAI,GAAE,cAAc,CAAA;AAChC,CAAC,CAAA;AAFY,QAAA,QAAQ,YAEpB;AAEM,MAAM,IAAI,GAAG,CAAC,SAAyC,EAAQ,EAAE;IACtE,MAAM,MAAM,GAAG,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,GAAG,CAAA;IAC7B,uBACE,GAAG,EAAE,MAAM,EACX,MAAM,EACN,KAAK,EAAE,IAAA,gBAAQ,GAAE,EACjB,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAC5B,SAAS,EAAE,qBAAS,CAAC,KAAK,EAAE,EAC5B,QAAQ,EAAE,qBAAS,CAAC,IAAI,EAAE,EAC1B,QAAQ,EAAE,SAAM,CAAC,EAAE,EAAE,IAClB,SAAS,EACb;AACH,CAAC,CAAA;AAbY,QAAA,IAAI,QAahB;AAEM,MAAM,SAAS,GAAG,CAAC,SAAe,EAAa,EAAE;IACtD,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,KAAK,EAAE;YACL,MAAM,EAAE,IAAI;SACb,EACD,OAAO,EAAE;YACP,MAAM,EAAE,IAAI;SACb,IACF;AACH,CAAC,CAAA;AAVY,QAAA,SAAS,aAUrB;AAEM,MAAM,aAAa,GAAG,CAAC,SAAe,EAAiB,EAAE;IAC9D,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,KAAK,EAAE;YACL,MAAM,EAAE,IAAI;SACb,IACF;AACH,CAAC,CAAA;AAPY,QAAA,aAAa,iBAOzB;AAEM,MAAM,WAAW,GAAG,CAAC,SAAyB,EAAe,EAAE;IACpE,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,OAAO,EAAE;YACP,MAAM,EAAE,IAAI;SACb,IACF;AACH,CAAC,CAAA;AAPY,QAAA,WAAW,eAOvB;AAEM,MAAM,cAAc,GAAG,CAAC,KAAa,EAAE,SAAe,EAAe,EAAE;IAC5E,uCACK,IAAA,YAAI,EAAC,SAAS,CAAC,KAClB,OAAO,EAAE;YACP,IAAI,EAAE,CAAC,KAAK,CAAC;SACd,IACF;AACH,CAAC,CAAA;AAPY,QAAA,cAAc,kBAO1B;AAED,SAAgB,OAAO,CACrB,OAAiD,EAAE;;IAEnD,MAAM,IAAI,GAAG,IAAA,YAAI,EAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,IAAI,CAAC,QAAQ,CAAA;IAEpB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,IAAA,iBAAW,EAAC,IAAI,CAAC,CAAA;IAClC,CAAC;IAED,uCACK,IAAI,KACP,kBAAkB,EAAE,KAAK,EACzB,MAAM,EAAE,MAAA,IAAI,CAAC,OAAO,0CAAE,MAAM,EAC5B,QAAQ,EAAE,MAAA,IAAI,CAAC,OAAO,0CAAE,QAAS,EACjC,YAAY,EAAE,MAAA,IAAI,CAAC,OAAO,0CAAE,YAAa,IAC1C;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@budibase/backend-core",
3
- "version": "2.32.11",
3
+ "version": "2.32.13",
4
4
  "description": "Budibase backend core libraries used in server and worker",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -23,8 +23,8 @@
23
23
  "dependencies": {
24
24
  "@budibase/nano": "10.1.5",
25
25
  "@budibase/pouchdb-replication-stream": "1.2.11",
26
- "@budibase/shared-core": "2.32.11",
27
- "@budibase/types": "2.32.11",
26
+ "@budibase/shared-core": "2.32.13",
27
+ "@budibase/types": "2.32.13",
28
28
  "aws-cloudfront-sign": "3.0.2",
29
29
  "aws-sdk": "2.1030.0",
30
30
  "bcrypt": "5.1.0",
@@ -95,5 +95,5 @@
95
95
  }
96
96
  }
97
97
  },
98
- "gitHead": "1a1f2ff0948a76863847ce30b2255f43978d6c02"
98
+ "gitHead": "0478570f8b4ec37b7593a8a1db9715e5e9d99839"
99
99
  }
@@ -371,11 +371,21 @@ export class DatabaseImpl implements Database {
371
371
  return this.performCall(() => {
372
372
  return async () => {
373
373
  const response = await directCouchUrlCall(args)
374
- const json = await response.json()
374
+ const text = await response.text()
375
375
  if (response.status > 300) {
376
+ let json
377
+ try {
378
+ json = JSON.parse(text)
379
+ } catch (err) {
380
+ console.error(`SQS error: ${text}`)
381
+ throw new CouchDBError(
382
+ "error while running SQS query, please try again later",
383
+ { name: "sqs_error", status: response.status }
384
+ )
385
+ }
376
386
  throw json
377
387
  }
378
- return json as T
388
+ return JSON.parse(text) as T
379
389
  }
380
390
  })
381
391
  }
@@ -0,0 +1,300 @@
1
+ import env from "../environment"
2
+ import * as context from "../context"
3
+ import { PostHog, PostHogOptions } from "posthog-node"
4
+ import { FeatureFlag, IdentityType, UserCtx } from "@budibase/types"
5
+ import tracer from "dd-trace"
6
+ import { Duration } from "../utils"
7
+
8
+ let posthog: PostHog | undefined
9
+ export function init(opts?: PostHogOptions) {
10
+ if (
11
+ env.POSTHOG_TOKEN &&
12
+ env.POSTHOG_API_HOST &&
13
+ !env.SELF_HOSTED &&
14
+ env.POSTHOG_FEATURE_FLAGS_ENABLED
15
+ ) {
16
+ console.log("initializing posthog client...")
17
+ posthog = new PostHog(env.POSTHOG_TOKEN, {
18
+ host: env.POSTHOG_API_HOST,
19
+ personalApiKey: env.POSTHOG_PERSONAL_TOKEN,
20
+ featureFlagsPollingInterval: Duration.fromMinutes(3).toMs(),
21
+ ...opts,
22
+ })
23
+ } else {
24
+ console.log("posthog disabled")
25
+ }
26
+ }
27
+
28
+ export function shutdown() {
29
+ posthog?.shutdown()
30
+ }
31
+
32
+ export abstract class Flag<T> {
33
+ static boolean(defaultValue: boolean): Flag<boolean> {
34
+ return new BooleanFlag(defaultValue)
35
+ }
36
+
37
+ static string(defaultValue: string): Flag<string> {
38
+ return new StringFlag(defaultValue)
39
+ }
40
+
41
+ static number(defaultValue: number): Flag<number> {
42
+ return new NumberFlag(defaultValue)
43
+ }
44
+
45
+ protected constructor(public defaultValue: T) {}
46
+
47
+ abstract parse(value: any): T
48
+ }
49
+
50
+ type UnwrapFlag<F> = F extends Flag<infer U> ? U : never
51
+
52
+ export type FlagValues<T> = {
53
+ [K in keyof T]: UnwrapFlag<T[K]>
54
+ }
55
+
56
+ type KeysOfType<T, U> = {
57
+ [K in keyof T]: T[K] extends Flag<U> ? K : never
58
+ }[keyof T]
59
+
60
+ class BooleanFlag extends Flag<boolean> {
61
+ parse(value: any) {
62
+ if (typeof value === "string") {
63
+ return ["true", "t", "1"].includes(value.toLowerCase())
64
+ }
65
+
66
+ if (typeof value === "boolean") {
67
+ return value
68
+ }
69
+
70
+ throw new Error(`could not parse value "${value}" as boolean`)
71
+ }
72
+ }
73
+
74
+ class StringFlag extends Flag<string> {
75
+ parse(value: any) {
76
+ if (typeof value === "string") {
77
+ return value
78
+ }
79
+ throw new Error(`could not parse value "${value}" as string`)
80
+ }
81
+ }
82
+
83
+ class NumberFlag extends Flag<number> {
84
+ parse(value: any) {
85
+ if (typeof value === "number") {
86
+ return value
87
+ }
88
+
89
+ if (typeof value === "string") {
90
+ const parsed = parseFloat(value)
91
+ if (!isNaN(parsed)) {
92
+ return parsed
93
+ }
94
+ }
95
+
96
+ throw new Error(`could not parse value "${value}" as number`)
97
+ }
98
+ }
99
+
100
+ export interface EnvFlagEntry {
101
+ tenantId: string
102
+ key: string
103
+ value: boolean
104
+ }
105
+
106
+ export function parseEnvFlags(flags: string): EnvFlagEntry[] {
107
+ const split = flags.split(",").map(x => x.split(":"))
108
+ const result: EnvFlagEntry[] = []
109
+ for (const [tenantId, ...features] of split) {
110
+ for (let feature of features) {
111
+ let value = true
112
+ if (feature.startsWith("!")) {
113
+ feature = feature.slice(1)
114
+ value = false
115
+ }
116
+ result.push({ tenantId, key: feature, value })
117
+ }
118
+ }
119
+ return result
120
+ }
121
+
122
+ export class FlagSet<V extends Flag<any>, T extends { [key: string]: V }> {
123
+ // This is used to safely cache flags sets in the current request context.
124
+ // Because multiple sets could theoretically exist, we don't want the cache of
125
+ // one to leak into another.
126
+ private readonly setId: string
127
+
128
+ constructor(private readonly flagSchema: T) {
129
+ this.setId = crypto.randomUUID()
130
+ }
131
+
132
+ defaults(): FlagValues<T> {
133
+ return Object.keys(this.flagSchema).reduce((acc, key) => {
134
+ const typedKey = key as keyof T
135
+ acc[typedKey] = this.flagSchema[key].defaultValue
136
+ return acc
137
+ }, {} as FlagValues<T>)
138
+ }
139
+
140
+ isFlagName(name: string | number | symbol): name is keyof T {
141
+ return this.flagSchema[name as keyof T] !== undefined
142
+ }
143
+
144
+ async get<K extends keyof T>(
145
+ key: K,
146
+ ctx?: UserCtx
147
+ ): Promise<FlagValues<T>[K]> {
148
+ const flags = await this.fetch(ctx)
149
+ return flags[key]
150
+ }
151
+
152
+ async isEnabled<K extends KeysOfType<T, boolean>>(
153
+ key: K,
154
+ ctx?: UserCtx
155
+ ): Promise<boolean> {
156
+ const flags = await this.fetch(ctx)
157
+ return flags[key]
158
+ }
159
+
160
+ async fetch(ctx?: UserCtx): Promise<FlagValues<T>> {
161
+ return await tracer.trace("features.fetch", async span => {
162
+ const cachedFlags = context.getFeatureFlags<FlagValues<T>>(this.setId)
163
+ if (cachedFlags) {
164
+ span?.addTags({ fromCache: true })
165
+ return cachedFlags
166
+ }
167
+
168
+ const tags: Record<string, any> = {}
169
+ const flagValues = this.defaults()
170
+ const currentTenantId = context.getTenantId()
171
+ const specificallySetFalse = new Set<string>()
172
+
173
+ for (const { tenantId, key, value } of parseEnvFlags(
174
+ env.TENANT_FEATURE_FLAGS || ""
175
+ )) {
176
+ if (!tenantId || (tenantId !== "*" && tenantId !== currentTenantId)) {
177
+ continue
178
+ }
179
+
180
+ tags[`readFromEnvironmentVars`] = true
181
+
182
+ if (value === false) {
183
+ specificallySetFalse.add(key)
184
+ }
185
+
186
+ // ignore unknown flags
187
+ if (!this.isFlagName(key)) {
188
+ continue
189
+ }
190
+
191
+ if (typeof flagValues[key] !== "boolean") {
192
+ throw new Error(`Feature: ${key} is not a boolean`)
193
+ }
194
+
195
+ // @ts-expect-error - TS does not like you writing into a generic type,
196
+ // but we know that it's okay in this case because it's just an object.
197
+ flagValues[key as keyof FlagValues] = value
198
+ tags[`flags.${key}.source`] = "environment"
199
+ }
200
+
201
+ const license = ctx?.user?.license
202
+ if (license) {
203
+ tags[`readFromLicense`] = true
204
+
205
+ for (const feature of license.features) {
206
+ if (!this.isFlagName(feature)) {
207
+ continue
208
+ }
209
+
210
+ if (
211
+ flagValues[feature] === true ||
212
+ specificallySetFalse.has(feature)
213
+ ) {
214
+ // If the flag is already set to through environment variables, we
215
+ // don't want to override it back to false here.
216
+ continue
217
+ }
218
+
219
+ // @ts-expect-error - TS does not like you writing into a generic type,
220
+ // but we know that it's okay in this case because it's just an object.
221
+ flagValues[feature] = true
222
+ tags[`flags.${feature}.source`] = "license"
223
+ }
224
+ }
225
+
226
+ const identity = context.getIdentity()
227
+ tags[`identity.type`] = identity?.type
228
+ tags[`identity.tenantId`] = identity?.tenantId
229
+ tags[`identity._id`] = identity?._id
230
+
231
+ if (posthog && identity?.type === IdentityType.USER) {
232
+ tags[`readFromPostHog`] = true
233
+
234
+ const personProperties: Record<string, string> = {}
235
+ if (identity.tenantId) {
236
+ personProperties.tenantId = identity.tenantId
237
+ }
238
+
239
+ const posthogFlags = await posthog.getAllFlagsAndPayloads(
240
+ identity._id,
241
+ {
242
+ personProperties,
243
+ }
244
+ )
245
+
246
+ for (const [name, value] of Object.entries(posthogFlags.featureFlags)) {
247
+ if (!this.isFlagName(name)) {
248
+ // We don't want an unexpected PostHog flag to break the app, so we
249
+ // just log it and continue.
250
+ console.warn(`Unexpected posthog flag "${name}": ${value}`)
251
+ continue
252
+ }
253
+
254
+ if (flagValues[name] === true || specificallySetFalse.has(name)) {
255
+ // If the flag is already set to through environment variables, we
256
+ // don't want to override it back to false here.
257
+ continue
258
+ }
259
+
260
+ const payload = posthogFlags.featureFlagPayloads?.[name]
261
+ const flag = this.flagSchema[name]
262
+ try {
263
+ // @ts-expect-error - TS does not like you writing into a generic
264
+ // type, but we know that it's okay in this case because it's just
265
+ // an object.
266
+ flagValues[name] = flag.parse(payload || value)
267
+ tags[`flags.${name}.source`] = "posthog"
268
+ } catch (err) {
269
+ // We don't want an invalid PostHog flag to break the app, so we just
270
+ // log it and continue.
271
+ console.warn(`Error parsing posthog flag "${name}": ${value}`, err)
272
+ }
273
+ }
274
+ }
275
+
276
+ context.setFeatureFlags(this.setId, flagValues)
277
+ for (const [key, value] of Object.entries(flagValues)) {
278
+ tags[`flags.${key}.value`] = value
279
+ }
280
+ span?.addTags(tags)
281
+
282
+ return flagValues
283
+ })
284
+ }
285
+ }
286
+
287
+ // This is the primary source of truth for feature flags. If you want to add a
288
+ // new flag, add it here and use the `fetch` and `get` functions to access it.
289
+ // All of the machinery in this file is to make sure that flags have their
290
+ // default values set correctly and their types flow through the system.
291
+ export const flags = new FlagSet({
292
+ DEFAULT_VALUES: Flag.boolean(env.isDev()),
293
+ AUTOMATION_BRANCHING: Flag.boolean(env.isDev()),
294
+ SQS: Flag.boolean(env.isDev()),
295
+ [FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(env.isDev()),
296
+ [FeatureFlag.ENRICHED_RELATIONSHIPS]: Flag.boolean(env.isDev()),
297
+ })
298
+
299
+ type UnwrapPromise<T> = T extends Promise<infer U> ? U : T
300
+ export type FeatureFlags = UnwrapPromise<ReturnType<typeof flags.fetch>>