@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,139 +0,0 @@
1
- import { DBTestConfiguration } from "../../../tests/extra"
2
- import { structures } from "../../../tests"
3
- import { Writethrough } from "../writethrough"
4
- import { getDB } from "../../db"
5
- import { Document } from "@budibase/types"
6
- import tk from "timekeeper"
7
-
8
- tk.freeze(Date.now())
9
-
10
- interface ValueDoc extends Document {
11
- value: any
12
- }
13
-
14
- const DELAY = 5000
15
-
16
- describe("writethrough", () => {
17
- const config = new DBTestConfiguration()
18
-
19
- const db = getDB(structures.db.id())
20
- const db2 = getDB(structures.db.id())
21
-
22
- const writethrough = new Writethrough(db, DELAY)
23
- const writethrough2 = new Writethrough(db2, DELAY)
24
-
25
- const docId = structures.uuid()
26
-
27
- beforeEach(() => {
28
- jest.clearAllMocks()
29
- })
30
-
31
- describe("put", () => {
32
- let current: any
33
-
34
- it("should be able to store, will go to DB", async () => {
35
- await config.doInTenant(async () => {
36
- const response = await writethrough.put({
37
- _id: docId,
38
- value: 1,
39
- })
40
- const output = await db.get<any>(response.id)
41
- current = output
42
- expect(output.value).toBe(1)
43
- })
44
- })
45
-
46
- it("second put shouldn't update DB", async () => {
47
- await config.doInTenant(async () => {
48
- const response = await writethrough.put({ ...current, value: 2 })
49
- const output = await db.get<any>(response.id)
50
- expect(current._rev).toBe(output._rev)
51
- expect(output.value).toBe(1)
52
- })
53
- })
54
-
55
- it("should put it again after delay period", async () => {
56
- await config.doInTenant(async () => {
57
- tk.freeze(Date.now() + DELAY + 1)
58
- const response = await writethrough.put({ ...current, value: 3 })
59
- const output = await db.get<any>(response.id)
60
- expect(response.rev).not.toBe(current._rev)
61
- expect(output.value).toBe(3)
62
-
63
- current = output
64
- })
65
- })
66
-
67
- it("should handle parallel DB updates ignoring conflicts", async () => {
68
- await config.doInTenant(async () => {
69
- tk.freeze(Date.now() + DELAY + 1)
70
- const responses = await Promise.all([
71
- writethrough.put({ ...current, value: 4 }),
72
- writethrough.put({ ...current, value: 4 }),
73
- writethrough.put({ ...current, value: 4 }),
74
- ])
75
-
76
- // with a lock, this will work
77
- const newRev = responses.map(x => x.rev).find(x => x !== current._rev)
78
- expect(newRev).toBeDefined()
79
- expect(responses.map(x => x.rev)).toEqual(
80
- expect.arrayContaining([current._rev, current._rev, newRev])
81
- )
82
-
83
- const output = await db.get<any>(current._id)
84
- expect(output.value).toBe(4)
85
- expect(output._rev).toBe(newRev)
86
-
87
- current = output
88
- })
89
- })
90
-
91
- it("should handle updates with documents falling behind", async () => {
92
- await config.doInTenant(async () => {
93
- tk.freeze(Date.now() + DELAY + 1)
94
-
95
- const id = structures.uuid()
96
- await writethrough.put({ _id: id, value: 1 })
97
- const doc = await writethrough.get(id)
98
-
99
- // Updating document
100
- tk.freeze(Date.now() + DELAY + 1)
101
- await writethrough.put({ ...doc, value: 2 })
102
-
103
- // Update with the old rev value
104
- tk.freeze(Date.now() + DELAY + 1)
105
- const res = await writethrough.put({
106
- ...doc,
107
- value: 3,
108
- })
109
- expect(res.ok).toBe(true)
110
-
111
- const output = await db.get<any>(id)
112
- expect(output.value).toBe(3)
113
- expect(output._rev).toBe(res.rev)
114
- })
115
- })
116
- })
117
-
118
- describe("get", () => {
119
- it("should be able to retrieve", async () => {
120
- await config.doInTenant(async () => {
121
- const response = await writethrough.get<ValueDoc>(docId)
122
- expect(response.value).toBe(4)
123
- })
124
- })
125
- })
126
-
127
- describe("same doc, different databases (tenancy)", () => {
128
- it("should be able to two different databases", async () => {
129
- await config.doInTenant(async () => {
130
- const resp1 = await writethrough.put({ _id: "db1", value: "first" })
131
- const resp2 = await writethrough2.put({ _id: "db1", value: "second" })
132
- expect(resp1.rev).toBeDefined()
133
- expect(resp2.rev).toBeDefined()
134
- expect((await db.get<any>("db1")).value).toBe("first")
135
- expect((await db2.get<any>("db1")).value).toBe("second")
136
- })
137
- })
138
- })
139
- })
package/src/cache/user.ts DELETED
@@ -1,154 +0,0 @@
1
- import * as redis from "../redis/init"
2
- import * as tenancy from "../tenancy"
3
- import * as context from "../context"
4
- import * as platform from "../platform"
5
- import env from "../environment"
6
- import * as accounts from "../accounts"
7
- import { UserDB } from "../users"
8
- import { sdk } from "@budibase/shared-core"
9
- import { User, UserMetadata } from "@budibase/types"
10
-
11
- const EXPIRY_SECONDS = 3600
12
-
13
- /**
14
- * The default populate user function
15
- */
16
- async function populateFromDB(userId: string, tenantId: string) {
17
- const db = tenancy.getTenantDB(tenantId)
18
- const user = await db.get<UserMetadata>(userId)
19
- user.budibaseAccess = true
20
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
21
- const account = await accounts.getAccount(user.email)
22
- if (account) {
23
- user.account = account
24
- user.accountPortalAccess = true
25
- }
26
- }
27
-
28
- return user
29
- }
30
-
31
- async function populateUsersFromDB(
32
- userIds: string[]
33
- ): Promise<{ users: User[]; notFoundIds?: string[] }> {
34
- const getUsersResponse = await UserDB.bulkGet(userIds)
35
-
36
- // Handle missed user ids
37
- const notFoundIds = userIds.filter((uid, i) => !getUsersResponse[i])
38
-
39
- const users = getUsersResponse.filter(x => x)
40
-
41
- await Promise.all(
42
- users.map(async (user: any) => {
43
- user.budibaseAccess = true
44
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
45
- const account = await accounts.getAccount(user.email)
46
- if (account) {
47
- user.account = account
48
- user.accountPortalAccess = true
49
- }
50
- }
51
- })
52
- )
53
-
54
- if (notFoundIds.length) {
55
- return { users, notFoundIds }
56
- }
57
- return { users }
58
- }
59
-
60
- /**
61
- * Get the requested user by id.
62
- * Use redis cache to first read the user.
63
- * If not present fallback to loading the user directly and re-caching.
64
- * @param userId the id of the user to get
65
- * @param tenantId the tenant of the user to get
66
- * @param email the email of the user to populate from account if needed
67
- * @param populateUser function to provide the user for re-caching. default to couch db
68
- * @returns
69
- */
70
- export async function getUser({
71
- userId,
72
- tenantId,
73
- email,
74
- populateUser,
75
- }: {
76
- userId: string
77
- email?: string
78
- tenantId?: string
79
- populateUser?: (
80
- userId: string,
81
- tenantId: string,
82
- email?: string
83
- ) => Promise<User>
84
- }) {
85
- if (!populateUser) {
86
- populateUser = populateFromDB
87
- }
88
- if (!tenantId) {
89
- try {
90
- tenantId = context.getTenantId()
91
- } catch (err) {
92
- tenantId = await platform.users.lookupTenantId(userId)
93
- }
94
- }
95
- const client = await redis.getUserClient()
96
- // try cache
97
- let user: User = await client.get(userId)
98
- if (!user) {
99
- user = await populateUser(userId, tenantId, email)
100
- await client.store(userId, user, EXPIRY_SECONDS)
101
- }
102
- if (user && !user.tenantId && tenantId) {
103
- // make sure the tenant ID is always correct/set
104
- user.tenantId = tenantId
105
- }
106
- // if has groups, could have builder permissions granted by a group
107
- if (user.userGroups && !sdk.users.isGlobalBuilder(user)) {
108
- await context.doInTenant(tenantId, async () => {
109
- const appIds = await UserDB.getGroupBuilderAppIds(user)
110
- if (appIds.length) {
111
- const existing = user.builder?.apps || []
112
- user.builder = {
113
- apps: [...new Set(existing.concat(appIds))],
114
- }
115
- }
116
- })
117
- }
118
- return user
119
- }
120
-
121
- /**
122
- * Get the requested users by id.
123
- * Use redis cache to first read the users.
124
- * If not present fallback to loading the users directly and re-caching.
125
- * @param userIds the ids of the user to get
126
- * @param tenantId the tenant of the users to get
127
- * @returns
128
- */
129
- export async function getUsers(
130
- userIds: string[]
131
- ): Promise<{ users: User[]; notFoundIds?: string[] }> {
132
- const client = await redis.getUserClient()
133
- // try cache
134
- let usersFromCache = await client.bulkGet<User>(userIds)
135
- const missingUsersFromCache = userIds.filter(uid => !usersFromCache[uid])
136
- const users = Object.values(usersFromCache)
137
- let notFoundIds
138
-
139
- if (missingUsersFromCache.length) {
140
- const usersFromDb = await populateUsersFromDB(missingUsersFromCache)
141
-
142
- notFoundIds = usersFromDb.notFoundIds
143
- for (const userToCache of usersFromDb.users) {
144
- await client.store(userToCache._id!, userToCache, EXPIRY_SECONDS)
145
- }
146
- users.push(...usersFromDb.users)
147
- }
148
- return { users, notFoundIds: notFoundIds }
149
- }
150
-
151
- export async function invalidateUser(userId: string) {
152
- const client = await redis.getUserClient()
153
- await client.delete(userId)
154
- }
@@ -1,133 +0,0 @@
1
- import BaseCache from "./base"
2
- import { getWritethroughClient } from "../redis/init"
3
- import { logWarn } from "../logging"
4
- import { Database, Document, LockName, LockType } from "@budibase/types"
5
- import * as locks from "../redis/redlockImpl"
6
-
7
- const DEFAULT_WRITE_RATE_MS = 10000
8
- let CACHE: BaseCache | null = null
9
-
10
- interface CacheItem<T extends Document> {
11
- doc: T
12
- lastWrite: number
13
- }
14
-
15
- async function getCache() {
16
- if (!CACHE) {
17
- const client = await getWritethroughClient()
18
- CACHE = new BaseCache(client)
19
- }
20
- return CACHE
21
- }
22
-
23
- function makeCacheKey(db: Database, key: string) {
24
- return db.name + key
25
- }
26
-
27
- function makeCacheItem<T extends Document>(
28
- doc: T,
29
- lastWrite: number | null = null
30
- ): CacheItem<T> {
31
- return { doc, lastWrite: lastWrite || Date.now() }
32
- }
33
-
34
- async function put(
35
- db: Database,
36
- doc: Document,
37
- writeRateMs: number = DEFAULT_WRITE_RATE_MS
38
- ) {
39
- const cache = await getCache()
40
- const key = doc._id
41
- let cacheItem: CacheItem<any> | undefined
42
- if (key) {
43
- cacheItem = await cache.get(makeCacheKey(db, key))
44
- }
45
- const updateDb = !cacheItem || cacheItem.lastWrite < Date.now() - writeRateMs
46
- let output = doc
47
- if (updateDb) {
48
- const lockResponse = await locks.doWithLock(
49
- {
50
- type: LockType.TRY_ONCE,
51
- name: LockName.PERSIST_WRITETHROUGH,
52
- resource: key,
53
- ttl: 15000,
54
- },
55
- async () => {
56
- const writeDb = async (toWrite: any) => {
57
- // doc should contain the _id and _rev
58
- const response = await db.put(toWrite, { force: true })
59
- output._id = response.id
60
- output._rev = response.rev
61
- }
62
- try {
63
- await writeDb(doc)
64
- } catch (err: any) {
65
- if (err.status !== 409) {
66
- throw err
67
- } else {
68
- // Swallow 409s but log them
69
- logWarn(`Ignoring conflict in write-through cache`)
70
- }
71
- }
72
- }
73
- )
74
-
75
- if (!lockResponse.executed) {
76
- logWarn(`Ignoring redlock conflict in write-through cache`)
77
- }
78
- }
79
- // if we are updating the DB then need to set the lastWrite to now
80
- cacheItem = makeCacheItem(output, updateDb ? null : cacheItem?.lastWrite)
81
- if (output._id) {
82
- await cache.store(makeCacheKey(db, output._id), cacheItem)
83
- }
84
- return { ok: true, id: output._id, rev: output._rev }
85
- }
86
-
87
- async function get<T extends Document>(db: Database, id: string): Promise<T> {
88
- const cache = await getCache()
89
- const cacheKey = makeCacheKey(db, id)
90
- let cacheItem: CacheItem<T> = await cache.get(cacheKey)
91
- if (!cacheItem) {
92
- const doc = await db.get<T>(id)
93
- cacheItem = makeCacheItem(doc)
94
- await cache.store(cacheKey, cacheItem)
95
- }
96
- return cacheItem.doc
97
- }
98
-
99
- async function remove(db: Database, docOrId: any, rev?: any): Promise<void> {
100
- const cache = await getCache()
101
- if (!docOrId) {
102
- throw new Error("No ID/Rev provided.")
103
- }
104
- const id = typeof docOrId === "string" ? docOrId : docOrId._id
105
- rev = typeof docOrId === "string" ? rev : docOrId._rev
106
- try {
107
- await cache.delete(makeCacheKey(db, id))
108
- } finally {
109
- await db.remove(id, rev)
110
- }
111
- }
112
-
113
- export class Writethrough {
114
- db: Database
115
- writeRateMs: number
116
-
117
- constructor(db: Database, writeRateMs: number = DEFAULT_WRITE_RATE_MS) {
118
- this.db = db
119
- this.writeRateMs = writeRateMs
120
- }
121
-
122
- async put(doc: any, writeRateMs: number = this.writeRateMs) {
123
- return put(this.db, doc, writeRateMs)
124
- }
125
-
126
- async get<T extends Document>(id: string) {
127
- return get<T>(this.db, id)
128
- }
129
-
130
- async remove(docOrId: any, rev?: any) {
131
- return remove(this.db, docOrId, rev)
132
- }
133
- }
@@ -1,263 +0,0 @@
1
- import {
2
- AIConfig,
3
- Config,
4
- ConfigType,
5
- GoogleConfig,
6
- GoogleInnerConfig,
7
- OIDCConfig,
8
- OIDCInnerConfig,
9
- OIDCLogosConfig,
10
- SCIMConfig,
11
- SCIMInnerConfig,
12
- SettingsConfig,
13
- SettingsInnerConfig,
14
- SMTPConfig,
15
- SMTPInnerConfig,
16
- } from "@budibase/types"
17
- import { DocumentType, SEPARATOR } from "../constants"
18
- import { CacheKey, TTL, withCache } from "../cache"
19
- import * as context from "../context"
20
- import env from "../environment"
21
-
22
- // UTILS
23
-
24
- /**
25
- * Generates a new configuration ID.
26
- * @returns The new configuration ID which the config doc can be stored under.
27
- */
28
- export function generateConfigID(type: ConfigType) {
29
- return `${DocumentType.CONFIG}${SEPARATOR}${type}`
30
- }
31
-
32
- export async function getConfig<T extends Config>(
33
- type: ConfigType
34
- ): Promise<T | undefined> {
35
- const db = context.getGlobalDB()
36
- try {
37
- // await to catch error
38
- return (await db.get(generateConfigID(type))) as T
39
- } catch (e: any) {
40
- if (e.status === 404) {
41
- return
42
- }
43
- throw e
44
- }
45
- }
46
-
47
- export async function save(
48
- config: Config
49
- ): Promise<{ id: string; rev: string }> {
50
- const db = context.getGlobalDB()
51
- return db.put(config)
52
- }
53
-
54
- // SETTINGS
55
-
56
- export async function getSettingsConfigDoc(): Promise<SettingsConfig> {
57
- let config = await getConfig<SettingsConfig>(ConfigType.SETTINGS)
58
-
59
- if (!config) {
60
- config = {
61
- _id: generateConfigID(ConfigType.SETTINGS),
62
- type: ConfigType.SETTINGS,
63
- config: {},
64
- }
65
- }
66
-
67
- // overridden fields
68
- config.config.platformUrl = await getPlatformUrl({
69
- tenantAware: true,
70
- config: config.config,
71
- })
72
- config.config.analyticsEnabled = await analyticsEnabled({
73
- config: config.config,
74
- })
75
-
76
- return config
77
- }
78
-
79
- export async function getSettingsConfig(): Promise<SettingsInnerConfig> {
80
- return (await getSettingsConfigDoc()).config
81
- }
82
-
83
- export async function getPlatformUrl(
84
- opts: { tenantAware: boolean; config?: SettingsInnerConfig } = {
85
- tenantAware: true,
86
- }
87
- ) {
88
- let platformUrl = env.PLATFORM_URL || "http://localhost:10000"
89
-
90
- if (!env.SELF_HOSTED && env.MULTI_TENANCY && opts.tenantAware) {
91
- // cloud and multi tenant - add the tenant to the default platform url
92
- const tenantId = context.getTenantId()
93
- if (!platformUrl.includes("localhost:")) {
94
- platformUrl = platformUrl.replace("://", `://${tenantId}.`)
95
- }
96
- } else if (env.SELF_HOSTED) {
97
- const config = opts?.config
98
- ? opts.config
99
- : // direct to db to prevent infinite loop
100
- (await getConfig<SettingsConfig>(ConfigType.SETTINGS))?.config
101
- if (config?.platformUrl) {
102
- platformUrl = config.platformUrl
103
- }
104
- }
105
-
106
- return platformUrl
107
- }
108
-
109
- export const analyticsEnabled = async (opts?: {
110
- config?: SettingsInnerConfig
111
- }) => {
112
- // cloud - always use the environment variable
113
- if (!env.SELF_HOSTED) {
114
- return !!env.ENABLE_ANALYTICS
115
- }
116
-
117
- // self host - prefer the settings doc
118
- // use cache as events have high throughput
119
- const enabledInDB = await withCache(
120
- CacheKey.ANALYTICS_ENABLED,
121
- TTL.ONE_DAY,
122
- async () => {
123
- const config = opts?.config
124
- ? opts.config
125
- : // direct to db to prevent infinite loop
126
- (await getConfig<SettingsConfig>(ConfigType.SETTINGS))?.config
127
-
128
- // need to do explicit checks in case the field is not set
129
- if (config?.analyticsEnabled === false) {
130
- return false
131
- } else if (config?.analyticsEnabled === true) {
132
- return true
133
- }
134
- }
135
- )
136
-
137
- if (enabledInDB !== undefined) {
138
- return enabledInDB
139
- }
140
-
141
- // fallback to the environment variable
142
- // explicitly check for 0 or false here, undefined or otherwise is treated as true
143
- const envEnabled: any = env.ENABLE_ANALYTICS
144
- if (envEnabled === 0 || envEnabled === false) {
145
- return false
146
- } else {
147
- return true
148
- }
149
- }
150
-
151
- // GOOGLE
152
-
153
- async function getGoogleConfigDoc(): Promise<GoogleConfig | undefined> {
154
- return await getConfig<GoogleConfig>(ConfigType.GOOGLE)
155
- }
156
-
157
- export async function getGoogleConfig(): Promise<
158
- GoogleInnerConfig | undefined
159
- > {
160
- const config = await getGoogleConfigDoc()
161
- return config?.config
162
- }
163
-
164
- export async function getGoogleDatasourceConfig(): Promise<
165
- GoogleInnerConfig | undefined
166
- > {
167
- if (!env.SELF_HOSTED) {
168
- // always use the env vars in cloud
169
- return getDefaultGoogleConfig()
170
- }
171
-
172
- // prefer the config in self-host
173
- let config = await getGoogleConfig()
174
-
175
- // fallback to env vars
176
- if (!config || !config.activated) {
177
- config = getDefaultGoogleConfig()
178
- }
179
-
180
- return config
181
- }
182
-
183
- export function getDefaultGoogleConfig(): GoogleInnerConfig | undefined {
184
- if (env.GOOGLE_CLIENT_ID && env.GOOGLE_CLIENT_SECRET) {
185
- return {
186
- clientID: env.GOOGLE_CLIENT_ID!,
187
- clientSecret: env.GOOGLE_CLIENT_SECRET!,
188
- activated: true,
189
- }
190
- }
191
- }
192
-
193
- // OIDC
194
-
195
- export async function getOIDCLogosDoc(): Promise<OIDCLogosConfig | undefined> {
196
- return getConfig<OIDCLogosConfig>(ConfigType.OIDC_LOGOS)
197
- }
198
-
199
- async function getOIDCConfigDoc(): Promise<OIDCConfig | undefined> {
200
- return getConfig<OIDCConfig>(ConfigType.OIDC)
201
- }
202
-
203
- export async function getOIDCConfig(): Promise<OIDCInnerConfig | undefined> {
204
- const config = (await getOIDCConfigDoc())?.config
205
- // default to the 0th config
206
- return config?.configs && config.configs[0]
207
- }
208
-
209
- /**
210
- * @param configId The config id of the inner config to retrieve
211
- */
212
- export async function getOIDCConfigById(
213
- configId: string
214
- ): Promise<OIDCInnerConfig | undefined> {
215
- const config = (await getConfig<OIDCConfig>(ConfigType.OIDC))?.config
216
- return config && config.configs.filter((c: any) => c.uuid === configId)[0]
217
- }
218
-
219
- // SMTP
220
-
221
- export async function getSMTPConfigDoc(): Promise<SMTPConfig | undefined> {
222
- return getConfig<SMTPConfig>(ConfigType.SMTP)
223
- }
224
-
225
- export async function getSMTPConfig(
226
- isAutomation?: boolean
227
- ): Promise<SMTPInnerConfig | undefined> {
228
- const config = await getSMTPConfigDoc()
229
- if (config) {
230
- return config.config
231
- }
232
-
233
- // always allow fallback in self host
234
- // in cloud don't allow for automations
235
- const allowFallback = env.SELF_HOSTED || !isAutomation
236
-
237
- // Use an SMTP fallback configuration from env variables
238
- if (env.SMTP_FALLBACK_ENABLED && allowFallback) {
239
- return {
240
- port: env.SMTP_PORT,
241
- host: env.SMTP_HOST!,
242
- secure: false,
243
- from: env.SMTP_FROM_ADDRESS!,
244
- auth: {
245
- user: env.SMTP_USER!,
246
- pass: env.SMTP_PASSWORD!,
247
- },
248
- }
249
- }
250
- }
251
-
252
- // SCIM
253
-
254
- export async function getSCIMConfig(): Promise<SCIMInnerConfig | undefined> {
255
- const config = await getConfig<SCIMConfig>(ConfigType.SCIM)
256
- return config?.config
257
- }
258
-
259
- // AI
260
-
261
- export async function getAIConfig(): Promise<AIConfig | undefined> {
262
- return getConfig<AIConfig>(ConfigType.AI)
263
- }
@@ -1 +0,0 @@
1
- export * from "./configs"