@budibase/backend-core 2.9.40-alpha.6 → 2.10.1

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 (252) hide show
  1. package/dist/index.js +5 -4
  2. package/dist/index.js.map +2 -2
  3. package/dist/index.js.meta.json +1 -1
  4. package/dist/package.json +6 -6
  5. package/dist/src/cache/appMetadata.js +1 -1
  6. package/dist/src/cache/appMetadata.js.map +1 -1
  7. package/dist/src/constants/misc.d.ts +0 -2
  8. package/dist/src/constants/misc.js +0 -2
  9. package/dist/src/constants/misc.js.map +1 -1
  10. package/dist/src/environment.js +5 -4
  11. package/dist/src/environment.js.map +1 -1
  12. package/dist/src/logging/system.d.ts +1 -1
  13. package/dist/src/timers/timers.d.ts +1 -1
  14. package/package.json +6 -6
  15. package/src/accounts/accounts.ts +82 -0
  16. package/src/accounts/api.ts +59 -0
  17. package/src/accounts/index.ts +1 -0
  18. package/src/auth/auth.ts +208 -0
  19. package/src/auth/index.ts +1 -0
  20. package/src/auth/tests/auth.spec.ts +14 -0
  21. package/src/blacklist/blacklist.ts +54 -0
  22. package/src/blacklist/index.ts +1 -0
  23. package/src/blacklist/tests/blacklist.spec.ts +46 -0
  24. package/src/cache/appMetadata.ts +88 -0
  25. package/src/cache/base/index.ts +92 -0
  26. package/src/cache/generic.ts +30 -0
  27. package/src/cache/index.ts +5 -0
  28. package/src/cache/tests/writethrough.spec.ts +138 -0
  29. package/src/cache/user.ts +83 -0
  30. package/src/cache/writethrough.ts +133 -0
  31. package/src/configs/configs.ts +257 -0
  32. package/src/configs/index.ts +1 -0
  33. package/src/configs/tests/configs.spec.ts +184 -0
  34. package/src/constants/db.ts +63 -0
  35. package/src/constants/index.ts +2 -0
  36. package/src/constants/misc.ts +50 -0
  37. package/src/context/Context.ts +14 -0
  38. package/src/context/identity.ts +58 -0
  39. package/src/context/index.ts +3 -0
  40. package/src/context/mainContext.ts +310 -0
  41. package/src/context/tests/index.spec.ts +147 -0
  42. package/src/context/types.ts +11 -0
  43. package/src/db/Replication.ts +84 -0
  44. package/src/db/constants.ts +10 -0
  45. package/src/db/couch/DatabaseImpl.ts +238 -0
  46. package/src/db/couch/connections.ts +77 -0
  47. package/src/db/couch/index.ts +5 -0
  48. package/src/db/couch/pouchDB.ts +97 -0
  49. package/src/db/couch/pouchDump.ts +0 -0
  50. package/src/db/couch/utils.ts +50 -0
  51. package/src/db/db.ts +43 -0
  52. package/src/db/errors.ts +14 -0
  53. package/src/db/index.ts +12 -0
  54. package/src/db/lucene.ts +750 -0
  55. package/src/db/searchIndexes/index.ts +1 -0
  56. package/src/db/searchIndexes/searchIndexes.ts +62 -0
  57. package/src/db/tests/index.spec.js +25 -0
  58. package/src/db/tests/lucene.spec.ts +368 -0
  59. package/src/db/tests/pouch.spec.js +62 -0
  60. package/src/db/tests/utils.spec.ts +63 -0
  61. package/src/db/utils.ts +207 -0
  62. package/src/db/views.ts +241 -0
  63. package/src/docIds/conversions.ts +59 -0
  64. package/src/docIds/ids.ts +113 -0
  65. package/src/docIds/index.ts +2 -0
  66. package/src/docIds/newid.ts +5 -0
  67. package/src/docIds/params.ts +174 -0
  68. package/src/docUpdates/index.ts +29 -0
  69. package/src/environment.ts +201 -0
  70. package/src/errors/errors.ts +119 -0
  71. package/src/errors/index.ts +1 -0
  72. package/src/events/analytics.ts +6 -0
  73. package/src/events/asyncEvents/index.ts +2 -0
  74. package/src/events/asyncEvents/publisher.ts +12 -0
  75. package/src/events/asyncEvents/queue.ts +22 -0
  76. package/src/events/backfill.ts +183 -0
  77. package/src/events/documentId.ts +56 -0
  78. package/src/events/events.ts +40 -0
  79. package/src/events/identification.ts +310 -0
  80. package/src/events/index.ts +14 -0
  81. package/src/events/processors/AnalyticsProcessor.ts +64 -0
  82. package/src/events/processors/AuditLogsProcessor.ts +93 -0
  83. package/src/events/processors/LoggingProcessor.ts +37 -0
  84. package/src/events/processors/Processors.ts +52 -0
  85. package/src/events/processors/async/DocumentUpdateProcessor.ts +43 -0
  86. package/src/events/processors/index.ts +19 -0
  87. package/src/events/processors/posthog/PosthogProcessor.ts +118 -0
  88. package/src/events/processors/posthog/index.ts +2 -0
  89. package/src/events/processors/posthog/rateLimiting.ts +106 -0
  90. package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +168 -0
  91. package/src/events/processors/types.ts +1 -0
  92. package/src/events/publishers/account.ts +35 -0
  93. package/src/events/publishers/app.ts +155 -0
  94. package/src/events/publishers/auditLog.ts +26 -0
  95. package/src/events/publishers/auth.ts +73 -0
  96. package/src/events/publishers/automation.ts +110 -0
  97. package/src/events/publishers/backfill.ts +74 -0
  98. package/src/events/publishers/backup.ts +42 -0
  99. package/src/events/publishers/datasource.ts +48 -0
  100. package/src/events/publishers/email.ts +17 -0
  101. package/src/events/publishers/environmentVariable.ts +38 -0
  102. package/src/events/publishers/group.ts +99 -0
  103. package/src/events/publishers/index.ts +24 -0
  104. package/src/events/publishers/installation.ts +38 -0
  105. package/src/events/publishers/layout.ts +26 -0
  106. package/src/events/publishers/license.ts +84 -0
  107. package/src/events/publishers/org.ts +37 -0
  108. package/src/events/publishers/plugin.ts +47 -0
  109. package/src/events/publishers/query.ts +88 -0
  110. package/src/events/publishers/role.ts +62 -0
  111. package/src/events/publishers/rows.ts +29 -0
  112. package/src/events/publishers/screen.ts +36 -0
  113. package/src/events/publishers/serve.ts +43 -0
  114. package/src/events/publishers/table.ts +70 -0
  115. package/src/events/publishers/user.ts +202 -0
  116. package/src/events/publishers/view.ts +107 -0
  117. package/src/features/index.ts +78 -0
  118. package/src/features/installation.ts +17 -0
  119. package/src/features/tests/featureFlags.spec.ts +85 -0
  120. package/src/helpers.ts +9 -0
  121. package/src/index.ts +54 -0
  122. package/src/installation.ts +107 -0
  123. package/src/logging/alerts.ts +26 -0
  124. package/src/logging/correlation/correlation.ts +13 -0
  125. package/src/logging/correlation/index.ts +1 -0
  126. package/src/logging/correlation/middleware.ts +17 -0
  127. package/src/logging/index.ts +4 -0
  128. package/src/logging/pino/logger.ts +232 -0
  129. package/src/logging/pino/middleware.ts +45 -0
  130. package/src/logging/system.ts +81 -0
  131. package/src/logging/tests/system.spec.ts +61 -0
  132. package/src/middleware/adminOnly.ts +9 -0
  133. package/src/middleware/auditLog.ts +6 -0
  134. package/src/middleware/authenticated.ts +193 -0
  135. package/src/middleware/builderOnly.ts +21 -0
  136. package/src/middleware/builderOrAdmin.ts +21 -0
  137. package/src/middleware/csrf.ts +81 -0
  138. package/src/middleware/errorHandling.ts +29 -0
  139. package/src/middleware/index.ts +21 -0
  140. package/src/middleware/internalApi.ts +23 -0
  141. package/src/middleware/joi-validator.ts +45 -0
  142. package/src/middleware/matchers.ts +47 -0
  143. package/src/middleware/passport/datasource/google.ts +95 -0
  144. package/src/middleware/passport/local.ts +54 -0
  145. package/src/middleware/passport/sso/google.ts +77 -0
  146. package/src/middleware/passport/sso/oidc.ts +154 -0
  147. package/src/middleware/passport/sso/sso.ts +165 -0
  148. package/src/middleware/passport/sso/tests/google.spec.ts +67 -0
  149. package/src/middleware/passport/sso/tests/oidc.spec.ts +152 -0
  150. package/src/middleware/passport/sso/tests/sso.spec.ts +197 -0
  151. package/src/middleware/passport/utils.ts +38 -0
  152. package/src/middleware/querystringToBody.ts +28 -0
  153. package/src/middleware/tenancy.ts +36 -0
  154. package/src/middleware/tests/builder.spec.ts +180 -0
  155. package/src/middleware/tests/matchers.spec.ts +134 -0
  156. package/src/migrations/definitions.ts +40 -0
  157. package/src/migrations/index.ts +2 -0
  158. package/src/migrations/migrations.ts +191 -0
  159. package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +11 -0
  160. package/src/migrations/tests/migrations.spec.ts +64 -0
  161. package/src/objectStore/buckets/app.ts +40 -0
  162. package/src/objectStore/buckets/global.ts +29 -0
  163. package/src/objectStore/buckets/index.ts +3 -0
  164. package/src/objectStore/buckets/plugins.ts +71 -0
  165. package/src/objectStore/buckets/tests/app.spec.ts +171 -0
  166. package/src/objectStore/buckets/tests/global.spec.ts +74 -0
  167. package/src/objectStore/buckets/tests/plugins.spec.ts +111 -0
  168. package/src/objectStore/cloudfront.ts +41 -0
  169. package/src/objectStore/index.ts +3 -0
  170. package/src/objectStore/objectStore.ts +440 -0
  171. package/src/objectStore/utils.ts +27 -0
  172. package/src/platform/index.ts +3 -0
  173. package/src/platform/platformDb.ts +6 -0
  174. package/src/platform/tenants.ts +101 -0
  175. package/src/platform/tests/tenants.spec.ts +26 -0
  176. package/src/platform/users.ts +90 -0
  177. package/src/plugin/index.ts +1 -0
  178. package/src/plugin/tests/validation.spec.ts +83 -0
  179. package/src/plugin/utils.ts +156 -0
  180. package/src/queue/constants.ts +6 -0
  181. package/src/queue/inMemoryQueue.ts +141 -0
  182. package/src/queue/index.ts +2 -0
  183. package/src/queue/listeners.ts +195 -0
  184. package/src/queue/queue.ts +54 -0
  185. package/src/redis/index.ts +6 -0
  186. package/src/redis/init.ts +86 -0
  187. package/src/redis/redis.ts +308 -0
  188. package/src/redis/redlockImpl.ts +139 -0
  189. package/src/redis/utils.ts +117 -0
  190. package/src/security/encryption.ts +179 -0
  191. package/src/security/permissions.ts +158 -0
  192. package/src/security/roles.ts +389 -0
  193. package/src/security/sessions.ts +120 -0
  194. package/src/security/tests/encryption.spec.ts +31 -0
  195. package/src/security/tests/permissions.spec.ts +145 -0
  196. package/src/security/tests/sessions.spec.ts +12 -0
  197. package/src/tenancy/db.ts +6 -0
  198. package/src/tenancy/index.ts +2 -0
  199. package/src/tenancy/tenancy.ts +140 -0
  200. package/src/tenancy/tests/tenancy.spec.ts +184 -0
  201. package/src/timers/index.ts +1 -0
  202. package/src/timers/timers.ts +22 -0
  203. package/src/users/db.ts +484 -0
  204. package/src/users/events.ts +176 -0
  205. package/src/users/index.ts +4 -0
  206. package/src/users/lookup.ts +102 -0
  207. package/src/users/users.ts +276 -0
  208. package/src/users/utils.ts +55 -0
  209. package/src/utils/hashing.ts +14 -0
  210. package/src/utils/index.ts +3 -0
  211. package/src/utils/stringUtils.ts +8 -0
  212. package/src/utils/tests/utils.spec.ts +191 -0
  213. package/src/utils/utils.ts +239 -0
  214. package/tests/core/logging.ts +34 -0
  215. package/tests/core/utilities/index.ts +6 -0
  216. package/tests/core/utilities/jestUtils.ts +30 -0
  217. package/tests/core/utilities/mocks/alerts.ts +3 -0
  218. package/tests/core/utilities/mocks/date.ts +2 -0
  219. package/tests/core/utilities/mocks/events.ts +131 -0
  220. package/tests/core/utilities/mocks/fetch.ts +17 -0
  221. package/tests/core/utilities/mocks/index.ts +10 -0
  222. package/tests/core/utilities/mocks/licenses.ts +115 -0
  223. package/tests/core/utilities/mocks/posthog.ts +7 -0
  224. package/tests/core/utilities/structures/Chance.ts +20 -0
  225. package/tests/core/utilities/structures/accounts.ts +115 -0
  226. package/tests/core/utilities/structures/apps.ts +21 -0
  227. package/tests/core/utilities/structures/common.ts +7 -0
  228. package/tests/core/utilities/structures/db.ts +12 -0
  229. package/tests/core/utilities/structures/documents/index.ts +1 -0
  230. package/tests/core/utilities/structures/documents/platform/index.ts +1 -0
  231. package/tests/core/utilities/structures/documents/platform/installation.ts +12 -0
  232. package/tests/core/utilities/structures/generator.ts +2 -0
  233. package/tests/core/utilities/structures/index.ts +15 -0
  234. package/tests/core/utilities/structures/koa.ts +16 -0
  235. package/tests/core/utilities/structures/licenses.ts +167 -0
  236. package/tests/core/utilities/structures/plugins.ts +19 -0
  237. package/tests/core/utilities/structures/quotas.ts +67 -0
  238. package/tests/core/utilities/structures/scim.ts +80 -0
  239. package/tests/core/utilities/structures/shared.ts +19 -0
  240. package/tests/core/utilities/structures/sso.ts +119 -0
  241. package/tests/core/utilities/structures/tenants.ts +5 -0
  242. package/tests/core/utilities/structures/userGroups.ts +10 -0
  243. package/tests/core/utilities/structures/users.ts +73 -0
  244. package/tests/core/utilities/testContainerUtils.ts +85 -0
  245. package/tests/core/utilities/utils/index.ts +1 -0
  246. package/tests/core/utilities/utils/time.ts +3 -0
  247. package/tests/extra/DBTestConfiguration.ts +36 -0
  248. package/tests/extra/index.ts +2 -0
  249. package/tests/extra/testEnv.ts +95 -0
  250. package/tests/index.ts +1 -0
  251. package/tests/jestEnv.ts +6 -0
  252. package/tests/jestSetup.ts +28 -0
@@ -0,0 +1,140 @@
1
+ import {
2
+ DEFAULT_TENANT_ID,
3
+ getTenantId,
4
+ getTenantIDFromAppID,
5
+ isMultiTenant,
6
+ getPlatformURL,
7
+ } from "../context"
8
+ import {
9
+ BBContext,
10
+ TenantResolutionStrategy,
11
+ GetTenantIdOptions,
12
+ } from "@budibase/types"
13
+ import { Header } from "../constants"
14
+
15
+ export function addTenantToUrl(url: string) {
16
+ const tenantId = getTenantId()
17
+
18
+ if (isMultiTenant()) {
19
+ const char = url.indexOf("?") === -1 ? "?" : "&"
20
+ url += `${char}tenantId=${tenantId}`
21
+ }
22
+
23
+ return url
24
+ }
25
+
26
+ export const isUserInAppTenant = (appId: string, user?: any) => {
27
+ let userTenantId
28
+ if (user) {
29
+ userTenantId = user.tenantId || DEFAULT_TENANT_ID
30
+ } else {
31
+ userTenantId = getTenantId()
32
+ }
33
+ const tenantId = getTenantIDFromAppID(appId) || DEFAULT_TENANT_ID
34
+ return tenantId === userTenantId
35
+ }
36
+
37
+ const ALL_STRATEGIES = Object.values(TenantResolutionStrategy)
38
+
39
+ export const getTenantIDFromCtx = (
40
+ ctx: BBContext,
41
+ opts: GetTenantIdOptions
42
+ ): string | null => {
43
+ // exit early if not multi-tenant
44
+ if (!isMultiTenant()) {
45
+ return DEFAULT_TENANT_ID
46
+ }
47
+
48
+ // opt defaults
49
+ if (opts.allowNoTenant === undefined) {
50
+ opts.allowNoTenant = false
51
+ }
52
+ if (!opts.includeStrategies) {
53
+ opts.includeStrategies = ALL_STRATEGIES
54
+ }
55
+ if (!opts.excludeStrategies) {
56
+ opts.excludeStrategies = []
57
+ }
58
+
59
+ const isAllowed = (strategy: TenantResolutionStrategy) => {
60
+ // excluded takes precedence
61
+ if (opts.excludeStrategies?.includes(strategy)) {
62
+ return false
63
+ }
64
+ if (opts.includeStrategies?.includes(strategy)) {
65
+ return true
66
+ }
67
+ }
68
+
69
+ // always use user first
70
+ if (isAllowed(TenantResolutionStrategy.USER)) {
71
+ const userTenantId = ctx.user?.tenantId
72
+ if (userTenantId) {
73
+ return userTenantId
74
+ }
75
+ }
76
+
77
+ // header
78
+ if (isAllowed(TenantResolutionStrategy.HEADER)) {
79
+ const headerTenantId = ctx.request.headers[Header.TENANT_ID]
80
+ if (headerTenantId) {
81
+ return headerTenantId as string
82
+ }
83
+ }
84
+
85
+ // query param
86
+ if (isAllowed(TenantResolutionStrategy.QUERY)) {
87
+ const queryTenantId = ctx.request.query.tenantId
88
+ if (queryTenantId) {
89
+ return queryTenantId as string
90
+ }
91
+ }
92
+
93
+ // subdomain
94
+ if (isAllowed(TenantResolutionStrategy.SUBDOMAIN)) {
95
+ // e.g. budibase.app or local.com:10000
96
+ const platformHost = new URL(getPlatformURL()).host.split(":")[0]
97
+ // e.g. tenant.budibase.app or tenant.local.com
98
+ const requestHost = ctx.host
99
+ // parse the tenant id from the difference
100
+ if (requestHost.includes(platformHost)) {
101
+ const tenantId = requestHost.substring(
102
+ 0,
103
+ requestHost.indexOf(`.${platformHost}`)
104
+ )
105
+ if (tenantId) {
106
+ return tenantId
107
+ }
108
+ }
109
+ }
110
+
111
+ // path
112
+ if (isAllowed(TenantResolutionStrategy.PATH)) {
113
+ // params - have to parse manually due to koa-router not run yet
114
+ const match = ctx.matched.find(
115
+ (m: any) => !!m.paramNames.find((p: any) => p.name === "tenantId")
116
+ )
117
+
118
+ // get the raw path url - without any query params
119
+ const ctxUrl = ctx.originalUrl
120
+ let url
121
+ if (ctxUrl.includes("?")) {
122
+ url = ctxUrl.split("?")[0]
123
+ } else {
124
+ url = ctxUrl
125
+ }
126
+
127
+ if (match) {
128
+ const params = match.params(url, match.captures(url), {})
129
+ if (params.tenantId) {
130
+ return params.tenantId
131
+ }
132
+ }
133
+ }
134
+
135
+ if (!opts.allowNoTenant) {
136
+ ctx.throw(403, "Tenant id not set")
137
+ }
138
+
139
+ return null
140
+ }
@@ -0,0 +1,184 @@
1
+ import { TenantResolutionStrategy } from "@budibase/types"
2
+ import { addTenantToUrl, isUserInAppTenant, getTenantIDFromCtx } from "../"
3
+ import { isMultiTenant, getTenantIDFromAppID } from "../../context"
4
+
5
+ jest.mock("../../context", () => ({
6
+ getTenantId: jest.fn(() => "budibase"),
7
+ isMultiTenant: jest.fn(() => true),
8
+ getTenantIDFromAppID: jest.fn(),
9
+ getPlatformURL: jest.fn(() => "https://app.com"),
10
+ DEFAULT_TENANT_ID: "default",
11
+ }))
12
+
13
+ const mockedIsMultiTenant = isMultiTenant as jest.MockedFunction<
14
+ typeof isMultiTenant
15
+ >
16
+ const mockedGetTenantIDFromAppID = getTenantIDFromAppID as jest.MockedFunction<
17
+ typeof getTenantIDFromAppID
18
+ >
19
+
20
+ describe("addTenantToUrl", () => {
21
+ it("should append tenantId parameter to the URL", () => {
22
+ const url = "https://budibase.com"
23
+ const expectedUrl = "https://budibase.com?tenantId=budibase"
24
+ expect(addTenantToUrl(url)).toEqual(expectedUrl)
25
+ })
26
+
27
+ it("should append tenantId parameter to the URL query string", () => {
28
+ const url = "https://budibase.com?var=test"
29
+ const expectedUrl = "https://budibase.com?var=test&tenantId=budibase"
30
+ expect(addTenantToUrl(url)).toEqual(expectedUrl)
31
+ })
32
+
33
+ it("should not append tenantId parameter to the URL if isMultiTenant is false", () => {
34
+ mockedIsMultiTenant.mockImplementation(() => false)
35
+
36
+ const url = "https://budibase.com"
37
+ const expectedUrl = "https://budibase.com"
38
+ expect(addTenantToUrl(url)).toEqual(expectedUrl)
39
+ })
40
+ })
41
+
42
+ describe("isUserInAppTenant", () => {
43
+ mockedGetTenantIDFromAppID.mockImplementation(() => "budibase")
44
+ const mockUser = { tenantId: "budibase" }
45
+
46
+ it("returns true if user tenant ID matches app tenant ID", () => {
47
+ const appId = "app-budibase"
48
+ const result = isUserInAppTenant(appId, mockUser)
49
+ expect(result).toBe(true)
50
+ })
51
+
52
+ it("uses default tenant ID if user is not provided", () => {
53
+ const appId = "app-budibase"
54
+ const result = isUserInAppTenant(appId)
55
+ expect(result).toBe(true)
56
+ })
57
+
58
+ it("uses default tenant ID if app tenant ID is not found", () => {
59
+ const appId = "not-budibase-app"
60
+ const result = isUserInAppTenant(appId, mockUser)
61
+ expect(result).toBe(true)
62
+ })
63
+
64
+ it("returns false if user tenant ID does not match app tenant ID", () => {
65
+ const appId = "app-budibase"
66
+ mockedGetTenantIDFromAppID.mockImplementation(() => "not-budibase")
67
+ const result = isUserInAppTenant(appId, mockUser)
68
+ expect(result).toBe(false)
69
+ })
70
+ })
71
+
72
+ let mockOpts: any = {}
73
+ function createCtx(opts: {
74
+ originalUrl?: string
75
+ headers?: Record<string, string>
76
+ qsTenantId?: string
77
+ userTenantId?: string
78
+ host?: string
79
+ path?: string
80
+ }) {
81
+ const createdCtx: any = {
82
+ originalUrl: opts.originalUrl || "budibase.com",
83
+ matched: [{ name: "name" }],
84
+ throw: jest.fn(),
85
+ request: { headers: {} },
86
+ }
87
+ if (opts.headers) {
88
+ createdCtx.request.headers = opts.headers
89
+ }
90
+ if (opts.qsTenantId) {
91
+ createdCtx.request.query = { tenantId: opts.qsTenantId }
92
+ }
93
+ if (opts.userTenantId) {
94
+ createdCtx.user = { tenantId: opts.userTenantId }
95
+ }
96
+ if (opts.host) {
97
+ createdCtx.host = opts.host
98
+ }
99
+ if (opts.path) {
100
+ createdCtx.matched = [
101
+ {
102
+ paramNames: [{ name: "tenantId" }],
103
+ params: () => ({ tenantId: opts.path }),
104
+ captures: jest.fn(),
105
+ },
106
+ ]
107
+ }
108
+
109
+ return createdCtx as any
110
+ }
111
+
112
+ describe("getTenantIDFromCtx", () => {
113
+ describe("when tenant can be found", () => {
114
+ it("returns the tenant ID from the user object", () => {
115
+ mockedIsMultiTenant.mockImplementation(() => true)
116
+ const ctx = createCtx({ userTenantId: "budibase" })
117
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toEqual("budibase")
118
+ })
119
+
120
+ it("returns the tenant ID from the header", () => {
121
+ mockedIsMultiTenant.mockImplementation(() => true)
122
+ const ctx = createCtx({ headers: { "x-budibase-tenant-id": "budibase" } })
123
+ mockOpts = { includeStrategies: [TenantResolutionStrategy.HEADER] }
124
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toEqual("budibase")
125
+ })
126
+
127
+ it("returns the tenant ID from the query param", () => {
128
+ mockedIsMultiTenant.mockImplementation(() => true)
129
+ mockOpts = { includeStrategies: [TenantResolutionStrategy.QUERY] }
130
+ const ctx = createCtx({ qsTenantId: "budibase" })
131
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toEqual("budibase")
132
+ })
133
+
134
+ it("returns the tenant ID from the subdomain", () => {
135
+ mockedIsMultiTenant.mockImplementation(() => true)
136
+ const ctx = createCtx({ host: "bb.app.com" })
137
+ mockOpts = { includeStrategies: [TenantResolutionStrategy.SUBDOMAIN] }
138
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toEqual("bb")
139
+ })
140
+
141
+ it("returns the tenant ID from the path", () => {
142
+ mockedIsMultiTenant.mockImplementation(() => true)
143
+ const ctx = createCtx({ path: "bb" })
144
+ mockOpts = { includeStrategies: [TenantResolutionStrategy.PATH] }
145
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toEqual("bb")
146
+ })
147
+ })
148
+
149
+ describe("when tenant cannot be found", () => {
150
+ it("throws a 403 error if allowNoTenant is false", () => {
151
+ const ctx = createCtx({})
152
+ mockOpts = {
153
+ allowNoTenant: false,
154
+ excludeStrategies: [
155
+ TenantResolutionStrategy.QUERY,
156
+ TenantResolutionStrategy.SUBDOMAIN,
157
+ TenantResolutionStrategy.PATH,
158
+ ],
159
+ }
160
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toBeNull()
161
+ expect(ctx.throw).toBeCalledTimes(1)
162
+ expect(ctx.throw).toBeCalledWith(403, "Tenant id not set")
163
+ })
164
+
165
+ it("returns null if allowNoTenant is true", () => {
166
+ const ctx = createCtx({})
167
+ mockOpts = {
168
+ allowNoTenant: true,
169
+ excludeStrategies: [
170
+ TenantResolutionStrategy.QUERY,
171
+ TenantResolutionStrategy.SUBDOMAIN,
172
+ TenantResolutionStrategy.PATH,
173
+ ],
174
+ }
175
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toBeNull()
176
+ })
177
+ })
178
+
179
+ it("returns the default tenant ID when isMultiTenant() returns false", () => {
180
+ mockedIsMultiTenant.mockImplementation(() => false)
181
+ const ctx = createCtx({})
182
+ expect(getTenantIDFromCtx(ctx, mockOpts)).toEqual("default")
183
+ })
184
+ })
@@ -0,0 +1 @@
1
+ export * from "./timers"
@@ -0,0 +1,22 @@
1
+ let intervals: NodeJS.Timeout[] = []
2
+
3
+ export function set(callback: () => any, period: number) {
4
+ const interval = setInterval(callback, period)
5
+ intervals.push(interval)
6
+ return interval
7
+ }
8
+
9
+ export function clear(interval: NodeJS.Timeout) {
10
+ const idx = intervals.indexOf(interval)
11
+ if (idx !== -1) {
12
+ intervals.splice(idx, 1)
13
+ }
14
+ clearInterval(interval)
15
+ }
16
+
17
+ export function cleanup() {
18
+ for (let interval of intervals) {
19
+ clearInterval(interval)
20
+ }
21
+ intervals = []
22
+ }