@budibase/server 1.0.105-alpha.3 → 1.0.105-alpha.32

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 (310) hide show
  1. package/builder/assets/index.0572486a.js +1296 -0
  2. package/builder/assets/{index.ea3718aa.css → index.f602f4de.css} +2 -2
  3. package/builder/index.html +2 -2
  4. package/coverage/clover.xml +711 -1678
  5. package/coverage/coverage-final.json +30 -45
  6. package/coverage/lcov-report/api/controllers/analytics.js.html +8 -3
  7. package/coverage/lcov-report/api/controllers/apikeys.js.html +9 -4
  8. package/coverage/lcov-report/api/controllers/auth.js.html +8 -3
  9. package/coverage/lcov-report/api/controllers/automation.js.html +8 -3
  10. package/coverage/lcov-report/api/controllers/backup.js.html +8 -3
  11. package/coverage/lcov-report/api/controllers/cloud.js.html +8 -3
  12. package/coverage/lcov-report/api/controllers/component.js.html +8 -3
  13. package/coverage/lcov-report/api/controllers/datasource.js.html +11 -6
  14. package/coverage/lcov-report/api/controllers/dev.js.html +8 -3
  15. package/coverage/lcov-report/api/controllers/index.html +16 -26
  16. package/coverage/lcov-report/api/controllers/integration.js.html +8 -3
  17. package/coverage/lcov-report/api/controllers/layout.js.html +8 -3
  18. package/coverage/lcov-report/api/controllers/metadata.js.html +8 -3
  19. package/coverage/lcov-report/api/controllers/migrations.js.html +8 -3
  20. package/coverage/lcov-report/api/controllers/permission.js.html +8 -3
  21. package/coverage/lcov-report/api/controllers/query/index.html +16 -26
  22. package/coverage/lcov-report/api/controllers/query/validation.js.html +8 -3
  23. package/coverage/lcov-report/api/controllers/role.js.html +10 -5
  24. package/coverage/lcov-report/api/controllers/routing.js.html +9 -4
  25. package/coverage/lcov-report/api/controllers/row/external.js.html +8 -3
  26. package/coverage/lcov-report/api/controllers/row/index.html +25 -35
  27. package/coverage/lcov-report/api/controllers/row/internal.js.html +32 -24
  28. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +21 -16
  29. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +24 -19
  30. package/coverage/lcov-report/api/controllers/row/utils.js.html +33 -19
  31. package/coverage/lcov-report/api/controllers/screen.js.html +9 -4
  32. package/coverage/lcov-report/api/controllers/script.js.html +8 -3
  33. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +55 -50
  34. package/coverage/lcov-report/api/controllers/table/external.js.html +8 -3
  35. package/coverage/lcov-report/api/controllers/table/index.html +19 -44
  36. package/coverage/lcov-report/api/controllers/table/index.js.html +20 -15
  37. package/coverage/lcov-report/api/controllers/templates.js.html +8 -3
  38. package/coverage/lcov-report/api/controllers/user.js.html +8 -3
  39. package/coverage/lcov-report/api/controllers/view/exporters.js.html +8 -3
  40. package/coverage/lcov-report/api/controllers/view/index.html +8 -3
  41. package/coverage/lcov-report/api/controllers/view/index.js.html +10 -5
  42. package/coverage/lcov-report/api/controllers/view/utils.js.html +8 -3
  43. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +8 -3
  44. package/coverage/lcov-report/api/controllers/webhook.js.html +10 -5
  45. package/coverage/lcov-report/api/index.html +18 -13
  46. package/coverage/lcov-report/api/index.js.html +28 -8
  47. package/coverage/lcov-report/api/routes/analytics.js.html +8 -3
  48. package/coverage/lcov-report/api/routes/apikeys.js.html +8 -3
  49. package/coverage/lcov-report/api/routes/auth.js.html +8 -3
  50. package/coverage/lcov-report/api/routes/automation.js.html +8 -3
  51. package/coverage/lcov-report/api/routes/backup.js.html +8 -3
  52. package/coverage/lcov-report/api/routes/cloud.js.html +8 -3
  53. package/coverage/lcov-report/api/routes/component.js.html +8 -3
  54. package/coverage/lcov-report/api/routes/datasource.js.html +8 -3
  55. package/coverage/lcov-report/api/routes/deploy.js.html +8 -3
  56. package/coverage/lcov-report/api/routes/dev.js.html +9 -4
  57. package/coverage/lcov-report/api/routes/index.html +13 -68
  58. package/coverage/lcov-report/api/routes/integration.js.html +8 -3
  59. package/coverage/lcov-report/api/routes/layout.js.html +8 -3
  60. package/coverage/lcov-report/api/routes/metadata.js.html +8 -3
  61. package/coverage/lcov-report/api/routes/migrations.js.html +8 -3
  62. package/coverage/lcov-report/api/routes/permission.js.html +8 -3
  63. package/coverage/lcov-report/api/routes/query.js.html +8 -3
  64. package/coverage/lcov-report/api/routes/role.js.html +8 -3
  65. package/coverage/lcov-report/api/routes/routing.js.html +8 -3
  66. package/coverage/lcov-report/api/routes/screen.js.html +8 -3
  67. package/coverage/lcov-report/api/routes/script.js.html +8 -3
  68. package/coverage/lcov-report/api/routes/table.js.html +8 -3
  69. package/coverage/lcov-report/api/routes/templates.js.html +8 -3
  70. package/coverage/lcov-report/api/routes/user.js.html +8 -3
  71. package/coverage/lcov-report/api/routes/utils/index.html +8 -3
  72. package/coverage/lcov-report/api/routes/utils/validators.js.html +8 -3
  73. package/coverage/lcov-report/api/routes/view.js.html +8 -3
  74. package/coverage/lcov-report/api/routes/webhook.js.html +8 -3
  75. package/coverage/lcov-report/automations/actions.js.html +21 -7
  76. package/coverage/lcov-report/automations/automationUtils.js.html +64 -23
  77. package/coverage/lcov-report/automations/bullboard.js.html +8 -3
  78. package/coverage/lcov-report/automations/index.html +27 -37
  79. package/coverage/lcov-report/automations/index.js.html +8 -3
  80. package/coverage/lcov-report/automations/steps/bash.js.html +8 -3
  81. package/coverage/lcov-report/automations/steps/delay.js.html +8 -3
  82. package/coverage/lcov-report/automations/steps/discord.js.html +8 -3
  83. package/coverage/lcov-report/automations/steps/executeQuery.js.html +8 -3
  84. package/coverage/lcov-report/automations/steps/executeScript.js.html +8 -3
  85. package/coverage/lcov-report/automations/steps/filter.js.html +8 -3
  86. package/coverage/lcov-report/automations/steps/index.html +31 -41
  87. package/coverage/lcov-report/automations/steps/integromat.js.html +8 -3
  88. package/coverage/lcov-report/{api/routes/static.js.html → automations/steps/loop.js.html} +70 -80
  89. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +9 -4
  90. package/coverage/lcov-report/automations/steps/queryRows.js.html +9 -4
  91. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +8 -3
  92. package/coverage/lcov-report/automations/steps/serverLog.js.html +8 -3
  93. package/coverage/lcov-report/automations/steps/slack.js.html +8 -3
  94. package/coverage/lcov-report/automations/steps/updateRow.js.html +8 -3
  95. package/coverage/lcov-report/automations/steps/utils.js.html +14 -9
  96. package/coverage/lcov-report/automations/steps/zapier.js.html +8 -3
  97. package/coverage/lcov-report/automations/triggerInfo/app.js.html +8 -3
  98. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +8 -3
  99. package/coverage/lcov-report/automations/triggerInfo/index.html +8 -3
  100. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -3
  101. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +8 -3
  102. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +8 -3
  103. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +8 -3
  104. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +8 -3
  105. package/coverage/lcov-report/automations/triggers.js.html +16 -11
  106. package/coverage/lcov-report/block-navigation.js +8 -0
  107. package/coverage/lcov-report/constants/index.html +12 -7
  108. package/coverage/lcov-report/constants/index.js.html +54 -31
  109. package/coverage/lcov-report/constants/layouts.js.html +8 -3
  110. package/coverage/lcov-report/constants/screens.js.html +8 -3
  111. package/coverage/lcov-report/db/client.js.html +26 -21
  112. package/coverage/lcov-report/db/inMemoryView.js.html +8 -3
  113. package/coverage/lcov-report/db/index.html +8 -3
  114. package/coverage/lcov-report/db/index.js.html +10 -5
  115. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +20 -15
  116. package/coverage/lcov-report/db/linkedRows/index.html +8 -3
  117. package/coverage/lcov-report/db/linkedRows/index.js.html +22 -17
  118. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +12 -7
  119. package/coverage/lcov-report/db/newid.js.html +11 -6
  120. package/coverage/lcov-report/db/utils.js.html +83 -78
  121. package/coverage/lcov-report/events/AutomationEmitter.js.html +14 -9
  122. package/coverage/lcov-report/events/index.html +8 -3
  123. package/coverage/lcov-report/events/index.js.html +9 -4
  124. package/coverage/lcov-report/events/utils.js.html +18 -13
  125. package/coverage/lcov-report/index.html +124 -119
  126. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +8 -3
  127. package/coverage/lcov-report/integrations/tests/index.html +8 -3
  128. package/coverage/lcov-report/middleware/appInfo.js.html +8 -3
  129. package/coverage/lcov-report/middleware/builder.js.html +8 -3
  130. package/coverage/lcov-report/middleware/currentapp.js.html +65 -15
  131. package/coverage/lcov-report/middleware/index.html +25 -50
  132. package/coverage/lcov-report/middleware/joi-validator.js.html +9 -4
  133. package/coverage/lcov-report/middleware/publicApi.js.html +8 -3
  134. package/coverage/lcov-report/middleware/resourceId.js.html +8 -3
  135. package/coverage/lcov-report/middleware/selfhost.js.html +9 -4
  136. package/coverage/lcov-report/middleware/utils.js.html +8 -3
  137. package/coverage/lcov-report/sorter.js +26 -0
  138. package/coverage/lcov-report/threads/automation.js.html +581 -90
  139. package/coverage/lcov-report/threads/index.html +27 -37
  140. package/coverage/lcov-report/threads/query.js.html +10 -5
  141. package/coverage/lcov-report/threads/utils.js.html +11 -6
  142. package/coverage/lcov-report/utilities/bcrypt.js.html +8 -3
  143. package/coverage/lcov-report/utilities/budibaseDir.js.html +8 -3
  144. package/coverage/lcov-report/utilities/centralPath.js.html +8 -3
  145. package/coverage/lcov-report/utilities/csvParser.js.html +10 -5
  146. package/coverage/lcov-report/utilities/global.js.html +9 -4
  147. package/coverage/lcov-report/utilities/index.html +8 -3
  148. package/coverage/lcov-report/utilities/index.js.html +11 -6
  149. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +32 -9
  150. package/coverage/lcov-report/utilities/queue/index.html +12 -7
  151. package/coverage/lcov-report/utilities/routing/index.html +8 -3
  152. package/coverage/lcov-report/utilities/routing/index.js.html +8 -3
  153. package/coverage/lcov-report/utilities/rowProcessor/index.html +8 -3
  154. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +46 -41
  155. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +18 -13
  156. package/coverage/lcov-report/utilities/scriptRunner.js.html +8 -3
  157. package/coverage/lcov-report/utilities/security.js.html +9 -4
  158. package/coverage/lcov-report/utilities/statusCodes.js.html +8 -3
  159. package/coverage/lcov-report/utilities/usageQuota/index.html +24 -34
  160. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +45 -40
  161. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +8 -3
  162. package/coverage/lcov-report/utilities/users.js.html +8 -3
  163. package/coverage/lcov-report/utilities/workerRequests.js.html +9 -4
  164. package/coverage/lcov.info +1141 -2837
  165. package/dist/api/controllers/application.js +138 -70
  166. package/dist/api/controllers/deploy/index.js +64 -35
  167. package/dist/api/controllers/public/applications.js +29 -9
  168. package/dist/api/controllers/public/queries.js +27 -7
  169. package/dist/api/controllers/public/rows.js +32 -12
  170. package/dist/api/controllers/public/tables.js +2 -2
  171. package/dist/api/controllers/public/users.js +8 -8
  172. package/dist/api/controllers/public/utils.js +1 -1
  173. package/dist/api/controllers/query/import/index.js +3 -3
  174. package/dist/api/controllers/query/index.js +57 -44
  175. package/dist/api/controllers/row/ExternalRequest.js +27 -27
  176. package/dist/api/controllers/row/index.js +83 -60
  177. package/dist/api/controllers/row/internal.js +2 -1
  178. package/dist/api/controllers/row/utils.js +2 -1
  179. package/dist/api/controllers/static/templates/BudibaseApp.svelte +3 -0
  180. package/dist/api/controllers/table/bulkFormula.js +2 -1
  181. package/dist/api/controllers/table/internal.js +40 -34
  182. package/dist/api/controllers/table/utils.js +271 -229
  183. package/dist/api/index.js +5 -0
  184. package/dist/api/routes/application.js +39 -13
  185. package/dist/api/routes/index.js +61 -56
  186. package/dist/api/routes/public/index.js +6 -9
  187. package/dist/api/routes/public/queries.js +1 -1
  188. package/dist/api/routes/public/rows.js +1 -1
  189. package/dist/api/routes/public/tables.js +3 -3
  190. package/dist/api/routes/public/users.js +1 -1
  191. package/dist/api/routes/row.js +43 -17
  192. package/dist/api/routes/static.js +40 -13
  193. package/dist/api/routes/tests/utilities/TestFunctions.js +62 -26
  194. package/dist/app.js +11 -4
  195. package/dist/automations/actions.js +3 -0
  196. package/dist/automations/automationUtils.js +10 -0
  197. package/dist/automations/steps/createRow.js +12 -12
  198. package/dist/automations/steps/deleteRow.js +13 -16
  199. package/dist/automations/steps/loop.js +51 -0
  200. package/dist/automations/tests/utilities/index.js +0 -2
  201. package/dist/automations/utils.js +187 -132
  202. package/dist/constants/index.js +5 -0
  203. package/dist/environment.js +1 -2
  204. package/dist/integrations/base/sql.js +2 -2
  205. package/dist/integrations/base/sqlTable.js +2 -2
  206. package/dist/integrations/googlesheets.js +1 -1
  207. package/dist/integrations/microsoftSqlServer.js +8 -8
  208. package/dist/integrations/mysql.js +9 -9
  209. package/dist/integrations/oracle.js +7 -7
  210. package/dist/integrations/postgres.js +7 -7
  211. package/dist/integrations/rest.js +1 -1
  212. package/dist/middleware/authorized.js +51 -51
  213. package/dist/middleware/currentapp.js +15 -1
  214. package/dist/migrations/functions/appUrls.js +1 -1
  215. package/dist/migrations/functions/developerQuota.js +49 -0
  216. package/dist/migrations/functions/publishedAppsQuota.js +47 -0
  217. package/dist/migrations/functions/quotas1.js +6 -2
  218. package/dist/migrations/functions/usageQuotas/index.js +0 -4
  219. package/dist/migrations/functions/usageQuotas/syncApps.js +4 -7
  220. package/dist/migrations/functions/usageQuotas/syncDevelopers.js +24 -0
  221. package/dist/migrations/functions/usageQuotas/syncPublishedApps.js +26 -0
  222. package/dist/migrations/functions/usageQuotas/syncRows.js +5 -8
  223. package/dist/migrations/index.js +17 -1
  224. package/dist/package.json +11 -8
  225. package/dist/threads/automation.js +149 -27
  226. package/dist/threads/index.js +35 -8
  227. package/dist/tsconfig.build.tsbuildinfo +1 -0
  228. package/dist/utilities/queue/inMemoryQueue.js +6 -1
  229. package/nodemon.json +1 -1
  230. package/package.json +12 -9
  231. package/scripts/dev/manage.js +2 -0
  232. package/src/api/controllers/{application.js → application.ts} +103 -44
  233. package/src/api/controllers/deploy/{index.js → index.ts} +45 -28
  234. package/src/api/controllers/public/applications.ts +2 -2
  235. package/src/api/controllers/public/queries.ts +1 -1
  236. package/src/api/controllers/public/rows.ts +1 -1
  237. package/src/api/controllers/query/{index.js → index.ts} +51 -48
  238. package/src/api/controllers/row/ExternalRequest.ts +1 -1
  239. package/src/api/controllers/row/{index.js → index.ts} +24 -17
  240. package/src/api/controllers/row/internal.js +2 -1
  241. package/src/api/controllers/row/utils.js +4 -1
  242. package/src/api/controllers/static/templates/BudibaseApp.svelte +3 -0
  243. package/src/api/controllers/table/bulkFormula.js +1 -1
  244. package/src/api/controllers/table/{internal.js → internal.ts} +27 -24
  245. package/src/api/controllers/table/{utils.js → utils.ts} +86 -69
  246. package/src/api/index.js +5 -0
  247. package/src/api/routes/{application.js → application.ts} +8 -14
  248. package/src/api/routes/index.ts +60 -0
  249. package/src/api/routes/public/index.ts +1 -4
  250. package/src/api/routes/{row.js → row.ts} +7 -15
  251. package/src/api/routes/{static.js → static.ts} +11 -11
  252. package/src/api/routes/tests/utilities/{TestFunctions.js → TestFunctions.ts} +42 -25
  253. package/src/app.ts +1 -2
  254. package/src/automations/actions.js +3 -0
  255. package/src/automations/automationUtils.js +12 -0
  256. package/src/automations/steps/{createRow.js → createRow.ts} +9 -15
  257. package/src/automations/steps/{deleteRow.js → deleteRow.ts} +10 -16
  258. package/src/automations/steps/loop.js +50 -0
  259. package/src/automations/tests/automation.spec.js +0 -1
  260. package/src/automations/tests/{createRow.spec.js → createRow.spec.ts} +4 -15
  261. package/src/automations/tests/{deleteRow.spec.js → deleteRow.spec.ts} +3 -5
  262. package/src/automations/tests/utilities/index.js +0 -2
  263. package/src/automations/{utils.js → utils.ts} +39 -27
  264. package/src/constants/index.js +6 -0
  265. package/src/environment.js +1 -2
  266. package/src/middleware/{authorized.js → authorized.ts} +20 -14
  267. package/src/middleware/currentapp.js +16 -1
  268. package/src/migrations/functions/developerQuota.ts +15 -0
  269. package/src/migrations/functions/publishedAppsQuota.ts +13 -0
  270. package/src/migrations/functions/tests/quotas1.spec.js +0 -2
  271. package/src/migrations/functions/usageQuotas/index.ts +0 -5
  272. package/src/migrations/functions/usageQuotas/syncApps.ts +3 -6
  273. package/src/migrations/functions/usageQuotas/syncDevelopers.ts +19 -0
  274. package/src/migrations/functions/usageQuotas/syncPublishedApps.ts +21 -0
  275. package/src/migrations/functions/usageQuotas/syncRows.ts +3 -6
  276. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.ts +32 -0
  277. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +38 -0
  278. package/src/migrations/index.ts +13 -1
  279. package/src/module.d.ts +4 -0
  280. package/src/threads/automation.js +196 -34
  281. package/src/threads/{index.js → index.ts} +14 -12
  282. package/src/utilities/queue/inMemoryQueue.js +7 -1
  283. package/tsconfig.build.json +10 -0
  284. package/tsconfig.json +2 -2
  285. package/builder/assets/index.5778ea01.js +0 -1291
  286. package/coverage/lcov-report/api/controllers/application.js.html +0 -1430
  287. package/coverage/lcov-report/api/controllers/query/index.js.html +0 -713
  288. package/coverage/lcov-report/api/controllers/row/index.js.html +0 -524
  289. package/coverage/lcov-report/api/controllers/table/internal.js.html +0 -548
  290. package/coverage/lcov-report/api/controllers/table/utils.js.html +0 -1331
  291. package/coverage/lcov-report/api/routes/application.js.html +0 -179
  292. package/coverage/lcov-report/api/routes/index.js.html +0 -266
  293. package/coverage/lcov-report/api/routes/row.js.html +0 -908
  294. package/coverage/lcov-report/automations/steps/createRow.js.html +0 -380
  295. package/coverage/lcov-report/automations/steps/deleteRow.js.html +0 -347
  296. package/coverage/lcov-report/automations/utils.js.html +0 -662
  297. package/coverage/lcov-report/middleware/authorized.js.html +0 -458
  298. package/coverage/lcov-report/middleware/usageQuota.js.html +0 -572
  299. package/coverage/lcov-report/threads/index.js.html +0 -278
  300. package/coverage/lcov-report/utilities/usageQuota/index.js.html +0 -359
  301. package/dist/middleware/usageQuota.js +0 -154
  302. package/dist/tsconfig.tsbuildinfo +0 -1
  303. package/dist/utilities/usageQuota/index.js +0 -86
  304. package/src/api/routes/index.js +0 -62
  305. package/src/middleware/tests/usageQuota.spec.js +0 -134
  306. package/src/middleware/usageQuota.js +0 -164
  307. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +0 -37
  308. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +0 -43
  309. package/src/utilities/tests/usageQuota/usageQuota.spec.js +0 -72
  310. package/src/utilities/usageQuota/index.js +0 -93
@@ -1,8 +1,8 @@
1
- const {
1
+ import {
2
2
  getUserRoleHierarchy,
3
3
  getRequiredResourceRole,
4
4
  BUILTIN_ROLE_IDS,
5
- } = require("@budibase/backend-core/roles")
5
+ } from "@budibase/backend-core/roles"
6
6
  const {
7
7
  PermissionTypes,
8
8
  PermissionLevels,
@@ -13,7 +13,7 @@ const { isWebhookEndpoint } = require("./utils")
13
13
  const { buildCsrfMiddleware } = require("@budibase/backend-core/auth")
14
14
  const { getAppId } = require("@budibase/backend-core/context")
15
15
 
16
- function hasResource(ctx) {
16
+ function hasResource(ctx: any) {
17
17
  return ctx.resourceId != null
18
18
  }
19
19
 
@@ -25,7 +25,12 @@ const csrf = buildCsrfMiddleware()
25
25
  * - Builders can access all resources.
26
26
  * - Otherwise the user must have the required role.
27
27
  */
28
- const checkAuthorized = async (ctx, resourceRoles, permType, permLevel) => {
28
+ const checkAuthorized = async (
29
+ ctx: any,
30
+ resourceRoles: any,
31
+ permType: any,
32
+ permLevel: any
33
+ ) => {
29
34
  // check if this is a builder api and the user is not a builder
30
35
  const isBuilder = ctx.user && ctx.user.builder && ctx.user.builder.global
31
36
  const isBuilderApi = permType === PermissionTypes.BUILDER
@@ -40,10 +45,10 @@ const checkAuthorized = async (ctx, resourceRoles, permType, permLevel) => {
40
45
  }
41
46
 
42
47
  const checkAuthorizedResource = async (
43
- ctx,
44
- resourceRoles,
45
- permType,
46
- permLevel
48
+ ctx: any,
49
+ resourceRoles: any,
50
+ permType: any,
51
+ permLevel: any
47
52
  ) => {
48
53
  // get the user's roles
49
54
  const roleId = ctx.roleId || BUILTIN_ROLE_IDS.PUBLIC
@@ -54,7 +59,9 @@ const checkAuthorizedResource = async (
54
59
  // check if the user has the required role
55
60
  if (resourceRoles.length > 0) {
56
61
  // deny access if the user doesn't have the required resource role
57
- const found = userRoles.find(role => resourceRoles.indexOf(role._id) !== -1)
62
+ const found = userRoles.find(
63
+ (role: any) => resourceRoles.indexOf(role._id) !== -1
64
+ )
58
65
  if (!found) {
59
66
  ctx.throw(403, permError)
60
67
  }
@@ -64,9 +71,8 @@ const checkAuthorizedResource = async (
64
71
  }
65
72
  }
66
73
 
67
- module.exports =
68
- (permType, permLevel = null, opts = { schema: false }) =>
69
- async (ctx, next) => {
74
+ export = (permType: any, permLevel: any = null, opts = { schema: false }) =>
75
+ async (ctx: any, next: any) => {
70
76
  // webhooks don't need authentication, each webhook unique
71
77
  // also internal requests (between services) don't need authorized
72
78
  if (isWebhookEndpoint(ctx) || ctx.internal) {
@@ -82,8 +88,8 @@ module.exports =
82
88
  await builderMiddleware(ctx, permType)
83
89
 
84
90
  // get the resource roles
85
- let resourceRoles = [],
86
- otherLevelRoles
91
+ let resourceRoles: any = []
92
+ let otherLevelRoles: any = []
87
93
  const otherLevel =
88
94
  permLevel === PermissionLevels.READ
89
95
  ? PermissionLevels.WRITE
@@ -4,7 +4,7 @@ const {
4
4
  getCookie,
5
5
  clearCookie,
6
6
  } = require("@budibase/backend-core/utils")
7
- const { Cookies } = require("@budibase/backend-core/constants")
7
+ const { Cookies, Headers } = require("@budibase/backend-core/constants")
8
8
  const { getRole } = require("@budibase/backend-core/roles")
9
9
  const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles")
10
10
  const { generateUserMetadataID, isDevAppID } = require("../db/utils")
@@ -63,6 +63,21 @@ module.exports = async (ctx, next) => {
63
63
  appId = requestAppId
64
64
  // retrieving global user gets the right role
65
65
  roleId = globalUser.roleId || roleId
66
+
67
+ // Allow builders to specify their role via a header
68
+ const isBuilder =
69
+ globalUser && globalUser.builder && globalUser.builder.global
70
+ const isDevApp = appId && isDevAppID(appId)
71
+ const roleHeader = ctx.request && ctx.request.headers[Headers.PREVIEW_ROLE]
72
+ if (isBuilder && isDevApp && roleHeader) {
73
+ // Ensure the role is valid by ensuring a definition exists
74
+ try {
75
+ await getRole(roleHeader)
76
+ roleId = roleHeader
77
+ } catch (error) {
78
+ // Swallow error and do nothing
79
+ }
80
+ }
66
81
  }
67
82
 
68
83
  // nothing more to do
@@ -0,0 +1,15 @@
1
+ const { createUserBuildersView } = require("@budibase/backend-core/db")
2
+ import * as syncDevelopers from "./usageQuotas/syncDevelopers"
3
+
4
+ /**
5
+ * Date:
6
+ * March 2022
7
+ *
8
+ * Description:
9
+ * Create the builder users view and sync the developer count
10
+ */
11
+
12
+ export const run = async (db: any) => {
13
+ await createUserBuildersView(db)
14
+ await syncDevelopers.run()
15
+ }
@@ -0,0 +1,13 @@
1
+ import * as syncPublishedApps from "./usageQuotas/syncPublishedApps"
2
+
3
+ /**
4
+ * Date:
5
+ * March 2022
6
+ *
7
+ * Description:
8
+ * Sync the published apps count
9
+ */
10
+
11
+ export const run = async (db: any) => {
12
+ await syncPublishedApps.run()
13
+ }
@@ -1,4 +1,3 @@
1
- const env = require("../../../environment")
2
1
  const TestConfig = require("../../../tests/utilities/TestConfiguration")
3
2
 
4
3
  const syncApps = jest.fn()
@@ -14,7 +13,6 @@ describe("run", () => {
14
13
 
15
14
  beforeEach(async () => {
16
15
  await config.init()
17
- env._set("USE_QUOTAS", 1)
18
16
  })
19
17
 
20
18
  afterAll(config.end)
@@ -1,8 +1,3 @@
1
- const { useQuotas } = require("../../../utilities/usageQuota")
2
-
3
1
  export const runQuotaMigration = async (migration: Function) => {
4
- if (!useQuotas()) {
5
- return
6
- }
7
2
  await migration()
8
3
  }
@@ -1,9 +1,8 @@
1
- import { getGlobalDB, getTenantId } from "@budibase/backend-core/tenancy"
1
+ import { getTenantId } from "@budibase/backend-core/tenancy"
2
2
  import { getAllApps } from "@budibase/backend-core/db"
3
- import { getUsageQuotaDoc } from "../../../utilities/usageQuota"
3
+ import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
4
4
 
5
5
  export const run = async () => {
6
- const db = getGlobalDB()
7
6
  // get app count
8
7
  // @ts-ignore
9
8
  const devApps = await getAllApps({ dev: true })
@@ -12,7 +11,5 @@ export const run = async () => {
12
11
  // sync app count
13
12
  const tenantId = getTenantId()
14
13
  console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`)
15
- const usageDoc = await getUsageQuotaDoc(db)
16
- usageDoc.usageQuota.apps = appCount
17
- await db.put(usageDoc)
14
+ await quotas.setUsage(appCount, StaticQuotaName.APPS, QuotaUsageType.STATIC)
18
15
  }
@@ -0,0 +1,19 @@
1
+ import { getTenantId } from "@budibase/backend-core/tenancy"
2
+ import { utils } from "@budibase/backend-core"
3
+ import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
4
+
5
+ export const run = async () => {
6
+ // get developer count
7
+ const developerCount = await utils.getBuildersCount()
8
+
9
+ // sync developer count
10
+ const tenantId = getTenantId()
11
+ console.log(
12
+ `[Tenant: ${tenantId}] Syncing developer count: ${developerCount}`
13
+ )
14
+ await quotas.setUsage(
15
+ developerCount,
16
+ StaticQuotaName.DEVELOPERS,
17
+ QuotaUsageType.STATIC
18
+ )
19
+ }
@@ -0,0 +1,21 @@
1
+ import { getTenantId } from "@budibase/backend-core/tenancy"
2
+ import { getAllApps } from "@budibase/backend-core/db"
3
+ import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
4
+
5
+ export const run = async () => {
6
+ // get app count
7
+ const opts: any = { dev: false }
8
+ const prodApps = await getAllApps(opts)
9
+ const prodAppCount = prodApps ? prodApps.length : 0
10
+
11
+ // sync app count
12
+ const tenantId = getTenantId()
13
+ console.log(
14
+ `[Tenant: ${tenantId}] Syncing published app count: ${prodAppCount}`
15
+ )
16
+ await quotas.setUsage(
17
+ prodAppCount,
18
+ StaticQuotaName.PUBLISHED_APPS,
19
+ QuotaUsageType.STATIC
20
+ )
21
+ }
@@ -1,10 +1,9 @@
1
- import { getGlobalDB, getTenantId } from "@budibase/backend-core/tenancy"
1
+ import { getTenantId } from "@budibase/backend-core/tenancy"
2
2
  import { getAllApps } from "@budibase/backend-core/db"
3
- import { getUsageQuotaDoc } from "../../../utilities/usageQuota"
4
3
  import { getUniqueRows } from "../../../utilities/usageQuota/rows"
4
+ import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
5
5
 
6
6
  export const run = async () => {
7
- const db = getGlobalDB()
8
7
  // get all rows in all apps
9
8
  // @ts-ignore
10
9
  const allApps = await getAllApps({ all: true })
@@ -16,7 +15,5 @@ export const run = async () => {
16
15
  // sync row count
17
16
  const tenantId = getTenantId()
18
17
  console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`)
19
- const usageDoc = await getUsageQuotaDoc(db)
20
- usageDoc.usageQuota.rows = rowCount
21
- await db.put(usageDoc)
18
+ await quotas.setUsage(rowCount, StaticQuotaName.ROWS, QuotaUsageType.STATIC)
22
19
  }
@@ -0,0 +1,32 @@
1
+ import TestConfig from "../../../../tests/utilities/TestConfiguration"
2
+ import * as syncApps from "../syncApps"
3
+ import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
4
+
5
+ describe("syncApps", () => {
6
+ let config = new TestConfig(false)
7
+
8
+ beforeEach(async () => {
9
+ await config.init()
10
+ })
11
+
12
+ afterAll(config.end)
13
+
14
+ it("runs successfully", async () => {
15
+ // create the usage quota doc and mock usages
16
+ await quotas.getQuotaUsage()
17
+ await quotas.setUsage(3, StaticQuotaName.APPS, QuotaUsageType.STATIC)
18
+
19
+ let usageDoc = await quotas.getQuotaUsage()
20
+ expect(usageDoc.usageQuota.apps).toEqual(3)
21
+
22
+ // create an extra app to test the migration
23
+ await config.createApp("quota-test")
24
+
25
+ // migrate
26
+ await syncApps.run()
27
+
28
+ // assert the migration worked
29
+ usageDoc = await quotas.getQuotaUsage()
30
+ expect(usageDoc.usageQuota.apps).toEqual(2)
31
+ })
32
+ })
@@ -0,0 +1,38 @@
1
+ import TestConfig from "../../../../tests/utilities/TestConfiguration"
2
+ import * as syncRows from "../syncRows"
3
+ import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
4
+
5
+ describe("syncRows", () => {
6
+ let config = new TestConfig(false)
7
+
8
+ beforeEach(async () => {
9
+ await config.init()
10
+ })
11
+
12
+ afterAll(config.end)
13
+
14
+ it("runs successfully", async () => {
15
+ // create the usage quota doc and mock usages
16
+ await quotas.getQuotaUsage()
17
+ await quotas.setUsage(300, StaticQuotaName.ROWS, QuotaUsageType.STATIC)
18
+
19
+ let usageDoc = await quotas.getQuotaUsage()
20
+ expect(usageDoc.usageQuota.rows).toEqual(300)
21
+
22
+ // app 1
23
+ await config.createTable()
24
+ await config.createRow()
25
+ // app 2
26
+ await config.createApp("second-app")
27
+ await config.createTable()
28
+ await config.createRow()
29
+ await config.createRow()
30
+
31
+ // migrate
32
+ await syncRows.run()
33
+
34
+ // assert the migration worked
35
+ usageDoc = await quotas.getQuotaUsage()
36
+ expect(usageDoc.usageQuota.rows).toEqual(3)
37
+ })
38
+ })
@@ -8,6 +8,8 @@ const {
8
8
  import * as userEmailViewCasing from "./functions/userEmailViewCasing"
9
9
  import * as quota1 from "./functions/quotas1"
10
10
  import * as appUrls from "./functions/appUrls"
11
+ import * as developerQuota from "./functions/developerQuota"
12
+ import * as publishedAppsQuota from "./functions/publishedAppsQuota"
11
13
 
12
14
  export interface Migration {
13
15
  type: string
@@ -27,7 +29,7 @@ export interface Migration {
27
29
  */
28
30
  export interface MigrationOptions {
29
31
  tenantIds?: string[]
30
- forced?: {
32
+ force?: {
31
33
  [type: string]: string[]
32
34
  }
33
35
  }
@@ -49,6 +51,16 @@ export const MIGRATIONS: Migration[] = [
49
51
  opts: { all: true },
50
52
  fn: appUrls.run,
51
53
  },
54
+ {
55
+ type: MIGRATION_TYPES.GLOBAL,
56
+ name: "developer_quota",
57
+ fn: developerQuota.run,
58
+ },
59
+ {
60
+ type: MIGRATION_TYPES.GLOBAL,
61
+ name: "published_apps_quota",
62
+ fn: publishedAppsQuota.run,
63
+ },
52
64
  ]
53
65
 
54
66
  export const migrate = async (options?: MigrationOptions) => {
package/src/module.d.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  declare module "@budibase/backend-core"
2
2
  declare module "@budibase/backend-core/tenancy"
3
3
  declare module "@budibase/backend-core/db"
4
+ declare module "@budibase/backend-core/context"
5
+ declare module "@budibase/backend-core/cache"
6
+ declare module "@budibase/backend-core/permissions"
7
+ declare module "@budibase/backend-core/roles"
@@ -8,10 +8,14 @@ const { DocumentTypes } = require("../db/utils")
8
8
  const { doInTenant } = require("@budibase/backend-core/tenancy")
9
9
  const { definitions: triggerDefs } = require("../automations/triggerInfo")
10
10
  const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
11
-
11
+ const { AutomationErrors } = require("../constants")
12
12
  const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
13
+ const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
14
+
13
15
  const CRON_STEP_ID = triggerDefs.CRON.stepId
14
16
  const STOPPED_STATUS = { success: false, status: "STOPPED" }
17
+ const { cloneDeep } = require("lodash/fp")
18
+ const env = require("../environment")
15
19
 
16
20
  /**
17
21
  * The automation orchestrator is a class responsible for executing automations.
@@ -74,50 +78,208 @@ class Orchestrator {
74
78
  this.executionOutput.steps.push(stepObj)
75
79
  }
76
80
 
81
+ updateContextAndOutput(loopStepNumber, step, output, result) {
82
+ this.executionOutput.steps.splice(loopStepNumber, 0, {
83
+ id: step.id,
84
+ stepId: step.stepId,
85
+ outputs: {
86
+ ...output,
87
+ success: result.success,
88
+ status: result.status,
89
+ },
90
+ inputs: step.inputs,
91
+ })
92
+ this._context.steps.splice(loopStepNumber, 0, {
93
+ ...output,
94
+ success: result.success,
95
+ status: result.status,
96
+ })
97
+ }
98
+
77
99
  async execute() {
78
100
  let automation = this._automation
79
101
  const app = await this.getApp()
80
102
  let stopped = false
103
+ let loopStep
104
+
105
+ let stepCount = 0
106
+ let loopStepNumber
107
+ let loopSteps = []
81
108
  for (let step of automation.definition.steps) {
82
- // execution stopped, record state for that
83
- if (stopped) {
84
- this.updateExecutionOutput(step.id, step.stepId, {}, STOPPED_STATUS)
109
+ stepCount++
110
+ let input
111
+ if (step.stepId === LOOP_STEP_ID) {
112
+ loopStep = step
113
+ loopStepNumber = stepCount
85
114
  continue
86
115
  }
87
- let stepFn = await this.getStepFunctionality(step.stepId)
88
- step.inputs = await processObject(step.inputs, this._context)
89
- step.inputs = automationUtils.cleanInputValues(
90
- step.inputs,
91
- step.schema.inputs
92
- )
93
- // appId is always passed
94
- try {
95
- let tenantId = app.tenantId || DEFAULT_TENANT_ID
96
- const outputs = await doInTenant(tenantId, () => {
97
- return stepFn({
98
- inputs: step.inputs,
99
- appId: this._appId,
100
- emitter: this._emitter,
101
- context: this._context,
102
- })
103
- })
104
- this._context.steps.push(outputs)
105
- // if filter causes us to stop execution don't break the loop, set a var
106
- // so that we can finish iterating through the steps and record that it stopped
107
- if (step.stepId === FILTER_STEP_ID && !outputs.success) {
108
- stopped = true
109
- this.updateExecutionOutput(step.id, step.stepId, step.inputs, {
110
- ...outputs,
111
- ...STOPPED_STATUS,
112
- })
116
+
117
+ if (loopStep) {
118
+ input = await processObject(loopStep.inputs, this._context)
119
+ }
120
+ let iterations = loopStep ? input.binding.length : 1
121
+ let iterationCount = 0
122
+ for (let index = 0; index < iterations; index++) {
123
+ let originalStepInput = cloneDeep(step.inputs)
124
+
125
+ // Handle if the user has set a max iteration count or if it reaches the max limit set by us
126
+ if (loopStep) {
127
+ // lets first of all handle the input
128
+ // if the input is array then use it, if it is a string then split it on every new line
129
+ let newInput = await processObject(
130
+ loopStep.inputs,
131
+ cloneDeep(this._context)
132
+ )
133
+ newInput = automationUtils.cleanInputValues(
134
+ newInput,
135
+ loopStep.schema.inputs
136
+ )
137
+ this._context.steps[loopStepNumber] = {
138
+ currentItem: newInput.binding[index],
139
+ }
140
+
141
+ let tempOutput = { items: loopSteps, iterations: iterationCount }
142
+ if (
143
+ (loopStep.inputs.option === "Array" &&
144
+ !Array.isArray(newInput.binding)) ||
145
+ (loopStep.inputs.option === "String" &&
146
+ typeof newInput.binding !== "string")
147
+ ) {
148
+ this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
149
+ status: AutomationErrors.INCORRECT_TYPE,
150
+ success: false,
151
+ })
152
+ loopSteps = null
153
+ loopStep = null
154
+ break
155
+ }
156
+
157
+ // The "Loop" binding in the front end is "fake", so replace it here so the context can understand it
158
+ // Pretty hacky because we need to account for the row object
159
+ for (let [key, value] of Object.entries(originalStepInput)) {
160
+ if (typeof value === "object") {
161
+ for (let [innerKey, innerValue] of Object.entries(
162
+ originalStepInput[key]
163
+ )) {
164
+ if (typeof innerValue === "string") {
165
+ originalStepInput[key][innerKey] =
166
+ automationUtils.substituteLoopStep(
167
+ innerValue,
168
+ `steps.${loopStepNumber}`
169
+ )
170
+ }
171
+ }
172
+ } else {
173
+ if (typeof value === "string") {
174
+ originalStepInput[key] = automationUtils.substituteLoopStep(
175
+ value,
176
+ `steps.${loopStepNumber}`
177
+ )
178
+ }
179
+ }
180
+ }
181
+
182
+ if (
183
+ index === parseInt(env.AUTOMATION_MAX_ITERATIONS) ||
184
+ index === loopStep.inputs.iterations
185
+ ) {
186
+ this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
187
+ status: AutomationErrors.MAX_ITERATIONS,
188
+ success: true,
189
+ })
190
+ loopSteps = null
191
+ loopStep = null
192
+ break
193
+ }
194
+
195
+ if (
196
+ this._context.steps[loopStepNumber]?.currentItem ===
197
+ loopStep.inputs.failure
198
+ ) {
199
+ this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
200
+ status: AutomationErrors.FAILURE_CONDITION,
201
+ success: false,
202
+ })
203
+ loopSteps = null
204
+ loopStep = null
205
+ break
206
+ }
207
+ }
208
+
209
+ // execution stopped, record state for that
210
+ if (stopped) {
211
+ this.updateExecutionOutput(step.id, step.stepId, {}, STOPPED_STATUS)
113
212
  continue
114
213
  }
115
- this.updateExecutionOutput(step.id, step.stepId, step.inputs, outputs)
116
- } catch (err) {
117
- console.error(`Automation error - ${step.stepId} - ${err}`)
118
- return err
214
+
215
+ // If it's a loop step, we need to manually add the bindings to the context
216
+ let stepFn = await this.getStepFunctionality(step.stepId)
217
+ let inputs = await processObject(originalStepInput, this._context)
218
+ inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs)
219
+ try {
220
+ // appId is always passed
221
+ let tenantId = app.tenantId || DEFAULT_TENANT_ID
222
+ const outputs = await doInTenant(tenantId, () => {
223
+ return stepFn({
224
+ inputs: inputs,
225
+ appId: this._appId,
226
+ emitter: this._emitter,
227
+ context: this._context,
228
+ })
229
+ })
230
+ this._context.steps[stepCount] = outputs
231
+ // if filter causes us to stop execution don't break the loop, set a var
232
+ // so that we can finish iterating through the steps and record that it stopped
233
+ if (step.stepId === FILTER_STEP_ID && !outputs.success) {
234
+ stopped = true
235
+ this.updateExecutionOutput(step.id, step.stepId, step.inputs, {
236
+ ...outputs,
237
+ ...STOPPED_STATUS,
238
+ })
239
+ continue
240
+ }
241
+ if (loopStep && loopSteps) {
242
+ loopSteps.push(outputs)
243
+ } else {
244
+ this.updateExecutionOutput(
245
+ step.id,
246
+ step.stepId,
247
+ step.inputs,
248
+ outputs
249
+ )
250
+ }
251
+ } catch (err) {
252
+ console.error(`Automation error - ${step.stepId} - ${err}`)
253
+ return err
254
+ }
255
+ if (loopStep) {
256
+ iterationCount++
257
+ if (index === iterations - 1) {
258
+ loopStep = null
259
+ this._context.steps.splice(loopStepNumber, 1)
260
+ break
261
+ }
262
+ }
263
+ }
264
+
265
+ if (loopSteps && loopSteps.length) {
266
+ let tempOutput = {
267
+ success: true,
268
+ items: loopSteps,
269
+ iterations: iterationCount,
270
+ }
271
+ this.executionOutput.steps.splice(loopStepNumber + 1, 0, {
272
+ id: step.id,
273
+ stepId: step.stepId,
274
+ outputs: tempOutput,
275
+ inputs: step.inputs,
276
+ })
277
+
278
+ this._context.steps.splice(loopStepNumber, 0, tempOutput)
279
+ loopSteps = null
119
280
  }
120
281
  }
282
+
121
283
  return this.executionOutput
122
284
  }
123
285
  }