@budibase/server 1.0.49 → 1.0.50-alpha.3

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 (381) hide show
  1. package/__mocks__/arangojs.ts +1 -1
  2. package/__mocks__/aws-sdk.ts +4 -4
  3. package/__mocks__/mongodb.ts +4 -5
  4. package/__mocks__/mssql.ts +3 -3
  5. package/__mocks__/node-fetch.ts +2 -1
  6. package/__mocks__/pg.ts +3 -5
  7. package/builder/assets/{index.2c37968e.js → index.9fe798bd.js} +252 -249
  8. package/builder/assets/index.c0cc369d.css +6 -0
  9. package/builder/assets/{vendor.f9faf6ab.js → vendor.5ad9695a.js} +202 -106
  10. package/builder/index.html +3 -3
  11. package/coverage/clover.xml +3105 -2814
  12. package/coverage/coverage-final.json +106 -101
  13. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/application.js.html +257 -152
  16. package/coverage/lcov-report/api/controllers/auth.js.html +22 -13
  17. package/coverage/lcov-report/api/controllers/automation.js.html +39 -69
  18. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/cloud.js.html +8 -11
  20. package/coverage/lcov-report/api/controllers/component.js.html +13 -16
  21. package/coverage/lcov-report/api/controllers/datasource.js.html +81 -51
  22. package/coverage/lcov-report/api/controllers/dev.js.html +6 -6
  23. package/coverage/lcov-report/api/controllers/index.html +78 -78
  24. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/layout.js.html +9 -9
  26. package/coverage/lcov-report/api/controllers/metadata.js.html +6 -21
  27. package/coverage/lcov-report/api/controllers/migrations.js.html +119 -0
  28. package/coverage/lcov-report/api/controllers/permission.js.html +19 -19
  29. package/coverage/lcov-report/api/controllers/query/index.html +10 -10
  30. package/coverage/lcov-report/api/controllers/query/index.js.html +38 -35
  31. package/coverage/lcov-report/api/controllers/query/validation.js.html +6 -6
  32. package/coverage/lcov-report/api/controllers/role.js.html +16 -16
  33. package/coverage/lcov-report/api/controllers/routing.js.html +7 -10
  34. package/coverage/lcov-report/api/controllers/row/external.js.html +48 -141
  35. package/coverage/lcov-report/api/controllers/row/index.html +55 -40
  36. package/coverage/lcov-report/api/controllers/row/index.js.html +26 -26
  37. package/coverage/lcov-report/api/controllers/row/internal.js.html +118 -226
  38. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +52 -34
  39. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +548 -0
  40. package/coverage/lcov-report/api/controllers/row/utils.js.html +47 -62
  41. package/coverage/lcov-report/api/controllers/screen.js.html +15 -21
  42. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  43. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +599 -0
  44. package/coverage/lcov-report/api/controllers/table/external.js.html +25 -34
  45. package/coverage/lcov-report/api/controllers/table/index.html +58 -43
  46. package/coverage/lcov-report/api/controllers/table/index.js.html +58 -82
  47. package/coverage/lcov-report/api/controllers/table/internal.js.html +81 -66
  48. package/coverage/lcov-report/api/controllers/table/utils.js.html +218 -110
  49. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  50. package/coverage/lcov-report/api/controllers/user.js.html +79 -76
  51. package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
  52. package/coverage/lcov-report/api/controllers/view/index.html +16 -16
  53. package/coverage/lcov-report/api/controllers/view/index.js.html +27 -33
  54. package/coverage/lcov-report/api/controllers/view/utils.js.html +35 -20
  55. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
  56. package/coverage/lcov-report/api/controllers/webhook.js.html +34 -28
  57. package/coverage/lcov-report/api/index.html +1 -1
  58. package/coverage/lcov-report/api/index.js.html +8 -8
  59. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/index.html +18 -18
  71. package/coverage/lcov-report/api/routes/index.js.html +3 -3
  72. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/{hosting.js.html → migrations.js.html} +17 -14
  76. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  83. package/coverage/lcov-report/api/routes/static.js.html +17 -2
  84. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  85. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  86. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  87. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  88. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  89. package/coverage/lcov-report/automations/actions.js.html +24 -24
  90. package/coverage/lcov-report/automations/automationUtils.js.html +7 -10
  91. package/coverage/lcov-report/automations/bullboard.js.html +16 -16
  92. package/coverage/lcov-report/automations/index.html +18 -18
  93. package/coverage/lcov-report/automations/index.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
  95. package/coverage/lcov-report/automations/steps/createRow.js.html +13 -22
  96. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  97. package/coverage/lcov-report/automations/steps/deleteRow.js.html +11 -20
  98. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  99. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  100. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  101. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  102. package/coverage/lcov-report/automations/steps/index.html +13 -13
  103. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  104. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  105. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  106. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  107. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  108. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  109. package/coverage/lcov-report/automations/steps/updateRow.js.html +7 -7
  110. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  111. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  112. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  115. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  116. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  117. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  118. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  119. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  120. package/coverage/lcov-report/automations/triggers.js.html +61 -55
  121. package/coverage/lcov-report/automations/utils.js.html +54 -42
  122. package/coverage/lcov-report/constants/index.html +5 -5
  123. package/coverage/lcov-report/constants/index.js.html +53 -26
  124. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  125. package/coverage/lcov-report/constants/screens.js.html +4 -4
  126. package/coverage/lcov-report/db/client.js.html +18 -18
  127. package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
  128. package/coverage/lcov-report/db/index.html +15 -15
  129. package/coverage/lcov-report/db/index.js.html +3 -3
  130. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +25 -37
  131. package/coverage/lcov-report/db/linkedRows/index.html +27 -27
  132. package/coverage/lcov-report/db/linkedRows/index.js.html +51 -96
  133. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +42 -42
  134. package/coverage/lcov-report/db/newid.js.html +4 -4
  135. package/coverage/lcov-report/db/utils.js.html +87 -87
  136. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  137. package/coverage/lcov-report/events/index.html +1 -1
  138. package/coverage/lcov-report/events/index.js.html +5 -5
  139. package/coverage/lcov-report/events/utils.js.html +3 -3
  140. package/coverage/lcov-report/index.html +135 -120
  141. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  142. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  143. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  144. package/coverage/lcov-report/middleware/authorized.js.html +173 -65
  145. package/coverage/lcov-report/middleware/builder.js.html +10 -10
  146. package/coverage/lcov-report/middleware/currentapp.js.html +95 -83
  147. package/coverage/lcov-report/middleware/index.html +38 -38
  148. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  149. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  150. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  151. package/coverage/lcov-report/middleware/usageQuota.js.html +281 -53
  152. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  153. package/coverage/lcov-report/threads/automation.js.html +30 -24
  154. package/coverage/lcov-report/threads/index.html +26 -26
  155. package/coverage/lcov-report/threads/index.js.html +10 -10
  156. package/coverage/lcov-report/threads/query.js.html +39 -24
  157. package/coverage/lcov-report/threads/utils.js.html +14 -14
  158. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  159. package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
  160. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  161. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  162. package/coverage/lcov-report/utilities/global.js.html +58 -49
  163. package/coverage/lcov-report/utilities/index.html +37 -37
  164. package/coverage/lcov-report/utilities/index.js.html +43 -73
  165. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
  166. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  167. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  168. package/coverage/lcov-report/utilities/routing/index.js.html +7 -7
  169. package/coverage/lcov-report/utilities/rowProcessor/index.html +27 -27
  170. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +97 -103
  171. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +75 -27
  172. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  173. package/coverage/lcov-report/utilities/security.js.html +8 -8
  174. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  175. package/coverage/lcov-report/utilities/usageQuota/index.html +141 -0
  176. package/coverage/lcov-report/utilities/usageQuota/index.js.html +359 -0
  177. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +305 -0
  178. package/coverage/lcov-report/{api/controllers/hosting.js.html → utilities/usageQuota/usageQuoteReset.js.html} +36 -48
  179. package/coverage/lcov-report/utilities/users.js.html +9 -9
  180. package/coverage/lcov-report/utilities/workerRequests.js.html +43 -112
  181. package/coverage/lcov.info +5010 -4425
  182. package/dist/api/controllers/application.js +90 -60
  183. package/dist/api/controllers/auth.js +8 -5
  184. package/dist/api/controllers/automation.js +14 -19
  185. package/dist/api/controllers/cloud.js +2 -3
  186. package/dist/api/controllers/component.js +3 -4
  187. package/dist/api/controllers/datasource.js +20 -10
  188. package/dist/api/controllers/deploy/Deployment.js +3 -6
  189. package/dist/api/controllers/deploy/index.js +12 -13
  190. package/dist/api/controllers/dev.js +5 -5
  191. package/dist/api/controllers/layout.js +3 -3
  192. package/dist/api/controllers/metadata.js +4 -4
  193. package/dist/api/controllers/migrations.js +21 -0
  194. package/dist/api/controllers/permission.js +4 -4
  195. package/dist/api/controllers/query/import/index.js +4 -6
  196. package/dist/api/controllers/query/index.js +11 -10
  197. package/dist/api/controllers/role.js +5 -5
  198. package/dist/api/controllers/routing.js +5 -6
  199. package/dist/api/controllers/row/ExternalRequest.js +90 -67
  200. package/dist/api/controllers/row/external.js +14 -22
  201. package/dist/api/controllers/row/internal.js +55 -93
  202. package/dist/api/controllers/row/internalSearch.js +23 -17
  203. package/dist/api/controllers/row/staticFormula.js +147 -0
  204. package/dist/api/controllers/row/utils.js +13 -14
  205. package/dist/api/controllers/screen.js +5 -7
  206. package/dist/api/controllers/static/index.js +62 -16
  207. package/dist/api/controllers/table/bulkFormula.js +159 -0
  208. package/dist/api/controllers/table/external.js +7 -10
  209. package/dist/api/controllers/table/index.js +16 -13
  210. package/dist/api/controllers/table/internal.js +22 -16
  211. package/dist/api/controllers/table/utils.js +62 -35
  212. package/dist/api/controllers/user.js +43 -43
  213. package/dist/api/controllers/view/index.js +8 -10
  214. package/dist/api/controllers/view/utils.js +9 -4
  215. package/dist/api/controllers/webhook.js +10 -8
  216. package/dist/api/routes/index.js +2 -2
  217. package/dist/api/routes/migrations.js +9 -0
  218. package/dist/api/routes/static.js +2 -1
  219. package/dist/api/routes/tests/utilities/TestFunctions.js +37 -17
  220. package/dist/app.js +35 -5
  221. package/dist/automations/automationUtils.js +2 -3
  222. package/dist/automations/steps/createRow.js +3 -5
  223. package/dist/automations/steps/deleteRow.js +1 -4
  224. package/dist/automations/steps/updateRow.js +1 -1
  225. package/dist/automations/triggers.js +27 -25
  226. package/dist/automations/utils.js +10 -5
  227. package/dist/constants/index.js +7 -0
  228. package/dist/db/linkedRows/LinkController.js +3 -7
  229. package/dist/db/linkedRows/index.js +16 -27
  230. package/dist/db/linkedRows/linkUtils.js +6 -6
  231. package/dist/db/views/staticViews.js +9 -10
  232. package/dist/definitions/datasource.js +1 -0
  233. package/dist/environment.js +4 -1
  234. package/dist/integrations/base/sql.js +62 -21
  235. package/dist/integrations/googlesheets.js +340 -0
  236. package/dist/integrations/index.js +3 -0
  237. package/dist/integrations/utils.js +60 -9
  238. package/dist/middleware/authorized.js +57 -30
  239. package/dist/middleware/builder.js +2 -2
  240. package/dist/middleware/currentapp.js +41 -37
  241. package/dist/middleware/usageQuota.js +82 -15
  242. package/dist/migrations/functions/appUrls.js +46 -0
  243. package/dist/migrations/functions/quotas1.js +50 -0
  244. package/dist/migrations/functions/usageQuotas/index.js +20 -0
  245. package/dist/migrations/functions/usageQuotas/syncApps.js +29 -0
  246. package/dist/migrations/functions/usageQuotas/syncRows.js +33 -0
  247. package/dist/migrations/functions/userEmailViewCasing.js +24 -0
  248. package/dist/migrations/index.js +62 -0
  249. package/dist/package.json +8 -5
  250. package/dist/tests/utilities/TestConfiguration.js +80 -50
  251. package/dist/threads/automation.js +13 -11
  252. package/dist/threads/query.js +15 -11
  253. package/dist/tsconfig.tsbuildinfo +1 -1
  254. package/dist/utilities/fileSystem/index.js +4 -3
  255. package/dist/utilities/global.js +15 -12
  256. package/dist/utilities/index.js +7 -17
  257. package/dist/utilities/routing/index.js +5 -5
  258. package/dist/utilities/rowProcessor/index.js +23 -17
  259. package/dist/utilities/rowProcessor/utils.js +14 -4
  260. package/dist/utilities/{usageQuota.js → usageQuota/index.js} +45 -31
  261. package/dist/utilities/usageQuota/rows.js +78 -0
  262. package/dist/utilities/usageQuota/usageQuoteReset.js +16 -0
  263. package/dist/utilities/users.js +3 -3
  264. package/dist/utilities/workerRequests.js +4 -24
  265. package/nodemon.json +1 -1
  266. package/package.json +9 -6
  267. package/scripts/integrations/mssql/data/Dockerfile +1 -1
  268. package/scripts/integrations/mssql/data/setup.sql +17 -4
  269. package/scripts/integrations/postgres/init.sql +11 -6
  270. package/scripts/likeCypress.ts +1 -1
  271. package/src/api/controllers/application.js +85 -50
  272. package/src/api/controllers/auth.js +8 -5
  273. package/src/api/controllers/automation.js +13 -23
  274. package/src/api/controllers/cloud.js +2 -3
  275. package/src/api/controllers/component.js +3 -4
  276. package/src/api/controllers/datasource.js +21 -11
  277. package/src/api/controllers/deploy/Deployment.js +3 -7
  278. package/src/api/controllers/deploy/index.js +20 -13
  279. package/src/api/controllers/dev.js +5 -5
  280. package/src/api/controllers/layout.js +3 -3
  281. package/src/api/controllers/metadata.js +4 -9
  282. package/src/api/controllers/migrations.js +13 -0
  283. package/src/api/controllers/permission.js +4 -4
  284. package/src/api/controllers/query/import/index.ts +4 -6
  285. package/src/api/controllers/query/import/tests/index.spec.js +2 -1
  286. package/src/api/controllers/query/index.js +11 -10
  287. package/src/api/controllers/role.js +5 -5
  288. package/src/api/controllers/routing.js +5 -6
  289. package/src/api/controllers/row/ExternalRequest.ts +67 -43
  290. package/src/api/controllers/row/external.js +27 -58
  291. package/src/api/controllers/row/internal.js +54 -90
  292. package/src/api/controllers/row/internalSearch.js +23 -17
  293. package/src/api/controllers/row/staticFormula.js +156 -0
  294. package/src/api/controllers/row/utils.js +13 -18
  295. package/src/api/controllers/screen.js +5 -7
  296. package/src/api/controllers/static/index.js +66 -15
  297. package/src/api/controllers/table/bulkFormula.js +173 -0
  298. package/src/api/controllers/table/external.js +7 -10
  299. package/src/api/controllers/table/index.js +20 -28
  300. package/src/api/controllers/table/internal.js +24 -19
  301. package/src/api/controllers/table/utils.js +78 -42
  302. package/src/api/controllers/user.js +46 -45
  303. package/src/api/controllers/view/index.js +8 -10
  304. package/src/api/controllers/view/utils.js +9 -4
  305. package/src/api/controllers/webhook.js +10 -8
  306. package/src/api/routes/index.js +2 -2
  307. package/src/api/routes/migrations.js +14 -0
  308. package/src/api/routes/static.js +5 -0
  309. package/src/api/routes/tests/application.spec.js +2 -2
  310. package/src/api/routes/tests/auth.spec.js +1 -2
  311. package/src/api/routes/tests/automation.spec.js +1 -0
  312. package/src/api/routes/tests/misc.spec.js +0 -1
  313. package/src/api/routes/tests/routing.spec.js +21 -12
  314. package/src/api/routes/tests/row.spec.js +7 -4
  315. package/src/api/routes/tests/static.spec.js +98 -0
  316. package/src/api/routes/tests/utilities/TestFunctions.js +39 -17
  317. package/src/app.ts +18 -5
  318. package/src/automations/automationUtils.js +2 -3
  319. package/src/automations/steps/createRow.js +2 -5
  320. package/src/automations/steps/deleteRow.js +1 -4
  321. package/src/automations/steps/updateRow.js +1 -1
  322. package/src/automations/triggers.js +33 -31
  323. package/src/automations/utils.js +9 -5
  324. package/src/constants/index.js +9 -0
  325. package/src/db/linkedRows/LinkController.js +3 -7
  326. package/src/db/linkedRows/index.js +16 -31
  327. package/src/db/linkedRows/linkUtils.js +6 -6
  328. package/src/db/tests/linkController.spec.js +0 -1
  329. package/src/db/tests/linkTests.spec.js +5 -6
  330. package/src/db/views/staticViews.js +8 -10
  331. package/src/definitions/common.ts +3 -0
  332. package/src/definitions/datasource.ts +3 -0
  333. package/src/environment.js +4 -1
  334. package/src/integrations/base/sql.ts +75 -29
  335. package/src/integrations/googlesheets.ts +353 -0
  336. package/src/integrations/index.ts +3 -0
  337. package/src/integrations/tests/sql.spec.js +16 -0
  338. package/src/integrations/utils.ts +75 -12
  339. package/src/middleware/authorized.js +66 -30
  340. package/src/middleware/builder.js +2 -2
  341. package/src/middleware/currentapp.js +50 -46
  342. package/src/middleware/tests/authorized.spec.js +13 -6
  343. package/src/middleware/tests/currentapp.spec.js +6 -0
  344. package/src/middleware/tests/usageQuota.spec.js +18 -24
  345. package/src/middleware/usageQuota.js +93 -17
  346. package/src/migrations/functions/appUrls.ts +34 -0
  347. package/src/migrations/functions/quotas1.ts +20 -0
  348. package/src/migrations/functions/tests/appUrls.spec.js +29 -0
  349. package/src/migrations/functions/tests/quotas1.spec.js +27 -0
  350. package/src/migrations/functions/tests/userEmailViewCasing.spec.js +25 -0
  351. package/src/migrations/functions/usageQuotas/index.ts +8 -0
  352. package/src/migrations/functions/usageQuotas/syncApps.ts +18 -0
  353. package/src/migrations/functions/usageQuotas/syncRows.ts +22 -0
  354. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +37 -0
  355. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +43 -0
  356. package/src/migrations/functions/userEmailViewCasing.ts +13 -0
  357. package/src/migrations/index.ts +56 -0
  358. package/src/module.d.ts +3 -0
  359. package/src/tests/utilities/TestConfiguration.js +82 -55
  360. package/src/threads/automation.js +17 -15
  361. package/src/threads/query.js +17 -12
  362. package/src/utilities/fileSystem/index.js +4 -3
  363. package/src/utilities/global.js +15 -12
  364. package/src/utilities/index.js +7 -17
  365. package/src/utilities/routing/index.js +5 -5
  366. package/src/utilities/rowProcessor/index.js +25 -27
  367. package/src/utilities/rowProcessor/utils.js +23 -7
  368. package/src/utilities/tests/usageQuota/usageQuota.spec.js +72 -0
  369. package/src/utilities/usageQuota/index.js +93 -0
  370. package/src/utilities/usageQuota/rows.js +75 -0
  371. package/src/utilities/usageQuota/usageQuoteReset.js +18 -0
  372. package/src/utilities/users.js +3 -3
  373. package/src/utilities/workerRequests.js +4 -27
  374. package/tsconfig.json +4 -2
  375. package/builder/assets/index.39e01193.css +0 -1
  376. package/dist/api/controllers/hosting.js +0 -30
  377. package/dist/api/routes/hosting.js +0 -11
  378. package/src/api/controllers/hosting.js +0 -22
  379. package/src/api/routes/hosting.js +0 -13
  380. package/src/api/routes/tests/hosting.spec.js +0 -36
  381. package/src/utilities/usageQuota.js +0 -73
@@ -1,11 +1,11 @@
1
1
  const validateJs = require("validate.js")
2
2
  const { cloneDeep } = require("lodash/fp")
3
- const CouchDB = require("../../../db")
4
3
  const { InternalTables } = require("../../../db/utils")
5
4
  const userController = require("../user")
6
5
  const { FieldTypes } = require("../../../constants")
7
6
  const { processStringSync } = require("@budibase/string-templates")
8
7
  const { makeExternalQuery } = require("../../../integrations/base/utils")
8
+ const { getAppDB } = require("@budibase/backend-core/context")
9
9
 
10
10
  validateJs.extend(validateJs.validators.datetime, {
11
11
  parse: function (value) {
@@ -17,14 +17,15 @@ validateJs.extend(validateJs.validators.datetime, {
17
17
  },
18
18
  })
19
19
 
20
- exports.getDatasourceAndQuery = async (appId, json) => {
20
+ exports.getDatasourceAndQuery = async json => {
21
21
  const datasourceId = json.endpoint.datasourceId
22
- const db = new CouchDB(appId)
22
+ const db = getAppDB()
23
23
  const datasource = await db.get(datasourceId)
24
24
  return makeExternalQuery(datasource, json)
25
25
  }
26
26
 
27
- exports.findRow = async (ctx, db, tableId, rowId) => {
27
+ exports.findRow = async (ctx, tableId, rowId) => {
28
+ const db = getAppDB()
28
29
  let row
29
30
  // TODO remove special user case in future
30
31
  if (tableId === InternalTables.USER_METADATA) {
@@ -42,9 +43,9 @@ exports.findRow = async (ctx, db, tableId, rowId) => {
42
43
  return row
43
44
  }
44
45
 
45
- exports.validate = async ({ appId, tableId, row, table }) => {
46
+ exports.validate = async ({ tableId, row, table }) => {
46
47
  if (!table) {
47
- const db = new CouchDB(appId)
48
+ const db = getAppDB()
48
49
  table = await db.get(tableId)
49
50
  }
50
51
  const errors = {}
@@ -58,22 +59,16 @@ exports.validate = async ({ appId, tableId, row, table }) => {
58
59
  let res
59
60
 
60
61
  // Validate.js doesn't seem to handle array
61
- if (type === FieldTypes.ARRAY) {
62
- const hasValues =
63
- Array.isArray(row[fieldName]) && row[fieldName].length > 0
64
-
65
- // Check values are valid if values are specified
66
- if (hasValues) {
62
+ if (type === FieldTypes.ARRAY && row[fieldName]) {
63
+ if (row[fieldName].length) {
67
64
  row[fieldName].map(val => {
68
65
  if (!constraints.inclusion.includes(val)) {
69
- errors[fieldName] = "Value not in list"
66
+ errors[fieldName] = "Field not in list"
70
67
  }
71
68
  })
72
- }
73
-
74
- // Check for required constraint
75
- if (constraints.presence === true && !hasValues) {
76
- errors[fieldName] = "Required field"
69
+ } else if (constraints.presence && row[fieldName].length === 0) {
70
+ // non required MultiSelect creates an empty array, which should not throw errors
71
+ errors[fieldName] = [`${fieldName} is required`]
77
72
  }
78
73
  } else if (type === FieldTypes.JSON && typeof row[fieldName] === "string") {
79
74
  // this should only happen if there is an error
@@ -1,10 +1,9 @@
1
- const CouchDB = require("../../db")
2
1
  const { getScreenParams, generateScreenID } = require("../../db/utils")
3
2
  const { AccessController } = require("@budibase/backend-core/roles")
3
+ const { getAppDB } = require("@budibase/backend-core/context")
4
4
 
5
5
  exports.fetch = async ctx => {
6
- const appId = ctx.appId
7
- const db = new CouchDB(appId)
6
+ const db = getAppDB()
8
7
 
9
8
  const screens = (
10
9
  await db.allDocs(
@@ -14,15 +13,14 @@ exports.fetch = async ctx => {
14
13
  )
15
14
  ).rows.map(element => element.doc)
16
15
 
17
- ctx.body = await new AccessController(appId).checkScreensAccess(
16
+ ctx.body = await new AccessController().checkScreensAccess(
18
17
  screens,
19
18
  ctx.user.role._id
20
19
  )
21
20
  }
22
21
 
23
22
  exports.save = async ctx => {
24
- const appId = ctx.appId
25
- const db = new CouchDB(appId)
23
+ const db = getAppDB()
26
24
  let screen = ctx.request.body
27
25
 
28
26
  if (!screen._id) {
@@ -39,7 +37,7 @@ exports.save = async ctx => {
39
37
  }
40
38
 
41
39
  exports.destroy = async ctx => {
42
- const db = new CouchDB(ctx.appId)
40
+ const db = getAppDB()
43
41
  await db.remove(ctx.params.screenId, ctx.params.screenRev)
44
42
  ctx.body = {
45
43
  message: "Screen deleted successfully",
@@ -5,8 +5,7 @@ const { resolve, join } = require("../../../utilities/centralPath")
5
5
  const uuid = require("uuid")
6
6
  const { ObjectStoreBuckets } = require("../../../constants")
7
7
  const { processString } = require("@budibase/string-templates")
8
- const { getDeployedApps } = require("../../../utilities/workerRequests")
9
- const CouchDB = require("../../../db")
8
+ const { getAllApps } = require("@budibase/backend-core/db")
10
9
  const {
11
10
  loadHandlebarsFile,
12
11
  NODE_MODULES_PATH,
@@ -17,6 +16,9 @@ const { clientLibraryPath } = require("../../../utilities")
17
16
  const { upload } = require("../../../utilities/fileSystem")
18
17
  const { attachmentsRelativeURL } = require("../../../utilities")
19
18
  const { DocumentTypes } = require("../../../db/utils")
19
+ const { getAppDB, updateAppId } = require("@budibase/backend-core/context")
20
+ const AWS = require("aws-sdk")
21
+ const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
20
22
 
21
23
  async function prepareUpload({ s3Key, bucket, metadata, file }) {
22
24
  const response = await upload({
@@ -37,15 +39,19 @@ async function prepareUpload({ s3Key, bucket, metadata, file }) {
37
39
  }
38
40
  }
39
41
 
40
- async function checkForSelfHostedURL(ctx) {
41
- // the "appId" component of the URL may actually be a specific self hosted URL
42
+ async function getAppIdFromUrl(ctx) {
43
+ // the "appId" component of the URL can be the id or the custom url
42
44
  let possibleAppUrl = `/${encodeURI(ctx.params.appId).toLowerCase()}`
43
- const apps = await getDeployedApps()
44
- if (apps[possibleAppUrl] && apps[possibleAppUrl].appId) {
45
- return apps[possibleAppUrl].appId
46
- } else {
47
- return ctx.params.appId
48
- }
45
+
46
+ // search prod apps for a url that matches, exclude dev where id is always used
47
+ const apps = await getAllApps({ dev: false })
48
+ const app = apps.filter(
49
+ a => a.url && a.url.toLowerCase() === possibleAppUrl
50
+ )[0]
51
+
52
+ const appId = app && app.appId ? app.appId : ctx.params.appId
53
+ updateAppId(appId)
54
+ return appId
49
55
  }
50
56
 
51
57
  exports.serveBuilder = async function (ctx) {
@@ -75,12 +81,9 @@ exports.uploadFile = async function (ctx) {
75
81
  }
76
82
 
77
83
  exports.serveApp = async function (ctx) {
78
- let appId = ctx.params.appId
79
- if (env.SELF_HOSTED) {
80
- appId = await checkForSelfHostedURL(ctx)
81
- }
84
+ let appId = await getAppIdFromUrl(ctx)
82
85
  const App = require("./templates/BudibaseApp.svelte").default
83
- const db = new CouchDB(appId, { skip_setup: true })
86
+ const db = getAppDB({ skip_setup: true })
84
87
  const appInfo = await db.get(DocumentTypes.APP_METADATA)
85
88
 
86
89
  const { head, html, css } = App.render({
@@ -104,3 +107,51 @@ exports.serveClientLibrary = async function (ctx) {
104
107
  root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"),
105
108
  })
106
109
  }
110
+
111
+ exports.getSignedUploadURL = async function (ctx) {
112
+ const database = getAppDB()
113
+
114
+ // Ensure datasource is valid
115
+ let datasource
116
+ try {
117
+ const { datasourceId } = ctx.params
118
+ datasource = await database.get(datasourceId)
119
+ if (!datasource) {
120
+ ctx.throw(400, "The specified datasource could not be found")
121
+ }
122
+ } catch (error) {
123
+ ctx.throw(400, "The specified datasource could not be found")
124
+ }
125
+
126
+ // Ensure we aren't using a custom endpoint
127
+ if (datasource?.config?.endpoint) {
128
+ ctx.throw(400, "S3 datasources with custom endpoints are not supported")
129
+ }
130
+
131
+ // Determine type of datasource and generate signed URL
132
+ let signedUrl
133
+ let publicUrl
134
+ if (datasource.source === "S3") {
135
+ const { bucket, key } = ctx.request.body || {}
136
+ if (!bucket || !key) {
137
+ ctx.throw(400, "bucket and key values are required")
138
+ return
139
+ }
140
+ try {
141
+ const s3 = new AWS.S3({
142
+ region: AWS_REGION,
143
+ accessKeyId: datasource?.config?.accessKeyId,
144
+ secretAccessKey: datasource?.config?.secretAccessKey,
145
+ apiVersion: "2006-03-01",
146
+ signatureVersion: "v4",
147
+ })
148
+ const params = { Bucket: bucket, Key: key }
149
+ signedUrl = s3.getSignedUrl("putObject", params)
150
+ publicUrl = `https://${bucket}.s3.${AWS_REGION}.amazonaws.com/${key}`
151
+ } catch (error) {
152
+ ctx.throw(400, error)
153
+ }
154
+ }
155
+
156
+ ctx.body = { signedUrl, publicUrl }
157
+ }
@@ -0,0 +1,173 @@
1
+ const { FieldTypes, FormulaTypes } = require("../../../constants")
2
+ const { getAllInternalTables, clearColumns } = require("./utils")
3
+ const { doesContainStrings } = require("@budibase/string-templates")
4
+ const { cloneDeep } = require("lodash/fp")
5
+ const { isEqual, uniq } = require("lodash")
6
+ const { updateAllFormulasInTable } = require("../row/staticFormula")
7
+ const { getAppDB } = require("@budibase/backend-core/context")
8
+
9
+ function isStaticFormula(column) {
10
+ return (
11
+ column.type === FieldTypes.FORMULA &&
12
+ column.formulaType === FormulaTypes.STATIC
13
+ )
14
+ }
15
+
16
+ /**
17
+ * This retrieves the formula columns from a table schema that use a specified column name
18
+ * in the formula.
19
+ */
20
+ function getFormulaThatUseColumn(table, columnNames) {
21
+ let formula = []
22
+ columnNames = Array.isArray(columnNames) ? columnNames : [columnNames]
23
+ for (let column of Object.values(table.schema)) {
24
+ // not a static formula, or doesn't contain a relationship
25
+ if (!isStaticFormula(column)) {
26
+ continue
27
+ }
28
+ if (!doesContainStrings(column.formula, columnNames)) {
29
+ continue
30
+ }
31
+ formula.push(column.name)
32
+ }
33
+ return formula
34
+ }
35
+
36
+ /**
37
+ * This functions checks for when a related table, column or related column is deleted, if any
38
+ * tables need to have the formula column removed.
39
+ */
40
+ async function checkIfFormulaNeedsCleared(table, { oldTable, deletion }) {
41
+ // start by retrieving all tables, remove the current table from the list
42
+ const tables = (await getAllInternalTables()).filter(
43
+ tbl => tbl._id !== table._id
44
+ )
45
+ const schemaToUse = oldTable ? oldTable.schema : table.schema
46
+ let removedColumns = Object.values(schemaToUse).filter(
47
+ column => deletion || !table.schema[column.name]
48
+ )
49
+ // remove any formula columns that used related columns
50
+ for (let removed of removedColumns) {
51
+ let tableToUse = table
52
+ // if relationship, get the related table
53
+ if (removed.type === FieldTypes.LINK) {
54
+ tableToUse = tables.find(table => table._id === removed.tableId)
55
+ }
56
+ const columnsToDelete = getFormulaThatUseColumn(tableToUse, removed.name)
57
+ if (columnsToDelete.length > 0) {
58
+ await clearColumns(table, columnsToDelete)
59
+ }
60
+ // need a special case, where a column has been removed from this table, but was used
61
+ // in a different, related tables formula
62
+ if (!table.relatedFormula) {
63
+ continue
64
+ }
65
+ for (let relatedTableId of table.relatedFormula) {
66
+ const relatedColumns = Object.values(table.schema).filter(
67
+ column => column.tableId === relatedTableId
68
+ )
69
+ const relatedTable = tables.find(table => table._id === relatedTableId)
70
+ // look to see if the column was used in a relationship formula,
71
+ // relationships won't be used for this
72
+ if (relatedTable && relatedColumns && removed.type !== FieldTypes.LINK) {
73
+ let relatedFormulaToRemove = []
74
+ for (let column of relatedColumns) {
75
+ relatedFormulaToRemove = relatedFormulaToRemove.concat(
76
+ getFormulaThatUseColumn(relatedTable, [
77
+ column.fieldName,
78
+ removed.name,
79
+ ])
80
+ )
81
+ }
82
+ if (relatedFormulaToRemove.length > 0) {
83
+ await clearColumns(relatedTable, uniq(relatedFormulaToRemove))
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ /**
91
+ * This function adds a note to related tables that they are
92
+ * used in a static formula - so that the link controller
93
+ * can manage hydrating related rows formula fields. This is
94
+ * specifically only for static formula.
95
+ */
96
+ async function updateRelatedFormulaLinksOnTables(
97
+ table,
98
+ { deletion } = { deletion: false }
99
+ ) {
100
+ const db = getAppDB()
101
+ // start by retrieving all tables, remove the current table from the list
102
+ const tables = (await getAllInternalTables()).filter(
103
+ tbl => tbl._id !== table._id
104
+ )
105
+ // clone the tables, so we can compare at end
106
+ const initialTables = cloneDeep(tables)
107
+ // first find the related column names
108
+ const relatedColumns = Object.values(table.schema).filter(
109
+ col => col.type === FieldTypes.LINK
110
+ )
111
+ // we start by removing the formula field from all tables
112
+ for (let otherTable of tables) {
113
+ if (!otherTable.relatedFormula) {
114
+ continue
115
+ }
116
+ const index = otherTable.relatedFormula.indexOf(table._id)
117
+ if (index !== -1) {
118
+ otherTable.relatedFormula.splice(index, 1)
119
+ }
120
+ }
121
+ // if deleting, just remove the table IDs, don't try add
122
+ if (!deletion) {
123
+ for (let relatedCol of relatedColumns) {
124
+ let columns = getFormulaThatUseColumn(table, relatedCol.name)
125
+ if (!columns || columns.length === 0) {
126
+ continue
127
+ }
128
+ const relatedTable = tables.find(
129
+ related => related._id === relatedCol.tableId
130
+ )
131
+ // check if the table is already in the list of related formula, if it isn't, then add it
132
+ if (
133
+ relatedTable &&
134
+ (!relatedTable.relatedFormula ||
135
+ !relatedTable.relatedFormula.includes(table._id))
136
+ ) {
137
+ relatedTable.relatedFormula = relatedTable.relatedFormula
138
+ ? [...relatedTable.relatedFormula, table._id]
139
+ : [table._id]
140
+ }
141
+ }
142
+ }
143
+ // now we just need to compare all the tables and see if any need saved
144
+ for (let initial of initialTables) {
145
+ const found = tables.find(tbl => initial._id === tbl._id)
146
+ if (found && !isEqual(initial, found)) {
147
+ await db.put(found)
148
+ }
149
+ }
150
+ }
151
+
152
+ async function checkIfFormulaUpdated(table, { oldTable }) {
153
+ // look to see if any formula values have changed
154
+ const shouldUpdate = Object.values(table.schema).find(
155
+ column =>
156
+ isStaticFormula(column) &&
157
+ (!oldTable ||
158
+ !oldTable.schema[column.name] ||
159
+ !isEqual(oldTable.schema[column.name], column))
160
+ )
161
+ // if a static formula column has updated, then need to run the update
162
+ if (shouldUpdate != null) {
163
+ await updateAllFormulasInTable(table)
164
+ }
165
+ }
166
+
167
+ exports.runStaticFormulaChecks = async (table, { oldTable, deletion }) => {
168
+ await updateRelatedFormulaLinksOnTables(table, { deletion })
169
+ await checkIfFormulaNeedsCleared(table, { oldTable, deletion })
170
+ if (!deletion) {
171
+ await checkIfFormulaUpdated(table, { oldTable })
172
+ }
173
+ }
@@ -1,4 +1,3 @@
1
- const CouchDB = require("../../../db")
2
1
  const {
3
2
  buildExternalTableId,
4
3
  breakExternalTableId,
@@ -19,6 +18,7 @@ const { makeExternalQuery } = require("../../../integrations/base/utils")
19
18
  const { cloneDeep } = require("lodash/fp")
20
19
  const csvParser = require("../../../utilities/csvParser")
21
20
  const { handleRequest } = require("../row/external")
21
+ const { getAppDB } = require("@budibase/backend-core/context")
22
22
 
23
23
  async function makeTableRequest(
24
24
  datasource,
@@ -159,7 +159,6 @@ function isRelationshipSetup(column) {
159
159
  }
160
160
 
161
161
  exports.save = async function (ctx) {
162
- const appId = ctx.appId
163
162
  const table = ctx.request.body
164
163
  // can't do this right now
165
164
  delete table.dataImport
@@ -176,14 +175,14 @@ exports.save = async function (ctx) {
176
175
 
177
176
  let oldTable
178
177
  if (ctx.request.body && ctx.request.body._id) {
179
- oldTable = await getTable(appId, ctx.request.body._id)
178
+ oldTable = await getTable(ctx.request.body._id)
180
179
  }
181
180
 
182
181
  if (hasTypeChanged(tableToSave, oldTable)) {
183
182
  ctx.throw(400, "A column type has changed.")
184
183
  }
185
184
 
186
- const db = new CouchDB(appId)
185
+ const db = getAppDB()
187
186
  const datasource = await db.get(datasourceId)
188
187
  const oldTables = cloneDeep(datasource.entities)
189
188
  const tables = datasource.entities
@@ -267,14 +266,13 @@ exports.save = async function (ctx) {
267
266
  }
268
267
 
269
268
  exports.destroy = async function (ctx) {
270
- const appId = ctx.appId
271
- const tableToDelete = await getTable(appId, ctx.params.tableId)
269
+ const tableToDelete = await getTable(ctx.params.tableId)
272
270
  if (!tableToDelete || !tableToDelete.created) {
273
271
  ctx.throw(400, "Cannot delete tables which weren't created in Budibase.")
274
272
  }
275
273
  const datasourceId = getDatasourceId(tableToDelete)
276
274
 
277
- const db = new CouchDB(appId)
275
+ const db = getAppDB()
278
276
  const datasource = await db.get(datasourceId)
279
277
  const tables = datasource.entities
280
278
 
@@ -290,8 +288,7 @@ exports.destroy = async function (ctx) {
290
288
  }
291
289
 
292
290
  exports.bulkImport = async function (ctx) {
293
- const appId = ctx.appId
294
- const table = await getTable(appId, ctx.params.tableId)
291
+ const table = await getTable(ctx.params.tableId)
295
292
  const { dataImport } = ctx.request.body
296
293
  if (!dataImport || !dataImport.schema || !dataImport.csvString) {
297
294
  ctx.throw(400, "Provided data import information is invalid.")
@@ -300,7 +297,7 @@ exports.bulkImport = async function (ctx) {
300
297
  ...dataImport,
301
298
  existingTable: table,
302
299
  })
303
- await handleRequest(appId, DataSourceOperation.BULK_CREATE, table._id, {
300
+ await handleRequest(DataSourceOperation.BULK_CREATE, table._id, {
304
301
  rows,
305
302
  })
306
303
  return table
@@ -1,14 +1,10 @@
1
- const CouchDB = require("../../../db")
2
1
  const internal = require("./internal")
3
2
  const external = require("./external")
4
3
  const csvParser = require("../../../utilities/csvParser")
5
- const { isExternalTable } = require("../../../integrations/utils")
6
- const {
7
- getTableParams,
8
- getDatasourceParams,
9
- BudibaseInternalDB,
10
- } = require("../../../db/utils")
11
- const { getTable } = require("./utils")
4
+ const { isExternalTable, isSQL } = require("../../../integrations/utils")
5
+ const { getDatasourceParams } = require("../../../db/utils")
6
+ const { getAppDB } = require("@budibase/backend-core/context")
7
+ const { getTable, getAllInternalTables } = require("./utils")
12
8
 
13
9
  function pickApi({ tableId, table }) {
14
10
  if (table && !tableId) {
@@ -24,19 +20,9 @@ function pickApi({ tableId, table }) {
24
20
 
25
21
  // covers both internal and external
26
22
  exports.fetch = async function (ctx) {
27
- const db = new CouchDB(ctx.appId)
23
+ const db = getAppDB()
28
24
 
29
- const internalTables = await db.allDocs(
30
- getTableParams(null, {
31
- include_docs: true,
32
- })
33
- )
34
-
35
- const internal = internalTables.rows.map(row => ({
36
- ...row.doc,
37
- type: "internal",
38
- sourceId: BudibaseInternalDB._id,
39
- }))
25
+ const internal = await getAllInternalTables()
40
26
 
41
27
  const externalTables = await db.allDocs(
42
28
  getDatasourceParams("plus", {
@@ -44,12 +30,18 @@ exports.fetch = async function (ctx) {
44
30
  })
45
31
  )
46
32
 
47
- const external = externalTables.rows.flatMap(row => {
48
- return Object.values(row.doc.entities || {}).map(entity => ({
49
- ...entity,
50
- type: "external",
51
- sourceId: row.doc._id,
52
- }))
33
+ const external = externalTables.rows.flatMap(tableDoc => {
34
+ let entities = tableDoc.doc.entities
35
+ if (entities) {
36
+ return Object.values(entities).map(entity => ({
37
+ ...entity,
38
+ type: "external",
39
+ sourceId: tableDoc.doc._id,
40
+ sql: isSQL(tableDoc.doc),
41
+ }))
42
+ } else {
43
+ return []
44
+ }
53
45
  })
54
46
 
55
47
  ctx.body = [...internal, ...external]
@@ -57,7 +49,7 @@ exports.fetch = async function (ctx) {
57
49
 
58
50
  exports.find = async function (ctx) {
59
51
  const tableId = ctx.params.id
60
- ctx.body = await getTable(ctx.appId, tableId)
52
+ ctx.body = await getTable(tableId)
61
53
  }
62
54
 
63
55
  exports.save = async function (ctx) {
@@ -96,7 +88,7 @@ exports.validateCSVSchema = async function (ctx) {
96
88
  const { csvString, schema = {}, tableId } = ctx.request.body
97
89
  let existingTable
98
90
  if (tableId) {
99
- existingTable = await getTable(ctx.appId, tableId)
91
+ existingTable = await getTable(tableId)
100
92
  }
101
93
  let result = await csvParser.parse(csvString, schema)
102
94
  if (existingTable) {
@@ -1,4 +1,3 @@
1
- const CouchDB = require("../../../db")
2
1
  const linkRows = require("../../../db/linkedRows")
3
2
  const { getRowParams, generateTableID } = require("../../../db/utils")
4
3
  const { FieldTypes } = require("../../../constants")
@@ -8,10 +7,14 @@ const {
8
7
  getTable,
9
8
  handleDataImport,
10
9
  } = require("./utils")
10
+ const usageQuota = require("../../../utilities/usageQuota")
11
+ const { getAppDB } = require("@budibase/backend-core/context")
12
+ const env = require("../../../environment")
13
+ const { cleanupAttachments } = require("../../../utilities/rowProcessor")
14
+ const { runStaticFormulaChecks } = require("./bulkFormula")
11
15
 
12
16
  exports.save = async function (ctx) {
13
- const appId = ctx.appId
14
- const db = new CouchDB(appId)
17
+ const db = getAppDB()
15
18
  const { dataImport, ...rest } = ctx.request.body
16
19
  let tableToSave = {
17
20
  type: "table",
@@ -33,8 +36,7 @@ exports.save = async function (ctx) {
33
36
  // saving a table is a complex operation, involving many different steps, this
34
37
  // has been broken out into a utility to make it more obvious/easier to manipulate
35
38
  const tableSaveFunctions = new TableSaveFunctions({
36
- db,
37
- ctx,
39
+ user: ctx.user,
38
40
  oldTable,
39
41
  dataImport,
40
42
  })
@@ -79,7 +81,6 @@ exports.save = async function (ctx) {
79
81
  // update linked rows
80
82
  try {
81
83
  const linkResp = await linkRows.updateLinks({
82
- appId,
83
84
  eventType: oldTable
84
85
  ? linkRows.EventType.TABLE_UPDATED
85
86
  : linkRows.EventType.TABLE_SAVE,
@@ -103,13 +104,13 @@ exports.save = async function (ctx) {
103
104
  tableToSave._rev = result.rev
104
105
 
105
106
  tableToSave = await tableSaveFunctions.after(tableToSave)
106
-
107
+ // has to run after, make sure it has _id
108
+ await runStaticFormulaChecks(tableToSave, { oldTable })
107
109
  return tableToSave
108
110
  }
109
111
 
110
112
  exports.destroy = async function (ctx) {
111
- const appId = ctx.appId
112
- const db = new CouchDB(appId)
113
+ const db = getAppDB()
113
114
  const tableToDelete = await db.get(ctx.params.tableId)
114
115
 
115
116
  // Delete all rows for that table
@@ -119,10 +120,10 @@ exports.destroy = async function (ctx) {
119
120
  })
120
121
  )
121
122
  await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
123
+ await usageQuota.update(usageQuota.Properties.ROW, -rows.rows.length)
122
124
 
123
125
  // update linked rows
124
126
  await linkRows.updateLinks({
125
- appId,
126
127
  eventType: linkRows.EventType.TABLE_DELETE,
127
128
  table: tableToDelete,
128
129
  })
@@ -131,21 +132,25 @@ exports.destroy = async function (ctx) {
131
132
  await db.remove(tableToDelete)
132
133
 
133
134
  // remove table search index
134
- const currentIndexes = await db.getIndexes()
135
- const existingIndex = currentIndexes.indexes.find(
136
- existing => existing.name === `search:${ctx.params.tableId}`
137
- )
138
- if (existingIndex) {
139
- await db.deleteIndex(existingIndex)
135
+ if (!env.isTest()) {
136
+ const currentIndexes = await db.getIndexes()
137
+ const existingIndex = currentIndexes.indexes.find(
138
+ existing => existing.name === `search:${ctx.params.tableId}`
139
+ )
140
+ if (existingIndex) {
141
+ await db.deleteIndex(existingIndex)
142
+ }
140
143
  }
141
144
 
145
+ // has to run after, make sure it has _id
146
+ await runStaticFormulaChecks(tableToDelete, { deletion: true })
147
+ await cleanupAttachments(tableToDelete, { rows })
142
148
  return tableToDelete
143
149
  }
144
150
 
145
151
  exports.bulkImport = async function (ctx) {
146
- const appId = ctx.appId
147
- const table = await getTable(appId, ctx.params.tableId)
152
+ const table = await getTable(ctx.params.tableId)
148
153
  const { dataImport } = ctx.request.body
149
- await handleDataImport(appId, ctx.user, table, dataImport)
154
+ await handleDataImport(ctx.user, table, dataImport)
150
155
  return table
151
156
  }