@budibase/backend-core 3.2.4 → 3.2.6

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 (272) hide show
  1. package/dist/index.js.map +1 -1
  2. package/dist/index.js.meta.json +1 -1
  3. package/dist/package.json +11 -4
  4. package/dist/plugins.js.meta.json +1 -1
  5. package/package.json +11 -4
  6. package/src/accounts/accounts.ts +0 -82
  7. package/src/accounts/api.ts +0 -59
  8. package/src/accounts/index.ts +0 -1
  9. package/src/auth/auth.ts +0 -210
  10. package/src/auth/index.ts +0 -1
  11. package/src/auth/tests/auth.spec.ts +0 -14
  12. package/src/blacklist/blacklist.ts +0 -54
  13. package/src/blacklist/index.ts +0 -1
  14. package/src/blacklist/tests/blacklist.spec.ts +0 -46
  15. package/src/cache/appMetadata.ts +0 -88
  16. package/src/cache/base/index.ts +0 -150
  17. package/src/cache/docWritethrough.ts +0 -105
  18. package/src/cache/generic.ts +0 -33
  19. package/src/cache/index.ts +0 -8
  20. package/src/cache/invite.ts +0 -86
  21. package/src/cache/passwordReset.ts +0 -49
  22. package/src/cache/tests/docWritethrough.spec.ts +0 -296
  23. package/src/cache/tests/user.spec.ts +0 -145
  24. package/src/cache/tests/writethrough.spec.ts +0 -139
  25. package/src/cache/user.ts +0 -154
  26. package/src/cache/writethrough.ts +0 -133
  27. package/src/configs/configs.ts +0 -263
  28. package/src/configs/index.ts +0 -1
  29. package/src/configs/tests/configs.spec.ts +0 -184
  30. package/src/constants/db.ts +0 -75
  31. package/src/constants/index.ts +0 -2
  32. package/src/constants/misc.ts +0 -36
  33. package/src/context/Context.ts +0 -14
  34. package/src/context/identity.ts +0 -58
  35. package/src/context/index.ts +0 -3
  36. package/src/context/mainContext.ts +0 -422
  37. package/src/context/tests/index.spec.ts +0 -255
  38. package/src/context/types.ts +0 -26
  39. package/src/db/Replication.ts +0 -94
  40. package/src/db/couch/DatabaseImpl.ts +0 -511
  41. package/src/db/couch/connections.ts +0 -89
  42. package/src/db/couch/index.ts +0 -4
  43. package/src/db/couch/pouchDB.ts +0 -97
  44. package/src/db/couch/pouchDump.ts +0 -0
  45. package/src/db/couch/tests/DatabaseImpl.spec.ts +0 -118
  46. package/src/db/couch/utils.ts +0 -55
  47. package/src/db/db.ts +0 -34
  48. package/src/db/errors.ts +0 -14
  49. package/src/db/index.ts +0 -12
  50. package/src/db/instrumentation.ts +0 -199
  51. package/src/db/lucene.ts +0 -721
  52. package/src/db/searchIndexes/index.ts +0 -1
  53. package/src/db/searchIndexes/searchIndexes.ts +0 -62
  54. package/src/db/tests/DatabaseImpl.spec.ts +0 -55
  55. package/src/db/tests/connections.spec.ts +0 -22
  56. package/src/db/tests/index.spec.ts +0 -32
  57. package/src/db/tests/lucene.spec.ts +0 -400
  58. package/src/db/tests/pouch.spec.js +0 -62
  59. package/src/db/tests/utils.spec.ts +0 -63
  60. package/src/db/utils.ts +0 -208
  61. package/src/db/views.ts +0 -245
  62. package/src/docIds/conversions.ts +0 -60
  63. package/src/docIds/ids.ts +0 -126
  64. package/src/docIds/index.ts +0 -2
  65. package/src/docIds/newid.ts +0 -5
  66. package/src/docIds/params.ts +0 -189
  67. package/src/docUpdates/index.ts +0 -24
  68. package/src/environment.ts +0 -293
  69. package/src/errors/errors.ts +0 -119
  70. package/src/errors/index.ts +0 -1
  71. package/src/events/analytics.ts +0 -6
  72. package/src/events/asyncEvents/index.ts +0 -2
  73. package/src/events/asyncEvents/publisher.ts +0 -12
  74. package/src/events/asyncEvents/queue.ts +0 -22
  75. package/src/events/backfill.ts +0 -183
  76. package/src/events/documentId.ts +0 -56
  77. package/src/events/events.ts +0 -47
  78. package/src/events/identification.ts +0 -311
  79. package/src/events/index.ts +0 -15
  80. package/src/events/processors/AnalyticsProcessor.ts +0 -64
  81. package/src/events/processors/AuditLogsProcessor.ts +0 -92
  82. package/src/events/processors/LoggingProcessor.ts +0 -36
  83. package/src/events/processors/Processors.ts +0 -52
  84. package/src/events/processors/async/DocumentUpdateProcessor.ts +0 -38
  85. package/src/events/processors/index.ts +0 -19
  86. package/src/events/processors/posthog/PosthogProcessor.ts +0 -118
  87. package/src/events/processors/posthog/index.ts +0 -3
  88. package/src/events/processors/posthog/rateLimiting.ts +0 -106
  89. package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +0 -164
  90. package/src/events/processors/types.ts +0 -1
  91. package/src/events/publishers/account.ts +0 -41
  92. package/src/events/publishers/ai.ts +0 -21
  93. package/src/events/publishers/app.ts +0 -168
  94. package/src/events/publishers/auditLog.ts +0 -26
  95. package/src/events/publishers/auth.ts +0 -73
  96. package/src/events/publishers/automation.ts +0 -110
  97. package/src/events/publishers/backfill.ts +0 -74
  98. package/src/events/publishers/backup.ts +0 -42
  99. package/src/events/publishers/datasource.ts +0 -48
  100. package/src/events/publishers/email.ts +0 -17
  101. package/src/events/publishers/environmentVariable.ts +0 -38
  102. package/src/events/publishers/group.ts +0 -99
  103. package/src/events/publishers/index.ts +0 -25
  104. package/src/events/publishers/installation.ts +0 -38
  105. package/src/events/publishers/layout.ts +0 -26
  106. package/src/events/publishers/license.ts +0 -84
  107. package/src/events/publishers/org.ts +0 -37
  108. package/src/events/publishers/plugin.ts +0 -47
  109. package/src/events/publishers/query.ts +0 -89
  110. package/src/events/publishers/role.ts +0 -62
  111. package/src/events/publishers/rows.ts +0 -29
  112. package/src/events/publishers/screen.ts +0 -36
  113. package/src/events/publishers/serve.ts +0 -43
  114. package/src/events/publishers/table.ts +0 -70
  115. package/src/events/publishers/user.ts +0 -202
  116. package/src/events/publishers/view.ts +0 -107
  117. package/src/features/features.ts +0 -277
  118. package/src/features/index.ts +0 -2
  119. package/src/features/tests/features.spec.ts +0 -267
  120. package/src/features/tests/utils.ts +0 -64
  121. package/src/helpers.ts +0 -9
  122. package/src/index.ts +0 -59
  123. package/src/installation.ts +0 -115
  124. package/src/logging/alerts.ts +0 -26
  125. package/src/logging/correlation/correlation.ts +0 -15
  126. package/src/logging/correlation/index.ts +0 -1
  127. package/src/logging/correlation/middleware.ts +0 -18
  128. package/src/logging/index.ts +0 -4
  129. package/src/logging/pino/logger.ts +0 -239
  130. package/src/logging/pino/middleware.ts +0 -48
  131. package/src/logging/system.ts +0 -81
  132. package/src/logging/tests/system.spec.ts +0 -61
  133. package/src/middleware/adminOnly.ts +0 -9
  134. package/src/middleware/auditLog.ts +0 -6
  135. package/src/middleware/authenticated.ts +0 -247
  136. package/src/middleware/builderOnly.ts +0 -21
  137. package/src/middleware/builderOrAdmin.ts +0 -21
  138. package/src/middleware/contentSecurityPolicy.ts +0 -113
  139. package/src/middleware/csrf.ts +0 -81
  140. package/src/middleware/errorHandling.ts +0 -43
  141. package/src/middleware/index.ts +0 -24
  142. package/src/middleware/internalApi.ts +0 -23
  143. package/src/middleware/ip.ts +0 -12
  144. package/src/middleware/joi-validator.ts +0 -58
  145. package/src/middleware/matchers.ts +0 -39
  146. package/src/middleware/passport/datasource/google.ts +0 -102
  147. package/src/middleware/passport/local.ts +0 -54
  148. package/src/middleware/passport/sso/google.ts +0 -77
  149. package/src/middleware/passport/sso/oidc.ts +0 -152
  150. package/src/middleware/passport/sso/sso.ts +0 -138
  151. package/src/middleware/passport/sso/tests/google.spec.ts +0 -68
  152. package/src/middleware/passport/sso/tests/oidc.spec.ts +0 -144
  153. package/src/middleware/passport/sso/tests/sso.spec.ts +0 -197
  154. package/src/middleware/passport/utils.ts +0 -38
  155. package/src/middleware/querystringToBody.ts +0 -28
  156. package/src/middleware/tenancy.ts +0 -36
  157. package/src/middleware/tests/builder.spec.ts +0 -181
  158. package/src/middleware/tests/contentSecurityPolicy.spec.ts +0 -75
  159. package/src/middleware/tests/matchers.spec.ts +0 -100
  160. package/src/migrations/definitions.ts +0 -40
  161. package/src/migrations/index.ts +0 -2
  162. package/src/migrations/migrations.ts +0 -186
  163. package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +0 -11
  164. package/src/migrations/tests/migrations.spec.ts +0 -64
  165. package/src/objectStore/buckets/app.ts +0 -53
  166. package/src/objectStore/buckets/global.ts +0 -29
  167. package/src/objectStore/buckets/index.ts +0 -3
  168. package/src/objectStore/buckets/plugins.ts +0 -71
  169. package/src/objectStore/buckets/tests/app.spec.ts +0 -161
  170. package/src/objectStore/buckets/tests/global.spec.ts +0 -74
  171. package/src/objectStore/buckets/tests/plugins.spec.ts +0 -111
  172. package/src/objectStore/cloudfront.ts +0 -41
  173. package/src/objectStore/index.ts +0 -3
  174. package/src/objectStore/objectStore.ts +0 -585
  175. package/src/objectStore/utils.ts +0 -113
  176. package/src/platform/index.ts +0 -3
  177. package/src/platform/platformDb.ts +0 -6
  178. package/src/platform/tenants.ts +0 -101
  179. package/src/platform/tests/tenants.spec.ts +0 -26
  180. package/src/platform/users.ts +0 -129
  181. package/src/plugin/index.ts +0 -1
  182. package/src/plugin/tests/validation.spec.ts +0 -209
  183. package/src/plugin/utils.ts +0 -175
  184. package/src/queue/constants.ts +0 -8
  185. package/src/queue/inMemoryQueue.ts +0 -189
  186. package/src/queue/index.ts +0 -2
  187. package/src/queue/listeners.ts +0 -199
  188. package/src/queue/queue.ts +0 -84
  189. package/src/redis/index.ts +0 -6
  190. package/src/redis/init.ts +0 -118
  191. package/src/redis/redis.ts +0 -358
  192. package/src/redis/redlockImpl.ts +0 -155
  193. package/src/redis/tests/redis.spec.ts +0 -207
  194. package/src/redis/tests/redlockImpl.spec.ts +0 -105
  195. package/src/redis/utils.ts +0 -128
  196. package/src/security/auth.ts +0 -24
  197. package/src/security/encryption.ts +0 -185
  198. package/src/security/index.ts +0 -1
  199. package/src/security/permissions.ts +0 -166
  200. package/src/security/roles.ts +0 -655
  201. package/src/security/secrets.ts +0 -20
  202. package/src/security/sessions.ts +0 -123
  203. package/src/security/tests/auth.spec.ts +0 -45
  204. package/src/security/tests/encryption.spec.ts +0 -31
  205. package/src/security/tests/permissions.spec.ts +0 -146
  206. package/src/security/tests/secrets.spec.ts +0 -35
  207. package/src/security/tests/sessions.spec.ts +0 -12
  208. package/src/sql/designDoc.ts +0 -17
  209. package/src/sql/index.ts +0 -5
  210. package/src/sql/sql.ts +0 -1854
  211. package/src/sql/sqlTable.ts +0 -319
  212. package/src/sql/utils.ts +0 -193
  213. package/src/tenancy/db.ts +0 -6
  214. package/src/tenancy/index.ts +0 -2
  215. package/src/tenancy/tenancy.ts +0 -148
  216. package/src/tenancy/tests/tenancy.spec.ts +0 -184
  217. package/src/timers/index.ts +0 -1
  218. package/src/timers/timers.ts +0 -22
  219. package/src/users/db.ts +0 -582
  220. package/src/users/events.ts +0 -176
  221. package/src/users/index.ts +0 -4
  222. package/src/users/lookup.ts +0 -99
  223. package/src/users/test/db.spec.ts +0 -188
  224. package/src/users/test/utils.spec.ts +0 -67
  225. package/src/users/users.ts +0 -353
  226. package/src/users/utils.ts +0 -81
  227. package/src/utils/Duration.ts +0 -56
  228. package/src/utils/hashing.ts +0 -15
  229. package/src/utils/index.ts +0 -4
  230. package/src/utils/stringUtils.ts +0 -8
  231. package/src/utils/tests/Duration.spec.ts +0 -19
  232. package/src/utils/tests/utils.spec.ts +0 -204
  233. package/src/utils/utils.ts +0 -249
  234. package/tests/core/logging.ts +0 -34
  235. package/tests/core/users/users.spec.js +0 -53
  236. package/tests/core/utilities/index.ts +0 -7
  237. package/tests/core/utilities/jestUtils.ts +0 -33
  238. package/tests/core/utilities/mocks/alerts.ts +0 -4
  239. package/tests/core/utilities/mocks/date.ts +0 -3
  240. package/tests/core/utilities/mocks/events.ts +0 -132
  241. package/tests/core/utilities/mocks/index.ts +0 -9
  242. package/tests/core/utilities/mocks/licenses.ts +0 -119
  243. package/tests/core/utilities/queue.ts +0 -9
  244. package/tests/core/utilities/structures/Chance.ts +0 -20
  245. package/tests/core/utilities/structures/accounts.ts +0 -80
  246. package/tests/core/utilities/structures/apps.ts +0 -21
  247. package/tests/core/utilities/structures/common.ts +0 -7
  248. package/tests/core/utilities/structures/db.ts +0 -12
  249. package/tests/core/utilities/structures/documents/index.ts +0 -1
  250. package/tests/core/utilities/structures/documents/platform/index.ts +0 -1
  251. package/tests/core/utilities/structures/documents/platform/installation.ts +0 -12
  252. package/tests/core/utilities/structures/generator.ts +0 -3
  253. package/tests/core/utilities/structures/index.ts +0 -15
  254. package/tests/core/utilities/structures/koa.ts +0 -16
  255. package/tests/core/utilities/structures/licenses.ts +0 -190
  256. package/tests/core/utilities/structures/plugins.ts +0 -19
  257. package/tests/core/utilities/structures/quotas.ts +0 -72
  258. package/tests/core/utilities/structures/scim.ts +0 -80
  259. package/tests/core/utilities/structures/sso.ts +0 -118
  260. package/tests/core/utilities/structures/tenants.ts +0 -5
  261. package/tests/core/utilities/structures/userGroups.ts +0 -10
  262. package/tests/core/utilities/structures/users.ts +0 -89
  263. package/tests/core/utilities/testContainerUtils.ts +0 -165
  264. package/tests/core/utilities/utils/index.ts +0 -2
  265. package/tests/core/utilities/utils/queue.ts +0 -27
  266. package/tests/core/utilities/utils/time.ts +0 -3
  267. package/tests/extra/DBTestConfiguration.ts +0 -36
  268. package/tests/extra/index.ts +0 -2
  269. package/tests/extra/testEnv.ts +0 -95
  270. package/tests/index.ts +0 -2
  271. package/tests/jestEnv.ts +0 -10
  272. package/tests/jestSetup.ts +0 -36
@@ -1,8 +0,0 @@
1
- export * as generic from "./generic"
2
- export * as user from "./user"
3
- export * as app from "./appMetadata"
4
- export * as writethrough from "./writethrough"
5
- export * as invite from "./invite"
6
- export * as passwordReset from "./passwordReset"
7
- export * from "./generic"
8
- export * as docWritethrough from "./docWritethrough"
@@ -1,86 +0,0 @@
1
- import * as utils from "../utils"
2
- import { Duration } from "../utils"
3
- import env from "../environment"
4
- import { getTenantId } from "../context"
5
- import * as redis from "../redis/init"
6
-
7
- const TTL_SECONDS = Duration.fromDays(7).toSeconds()
8
-
9
- interface Invite {
10
- email: string
11
- info: any
12
- }
13
-
14
- interface InviteWithCode extends Invite {
15
- code: string
16
- }
17
-
18
- /**
19
- * Given an invite code and invite body, allow the update an existing/valid invite in redis
20
- * @param code The invite code for an invite in redis
21
- * @param value The body of the updated user invitation
22
- */
23
- export async function updateCode(code: string, value: Invite) {
24
- const client = await redis.getInviteClient()
25
- await client.store(code, value, TTL_SECONDS)
26
- }
27
-
28
- /**
29
- * Generates an invitation code and writes it to redis - which can later be checked for user creation.
30
- * @param email the email address which the code is being sent to (for use later).
31
- * @param info Information to be carried along with the invitation.
32
- * @return returns the code that was stored to redis.
33
- */
34
- export async function createCode(email: string, info: any): Promise<string> {
35
- const code = utils.newid()
36
- const client = await redis.getInviteClient()
37
- await client.store(code, { email, info }, TTL_SECONDS)
38
- return code
39
- }
40
-
41
- /**
42
- * Checks that the provided invite code is valid - will return the email address of user that was invited.
43
- * @param code the invite code that was provided as part of the link.
44
- * @return If the code is valid then an email address will be returned.
45
- */
46
- export async function getCode(code: string): Promise<Invite> {
47
- const client = await redis.getInviteClient()
48
- const value = (await client.get(code)) as Invite | undefined
49
- if (!value) {
50
- throw "Invitation is not valid or has expired, please request a new one."
51
- }
52
- return value
53
- }
54
-
55
- export async function deleteCode(code: string) {
56
- const client = await redis.getInviteClient()
57
- await client.delete(code)
58
- }
59
-
60
- /**
61
- Get all currently available user invitations for the current tenant.
62
- **/
63
- export async function getInviteCodes(): Promise<InviteWithCode[]> {
64
- const client = await redis.getInviteClient()
65
- const invites: { key: string; value: Invite }[] = await client.scan()
66
-
67
- const results: InviteWithCode[] = invites.map(invite => {
68
- return {
69
- ...invite.value,
70
- code: invite.key,
71
- }
72
- })
73
- if (!env.MULTI_TENANCY) {
74
- return results
75
- }
76
- const tenantId = getTenantId()
77
- return results.filter(invite => tenantId === invite.info.tenantId)
78
- }
79
-
80
- export async function getExistingInvites(
81
- emails: string[]
82
- ): Promise<InviteWithCode[]> {
83
- return (await getInviteCodes()).filter(invite =>
84
- emails.includes(invite.email)
85
- )
86
- }
@@ -1,49 +0,0 @@
1
- import * as redis from "../redis/init"
2
- import * as utils from "../utils"
3
- import { Duration } from "../utils"
4
-
5
- const TTL_SECONDS = Duration.fromHours(1).toSeconds()
6
-
7
- interface PasswordReset {
8
- userId: string
9
- info: any
10
- }
11
-
12
- /**
13
- * Given a user ID this will store a code (that is returned) for an hour in redis.
14
- * The user can then return this code for resetting their password (through their reset link).
15
- * @param userId the ID of the user which is to be reset.
16
- * @param info Info about the user/the reset process.
17
- * @return returns the code that was stored to redis.
18
- */
19
- export async function createCode(userId: string, info: any): Promise<string> {
20
- const code = utils.newid()
21
- const client = await redis.getPasswordResetClient()
22
- await client.store(code, { userId, info }, TTL_SECONDS)
23
- return code
24
- }
25
-
26
- /**
27
- * Given a reset code this will lookup to redis, check if the code is valid.
28
- * @param code The code provided via the email link.
29
- * @return returns the user ID if it is found
30
- */
31
- export async function getCode(code: string): Promise<PasswordReset> {
32
- const client = await redis.getPasswordResetClient()
33
- const value = (await client.get(code)) as PasswordReset | undefined
34
- if (!value) {
35
- throw new Error(
36
- "Provided information is not valid, cannot reset password - please try again."
37
- )
38
- }
39
- return value
40
- }
41
-
42
- /**
43
- * Given a reset code this will invalidate it.
44
- * @param code The code provided via the email link.
45
- */
46
- export async function invalidateCode(code: string): Promise<void> {
47
- const client = await redis.getPasswordResetClient()
48
- await client.delete(code)
49
- }
@@ -1,296 +0,0 @@
1
- import tk from "timekeeper"
2
-
3
- import _ from "lodash"
4
- import {
5
- DBTestConfiguration,
6
- generator,
7
- structures,
8
- utils,
9
- } from "../../../tests"
10
- import { getDB } from "../../db"
11
-
12
- import {
13
- DocWritethrough,
14
- DocWritethroughProcessor,
15
- init,
16
- } from "../docWritethrough"
17
-
18
- const initialTime = Date.now()
19
-
20
- async function waitForQueueCompletion() {
21
- await utils.queue.processMessages(DocWritethroughProcessor.queue)
22
- }
23
-
24
- beforeAll(() => utils.queue.useRealQueues())
25
-
26
- describe("docWritethrough", () => {
27
- beforeAll(() => {
28
- init()
29
- })
30
-
31
- const config = new DBTestConfiguration()
32
-
33
- const db = getDB(structures.db.id())
34
- let documentId: string
35
- let docWritethrough: DocWritethrough
36
-
37
- describe("patch", () => {
38
- function generatePatchObject(fieldCount: number) {
39
- const keys = generator.unique(() => generator.guid(), fieldCount)
40
- return keys.reduce((acc, c) => {
41
- acc[c] = generator.word()
42
- return acc
43
- }, {} as Record<string, any>)
44
- }
45
-
46
- beforeEach(async () => {
47
- jest.clearAllMocks()
48
- documentId = structures.uuid()
49
- docWritethrough = new DocWritethrough(db, documentId)
50
- })
51
-
52
- it("patching will not persist until the messages are persisted", async () => {
53
- await config.doInTenant(async () => {
54
- await docWritethrough.patch(generatePatchObject(2))
55
- await docWritethrough.patch(generatePatchObject(2))
56
-
57
- expect(await db.exists(documentId)).toBe(false)
58
- })
59
- })
60
-
61
- it("patching will persist when the messages are persisted", async () => {
62
- await config.doInTenant(async () => {
63
- const patch1 = generatePatchObject(2)
64
- const patch2 = generatePatchObject(2)
65
- await docWritethrough.patch(patch1)
66
- await docWritethrough.patch(patch2)
67
-
68
- await waitForQueueCompletion()
69
-
70
- // This will not be persisted
71
- const patch3 = generatePatchObject(3)
72
- await docWritethrough.patch(patch3)
73
-
74
- expect(await db.tryGet(documentId)).toEqual({
75
- _id: documentId,
76
- ...patch1,
77
- ...patch2,
78
- _rev: expect.stringMatching(/2-.+/),
79
- createdAt: new Date(initialTime).toISOString(),
80
- updatedAt: new Date(initialTime).toISOString(),
81
- })
82
- })
83
- })
84
-
85
- it("patching will persist keeping the previous data", async () => {
86
- await config.doInTenant(async () => {
87
- const patch1 = generatePatchObject(2)
88
- const patch2 = generatePatchObject(2)
89
- await docWritethrough.patch(patch1)
90
- await docWritethrough.patch(patch2)
91
-
92
- await waitForQueueCompletion()
93
-
94
- const patch3 = generatePatchObject(3)
95
- await docWritethrough.patch(patch3)
96
-
97
- await waitForQueueCompletion()
98
-
99
- expect(await db.tryGet(documentId)).toEqual(
100
- expect.objectContaining({
101
- _id: documentId,
102
- ...patch1,
103
- ...patch2,
104
- ...patch3,
105
- })
106
- )
107
- })
108
- })
109
-
110
- it("date audit fields are set correctly when persisting", async () => {
111
- await config.doInTenant(async () => {
112
- const patch1 = generatePatchObject(2)
113
- const patch2 = generatePatchObject(2)
114
- await docWritethrough.patch(patch1)
115
- const date1 = new Date()
116
- await waitForQueueCompletion()
117
- await docWritethrough.patch(patch2)
118
-
119
- tk.travel(Date.now() + 100)
120
- const date2 = new Date()
121
- await waitForQueueCompletion()
122
-
123
- expect(date1).not.toEqual(date2)
124
- expect(await db.tryGet(documentId)).toEqual(
125
- expect.objectContaining({
126
- createdAt: date1.toISOString(),
127
- updatedAt: date2.toISOString(),
128
- })
129
- )
130
- })
131
- })
132
-
133
- it("concurrent patches will override keys", async () => {
134
- await config.doInTenant(async () => {
135
- const patch1 = generatePatchObject(2)
136
- await docWritethrough.patch(patch1)
137
- await waitForQueueCompletion()
138
- const patch2 = generatePatchObject(1)
139
- await docWritethrough.patch(patch2)
140
-
141
- const keyToOverride = _.sample(Object.keys(patch1))!
142
- expect(await db.tryGet(documentId)).toEqual(
143
- expect.objectContaining({
144
- [keyToOverride]: patch1[keyToOverride],
145
- })
146
- )
147
-
148
- await waitForQueueCompletion()
149
-
150
- const patch3 = {
151
- ...generatePatchObject(3),
152
- [keyToOverride]: generator.word(),
153
- }
154
- await docWritethrough.patch(patch3)
155
- await waitForQueueCompletion()
156
-
157
- expect(await db.tryGet(documentId)).toEqual(
158
- expect.objectContaining({
159
- ...patch1,
160
- ...patch2,
161
- ...patch3,
162
- })
163
- )
164
- })
165
- })
166
-
167
- it("concurrent patches to different docWritethrough will not pollute each other", async () => {
168
- await config.doInTenant(async () => {
169
- const secondDocWritethrough = new DocWritethrough(
170
- db,
171
- structures.db.id()
172
- )
173
-
174
- const doc1Patch = generatePatchObject(2)
175
- await docWritethrough.patch(doc1Patch)
176
- const doc2Patch = generatePatchObject(1)
177
- await secondDocWritethrough.patch(doc2Patch)
178
-
179
- await waitForQueueCompletion()
180
-
181
- const doc1Patch2 = generatePatchObject(3)
182
- await docWritethrough.patch(doc1Patch2)
183
- const doc2Patch2 = generatePatchObject(3)
184
- await secondDocWritethrough.patch(doc2Patch2)
185
- await waitForQueueCompletion()
186
-
187
- expect(await db.tryGet(docWritethrough.docId)).toEqual(
188
- expect.objectContaining({
189
- ...doc1Patch,
190
- ...doc1Patch2,
191
- })
192
- )
193
-
194
- expect(await db.tryGet(secondDocWritethrough.docId)).toEqual(
195
- expect.objectContaining({
196
- ...doc2Patch,
197
- ...doc2Patch2,
198
- })
199
- )
200
- })
201
- })
202
-
203
- it("cached values are persisted only once", async () => {
204
- await config.doInTenant(async () => {
205
- const initialPatch = generatePatchObject(5)
206
-
207
- await docWritethrough.patch(initialPatch)
208
- await waitForQueueCompletion()
209
-
210
- expect(await db.tryGet(documentId)).toEqual(
211
- expect.objectContaining(initialPatch)
212
- )
213
-
214
- await db.remove(await db.get(documentId))
215
-
216
- await waitForQueueCompletion()
217
- const extraPatch = generatePatchObject(5)
218
- await docWritethrough.patch(extraPatch)
219
- await waitForQueueCompletion()
220
-
221
- expect(await db.tryGet(documentId)).toEqual(
222
- expect.objectContaining(extraPatch)
223
- )
224
- expect(await db.tryGet(documentId)).not.toEqual(
225
- expect.objectContaining(initialPatch)
226
- )
227
- })
228
- })
229
-
230
- it("concurrent calls will not cause conflicts", async () => {
231
- async function parallelPatch(count: number) {
232
- const patches = Array.from({ length: count }).map(() =>
233
- generatePatchObject(1)
234
- )
235
- await Promise.all(patches.map(p => docWritethrough.patch(p)))
236
-
237
- return patches.reduce((acc, c) => {
238
- acc = { ...acc, ...c }
239
- return acc
240
- }, {})
241
- }
242
- const queueMessageSpy = jest.spyOn(DocWritethroughProcessor.queue, "add")
243
-
244
- await config.doInTenant(async () => {
245
- let patches = await parallelPatch(5)
246
- expect(queueMessageSpy).toHaveBeenCalledTimes(5)
247
-
248
- await waitForQueueCompletion()
249
- expect(await db.tryGet(documentId)).toEqual(
250
- expect.objectContaining(patches)
251
- )
252
-
253
- patches = { ...patches, ...(await parallelPatch(40)) }
254
- expect(queueMessageSpy).toHaveBeenCalledTimes(45)
255
-
256
- await waitForQueueCompletion()
257
- expect(await db.tryGet(documentId)).toEqual(
258
- expect.objectContaining(patches)
259
- )
260
-
261
- patches = { ...patches, ...(await parallelPatch(10)) }
262
- expect(queueMessageSpy).toHaveBeenCalledTimes(55)
263
-
264
- await waitForQueueCompletion()
265
- expect(await db.tryGet(documentId)).toEqual(
266
- expect.objectContaining(patches)
267
- )
268
- })
269
- })
270
-
271
- it("patches will execute in order", async () => {
272
- let incrementalValue = 0
273
- const keyToOverride = generator.word()
274
- async function incrementalPatches(count: number) {
275
- for (let i = 0; i < count; i++) {
276
- await docWritethrough.patch({ [keyToOverride]: ++incrementalValue })
277
- }
278
- }
279
-
280
- await config.doInTenant(async () => {
281
- await incrementalPatches(5)
282
-
283
- await waitForQueueCompletion()
284
- expect(await db.tryGet(documentId)).toEqual(
285
- expect.objectContaining({ [keyToOverride]: 5 })
286
- )
287
-
288
- await incrementalPatches(40)
289
- await waitForQueueCompletion()
290
- expect(await db.tryGet(documentId)).toEqual(
291
- expect.objectContaining({ [keyToOverride]: 45 })
292
- )
293
- })
294
- })
295
- })
296
- })
@@ -1,145 +0,0 @@
1
- import { User } from "@budibase/types"
2
- import { generator, structures } from "../../../tests"
3
- import { DBTestConfiguration } from "../../../tests/extra"
4
- import { getUsers } from "../user"
5
- import { getGlobalDB } from "../../context"
6
- import _ from "lodash"
7
-
8
- import * as redis from "../../redis/init"
9
- import { UserDB } from "../../users"
10
-
11
- const config = new DBTestConfiguration()
12
-
13
- describe("user cache", () => {
14
- describe("getUsers", () => {
15
- const users: User[] = []
16
- beforeAll(async () => {
17
- const userCount = 10
18
- const userIds = generator.arrayOf(() => generator.guid(), {
19
- min: userCount,
20
- max: userCount,
21
- })
22
-
23
- await config.doInTenant(async () => {
24
- const db = getGlobalDB()
25
- for (const userId of userIds) {
26
- const user = structures.users.user({ _id: userId })
27
- await db.put(user)
28
- users.push(user)
29
- }
30
- })
31
- })
32
-
33
- beforeEach(async () => {
34
- jest.clearAllMocks()
35
-
36
- const redisClient = await redis.getUserClient()
37
- await redisClient.clear()
38
- })
39
-
40
- it("when no user is in cache, all of them are retrieved from db", async () => {
41
- const usersToRequest = _.sampleSize(users, 5)
42
-
43
- const userIdsToRequest = usersToRequest.map(x => x._id!)
44
-
45
- jest.spyOn(UserDB, "bulkGet")
46
-
47
- const results = await config.doInTenant(() => getUsers(userIdsToRequest))
48
-
49
- expect(results.users).toHaveLength(5)
50
- expect(results).toEqual({
51
- users: usersToRequest.map(u => ({
52
- ...u,
53
- budibaseAccess: true,
54
- _rev: expect.any(String),
55
- })),
56
- })
57
-
58
- expect(UserDB.bulkGet).toHaveBeenCalledTimes(1)
59
- expect(UserDB.bulkGet).toHaveBeenCalledWith(userIdsToRequest)
60
- })
61
-
62
- it("on a second all, all of them are retrieved from cache", async () => {
63
- const usersToRequest = _.sampleSize(users, 5)
64
-
65
- const userIdsToRequest = usersToRequest.map(x => x._id!)
66
-
67
- jest.spyOn(UserDB, "bulkGet")
68
-
69
- await config.doInTenant(() => getUsers(userIdsToRequest))
70
- const resultsFromCache = await config.doInTenant(() =>
71
- getUsers(userIdsToRequest)
72
- )
73
-
74
- expect(resultsFromCache.users).toHaveLength(5)
75
- expect(resultsFromCache).toEqual({
76
- users: expect.arrayContaining(
77
- usersToRequest.map(u => ({
78
- ...u,
79
- budibaseAccess: true,
80
- _rev: expect.any(String),
81
- }))
82
- ),
83
- })
84
-
85
- expect(UserDB.bulkGet).toHaveBeenCalledTimes(1)
86
- })
87
-
88
- it("when some users are cached, only the missing ones are retrieved from db", async () => {
89
- const usersToRequest = _.sampleSize(users, 5)
90
-
91
- const userIdsToRequest = usersToRequest.map(x => x._id!)
92
-
93
- jest.spyOn(UserDB, "bulkGet")
94
-
95
- await config.doInTenant(() =>
96
- getUsers([userIdsToRequest[0], userIdsToRequest[3]])
97
- )
98
- ;(UserDB.bulkGet as jest.Mock).mockClear()
99
-
100
- const results = await config.doInTenant(() => getUsers(userIdsToRequest))
101
-
102
- expect(results.users).toHaveLength(5)
103
- expect(results).toEqual({
104
- users: expect.arrayContaining(
105
- usersToRequest.map(u => ({
106
- ...u,
107
- budibaseAccess: true,
108
- _rev: expect.any(String),
109
- }))
110
- ),
111
- })
112
-
113
- expect(UserDB.bulkGet).toHaveBeenCalledTimes(1)
114
- expect(UserDB.bulkGet).toHaveBeenCalledWith([
115
- userIdsToRequest[1],
116
- userIdsToRequest[2],
117
- userIdsToRequest[4],
118
- ])
119
- })
120
-
121
- it("requesting existing and unexisting ids will return found ones", async () => {
122
- const usersToRequest = _.sampleSize(users, 3)
123
- const missingIds = [generator.guid(), generator.guid()]
124
-
125
- const userIdsToRequest = _.shuffle([
126
- ...missingIds,
127
- ...usersToRequest.map(x => x._id!),
128
- ])
129
-
130
- const results = await config.doInTenant(() => getUsers(userIdsToRequest))
131
-
132
- expect(results.users).toHaveLength(3)
133
- expect(results).toEqual({
134
- users: expect.arrayContaining(
135
- usersToRequest.map(u => ({
136
- ...u,
137
- budibaseAccess: true,
138
- _rev: expect.any(String),
139
- }))
140
- ),
141
- notFoundIds: expect.arrayContaining(missingIds),
142
- })
143
- })
144
- })
145
- })