@budibase/server 1.0.105-alpha.21 → 1.0.105-alpha.24

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 (292) hide show
  1. package/builder/assets/{index.8d922c8c.js → index.06b1c616.js} +150 -147
  2. package/builder/assets/{index.b7e0672d.css → index.e3fb1cb4.css} +2 -2
  3. package/builder/index.html +2 -2
  4. package/coverage/clover.xml +517 -1564
  5. package/coverage/coverage-final.json +27 -43
  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 +23 -33
  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 +20 -15
  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 +52 -47
  34. package/coverage/lcov-report/api/controllers/table/external.js.html +8 -3
  35. package/coverage/lcov-report/api/controllers/table/index.html +17 -42
  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 +9 -4
  76. package/coverage/lcov-report/automations/automationUtils.js.html +20 -15
  77. package/coverage/lcov-report/automations/bullboard.js.html +8 -3
  78. package/coverage/lcov-report/automations/index.html +16 -26
  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 +16 -41
  87. package/coverage/lcov-report/automations/steps/integromat.js.html +8 -3
  88. package/coverage/lcov-report/automations/steps/loop.js.html +8 -3
  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 +8 -3
  108. package/coverage/lcov-report/constants/index.js.html +35 -30
  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 +122 -117
  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 +11 -6
  131. package/coverage/lcov-report/middleware/index.html +16 -41
  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 +55 -50
  139. package/coverage/lcov-report/threads/index.html +16 -26
  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 +759 -2599
  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/table/internal.js +40 -34
  179. package/dist/api/controllers/table/utils.js +271 -229
  180. package/dist/api/index.js +5 -0
  181. package/dist/api/routes/application.js +39 -13
  182. package/dist/api/routes/index.js +61 -56
  183. package/dist/api/routes/public/index.js +6 -9
  184. package/dist/api/routes/public/queries.js +1 -1
  185. package/dist/api/routes/public/rows.js +1 -1
  186. package/dist/api/routes/public/tables.js +3 -3
  187. package/dist/api/routes/public/users.js +1 -1
  188. package/dist/api/routes/row.js +43 -17
  189. package/dist/api/routes/static.js +40 -13
  190. package/dist/api/routes/tests/utilities/TestFunctions.js +62 -26
  191. package/dist/app.js +11 -4
  192. package/dist/automations/steps/createRow.js +12 -12
  193. package/dist/automations/steps/deleteRow.js +13 -16
  194. package/dist/automations/tests/utilities/index.js +0 -2
  195. package/dist/automations/utils.js +187 -132
  196. package/dist/environment.js +0 -2
  197. package/dist/integrations/base/sql.js +2 -2
  198. package/dist/integrations/base/sqlTable.js +2 -2
  199. package/dist/integrations/googlesheets.js +1 -1
  200. package/dist/integrations/microsoftSqlServer.js +8 -8
  201. package/dist/integrations/mysql.js +9 -9
  202. package/dist/integrations/oracle.js +7 -7
  203. package/dist/integrations/postgres.js +7 -7
  204. package/dist/integrations/rest.js +1 -1
  205. package/dist/middleware/authorized.js +51 -51
  206. package/dist/migrations/functions/appUrls.js +1 -1
  207. package/dist/migrations/functions/developerQuota.js +49 -0
  208. package/dist/migrations/functions/publishedAppsQuota.js +47 -0
  209. package/dist/migrations/functions/quotas1.js +6 -2
  210. package/dist/migrations/functions/usageQuotas/index.js +0 -4
  211. package/dist/migrations/functions/usageQuotas/syncApps.js +4 -7
  212. package/dist/migrations/functions/usageQuotas/syncDevelopers.js +24 -0
  213. package/dist/migrations/functions/usageQuotas/syncPublishedApps.js +26 -0
  214. package/dist/migrations/functions/usageQuotas/syncRows.js +5 -8
  215. package/dist/migrations/index.js +17 -1
  216. package/dist/package.json +10 -8
  217. package/dist/threads/index.js +35 -8
  218. package/dist/tsconfig.build.tsbuildinfo +1 -0
  219. package/dist/utilities/queue/inMemoryQueue.js +6 -1
  220. package/nodemon.json +1 -1
  221. package/package.json +11 -9
  222. package/scripts/dev/manage.js +2 -0
  223. package/src/api/controllers/{application.js → application.ts} +103 -44
  224. package/src/api/controllers/deploy/{index.js → index.ts} +45 -28
  225. package/src/api/controllers/public/applications.ts +2 -2
  226. package/src/api/controllers/public/queries.ts +1 -1
  227. package/src/api/controllers/public/rows.ts +1 -1
  228. package/src/api/controllers/query/{index.js → index.ts} +51 -48
  229. package/src/api/controllers/row/ExternalRequest.ts +1 -1
  230. package/src/api/controllers/row/{index.js → index.ts} +24 -17
  231. package/src/api/controllers/row/internal.js +2 -1
  232. package/src/api/controllers/table/{internal.js → internal.ts} +27 -24
  233. package/src/api/controllers/table/{utils.js → utils.ts} +86 -69
  234. package/src/api/index.js +5 -0
  235. package/src/api/routes/{application.js → application.ts} +8 -14
  236. package/src/api/routes/index.ts +60 -0
  237. package/src/api/routes/public/index.ts +1 -4
  238. package/src/api/routes/{row.js → row.ts} +7 -15
  239. package/src/api/routes/{static.js → static.ts} +11 -11
  240. package/src/api/routes/tests/utilities/{TestFunctions.js → TestFunctions.ts} +42 -25
  241. package/src/app.ts +1 -2
  242. package/src/automations/steps/{createRow.js → createRow.ts} +9 -15
  243. package/src/automations/steps/{deleteRow.js → deleteRow.ts} +10 -16
  244. package/src/automations/tests/automation.spec.js +0 -1
  245. package/src/automations/tests/{createRow.spec.js → createRow.spec.ts} +4 -15
  246. package/src/automations/tests/{deleteRow.spec.js → deleteRow.spec.ts} +3 -5
  247. package/src/automations/tests/utilities/index.js +0 -2
  248. package/src/automations/{utils.js → utils.ts} +39 -27
  249. package/src/environment.js +0 -2
  250. package/src/middleware/{authorized.js → authorized.ts} +20 -14
  251. package/src/migrations/functions/developerQuota.ts +15 -0
  252. package/src/migrations/functions/publishedAppsQuota.ts +13 -0
  253. package/src/migrations/functions/tests/quotas1.spec.js +0 -2
  254. package/src/migrations/functions/usageQuotas/index.ts +0 -5
  255. package/src/migrations/functions/usageQuotas/syncApps.ts +3 -6
  256. package/src/migrations/functions/usageQuotas/syncDevelopers.ts +19 -0
  257. package/src/migrations/functions/usageQuotas/syncPublishedApps.ts +21 -0
  258. package/src/migrations/functions/usageQuotas/syncRows.ts +3 -6
  259. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.ts +32 -0
  260. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +38 -0
  261. package/src/migrations/index.ts +13 -1
  262. package/src/module.d.ts +4 -0
  263. package/src/threads/{index.js → index.ts} +14 -12
  264. package/src/utilities/queue/inMemoryQueue.js +7 -1
  265. package/tsconfig.build.json +10 -0
  266. package/tsconfig.json +2 -2
  267. package/coverage/lcov-report/api/controllers/application.js.html +0 -1430
  268. package/coverage/lcov-report/api/controllers/query/index.js.html +0 -713
  269. package/coverage/lcov-report/api/controllers/row/index.js.html +0 -524
  270. package/coverage/lcov-report/api/controllers/table/internal.js.html +0 -548
  271. package/coverage/lcov-report/api/controllers/table/utils.js.html +0 -1331
  272. package/coverage/lcov-report/api/routes/application.js.html +0 -179
  273. package/coverage/lcov-report/api/routes/index.js.html +0 -266
  274. package/coverage/lcov-report/api/routes/row.js.html +0 -908
  275. package/coverage/lcov-report/api/routes/static.js.html +0 -245
  276. package/coverage/lcov-report/automations/steps/createRow.js.html +0 -380
  277. package/coverage/lcov-report/automations/steps/deleteRow.js.html +0 -347
  278. package/coverage/lcov-report/automations/utils.js.html +0 -662
  279. package/coverage/lcov-report/middleware/authorized.js.html +0 -458
  280. package/coverage/lcov-report/middleware/usageQuota.js.html +0 -572
  281. package/coverage/lcov-report/threads/index.js.html +0 -278
  282. package/coverage/lcov-report/utilities/usageQuota/index.js.html +0 -359
  283. package/dist/middleware/usageQuota.js +0 -154
  284. package/dist/tsconfig.tsbuildinfo +0 -1
  285. package/dist/utilities/usageQuota/index.js +0 -86
  286. package/src/api/routes/index.js +0 -62
  287. package/src/middleware/tests/usageQuota.spec.js +0 -134
  288. package/src/middleware/usageQuota.js +0 -164
  289. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +0 -37
  290. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +0 -43
  291. package/src/utilities/tests/usageQuota/usageQuota.spec.js +0 -72
  292. package/src/utilities/usageQuota/index.js +0 -93
@@ -1,86 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- const env = require("../../environment");
12
- const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy");
13
- const { StaticDatabases, generateNewUsageQuotaDoc, } = require("@budibase/backend-core/db");
14
- exports.useQuotas = () => {
15
- // check if quotas are enabled
16
- if (env.USE_QUOTAS) {
17
- // check if there are any tenants without limits
18
- if (env.EXCLUDE_QUOTAS_TENANTS) {
19
- const excludedTenants = env.EXCLUDE_QUOTAS_TENANTS.replace(/\s/g, "").split(",");
20
- const tenantId = getTenantId();
21
- if (excludedTenants.includes(tenantId)) {
22
- return false;
23
- }
24
- }
25
- return true;
26
- }
27
- return false;
28
- };
29
- exports.Properties = {
30
- ROW: "rows",
31
- UPLOAD: "storage",
32
- VIEW: "views",
33
- USER: "users",
34
- AUTOMATION: "automationRuns",
35
- APPS: "apps",
36
- EMAILS: "emails", // doesn't work yet
37
- };
38
- exports.getUsageQuotaDoc = (db) => __awaiter(void 0, void 0, void 0, function* () {
39
- let quota;
40
- try {
41
- quota = yield db.get(StaticDatabases.GLOBAL.docs.usageQuota);
42
- }
43
- catch (err) {
44
- // doc doesn't exist. Create it
45
- quota = generateNewUsageQuotaDoc();
46
- const response = yield db.put(quota);
47
- quota._rev = response.rev;
48
- }
49
- return quota;
50
- });
51
- /**
52
- * Given a specified tenantId this will add to the usage object for the specified property.
53
- * @param {string} property The property which is to be added to (within the nested usageQuota object).
54
- * @param {number} usage The amount (this can be negative) to adjust the number by.
55
- * @param {object} opts optional - options such as dryRun, to check what update will do.
56
- * @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
57
- * also been reset after this call.
58
- */
59
- exports.update = (property, usage, opts = { dryRun: false }) => __awaiter(void 0, void 0, void 0, function* () {
60
- if (!exports.useQuotas()) {
61
- return;
62
- }
63
- try {
64
- const db = getGlobalDB();
65
- const quota = yield exports.getUsageQuotaDoc(db);
66
- // increment the quota
67
- quota.usageQuota[property] += usage;
68
- if (quota.usageQuota[property] > quota.usageLimits[property] &&
69
- usage > 0 // allow for decrementing usage when the quota is already exceeded
70
- ) {
71
- throw new Error(`You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`);
72
- }
73
- if (quota.usageQuota[property] < 0) {
74
- // never go negative if the quota has previously been exceeded
75
- quota.usageQuota[property] = 0;
76
- }
77
- // update the usage quotas
78
- if (!opts.dryRun) {
79
- yield db.put(quota);
80
- }
81
- }
82
- catch (err) {
83
- console.error(`Error updating usage quotas for ${property}`, err);
84
- throw err;
85
- }
86
- });
@@ -1,62 +0,0 @@
1
- const authRoutes = require("./auth")
2
- const layoutRoutes = require("./layout")
3
- const screenRoutes = require("./screen")
4
- const userRoutes = require("./user")
5
- const applicationRoutes = require("./application")
6
- const tableRoutes = require("./table")
7
- const rowRoutes = require("./row")
8
- const viewRoutes = require("./view")
9
- const staticRoutes = require("./static")
10
- const componentRoutes = require("./component")
11
- const automationRoutes = require("./automation")
12
- const webhookRoutes = require("./webhook")
13
- const roleRoutes = require("./role")
14
- const deployRoutes = require("./deploy")
15
- const apiKeysRoutes = require("./apikeys")
16
- const templatesRoutes = require("./templates")
17
- const analyticsRoutes = require("./analytics")
18
- const routingRoutes = require("./routing")
19
- const integrationRoutes = require("./integration")
20
- const permissionRoutes = require("./permission")
21
- const datasourceRoutes = require("./datasource")
22
- const queryRoutes = require("./query")
23
- const backupRoutes = require("./backup")
24
- const metadataRoutes = require("./metadata")
25
- const devRoutes = require("./dev")
26
- const cloudRoutes = require("./cloud")
27
- const migrationRoutes = require("./migrations")
28
- const publicRoutes = require("./public")
29
-
30
- exports.mainRoutes = [
31
- authRoutes,
32
- deployRoutes,
33
- layoutRoutes,
34
- screenRoutes,
35
- userRoutes,
36
- applicationRoutes,
37
- automationRoutes,
38
- viewRoutes,
39
- componentRoutes,
40
- roleRoutes,
41
- apiKeysRoutes,
42
- templatesRoutes,
43
- analyticsRoutes,
44
- webhookRoutes,
45
- routingRoutes,
46
- integrationRoutes,
47
- permissionRoutes,
48
- datasourceRoutes,
49
- queryRoutes,
50
- backupRoutes,
51
- metadataRoutes,
52
- devRoutes,
53
- cloudRoutes,
54
- // these need to be handled last as they still use /api/:tableId
55
- // this could be breaking as koa may recognise other routes as this
56
- tableRoutes,
57
- rowRoutes,
58
- migrationRoutes,
59
- ]
60
-
61
- exports.publicRoutes = publicRoutes
62
- exports.staticRoutes = staticRoutes
@@ -1,134 +0,0 @@
1
- jest.mock("../../db")
2
- jest.mock("../../utilities/usageQuota")
3
- jest.mock("@budibase/backend-core/tenancy", () => ({
4
- getTenantId: () => "testing123"
5
- }))
6
-
7
- const usageQuotaMiddleware = require("../usageQuota")
8
- const usageQuota = require("../../utilities/usageQuota")
9
- const CouchDB = require("../../db")
10
- const env = require("../../environment")
11
-
12
- class TestConfiguration {
13
- constructor() {
14
- this.throw = jest.fn()
15
- this.next = jest.fn()
16
- this.middleware = usageQuotaMiddleware
17
- this.ctx = {
18
- throw: this.throw,
19
- next: this.next,
20
- appId: "test",
21
- request: {
22
- body: {}
23
- },
24
- req: {
25
- method: "POST",
26
- url: "/applications"
27
- }
28
- }
29
- usageQuota.useQuotas = () => true
30
- }
31
-
32
- executeMiddleware() {
33
- return this.middleware(this.ctx, this.next)
34
- }
35
-
36
- setProd(bool) {
37
- if (bool) {
38
- env.isDev = () => false
39
- env.isProd = () => true
40
- this.ctx.user = { tenantId: "test" }
41
- } else {
42
- env.isDev = () => true
43
- env.isProd = () => false
44
- }
45
- }
46
-
47
- setMethod(method) {
48
- this.ctx.req.method = method
49
- }
50
-
51
- setUrl(url) {
52
- this.ctx.req.url = url
53
- }
54
-
55
- setBody(body) {
56
- this.ctx.request.body = body
57
- }
58
-
59
- setFiles(files) {
60
- this.ctx.request.files = { file: files }
61
- }
62
- }
63
-
64
- describe("usageQuota middleware", () => {
65
- let config
66
-
67
- beforeEach(() => {
68
- config = new TestConfiguration()
69
- })
70
-
71
- it("skips the middleware if there is no usage property or method", async () => {
72
- await config.executeMiddleware()
73
- expect(config.next).toHaveBeenCalled()
74
- })
75
-
76
- it("passes through to next middleware if document already exists", async () => {
77
- config.setProd(true)
78
- config.setBody({
79
- _id: "test",
80
- _rev: "test",
81
- })
82
-
83
- CouchDB.mockImplementationOnce(() => ({
84
- get: async () => true
85
- }))
86
-
87
- await config.executeMiddleware()
88
-
89
- expect(config.next).toHaveBeenCalled()
90
- })
91
-
92
- it("throws if request has _id, but the document no longer exists", async () => {
93
- config.setBody({
94
- _id: "123",
95
- _rev: "test",
96
- })
97
- config.setProd(true)
98
-
99
- CouchDB.mockImplementationOnce(() => ({
100
- get: async () => {
101
- throw new Error()
102
- }
103
- }))
104
-
105
- await config.executeMiddleware()
106
- expect(config.throw).toHaveBeenCalledWith(404, `${config.ctx.request.body._id} does not exist`)
107
- })
108
-
109
- it("calculates and persists the correct usage quota for the relevant action", async () => {
110
- config.setUrl("/rows")
111
-
112
- await config.executeMiddleware()
113
-
114
- expect(usageQuota.update).toHaveBeenCalledWith("rows", 1)
115
- expect(config.next).toHaveBeenCalled()
116
- })
117
-
118
- // it("calculates the correct file size from a file upload call and adds it to quota", async () => {
119
- // config.setUrl("/upload")
120
- // config.setProd(true)
121
- // config.setFiles([
122
- // {
123
- // size: 100
124
- // },
125
- // {
126
- // size: 10000
127
- // },
128
- // ])
129
- // await config.executeMiddleware()
130
-
131
- // expect(usageQuota.update).toHaveBeenCalledWith("storage", 10100)
132
- // expect(config.next).toHaveBeenCalled()
133
- // })
134
- })
@@ -1,164 +0,0 @@
1
- const usageQuota = require("../utilities/usageQuota")
2
- const { getUniqueRows } = require("../utilities/usageQuota/rows")
3
- const {
4
- isExternalTable,
5
- isRowId: isExternalRowId,
6
- } = require("../integrations/utils")
7
- const { getAppDB } = require("@budibase/backend-core/context")
8
-
9
- // currently only counting new writes and deletes
10
- const METHOD_MAP = {
11
- POST: 1,
12
- DELETE: -1,
13
- }
14
-
15
- const DOMAIN_MAP = {
16
- rows: usageQuota.Properties.ROW,
17
- // upload: usageQuota.Properties.UPLOAD, // doesn't work yet
18
- // views: usageQuota.Properties.VIEW, // doesn't work yet
19
- // users: usageQuota.Properties.USER, // doesn't work yet
20
- applications: usageQuota.Properties.APPS,
21
- // this will not be updated by endpoint calls
22
- // instead it will be updated by triggerInfo
23
- // automationRuns: usageQuota.Properties.AUTOMATION, // doesn't work yet
24
- }
25
-
26
- function getProperty(url) {
27
- for (let domain of Object.keys(DOMAIN_MAP)) {
28
- if (url.indexOf(domain) !== -1) {
29
- return DOMAIN_MAP[domain]
30
- }
31
- }
32
- }
33
-
34
- module.exports = async (ctx, next) => {
35
- if (!usageQuota.useQuotas()) {
36
- return next()
37
- }
38
-
39
- let usage = METHOD_MAP[ctx.req.method]
40
- const property = getProperty(ctx.req.url)
41
- if (usage == null || property == null) {
42
- return next()
43
- }
44
- // post request could be a save of a pre-existing entry
45
- if (ctx.request.body && ctx.request.body._id && ctx.request.body._rev) {
46
- const usageId = ctx.request.body._id
47
- try {
48
- if (ctx.appId) {
49
- const db = getAppDB()
50
- await db.get(usageId)
51
- }
52
- return next()
53
- } catch (err) {
54
- if (
55
- isExternalTable(usageId) ||
56
- (ctx.request.body.tableId &&
57
- isExternalTable(ctx.request.body.tableId)) ||
58
- isExternalRowId(usageId)
59
- ) {
60
- return next()
61
- } else {
62
- ctx.throw(404, `${usageId} does not exist`)
63
- }
64
- }
65
- }
66
-
67
- // update usage for uploads to be the total size
68
- if (property === usageQuota.Properties.UPLOAD) {
69
- const files =
70
- ctx.request.files.file.length > 1
71
- ? Array.from(ctx.request.files.file)
72
- : [ctx.request.files.file]
73
- usage = files.map(file => file.size).reduce((total, size) => total + size)
74
- }
75
- try {
76
- await performRequest(ctx, next, property, usage)
77
- } catch (err) {
78
- ctx.throw(400, err)
79
- }
80
- }
81
-
82
- const performRequest = async (ctx, next, property, usage) => {
83
- const usageContext = {
84
- skipNext: false,
85
- skipUsage: false,
86
- [usageQuota.Properties.APPS]: {},
87
- }
88
-
89
- if (usage === -1) {
90
- if (PRE_DELETE[property]) {
91
- await PRE_DELETE[property](ctx, usageContext)
92
- }
93
- } else {
94
- if (PRE_CREATE[property]) {
95
- await PRE_CREATE[property](ctx, usageContext)
96
- }
97
- }
98
-
99
- // run the request
100
- if (!usageContext.skipNext) {
101
- await usageQuota.update(property, usage, { dryRun: true })
102
- await next()
103
- }
104
-
105
- if (usage === -1) {
106
- if (POST_DELETE[property]) {
107
- await POST_DELETE[property](ctx, usageContext)
108
- }
109
- } else {
110
- if (POST_CREATE[property]) {
111
- await POST_CREATE[property](ctx, usageContext)
112
- }
113
- }
114
-
115
- // update the usage
116
- if (!usageContext.skipUsage) {
117
- await usageQuota.update(property, usage)
118
- }
119
- }
120
-
121
- const appPreDelete = async (ctx, usageContext) => {
122
- if (ctx.query.unpublish) {
123
- // don't run usage decrement for unpublish
124
- usageContext.skipUsage = true
125
- return
126
- }
127
-
128
- // store the row count to delete
129
- const rows = await getUniqueRows([ctx.appId])
130
- if (rows.length) {
131
- usageContext[usageQuota.Properties.APPS] = { rowCount: rows.length }
132
- }
133
- }
134
-
135
- const appPostDelete = async (ctx, usageContext) => {
136
- // delete the app rows from usage
137
- const rowCount = usageContext[usageQuota.Properties.APPS].rowCount
138
- if (rowCount) {
139
- await usageQuota.update(usageQuota.Properties.ROW, -rowCount)
140
- }
141
- }
142
-
143
- const appPostCreate = async ctx => {
144
- // app import & template creation
145
- if (ctx.request.body.useTemplate === "true") {
146
- const rows = await getUniqueRows([ctx.response.body.appId])
147
- const rowCount = rows ? rows.length : 0
148
- await usageQuota.update(usageQuota.Properties.ROW, rowCount)
149
- }
150
- }
151
-
152
- const PRE_DELETE = {
153
- [usageQuota.Properties.APPS]: appPreDelete,
154
- }
155
-
156
- const POST_DELETE = {
157
- [usageQuota.Properties.APPS]: appPostDelete,
158
- }
159
-
160
- const PRE_CREATE = {}
161
-
162
- const POST_CREATE = {
163
- [usageQuota.Properties.APPS]: appPostCreate,
164
- }
@@ -1,37 +0,0 @@
1
- const { getGlobalDB } = require("@budibase/backend-core/tenancy")
2
- const TestConfig = require("../../../../tests/utilities/TestConfiguration")
3
- const { getUsageQuotaDoc, update, Properties } = require("../../../../utilities/usageQuota")
4
- const syncApps = require("../syncApps")
5
- const env = require("../../../../environment")
6
-
7
- describe("syncApps", () => {
8
- let config = new TestConfig(false)
9
-
10
- beforeEach(async () => {
11
- await config.init()
12
- env._set("USE_QUOTAS", 1)
13
- })
14
-
15
- afterAll(config.end)
16
-
17
- it("runs successfully", async () => {
18
- // create the usage quota doc and mock usages
19
- const db = getGlobalDB()
20
- await getUsageQuotaDoc(db)
21
- await update(Properties.APPS, 3)
22
-
23
- let usageDoc = await getUsageQuotaDoc(db)
24
- expect(usageDoc.usageQuota.apps).toEqual(3)
25
-
26
- // create an extra app to test the migration
27
- await config.createApp("quota-test")
28
-
29
- // migrate
30
- await syncApps.run()
31
-
32
- // assert the migration worked
33
- usageDoc = await getUsageQuotaDoc(db)
34
- expect(usageDoc.usageQuota.apps).toEqual(2)
35
- })
36
- })
37
-
@@ -1,43 +0,0 @@
1
- const { getGlobalDB } = require("@budibase/backend-core/tenancy")
2
- const TestConfig = require("../../../../tests/utilities/TestConfiguration")
3
- const { getUsageQuotaDoc, update, Properties } = require("../../../../utilities/usageQuota")
4
- const syncRows = require("../syncRows")
5
- const env = require("../../../../environment")
6
-
7
- describe("syncRows", () => {
8
- let config = new TestConfig(false)
9
-
10
- beforeEach(async () => {
11
- await config.init()
12
- env._set("USE_QUOTAS", 1)
13
- })
14
-
15
- afterAll(config.end)
16
-
17
- it("runs successfully", async () => {
18
- // create the usage quota doc and mock usages
19
- const db = getGlobalDB()
20
- await getUsageQuotaDoc(db)
21
- await update(Properties.ROW, 300)
22
-
23
- let usageDoc = await getUsageQuotaDoc(db)
24
- expect(usageDoc.usageQuota.rows).toEqual(300)
25
-
26
- // app 1
27
- await config.createTable()
28
- await config.createRow()
29
- // app 2
30
- await config.createApp("second-app")
31
- await config.createTable()
32
- await config.createRow()
33
- await config.createRow()
34
-
35
- // migrate
36
- await syncRows.run()
37
-
38
- // assert the migration worked
39
- usageDoc = await getUsageQuotaDoc(db)
40
- expect(usageDoc.usageQuota.rows).toEqual(3)
41
- })
42
- })
43
-
@@ -1,72 +0,0 @@
1
- const getTenantId = jest.fn()
2
- jest.mock("@budibase/backend-core/tenancy", () => ({
3
- getTenantId
4
- }))
5
- const usageQuota = require("../../usageQuota")
6
- const env = require("../../../environment")
7
-
8
- class TestConfiguration {
9
- constructor() {
10
- this.enableQuotas()
11
- }
12
-
13
- enableQuotas = () => {
14
- env.USE_QUOTAS = 1
15
- }
16
-
17
- disableQuotas = () => {
18
- env.USE_QUOTAS = null
19
- }
20
-
21
- setTenantId = (tenantId) => {
22
- getTenantId.mockReturnValue(tenantId)
23
- }
24
-
25
- setExcludedTenants = (tenants) => {
26
- env.EXCLUDE_QUOTAS_TENANTS = tenants
27
- }
28
-
29
- reset = () => {
30
- this.disableQuotas()
31
- this.setExcludedTenants(null)
32
- }
33
- }
34
-
35
- describe("usageQuota", () => {
36
- let config
37
-
38
- beforeEach(() => {
39
- config = new TestConfiguration()
40
- })
41
-
42
- afterEach(() => {
43
- config.reset()
44
- })
45
-
46
- describe("useQuotas", () => {
47
- it("works when no settings have been provided", () => {
48
- config.reset()
49
- expect(usageQuota.useQuotas()).toBe(false)
50
- })
51
- it("honours USE_QUOTAS setting", () => {
52
- config.disableQuotas()
53
- expect(usageQuota.useQuotas()).toBe(false)
54
-
55
- config.enableQuotas()
56
- expect(usageQuota.useQuotas()).toBe(true)
57
- })
58
- it("honours EXCLUDE_QUOTAS_TENANTS setting", () => {
59
- config.setTenantId("test")
60
-
61
- // tenantId is in the list
62
- config.setExcludedTenants("test, test2, test2")
63
- expect(usageQuota.useQuotas()).toBe(false)
64
- config.setExcludedTenants("test,test2,test2")
65
- expect(usageQuota.useQuotas()).toBe(false)
66
-
67
- // tenantId is not in the list
68
- config.setTenantId("other")
69
- expect(usageQuota.useQuotas()).toBe(true)
70
- })
71
- })
72
- })
@@ -1,93 +0,0 @@
1
- const env = require("../../environment")
2
- const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
3
- const {
4
- StaticDatabases,
5
- generateNewUsageQuotaDoc,
6
- } = require("@budibase/backend-core/db")
7
-
8
- exports.useQuotas = () => {
9
- // check if quotas are enabled
10
- if (env.USE_QUOTAS) {
11
- // check if there are any tenants without limits
12
- if (env.EXCLUDE_QUOTAS_TENANTS) {
13
- const excludedTenants = env.EXCLUDE_QUOTAS_TENANTS.replace(
14
- /\s/g,
15
- ""
16
- ).split(",")
17
- const tenantId = getTenantId()
18
- if (excludedTenants.includes(tenantId)) {
19
- return false
20
- }
21
- }
22
- return true
23
- }
24
- return false
25
- }
26
-
27
- exports.Properties = {
28
- ROW: "rows",
29
- UPLOAD: "storage", // doesn't work yet
30
- VIEW: "views", // doesn't work yet
31
- USER: "users", // doesn't work yet
32
- AUTOMATION: "automationRuns", // doesn't work yet
33
- APPS: "apps",
34
- EMAILS: "emails", // doesn't work yet
35
- }
36
-
37
- exports.getUsageQuotaDoc = async db => {
38
- let quota
39
- try {
40
- quota = await db.get(StaticDatabases.GLOBAL.docs.usageQuota)
41
- } catch (err) {
42
- // doc doesn't exist. Create it
43
- quota = generateNewUsageQuotaDoc()
44
- const response = await db.put(quota)
45
- quota._rev = response.rev
46
- }
47
-
48
- return quota
49
- }
50
-
51
- /**
52
- * Given a specified tenantId this will add to the usage object for the specified property.
53
- * @param {string} property The property which is to be added to (within the nested usageQuota object).
54
- * @param {number} usage The amount (this can be negative) to adjust the number by.
55
- * @param {object} opts optional - options such as dryRun, to check what update will do.
56
- * @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
57
- * also been reset after this call.
58
- */
59
- exports.update = async (property, usage, opts = { dryRun: false }) => {
60
- if (!exports.useQuotas()) {
61
- return
62
- }
63
-
64
- try {
65
- const db = getGlobalDB()
66
- const quota = await exports.getUsageQuotaDoc(db)
67
-
68
- // increment the quota
69
- quota.usageQuota[property] += usage
70
-
71
- if (
72
- quota.usageQuota[property] > quota.usageLimits[property] &&
73
- usage > 0 // allow for decrementing usage when the quota is already exceeded
74
- ) {
75
- throw new Error(
76
- `You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`
77
- )
78
- }
79
-
80
- if (quota.usageQuota[property] < 0) {
81
- // never go negative if the quota has previously been exceeded
82
- quota.usageQuota[property] = 0
83
- }
84
-
85
- // update the usage quotas
86
- if (!opts.dryRun) {
87
- await db.put(quota)
88
- }
89
- } catch (err) {
90
- console.error(`Error updating usage quotas for ${property}`, err)
91
- throw err
92
- }
93
- }