@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,239 @@
1
+ import { getAllApps } from "../db"
2
+ import { Header, MAX_VALID_DATE, DocumentType, SEPARATOR } from "../constants"
3
+ import env from "../environment"
4
+ import * as tenancy from "../tenancy"
5
+ import * as context from "../context"
6
+ import {
7
+ App,
8
+ AuditedEventFriendlyName,
9
+ Ctx,
10
+ Event,
11
+ TenantResolutionStrategy,
12
+ } from "@budibase/types"
13
+ import { SetOption } from "cookies"
14
+ const jwt = require("jsonwebtoken")
15
+
16
+ const APP_PREFIX = DocumentType.APP + SEPARATOR
17
+ const PROD_APP_PREFIX = "/app/"
18
+
19
+ const BUILDER_PREVIEW_PATH = "/app/preview"
20
+ const BUILDER_PREFIX = "/builder"
21
+ const BUILDER_APP_PREFIX = `${BUILDER_PREFIX}/app/`
22
+ const PUBLIC_API_PREFIX = "/api/public/v"
23
+
24
+ function confirmAppId(possibleAppId: string | undefined) {
25
+ return possibleAppId && possibleAppId.startsWith(APP_PREFIX)
26
+ ? possibleAppId
27
+ : undefined
28
+ }
29
+
30
+ export async function resolveAppUrl(ctx: Ctx) {
31
+ const appUrl = ctx.path.split("/")[2]
32
+ let possibleAppUrl = `/${appUrl.toLowerCase()}`
33
+
34
+ let tenantId: string | null = context.getTenantId()
35
+ if (env.MULTI_TENANCY) {
36
+ // always use the tenant id from the subdomain in multi tenancy
37
+ // this ensures the logged-in user tenant id doesn't overwrite
38
+ // e.g. in the case of viewing a public app while already logged-in to another tenant
39
+ tenantId = tenancy.getTenantIDFromCtx(ctx, {
40
+ includeStrategies: [TenantResolutionStrategy.SUBDOMAIN],
41
+ })
42
+ }
43
+
44
+ // search prod apps for a url that matches
45
+ const apps: App[] = await context.doInTenant(
46
+ tenantId,
47
+ () => getAllApps({ dev: false }) as Promise<App[]>
48
+ )
49
+ const app = apps.filter(
50
+ a => a.url && a.url.toLowerCase() === possibleAppUrl
51
+ )[0]
52
+
53
+ return app && app.appId ? app.appId : undefined
54
+ }
55
+
56
+ export function isServingApp(ctx: Ctx) {
57
+ // dev app
58
+ if (ctx.path.startsWith(`/${APP_PREFIX}`)) {
59
+ return true
60
+ }
61
+ // prod app
62
+ if (ctx.path.startsWith(PROD_APP_PREFIX)) {
63
+ return true
64
+ }
65
+ return false
66
+ }
67
+
68
+ export function isServingBuilder(ctx: Ctx): boolean {
69
+ return ctx.path.startsWith(BUILDER_APP_PREFIX)
70
+ }
71
+
72
+ export function isServingBuilderPreview(ctx: Ctx): boolean {
73
+ return ctx.path.startsWith(BUILDER_PREVIEW_PATH)
74
+ }
75
+
76
+ export function isPublicApiRequest(ctx: Ctx): boolean {
77
+ return ctx.path.startsWith(PUBLIC_API_PREFIX)
78
+ }
79
+
80
+ /**
81
+ * Given a request tries to find the appId, which can be located in various places
82
+ * @param {object} ctx The main request body to look through.
83
+ * @returns {string|undefined} If an appId was found it will be returned.
84
+ */
85
+ export async function getAppIdFromCtx(ctx: Ctx) {
86
+ // look in headers
87
+ const options = [ctx.request.headers[Header.APP_ID]]
88
+ let appId
89
+ for (let option of options) {
90
+ appId = confirmAppId(option as string)
91
+ if (appId) {
92
+ break
93
+ }
94
+ }
95
+
96
+ // look in body
97
+ if (!appId && ctx.request.body && ctx.request.body.appId) {
98
+ appId = confirmAppId(ctx.request.body.appId)
99
+ }
100
+
101
+ // look in the path
102
+ const pathId = parseAppIdFromUrl(ctx.path)
103
+ if (!appId && pathId) {
104
+ appId = confirmAppId(pathId)
105
+ }
106
+
107
+ // lookup using custom url - prod apps only
108
+ // filter out the builder preview path which collides with the prod app path
109
+ // to ensure we don't load all apps excessively
110
+ const isBuilderPreview = ctx.path.startsWith(BUILDER_PREVIEW_PATH)
111
+ const isViewingProdApp =
112
+ ctx.path.startsWith(PROD_APP_PREFIX) && !isBuilderPreview
113
+ if (!appId && isViewingProdApp) {
114
+ appId = confirmAppId(await resolveAppUrl(ctx))
115
+ }
116
+
117
+ // look in the referer - builder only
118
+ // make sure this is performed after prod app url resolution, in case the
119
+ // referer header is present from a builder redirect
120
+ const referer = ctx.request.headers.referer
121
+ if (!appId && referer?.includes(BUILDER_APP_PREFIX)) {
122
+ const refererId = parseAppIdFromUrl(ctx.request.headers.referer)
123
+ appId = confirmAppId(refererId)
124
+ }
125
+
126
+ return appId
127
+ }
128
+
129
+ function parseAppIdFromUrl(url?: string) {
130
+ if (!url) {
131
+ return
132
+ }
133
+ return url.split("/").find(subPath => subPath.startsWith(APP_PREFIX))
134
+ }
135
+
136
+ /**
137
+ * opens the contents of the specified encrypted JWT.
138
+ * @return {object} the contents of the token.
139
+ */
140
+ export function openJwt(token: string) {
141
+ if (!token) {
142
+ return token
143
+ }
144
+ try {
145
+ return jwt.verify(token, env.JWT_SECRET)
146
+ } catch (e) {
147
+ if (env.JWT_SECRET_FALLBACK) {
148
+ // fallback to enable rotation
149
+ return jwt.verify(token, env.JWT_SECRET_FALLBACK)
150
+ } else {
151
+ throw e
152
+ }
153
+ }
154
+ }
155
+
156
+ export function isValidInternalAPIKey(apiKey: string) {
157
+ if (env.INTERNAL_API_KEY && env.INTERNAL_API_KEY === apiKey) {
158
+ return true
159
+ }
160
+ // fallback to enable rotation
161
+ if (
162
+ env.INTERNAL_API_KEY_FALLBACK &&
163
+ env.INTERNAL_API_KEY_FALLBACK === apiKey
164
+ ) {
165
+ return true
166
+ }
167
+ return false
168
+ }
169
+
170
+ /**
171
+ * Get a cookie from context, and decrypt if necessary.
172
+ * @param {object} ctx The request which is to be manipulated.
173
+ * @param {string} name The name of the cookie to get.
174
+ */
175
+ export function getCookie(ctx: Ctx, name: string) {
176
+ const cookie = ctx.cookies.get(name)
177
+
178
+ if (!cookie) {
179
+ return cookie
180
+ }
181
+
182
+ return openJwt(cookie)
183
+ }
184
+
185
+ /**
186
+ * Store a cookie for the request - it will not expire.
187
+ * @param {object} ctx The request which is to be manipulated.
188
+ * @param {string} name The name of the cookie to set.
189
+ * @param {string|object} value The value of cookie which will be set.
190
+ * @param {object} opts options like whether to sign.
191
+ */
192
+ export function setCookie(
193
+ ctx: Ctx,
194
+ value: any,
195
+ name = "builder",
196
+ opts = { sign: true }
197
+ ) {
198
+ if (value && opts && opts.sign) {
199
+ value = jwt.sign(value, env.JWT_SECRET)
200
+ }
201
+
202
+ const config: SetOption = {
203
+ expires: MAX_VALID_DATE,
204
+ path: "/",
205
+ httpOnly: false,
206
+ overwrite: true,
207
+ }
208
+
209
+ if (env.COOKIE_DOMAIN) {
210
+ config.domain = env.COOKIE_DOMAIN
211
+ }
212
+
213
+ ctx.cookies.set(name, value, config)
214
+ }
215
+
216
+ /**
217
+ * Utility function, simply calls setCookie with an empty string for value
218
+ */
219
+ export function clearCookie(ctx: Ctx, name: string) {
220
+ setCookie(ctx, null, name)
221
+ }
222
+
223
+ /**
224
+ * Checks if the API call being made (based on the provided ctx object) is from the client. If
225
+ * the call is not from a client app then it is from the builder.
226
+ * @param {object} ctx The koa context object to be tested.
227
+ * @return {boolean} returns true if the call is from the client lib (a built app rather than the builder).
228
+ */
229
+ export function isClient(ctx: Ctx) {
230
+ return ctx.headers[Header.TYPE] === "client"
231
+ }
232
+
233
+ export function timeout(timeMs: number) {
234
+ return new Promise(resolve => setTimeout(resolve, timeMs))
235
+ }
236
+
237
+ export function isAudited(event: Event) {
238
+ return !!AuditedEventFriendlyName[event]
239
+ }
@@ -0,0 +1,34 @@
1
+ export enum LogLevel {
2
+ TRACE = "trace",
3
+ DEBUG = "debug",
4
+ INFO = "info",
5
+ WARN = "warn",
6
+ ERROR = "error",
7
+ }
8
+
9
+ const LOG_INDEX: { [key in LogLevel]: number } = {
10
+ [LogLevel.TRACE]: 1,
11
+ [LogLevel.DEBUG]: 2,
12
+ [LogLevel.INFO]: 3,
13
+ [LogLevel.WARN]: 4,
14
+ [LogLevel.ERROR]: 5,
15
+ }
16
+
17
+ const setIndex = LOG_INDEX[process.env.LOG_LEVEL as LogLevel]
18
+
19
+ if (setIndex > LOG_INDEX.trace) {
20
+ global.console.trace = jest.fn()
21
+ }
22
+
23
+ if (setIndex > LOG_INDEX.debug) {
24
+ global.console.debug = jest.fn()
25
+ }
26
+
27
+ if (setIndex > LOG_INDEX.info) {
28
+ global.console.info = jest.fn()
29
+ global.console.log = jest.fn()
30
+ }
31
+
32
+ if (setIndex > LOG_INDEX.warn) {
33
+ global.console.warn = jest.fn()
34
+ }
@@ -0,0 +1,6 @@
1
+ export * as mocks from "./mocks"
2
+ export * as structures from "./structures"
3
+ export { generator } from "./structures"
4
+ export * as testContainerUtils from "./testContainerUtils"
5
+ export * as utils from "./utils"
6
+ export * from "./jestUtils"
@@ -0,0 +1,30 @@
1
+ import { db } from "../../../src"
2
+
3
+ export function expectFunctionWasCalledTimesWith(
4
+ jestFunction: any,
5
+ times: number,
6
+ argument: any
7
+ ) {
8
+ expect(
9
+ jestFunction.mock.calls.filter((call: any) => call[0] === argument).length
10
+ ).toBe(times)
11
+ }
12
+
13
+ export const expectAnyInternalColsAttributes: {
14
+ [K in (typeof db.CONSTANT_INTERNAL_ROW_COLS)[number]]: any
15
+ } = {
16
+ tableId: expect.anything(),
17
+ type: expect.anything(),
18
+ _id: expect.anything(),
19
+ _rev: expect.anything(),
20
+ createdAt: expect.anything(),
21
+ updatedAt: expect.anything(),
22
+ }
23
+
24
+ export const expectAnyExternalColsAttributes: {
25
+ [K in (typeof db.CONSTANT_EXTERNAL_ROW_COLS)[number]]: any
26
+ } = {
27
+ tableId: expect.anything(),
28
+ _id: expect.anything(),
29
+ _rev: expect.anything(),
30
+ }
@@ -0,0 +1,3 @@
1
+ jest.mock("../../../../src/logging/alerts")
2
+ import * as _alerts from "../../../../src/logging/alerts"
3
+ export const alerts = jest.mocked(_alerts)
@@ -0,0 +1,2 @@
1
+ export const MOCK_DATE = new Date("2020-01-01T00:00:00.000Z")
2
+ export const MOCK_DATE_TIMESTAMP = 1577836800000
@@ -0,0 +1,131 @@
1
+ beforeAll(async () => {
2
+ const processors = await import("../../../../src/events/processors")
3
+ const events = await import("../../../../src/events")
4
+ jest.spyOn(processors.analyticsProcessor, "processEvent")
5
+
6
+ jest.spyOn(events.identification, "identifyTenantGroup")
7
+ jest.spyOn(events.identification, "identifyUser")
8
+
9
+ jest.spyOn(events.backfill, "appSucceeded")
10
+ jest.spyOn(events.backfill, "tenantSucceeded")
11
+
12
+ jest.spyOn(events.account, "created")
13
+ jest.spyOn(events.account, "deleted")
14
+ jest.spyOn(events.account, "verified")
15
+
16
+ jest.spyOn(events.app, "created")
17
+ jest.spyOn(events.app, "updated")
18
+ jest.spyOn(events.app, "deleted")
19
+ jest.spyOn(events.app, "published")
20
+ jest.spyOn(events.app, "unpublished")
21
+ jest.spyOn(events.app, "templateImported")
22
+ jest.spyOn(events.app, "fileImported")
23
+ jest.spyOn(events.app, "versionUpdated")
24
+ jest.spyOn(events.app, "versionReverted")
25
+ jest.spyOn(events.app, "reverted")
26
+ jest.spyOn(events.app, "exported")
27
+
28
+ jest.spyOn(events.auth, "login")
29
+ jest.spyOn(events.auth, "logout")
30
+ jest.spyOn(events.auth, "SSOCreated")
31
+ jest.spyOn(events.auth, "SSOUpdated")
32
+ jest.spyOn(events.auth, "SSOActivated")
33
+ jest.spyOn(events.auth, "SSODeactivated")
34
+
35
+ jest.spyOn(events.automation, "created")
36
+ jest.spyOn(events.automation, "deleted")
37
+ jest.spyOn(events.automation, "tested")
38
+ jest.spyOn(events.automation, "stepCreated")
39
+ jest.spyOn(events.automation, "stepDeleted")
40
+ jest.spyOn(events.automation, "triggerUpdated")
41
+
42
+ jest.spyOn(events.datasource, "created")
43
+ jest.spyOn(events.datasource, "updated")
44
+ jest.spyOn(events.datasource, "deleted")
45
+
46
+ jest.spyOn(events.email, "SMTPCreated")
47
+ jest.spyOn(events.email, "SMTPUpdated")
48
+
49
+ jest.spyOn(events.layout, "created")
50
+ jest.spyOn(events.layout, "deleted")
51
+
52
+ jest.spyOn(events.org, "nameUpdated")
53
+ jest.spyOn(events.org, "logoUpdated")
54
+ jest.spyOn(events.org, "platformURLUpdated")
55
+ jest.spyOn(events.org, "analyticsOptOut")
56
+
57
+ jest.spyOn(events.installation, "versionChecked")
58
+
59
+ jest.spyOn(events.query, "created")
60
+ jest.spyOn(events.query, "updated")
61
+ jest.spyOn(events.query, "deleted")
62
+ jest.spyOn(events.query, "imported")
63
+ jest.spyOn(events.query, "previewed")
64
+
65
+ jest.spyOn(events.role, "created")
66
+ jest.spyOn(events.role, "updated")
67
+ jest.spyOn(events.role, "deleted")
68
+ jest.spyOn(events.role, "assigned")
69
+ jest.spyOn(events.role, "unassigned")
70
+
71
+ jest.spyOn(events.rows, "imported")
72
+ jest.spyOn(events.rows, "created")
73
+
74
+ jest.spyOn(events.screen, "created")
75
+ jest.spyOn(events.screen, "deleted")
76
+
77
+ jest.spyOn(events.user, "created")
78
+ jest.spyOn(events.user, "updated")
79
+ jest.spyOn(events.user, "deleted")
80
+ jest.spyOn(events.user, "permissionAdminAssigned")
81
+ jest.spyOn(events.user, "permissionAdminRemoved")
82
+ jest.spyOn(events.user, "permissionBuilderAssigned")
83
+ jest.spyOn(events.user, "permissionBuilderRemoved")
84
+ jest.spyOn(events.user, "invited")
85
+ jest.spyOn(events.user, "inviteAccepted")
86
+ jest.spyOn(events.user, "passwordForceReset")
87
+ jest.spyOn(events.user, "passwordUpdated")
88
+ jest.spyOn(events.user, "passwordResetRequested")
89
+ jest.spyOn(events.user, "passwordReset")
90
+
91
+ jest.spyOn(events.group, "created")
92
+ jest.spyOn(events.group, "updated")
93
+ jest.spyOn(events.group, "deleted")
94
+ jest.spyOn(events.group, "usersAdded")
95
+ jest.spyOn(events.group, "usersDeleted")
96
+ jest.spyOn(events.group, "createdOnboarding")
97
+ jest.spyOn(events.group, "permissionsEdited")
98
+
99
+ jest.spyOn(events.serve, "servedBuilder")
100
+ jest.spyOn(events.serve, "servedApp")
101
+ jest.spyOn(events.serve, "servedAppPreview")
102
+
103
+ jest.spyOn(events.table, "created")
104
+ jest.spyOn(events.table, "updated")
105
+ jest.spyOn(events.table, "deleted")
106
+ jest.spyOn(events.table, "exported")
107
+ jest.spyOn(events.table, "imported")
108
+
109
+ jest.spyOn(events.view, "created")
110
+ jest.spyOn(events.view, "updated")
111
+ jest.spyOn(events.view, "deleted")
112
+ jest.spyOn(events.view, "exported")
113
+ jest.spyOn(events.view, "filterCreated")
114
+ jest.spyOn(events.view, "filterUpdated")
115
+ jest.spyOn(events.view, "filterDeleted")
116
+ jest.spyOn(events.view, "calculationCreated")
117
+ jest.spyOn(events.view, "calculationUpdated")
118
+ jest.spyOn(events.view, "calculationDeleted")
119
+
120
+ jest.spyOn(events.plugin, "init")
121
+ jest.spyOn(events.plugin, "imported")
122
+ jest.spyOn(events.plugin, "deleted")
123
+
124
+ jest.spyOn(events.license, "planChanged")
125
+ jest.spyOn(events.license, "activated")
126
+ jest.spyOn(events.license, "checkoutOpened")
127
+ jest.spyOn(events.license, "checkoutSuccess")
128
+ jest.spyOn(events.license, "portalOpened")
129
+ jest.spyOn(events.license, "paymentFailed")
130
+ jest.spyOn(events.license, "paymentRecovered")
131
+ })
@@ -0,0 +1,17 @@
1
+ const mockFetch = jest.fn((url: any, opts: any) => {
2
+ const fetch = jest.requireActual("node-fetch")
3
+ const env = jest.requireActual("../../../../src/environment").default
4
+ if (url.includes(env.COUCH_DB_URL) || url.includes("raw.github")) {
5
+ return fetch(url, opts)
6
+ }
7
+ return undefined
8
+ })
9
+
10
+ const enable = () => {
11
+ jest.mock("node-fetch", () => mockFetch)
12
+ }
13
+
14
+ export default {
15
+ ...mockFetch,
16
+ enable,
17
+ }
@@ -0,0 +1,10 @@
1
+ jest.mock("../../../../src/accounts")
2
+ import * as _accounts from "../../../../src/accounts"
3
+ export const accounts = jest.mocked(_accounts)
4
+
5
+ export * as date from "./date"
6
+ export * as licenses from "./licenses"
7
+ export { default as fetch } from "./fetch"
8
+ export * from "./alerts"
9
+ import "./events"
10
+ import "./posthog"
@@ -0,0 +1,115 @@
1
+ import { Feature, License, Quotas } from "@budibase/types"
2
+ import cloneDeep from "lodash/cloneDeep"
3
+
4
+ let CLOUD_FREE_LICENSE: License
5
+ let UNLIMITED_LICENSE: License
6
+ let getCachedLicense: any
7
+
8
+ // init for the packages other than pro
9
+ export function init(proPkg: any) {
10
+ initInternal({
11
+ CLOUD_FREE_LICENSE: proPkg.constants.licenses.CLOUD_FREE_LICENSE,
12
+ UNLIMITED_LICENSE: proPkg.constants.licenses.UNLIMITED_LICENSE,
13
+ getCachedLicense: proPkg.licensing.cache.getCachedLicense,
14
+ })
15
+ }
16
+
17
+ // init for the pro package
18
+ export function initInternal(opts: {
19
+ CLOUD_FREE_LICENSE: License
20
+ UNLIMITED_LICENSE: License
21
+ getCachedLicense: any
22
+ }) {
23
+ CLOUD_FREE_LICENSE = opts.CLOUD_FREE_LICENSE
24
+ UNLIMITED_LICENSE = opts.UNLIMITED_LICENSE
25
+ getCachedLicense = opts.getCachedLicense
26
+ }
27
+
28
+ export interface UseLicenseOpts {
29
+ features?: Feature[]
30
+ quotas?: Quotas
31
+ }
32
+
33
+ // LICENSES
34
+
35
+ export const useLicense = (license: License, opts?: UseLicenseOpts) => {
36
+ if (opts) {
37
+ if (opts.features) {
38
+ license.features.push(...opts.features)
39
+ }
40
+ if (opts.quotas) {
41
+ license.quotas = opts.quotas
42
+ }
43
+ }
44
+
45
+ getCachedLicense.mockReturnValue(license)
46
+
47
+ return license
48
+ }
49
+
50
+ export const useUnlimited = (opts?: UseLicenseOpts) => {
51
+ return useLicense(UNLIMITED_LICENSE, opts)
52
+ }
53
+
54
+ export const useCloudFree = () => {
55
+ return useLicense(CLOUD_FREE_LICENSE)
56
+ }
57
+
58
+ // FEATURES
59
+
60
+ const useFeature = (feature: Feature) => {
61
+ const license = cloneDeep(UNLIMITED_LICENSE)
62
+ const opts: UseLicenseOpts = {
63
+ features: [feature],
64
+ }
65
+
66
+ return useLicense(license, opts)
67
+ }
68
+
69
+ export const useBackups = () => {
70
+ return useFeature(Feature.APP_BACKUPS)
71
+ }
72
+
73
+ export const useEnforceableSSO = () => {
74
+ return useFeature(Feature.ENFORCEABLE_SSO)
75
+ }
76
+
77
+ export const useGroups = () => {
78
+ return useFeature(Feature.USER_GROUPS)
79
+ }
80
+
81
+ export const useEnvironmentVariables = () => {
82
+ return useFeature(Feature.ENVIRONMENT_VARIABLES)
83
+ }
84
+
85
+ export const useAuditLogs = () => {
86
+ return useFeature(Feature.AUDIT_LOGS)
87
+ }
88
+
89
+ export const usePublicApiUserRoles = () => {
90
+ return useFeature(Feature.USER_ROLE_PUBLIC_API)
91
+ }
92
+
93
+ export const useScimIntegration = () => {
94
+ return useFeature(Feature.SCIM)
95
+ }
96
+
97
+ export const useSyncAutomations = () => {
98
+ return useFeature(Feature.SYNC_AUTOMATIONS)
99
+ }
100
+
101
+ export const useAppBuilders = () => {
102
+ return useFeature(Feature.APP_BUILDERS)
103
+ }
104
+
105
+ export const useViewPermissions = () => {
106
+ return useFeature(Feature.VIEW_PERMISSIONS)
107
+ }
108
+
109
+ // QUOTAS
110
+
111
+ export const setAutomationLogsQuota = (value: number) => {
112
+ const license = cloneDeep(UNLIMITED_LICENSE)
113
+ license.quotas.constant.automationLogRetentionDays.value = value
114
+ return useLicense(license)
115
+ }
@@ -0,0 +1,7 @@
1
+ jest.mock("posthog-node", () => {
2
+ return jest.fn().mockImplementation(() => {
3
+ return {
4
+ capture: jest.fn(),
5
+ }
6
+ })
7
+ })
@@ -0,0 +1,20 @@
1
+ import Chance from "chance"
2
+
3
+ export default class CustomChance extends Chance {
4
+ arrayOf<T>(
5
+ generateFn: () => T,
6
+ opts: { min?: number; max?: number } = {}
7
+ ): T[] {
8
+ const itemCount = this.integer({
9
+ min: opts.min != null ? opts.min : 1,
10
+ max: opts.max != null ? opts.max : 50,
11
+ })
12
+
13
+ const items = []
14
+ for (let i = 0; i < itemCount; i++) {
15
+ items.push(generateFn())
16
+ }
17
+
18
+ return items
19
+ }
20
+ }