@budibase/server 1.0.198 → 1.0.199-alpha.0

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 (281) hide show
  1. package/Dockerfile +2 -0
  2. package/builder/assets/index.330d0d68.js +1315 -0
  3. package/builder/index.html +1 -1
  4. package/coverage/clover.xml +2089 -2001
  5. package/coverage/coverage-final.json +121 -122
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +6 -6
  7. package/coverage/lcov-report/api/controllers/auth.js.html +7 -7
  8. package/coverage/lcov-report/api/controllers/automation.js.html +174 -72
  9. package/coverage/lcov-report/api/controllers/backup.js.html +30 -6
  10. package/coverage/lcov-report/api/controllers/cloud.js.html +11 -11
  11. package/coverage/lcov-report/api/controllers/component.js.html +5 -5
  12. package/coverage/lcov-report/api/controllers/datasource.js.html +53 -41
  13. package/coverage/lcov-report/api/controllers/dev.js.html +94 -70
  14. package/coverage/lcov-report/api/controllers/index.html +57 -72
  15. package/coverage/lcov-report/api/controllers/integration.js.html +8 -8
  16. package/coverage/lcov-report/api/controllers/layout.js.html +28 -19
  17. package/coverage/lcov-report/api/controllers/metadata.js.html +9 -9
  18. package/coverage/lcov-report/api/controllers/migrations.js.html +4 -4
  19. package/coverage/lcov-report/api/controllers/permission.js.html +15 -15
  20. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/validation.js.html +10 -10
  22. package/coverage/lcov-report/api/controllers/role.js.html +78 -48
  23. package/coverage/lcov-report/api/controllers/routing.js.html +9 -9
  24. package/coverage/lcov-report/api/controllers/row/external.js.html +19 -19
  25. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/internal.js.html +54 -54
  27. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +9 -9
  28. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +24 -24
  29. package/coverage/lcov-report/api/controllers/row/utils.js.html +24 -24
  30. package/coverage/lcov-report/api/controllers/screen.js.html +56 -20
  31. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  32. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +49 -49
  33. package/coverage/lcov-report/api/controllers/table/external.js.html +23 -17
  34. package/coverage/lcov-report/api/controllers/table/index.html +26 -26
  35. package/coverage/lcov-report/api/controllers/table/index.js.html +85 -49
  36. package/coverage/lcov-report/api/controllers/templates.js.html +6 -6
  37. package/coverage/lcov-report/api/controllers/user.js.html +19 -19
  38. package/coverage/lcov-report/api/controllers/view/exporters.js.html +11 -11
  39. package/coverage/lcov-report/api/controllers/view/index.html +21 -21
  40. package/coverage/lcov-report/api/controllers/view/index.js.html +275 -65
  41. package/coverage/lcov-report/api/controllers/view/utils.js.html +23 -23
  42. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +40 -40
  43. package/coverage/lcov-report/api/controllers/webhook.js.html +17 -17
  44. package/coverage/lcov-report/api/index.html +15 -15
  45. package/coverage/lcov-report/api/index.js.html +39 -45
  46. package/coverage/lcov-report/api/routes/analytics.js.html +7 -13
  47. package/coverage/lcov-report/api/routes/apikeys.js.html +8 -8
  48. package/coverage/lcov-report/api/routes/auth.js.html +6 -6
  49. package/coverage/lcov-report/api/routes/automation.js.html +11 -11
  50. package/coverage/lcov-report/api/routes/backup.js.html +8 -8
  51. package/coverage/lcov-report/api/routes/cloud.js.html +8 -8
  52. package/coverage/lcov-report/api/routes/component.js.html +8 -8
  53. package/coverage/lcov-report/api/routes/datasource.js.html +9 -9
  54. package/coverage/lcov-report/api/routes/deploy.js.html +8 -8
  55. package/coverage/lcov-report/api/routes/dev.js.html +13 -13
  56. package/coverage/lcov-report/api/routes/index.html +1 -1
  57. package/coverage/lcov-report/api/routes/integration.js.html +8 -8
  58. package/coverage/lcov-report/api/routes/layout.js.html +8 -8
  59. package/coverage/lcov-report/api/routes/metadata.js.html +9 -9
  60. package/coverage/lcov-report/api/routes/migrations.js.html +7 -7
  61. package/coverage/lcov-report/api/routes/permission.js.html +9 -9
  62. package/coverage/lcov-report/api/routes/query.js.html +10 -10
  63. package/coverage/lcov-report/api/routes/role.js.html +9 -9
  64. package/coverage/lcov-report/api/routes/routing.js.html +8 -8
  65. package/coverage/lcov-report/api/routes/screen.js.html +9 -9
  66. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/table.js.html +10 -10
  68. package/coverage/lcov-report/api/routes/templates.js.html +8 -8
  69. package/coverage/lcov-report/api/routes/user.js.html +8 -8
  70. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/validators.js.html +36 -36
  72. package/coverage/lcov-report/api/routes/view.js.html +10 -10
  73. package/coverage/lcov-report/api/routes/webhook.js.html +9 -9
  74. package/coverage/lcov-report/automations/actions.js.html +25 -25
  75. package/coverage/lcov-report/automations/automationUtils.js.html +8 -8
  76. package/coverage/lcov-report/automations/bullboard.js.html +35 -35
  77. package/coverage/lcov-report/automations/index.html +29 -29
  78. package/coverage/lcov-report/automations/index.js.html +29 -17
  79. package/coverage/lcov-report/automations/steps/bash.js.html +7 -7
  80. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  81. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  82. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  83. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  84. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  85. package/coverage/lcov-report/automations/steps/index.html +1 -1
  86. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  87. package/coverage/lcov-report/automations/steps/loop.js.html +2 -2
  88. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  89. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  90. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  91. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  92. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  93. package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
  94. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  95. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  96. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  97. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  98. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  100. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  101. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  102. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  103. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  104. package/coverage/lcov-report/automations/triggers.js.html +18 -18
  105. package/coverage/lcov-report/constants/index.html +1 -1
  106. package/coverage/lcov-report/constants/index.js.html +30 -30
  107. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  108. package/coverage/lcov-report/constants/screens.js.html +4 -4
  109. package/coverage/lcov-report/db/inMemoryView.js.html +5 -5
  110. package/coverage/lcov-report/db/index.html +1 -1
  111. package/coverage/lcov-report/db/index.js.html +9 -9
  112. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +17 -17
  113. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.js.html +36 -36
  115. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +19 -19
  116. package/coverage/lcov-report/db/newid.js.html +4 -4
  117. package/coverage/lcov-report/db/utils.js.html +81 -81
  118. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  119. package/coverage/lcov-report/events/index.html +1 -1
  120. package/coverage/lcov-report/events/index.js.html +7 -7
  121. package/coverage/lcov-report/events/utils.js.html +10 -10
  122. package/coverage/lcov-report/index.html +74 -74
  123. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  124. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  125. package/coverage/lcov-report/middleware/appInfo.js.html +5 -5
  126. package/coverage/lcov-report/middleware/builder.js.html +20 -20
  127. package/coverage/lcov-report/middleware/currentapp.js.html +49 -49
  128. package/coverage/lcov-report/middleware/index.html +1 -1
  129. package/coverage/lcov-report/middleware/joi-validator.js.html +14 -14
  130. package/coverage/lcov-report/middleware/publicApi.js.html +5 -5
  131. package/coverage/lcov-report/middleware/resourceId.js.html +29 -29
  132. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  133. package/coverage/lcov-report/middleware/utils.js.html +4 -4
  134. package/coverage/lcov-report/threads/automation.js.html +1 -1
  135. package/coverage/lcov-report/threads/index.html +1 -1
  136. package/coverage/lcov-report/threads/query.js.html +1 -1
  137. package/coverage/lcov-report/threads/utils.js.html +13 -13
  138. package/coverage/lcov-report/utilities/budibaseDir.js.html +3 -3
  139. package/coverage/lcov-report/utilities/centralPath.js.html +14 -14
  140. package/coverage/lcov-report/utilities/csvParser.js.html +34 -34
  141. package/coverage/lcov-report/utilities/global.js.html +28 -28
  142. package/coverage/lcov-report/utilities/index.html +25 -25
  143. package/coverage/lcov-report/utilities/index.js.html +41 -41
  144. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +18 -18
  145. package/coverage/lcov-report/utilities/queue/index.html +15 -15
  146. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  147. package/coverage/lcov-report/utilities/routing/index.js.html +6 -6
  148. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +59 -59
  150. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +15 -15
  151. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  152. package/coverage/lcov-report/utilities/security.js.html +8 -8
  153. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  154. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +30 -30
  156. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  157. package/coverage/lcov-report/utilities/users.js.html +7 -7
  158. package/coverage/lcov-report/utilities/workerRequests.js.html +29 -29
  159. package/coverage/lcov.info +2903 -2762
  160. package/dist/api/controllers/analytics.js +7 -30
  161. package/dist/api/controllers/application.js +56 -16
  162. package/dist/api/controllers/automation.js +31 -2
  163. package/dist/api/controllers/backup.js +7 -0
  164. package/dist/api/controllers/datasource.js +8 -2
  165. package/dist/api/controllers/deploy/index.js +6 -2
  166. package/dist/api/controllers/dev.js +9 -2
  167. package/dist/api/controllers/layout.js +3 -0
  168. package/dist/api/controllers/query/import/index.js +12 -2
  169. package/dist/api/controllers/query/import/sources/curl.js +3 -0
  170. package/dist/api/controllers/query/import/sources/openapi2.js +3 -0
  171. package/dist/api/controllers/query/import/sources/openapi3.js +3 -0
  172. package/dist/api/controllers/query/index.js +16 -2
  173. package/dist/api/controllers/role.js +11 -0
  174. package/dist/api/controllers/screen.js +10 -1
  175. package/dist/api/controllers/static/index.js +29 -15
  176. package/dist/api/controllers/table/external.js +2 -0
  177. package/dist/api/controllers/table/index.js +12 -0
  178. package/dist/api/controllers/table/utils.js +3 -3
  179. package/dist/api/controllers/view/index.js +62 -6
  180. package/dist/api/index.js +2 -4
  181. package/dist/api/routes/analytics.js +1 -3
  182. package/dist/app.js +16 -8
  183. package/dist/automations/index.js +4 -0
  184. package/dist/environment.js +4 -2
  185. package/dist/migrations/functions/backfill/app/automations.js +31 -0
  186. package/dist/migrations/functions/backfill/app/datasources.js +28 -0
  187. package/dist/migrations/functions/backfill/app/layouts.js +33 -0
  188. package/dist/migrations/functions/backfill/app/queries.js +32 -0
  189. package/dist/migrations/functions/backfill/app/roles.js +28 -0
  190. package/dist/migrations/functions/backfill/app/screens.js +28 -0
  191. package/dist/migrations/functions/backfill/app/tables.js +40 -0
  192. package/dist/migrations/functions/backfill/app.js +175 -0
  193. package/dist/migrations/functions/backfill/global/configs.js +61 -0
  194. package/dist/migrations/functions/backfill/global/quotas.js +60 -0
  195. package/dist/migrations/functions/backfill/global/users.js +50 -0
  196. package/dist/migrations/functions/backfill/global.js +189 -0
  197. package/dist/migrations/functions/backfill/index.js +32 -0
  198. package/dist/migrations/functions/backfill/installation.js +81 -0
  199. package/dist/migrations/index.js +95 -31
  200. package/dist/migrations/tests/helpers.js +72 -0
  201. package/dist/migrations/tests/structures.js +37 -0
  202. package/dist/package.json +79 -69
  203. package/dist/tests/utilities/TestConfiguration.js +121 -93
  204. package/dist/tests/utilities/structures.js +45 -0
  205. package/dist/tsconfig.build.tsbuildinfo +1 -1
  206. package/nodemon.json +1 -1
  207. package/package.json +80 -70
  208. package/scripts/dev/manage.js +2 -0
  209. package/scripts/jestSetup.js +7 -0
  210. package/scripts/likeCypress.ts +1 -1
  211. package/src/api/controllers/analytics.ts +8 -0
  212. package/src/api/controllers/application.ts +60 -18
  213. package/src/api/controllers/automation.js +36 -2
  214. package/src/api/controllers/backup.js +8 -0
  215. package/src/api/controllers/datasource.js +8 -4
  216. package/src/api/controllers/deploy/index.ts +6 -2
  217. package/src/api/controllers/dev.js +10 -2
  218. package/src/api/controllers/layout.js +3 -0
  219. package/src/api/controllers/query/import/index.ts +16 -3
  220. package/src/api/controllers/query/import/sources/base/index.ts +2 -1
  221. package/src/api/controllers/query/import/sources/curl.ts +4 -0
  222. package/src/api/controllers/query/import/sources/openapi2.ts +4 -0
  223. package/src/api/controllers/query/import/sources/openapi3.ts +4 -0
  224. package/src/api/controllers/query/import/tests/index.spec.js +20 -7
  225. package/src/api/controllers/query/index.ts +16 -3
  226. package/src/api/controllers/role.js +10 -0
  227. package/src/api/controllers/screen.js +13 -1
  228. package/src/api/controllers/static/index.js +28 -15
  229. package/src/api/controllers/table/external.js +2 -0
  230. package/src/api/controllers/table/index.js +12 -0
  231. package/src/api/controllers/table/utils.ts +4 -4
  232. package/src/api/controllers/view/index.js +76 -6
  233. package/src/api/index.js +2 -4
  234. package/src/api/routes/analytics.js +1 -3
  235. package/src/api/routes/public/utils/Endpoint.ts +1 -1
  236. package/src/api/routes/tests/__snapshots__/datasource.spec.js.snap +5 -1
  237. package/src/api/routes/tests/application.spec.js +64 -4
  238. package/src/api/routes/tests/automation.spec.js +168 -60
  239. package/src/api/routes/tests/backup.spec.js +2 -0
  240. package/src/api/routes/tests/data/export.txt +1 -0
  241. package/src/api/routes/tests/datasource.spec.js +5 -0
  242. package/src/api/routes/tests/deployment.spec.js +25 -0
  243. package/src/api/routes/tests/dev.spec.js +40 -0
  244. package/src/api/routes/tests/layout.spec.js +4 -0
  245. package/src/api/routes/tests/query.spec.js +56 -13
  246. package/src/api/routes/tests/role.spec.js +40 -7
  247. package/src/api/routes/tests/row.spec.js +2 -3
  248. package/src/api/routes/tests/screen.spec.js +30 -4
  249. package/src/api/routes/tests/static.spec.js +120 -54
  250. package/src/api/routes/tests/table.spec.js +102 -38
  251. package/src/api/routes/tests/view.spec.js +222 -43
  252. package/src/app.ts +18 -9
  253. package/src/automations/index.js +4 -0
  254. package/src/automations/tests/delay.spec.js +4 -0
  255. package/src/environment.js +5 -2
  256. package/src/migrations/functions/backfill/app/automations.ts +26 -0
  257. package/src/migrations/functions/backfill/app/datasources.ts +22 -0
  258. package/src/migrations/functions/backfill/app/layouts.ts +29 -0
  259. package/src/migrations/functions/backfill/app/queries.ts +33 -0
  260. package/src/migrations/functions/backfill/app/roles.ts +22 -0
  261. package/src/migrations/functions/backfill/app/screens.ts +22 -0
  262. package/src/migrations/functions/backfill/app/tables.ts +36 -0
  263. package/src/migrations/functions/backfill/app.ts +148 -0
  264. package/src/migrations/functions/backfill/global/configs.ts +66 -0
  265. package/src/migrations/functions/backfill/global/quotas.ts +60 -0
  266. package/src/migrations/functions/backfill/global/users.ts +49 -0
  267. package/src/migrations/functions/backfill/global.ts +194 -0
  268. package/src/migrations/functions/backfill/index.ts +7 -0
  269. package/src/migrations/functions/backfill/installation.ts +51 -0
  270. package/src/migrations/index.ts +120 -51
  271. package/src/migrations/tests/helpers.ts +40 -0
  272. package/src/migrations/tests/index.spec.ts +132 -0
  273. package/src/migrations/tests/structures.ts +66 -0
  274. package/src/module.d.ts +0 -1
  275. package/src/tests/utilities/TestConfiguration.js +138 -90
  276. package/src/tests/utilities/structures.js +71 -0
  277. package/tsconfig.build.json +20 -5
  278. package/tsconfig.json +22 -17
  279. package/builder/assets/index.753ce79d.js +0 -1315
  280. package/coverage/lcov-report/api/controllers/analytics.js.html +0 -202
  281. package/src/api/controllers/analytics.js +0 -39
@@ -0,0 +1,148 @@
1
+ import * as automations from "./app/automations"
2
+ import * as datasources from "./app/datasources"
3
+ import * as layouts from "./app/layouts"
4
+ import * as queries from "./app/queries"
5
+ import * as roles from "./app/roles"
6
+ import * as tables from "./app/tables"
7
+ import * as screens from "./app/screens"
8
+ import * as global from "./global"
9
+ import { App, AppBackfillSucceededEvent, Event } from "@budibase/types"
10
+ import { db as dbUtils, events } from "@budibase/backend-core"
11
+ import env from "../../../environment"
12
+ import { DEFAULT_TIMESTAMP } from "."
13
+
14
+ const failGraceful = env.SELF_HOSTED && !env.isDev()
15
+
16
+ const handleError = (e: any, errors?: any) => {
17
+ if (failGraceful) {
18
+ if (errors) {
19
+ errors.push(e)
20
+ }
21
+ return
22
+ }
23
+ throw e
24
+ }
25
+
26
+ const EVENTS = [
27
+ Event.AUTOMATION_CREATED,
28
+ Event.AUTOMATION_STEP_CREATED,
29
+ Event.DATASOURCE_CREATED,
30
+ Event.LAYOUT_CREATED,
31
+ Event.QUERY_CREATED,
32
+ Event.ROLE_CREATED,
33
+ Event.SCREEN_CREATED,
34
+ Event.TABLE_CREATED,
35
+ Event.VIEW_CREATED,
36
+ Event.VIEW_CALCULATION_CREATED,
37
+ Event.VIEW_FILTER_CREATED,
38
+ Event.APP_PUBLISHED,
39
+ Event.APP_CREATED,
40
+ ]
41
+
42
+ /**
43
+ * Date:
44
+ * May 2022
45
+ *
46
+ * Description:
47
+ * Backfill app events.
48
+ */
49
+
50
+ export const run = async (appDb: any) => {
51
+ try {
52
+ if (await global.isComplete()) {
53
+ // make sure new apps aren't backfilled
54
+ // return if the global migration for this tenant is complete
55
+ // which runs after the app migrations
56
+ return
57
+ }
58
+
59
+ // tell the event pipeline to start caching
60
+ // events for this tenant
61
+ await events.backfillCache.start(EVENTS)
62
+
63
+ let timestamp: string | number = DEFAULT_TIMESTAMP
64
+ const app: App = await appDb.get(dbUtils.DocumentTypes.APP_METADATA)
65
+ if (app.createdAt) {
66
+ timestamp = app.createdAt as string
67
+ }
68
+
69
+ if (dbUtils.isProdAppID(app.appId)) {
70
+ await events.app.published(app, timestamp)
71
+ }
72
+
73
+ const totals: any = {}
74
+ const errors: any = []
75
+
76
+ if (dbUtils.isDevAppID(app.appId)) {
77
+ await events.app.created(app, timestamp)
78
+ try {
79
+ totals.automations = await automations.backfill(appDb, timestamp)
80
+ } catch (e) {
81
+ handleError(e, errors)
82
+ }
83
+
84
+ try {
85
+ totals.datasources = await datasources.backfill(appDb, timestamp)
86
+ } catch (e) {
87
+ handleError(e, errors)
88
+ }
89
+
90
+ try {
91
+ totals.layouts = await layouts.backfill(appDb, timestamp)
92
+ } catch (e) {
93
+ handleError(e, errors)
94
+ }
95
+
96
+ try {
97
+ totals.queries = await queries.backfill(appDb, timestamp)
98
+ } catch (e) {
99
+ handleError(e, errors)
100
+ }
101
+
102
+ try {
103
+ totals.roles = await roles.backfill(appDb, timestamp)
104
+ } catch (e) {
105
+ handleError(e, errors)
106
+ }
107
+
108
+ try {
109
+ totals.screens = await screens.backfill(appDb, timestamp)
110
+ } catch (e) {
111
+ handleError(e, errors)
112
+ }
113
+
114
+ try {
115
+ totals.tables = await tables.backfill(appDb, timestamp)
116
+ } catch (e) {
117
+ handleError(e, errors)
118
+ }
119
+ }
120
+
121
+ const properties: AppBackfillSucceededEvent = {
122
+ appId: app.appId,
123
+ automations: totals.automations,
124
+ datasources: totals.datasources,
125
+ layouts: totals.layouts,
126
+ queries: totals.queries,
127
+ roles: totals.roles,
128
+ tables: totals.tables,
129
+ screens: totals.screens,
130
+ }
131
+
132
+ if (errors.length) {
133
+ properties.errors = errors.map((e: any) =>
134
+ JSON.stringify(e, Object.getOwnPropertyNames(e))
135
+ )
136
+ properties.errorCount = errors.length
137
+ } else {
138
+ properties.errorCount = 0
139
+ }
140
+
141
+ await events.backfill.appSucceeded(properties)
142
+ // tell the event pipeline to stop caching events for this tenant
143
+ await events.backfillCache.end()
144
+ } catch (e) {
145
+ handleError(e)
146
+ await events.backfill.appFailed(e)
147
+ }
148
+ }
@@ -0,0 +1,66 @@
1
+ import { events, db as dbUtils } from "@budibase/backend-core"
2
+ import {
3
+ Config,
4
+ isSMTPConfig,
5
+ isGoogleConfig,
6
+ isOIDCConfig,
7
+ isSettingsConfig,
8
+ } from "@budibase/types"
9
+ import env from "./../../../../environment"
10
+
11
+ const getConfigs = async (globalDb: any): Promise<Config[]> => {
12
+ const response = await globalDb.allDocs(
13
+ dbUtils.getConfigParams(
14
+ {},
15
+ {
16
+ include_docs: true,
17
+ }
18
+ )
19
+ )
20
+ return response.rows.map((row: any) => row.doc)
21
+ }
22
+
23
+ export const backfill = async (
24
+ globalDb: any,
25
+ timestamp: string | number | undefined
26
+ ) => {
27
+ const configs = await getConfigs(globalDb)
28
+
29
+ for (const config of configs) {
30
+ if (isSMTPConfig(config)) {
31
+ await events.email.SMTPCreated(timestamp)
32
+ }
33
+ if (isGoogleConfig(config)) {
34
+ await events.auth.SSOCreated("google", timestamp)
35
+ if (config.config.activated) {
36
+ await events.auth.SSOActivated("google", timestamp)
37
+ }
38
+ }
39
+ if (isOIDCConfig(config)) {
40
+ await events.auth.SSOCreated("oidc", timestamp)
41
+ if (config.config.configs[0].activated) {
42
+ await events.auth.SSOActivated("oidc", timestamp)
43
+ }
44
+ }
45
+ if (isSettingsConfig(config)) {
46
+ const company = config.config.company
47
+ if (company && company !== "Budibase") {
48
+ await events.org.nameUpdated(timestamp)
49
+ }
50
+
51
+ const logoUrl = config.config.logoUrl
52
+ if (logoUrl) {
53
+ await events.org.logoUpdated(timestamp)
54
+ }
55
+
56
+ const platformUrl = config.config.platformUrl
57
+ if (
58
+ platformUrl &&
59
+ platformUrl !== "http://localhost:10000" &&
60
+ env.SELF_HOSTED
61
+ ) {
62
+ await events.org.platformURLUpdated(timestamp)
63
+ }
64
+ }
65
+ }
66
+ }
@@ -0,0 +1,60 @@
1
+ import { DEFAULT_TIMESTAMP } from "./../index"
2
+ import { events } from "@budibase/backend-core"
3
+ import { quotas } from "@budibase/pro"
4
+ import { App } from "@budibase/types"
5
+
6
+ const getOldestCreatedAt = (allApps: App[]): string | undefined => {
7
+ const timestamps = allApps
8
+ .filter(app => !!app.createdAt)
9
+ .map(app => app.createdAt as string)
10
+ .sort((a, b) => new Date(a).getTime() - new Date(b).getTime())
11
+
12
+ if (timestamps.length) {
13
+ return timestamps[0]
14
+ }
15
+ }
16
+
17
+ const getMonthTimestamp = (monthString: string): number => {
18
+ const parts = monthString.split("-")
19
+ const month = parseInt(parts[0]) - 1 // we already do +1 in month string calculation
20
+ const year = parseInt(parts[1])
21
+
22
+ // using 0 as the day in next month gives us last day in previous month
23
+ const date = new Date(year, month + 1, 0).getTime()
24
+ const now = new Date().getTime()
25
+
26
+ if (date > now) {
27
+ return now
28
+ } else {
29
+ return date
30
+ }
31
+ }
32
+
33
+ export const backfill = async (allApps: App[]) => {
34
+ const usage = await quotas.getQuotaUsage()
35
+
36
+ const rows = usage.usageQuota.rows
37
+ let timestamp: string | number = DEFAULT_TIMESTAMP
38
+
39
+ const oldestAppTimestamp = getOldestCreatedAt(allApps)
40
+ if (oldestAppTimestamp) {
41
+ timestamp = oldestAppTimestamp
42
+ }
43
+
44
+ await events.rows.created(rows, timestamp)
45
+
46
+ for (const [monthString, quotas] of Object.entries(usage.monthly)) {
47
+ if (monthString === "current") {
48
+ continue
49
+ }
50
+ const monthTimestamp = getMonthTimestamp(monthString)
51
+
52
+ const queries = quotas.queries
53
+ await events.query.run(queries, monthTimestamp)
54
+
55
+ const automations = quotas.automations
56
+ await events.automation.run(automations, monthTimestamp)
57
+ }
58
+
59
+ return usage
60
+ }
@@ -0,0 +1,49 @@
1
+ import { events, db as dbUtils } from "@budibase/backend-core"
2
+ import { User, CloudAccount } from "@budibase/types"
3
+ import { DEFAULT_TIMESTAMP } from ".."
4
+
5
+ // manually define user doc params - normally server doesn't read users from the db
6
+ const getUserParams = (props: any) => {
7
+ return dbUtils.getDocParams(dbUtils.DocumentTypes.USER, null, props)
8
+ }
9
+
10
+ export const getUsers = async (globalDb: any): Promise<User[]> => {
11
+ const response = await globalDb.allDocs(
12
+ getUserParams({
13
+ include_docs: true,
14
+ })
15
+ )
16
+ return response.rows.map((row: any) => row.doc)
17
+ }
18
+
19
+ export const backfill = async (
20
+ globalDb: any,
21
+ account: CloudAccount | undefined
22
+ ) => {
23
+ const users = await getUsers(globalDb)
24
+
25
+ for (const user of users) {
26
+ let timestamp: string | number = DEFAULT_TIMESTAMP
27
+ if (user.createdAt) {
28
+ timestamp = user.createdAt
29
+ }
30
+ await events.identification.identifyUser(user, account, timestamp)
31
+ await events.user.created(user, timestamp)
32
+
33
+ if (user.admin?.global) {
34
+ await events.user.permissionAdminAssigned(user, timestamp)
35
+ }
36
+
37
+ if (user.builder?.global) {
38
+ await events.user.permissionBuilderAssigned(user, timestamp)
39
+ }
40
+
41
+ if (user.roles) {
42
+ for (const [appId, role] of Object.entries(user.roles)) {
43
+ await events.role.assigned(user, role, timestamp)
44
+ }
45
+ }
46
+ }
47
+
48
+ return users.length
49
+ }
@@ -0,0 +1,194 @@
1
+ import * as users from "./global/users"
2
+ import * as configs from "./global/configs"
3
+ import * as quotas from "./global/quotas"
4
+ import {
5
+ tenancy,
6
+ events,
7
+ migrations,
8
+ accounts,
9
+ db as dbUtils,
10
+ } from "@budibase/backend-core"
11
+ import { QuotaUsage } from "@budibase/pro"
12
+ import {
13
+ CloudAccount,
14
+ App,
15
+ TenantBackfillSucceededEvent,
16
+ Event,
17
+ } from "@budibase/types"
18
+ import env from "../../../environment"
19
+ import { DEFAULT_TIMESTAMP } from "."
20
+
21
+ const failGraceful = env.SELF_HOSTED && !env.isDev()
22
+
23
+ const handleError = (e: any, errors?: any) => {
24
+ if (failGraceful) {
25
+ if (errors) {
26
+ errors.push(e)
27
+ }
28
+ return
29
+ }
30
+ throw e
31
+ }
32
+
33
+ const formatUsage = (usage: QuotaUsage) => {
34
+ let maxAutomations = 0
35
+ let maxQueries = 0
36
+ let rows = 0
37
+ let developers = 0
38
+
39
+ if (usage) {
40
+ if (usage.usageQuota) {
41
+ rows = usage.usageQuota.rows
42
+ developers = usage.usageQuota.developers
43
+ }
44
+
45
+ if (usage.monthly) {
46
+ for (const value of Object.values(usage.monthly)) {
47
+ if (value.automations > maxAutomations) {
48
+ maxAutomations = value.automations
49
+ }
50
+ if (value.queries > maxQueries) {
51
+ maxQueries = value.queries
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ return {
58
+ maxAutomations,
59
+ maxQueries,
60
+ rows,
61
+ developers,
62
+ }
63
+ }
64
+
65
+ const EVENTS = [
66
+ Event.EMAIL_SMTP_CREATED,
67
+ Event.AUTH_SSO_CREATED,
68
+ Event.AUTH_SSO_ACTIVATED,
69
+ Event.ORG_NAME_UPDATED,
70
+ Event.ORG_LOGO_UPDATED,
71
+ Event.ORG_PLATFORM_URL_UPDATED,
72
+ Event.USER_CREATED,
73
+ Event.USER_PERMISSION_ADMIN_ASSIGNED,
74
+ Event.USER_PERMISSION_BUILDER_ASSIGNED,
75
+ Event.ROLE_ASSIGNED,
76
+ Event.ROWS_CREATED,
77
+ Event.QUERIES_RUN,
78
+ Event.AUTOMATIONS_RUN,
79
+ ]
80
+
81
+ /**
82
+ * Date:
83
+ * May 2022
84
+ *
85
+ * Description:
86
+ * Backfill global events.
87
+ */
88
+
89
+ export const run = async (db: any) => {
90
+ try {
91
+ const tenantId = tenancy.getTenantId()
92
+ let timestamp: string | number = DEFAULT_TIMESTAMP
93
+
94
+ const totals: any = {}
95
+ const errors: any = []
96
+
97
+ try {
98
+ const installTimestamp = await getInstallTimestamp(db)
99
+ if (installTimestamp) {
100
+ timestamp = installTimestamp
101
+ }
102
+ } catch (e) {
103
+ handleError(e, errors)
104
+ }
105
+
106
+ let account: CloudAccount | undefined
107
+ if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
108
+ account = await accounts.getAccountByTenantId(tenantId)
109
+ }
110
+
111
+ try {
112
+ await events.identification.identifyTenantGroup(
113
+ tenantId,
114
+ account,
115
+ timestamp
116
+ )
117
+ } catch (e) {
118
+ handleError(e, errors)
119
+ }
120
+
121
+ // tell the event pipeline to start caching
122
+ // events for this tenant
123
+ await events.backfillCache.start(EVENTS)
124
+
125
+ try {
126
+ await configs.backfill(db, timestamp)
127
+ } catch (e) {
128
+ handleError(e, errors)
129
+ }
130
+
131
+ try {
132
+ totals.users = await users.backfill(db, account)
133
+ } catch (e) {
134
+ handleError(e, errors)
135
+ }
136
+
137
+ try {
138
+ const allApps: App[] = await dbUtils.getAllApps({ dev: true })
139
+ totals.apps = allApps.length
140
+
141
+ totals.usage = await quotas.backfill(allApps)
142
+ } catch (e) {
143
+ handleError(e, errors)
144
+ }
145
+
146
+ const properties: TenantBackfillSucceededEvent = {
147
+ apps: totals.apps,
148
+ users: totals.users,
149
+ ...formatUsage(totals.usage),
150
+ usage: totals.usage,
151
+ }
152
+
153
+ if (errors.length) {
154
+ properties.errors = errors.map((e: any) =>
155
+ JSON.stringify(e, Object.getOwnPropertyNames(e))
156
+ )
157
+ properties.errorCount = errors.length
158
+ } else {
159
+ properties.errorCount = 0
160
+ }
161
+
162
+ await events.backfill.tenantSucceeded(properties)
163
+ // tell the event pipeline to stop caching events for this tenant
164
+ await events.backfillCache.end()
165
+ } catch (e) {
166
+ handleError(e)
167
+ await events.backfill.tenantFailed(e)
168
+ }
169
+ }
170
+
171
+ export const isComplete = async (): Promise<boolean> => {
172
+ const globalDb = tenancy.getGlobalDB()
173
+ const migrationsDoc = await migrations.getMigrationsDoc(globalDb)
174
+ return !!migrationsDoc.event_global_backfill
175
+ }
176
+
177
+ export const getInstallTimestamp = async (
178
+ globalDb: any
179
+ ): Promise<number | undefined> => {
180
+ const allUsers = await users.getUsers(globalDb)
181
+
182
+ // get the oldest user timestamp
183
+ const timestamps = allUsers
184
+ .map(user => user.createdAt)
185
+ .filter(timestamp => !!timestamp)
186
+ .sort(
187
+ (a, b) =>
188
+ new Date(a as number).getTime() - new Date(b as number).getTime()
189
+ )
190
+
191
+ if (timestamps.length) {
192
+ return timestamps[0]
193
+ }
194
+ }
@@ -0,0 +1,7 @@
1
+ export * as app from "./app"
2
+ export * as global from "./global"
3
+ export * as installation from "./installation"
4
+
5
+ // historical events are free in posthog - make sure we default to a
6
+ // historical time if no other can be found
7
+ export const DEFAULT_TIMESTAMP = new Date(2022, 0, 1).getTime()
@@ -0,0 +1,51 @@
1
+ import { DEFAULT_TIMESTAMP } from "./index"
2
+ import { events, tenancy, installation } from "@budibase/backend-core"
3
+ import { Installation } from "@budibase/types"
4
+ import * as global from "./global"
5
+ import env from "../../../environment"
6
+
7
+ const failGraceful = env.SELF_HOSTED
8
+
9
+ const handleError = (e: any, errors?: any) => {
10
+ if (failGraceful) {
11
+ if (errors) {
12
+ errors.push(e)
13
+ }
14
+ return
15
+ }
16
+ throw e
17
+ }
18
+
19
+ /**
20
+ * Date:
21
+ * May 2022
22
+ *
23
+ * Description:
24
+ * Backfill installation events.
25
+ */
26
+
27
+ export const run = async () => {
28
+ try {
29
+ // need to use the default tenant to try to get the installation time
30
+ await tenancy.doInTenant(tenancy.DEFAULT_TENANT_ID, async () => {
31
+ const db = tenancy.getGlobalDB()
32
+ let timestamp: string | number = DEFAULT_TIMESTAMP
33
+
34
+ const installTimestamp = await global.getInstallTimestamp(db)
35
+ if (installTimestamp) {
36
+ timestamp = installTimestamp
37
+ }
38
+
39
+ const install: Installation = await installation.getInstall()
40
+ await events.identification.identifyInstallationGroup(
41
+ install.installId,
42
+ timestamp
43
+ )
44
+ })
45
+ await events.backfill.installationSucceeded()
46
+ throw new Error("fail")
47
+ } catch (e) {
48
+ handleError(e)
49
+ await events.backfill.installationFailed(e)
50
+ }
51
+ }