@budibase/server 1.0.46-alpha.7 → 1.0.48

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 (251) hide show
  1. package/builder/assets/{index.dd9e386f.css → index.39e01193.css} +1 -1
  2. package/builder/assets/{index.af9e71d8.js → index.e083dcaf.js} +221 -223
  3. package/builder/assets/{vendor.3bd2f661.js → vendor.f9faf6ab.js} +12 -12
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +1637 -1793
  6. package/coverage/coverage-final.json +94 -98
  7. package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/application.js.html +126 -210
  10. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/automation.js.html +21 -21
  12. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/component.js.html +4 -4
  15. package/coverage/lcov-report/api/controllers/datasource.js.html +36 -72
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/{migrations/usageQuotas/syncRows.js.html → api/controllers/hosting.js.html} +44 -41
  18. package/coverage/lcov-report/api/controllers/index.html +42 -27
  19. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
  21. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/permission.js.html +15 -15
  23. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  24. package/coverage/lcov-report/api/controllers/query/index.js.html +19 -19
  25. package/coverage/lcov-report/api/controllers/query/validation.js.html +6 -6
  26. package/coverage/lcov-report/api/controllers/role.js.html +9 -9
  27. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/external.js.html +16 -16
  29. package/coverage/lcov-report/api/controllers/row/index.html +15 -15
  30. package/coverage/lcov-report/api/controllers/row/index.js.html +26 -26
  31. package/coverage/lcov-report/api/controllers/row/internal.js.html +44 -44
  32. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +8 -8
  33. package/coverage/lcov-report/api/controllers/row/utils.js.html +57 -39
  34. package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
  35. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  36. package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
  37. package/coverage/lcov-report/api/controllers/table/index.html +32 -32
  38. package/coverage/lcov-report/api/controllers/table/index.js.html +39 -57
  39. package/coverage/lcov-report/api/controllers/table/internal.js.html +34 -40
  40. package/coverage/lcov-report/api/controllers/table/utils.js.html +122 -83
  41. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/user.js.html +20 -20
  43. package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
  44. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  45. package/coverage/lcov-report/api/controllers/view/index.js.html +14 -14
  46. package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
  47. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
  48. package/coverage/lcov-report/api/controllers/webhook.js.html +15 -15
  49. package/coverage/lcov-report/api/index.html +1 -1
  50. package/coverage/lcov-report/api/index.js.html +10 -10
  51. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  62. package/coverage/lcov-report/{migrations/usageQuotas/syncApps.js.html → api/routes/hosting.js.html} +27 -42
  63. package/coverage/lcov-report/api/routes/index.html +22 -7
  64. package/coverage/lcov-report/api/routes/index.js.html +10 -4
  65. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/static.js.html +2 -17
  76. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  78. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  81. package/coverage/lcov-report/automations/actions.js.html +24 -24
  82. package/coverage/lcov-report/automations/automationUtils.js.html +5 -5
  83. package/coverage/lcov-report/automations/bullboard.js.html +16 -16
  84. package/coverage/lcov-report/automations/index.html +1 -1
  85. package/coverage/lcov-report/automations/index.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
  87. package/coverage/lcov-report/automations/steps/createRow.js.html +19 -13
  88. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  89. package/coverage/lcov-report/automations/steps/deleteRow.js.html +20 -11
  90. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  91. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  92. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  93. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  94. package/coverage/lcov-report/automations/steps/index.html +13 -13
  95. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  96. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  97. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  98. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  99. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  100. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  101. package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
  102. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  103. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  104. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  105. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  106. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  107. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  108. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  109. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  110. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  111. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  112. package/coverage/lcov-report/automations/triggers.js.html +18 -18
  113. package/coverage/lcov-report/automations/utils.js.html +32 -32
  114. package/coverage/lcov-report/constants/index.html +11 -11
  115. package/coverage/lcov-report/constants/index.js.html +37 -40
  116. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  117. package/coverage/lcov-report/constants/screens.js.html +4 -4
  118. package/coverage/lcov-report/db/client.js.html +18 -18
  119. package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
  120. package/coverage/lcov-report/db/index.html +15 -15
  121. package/coverage/lcov-report/db/index.js.html +3 -3
  122. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +18 -18
  123. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  124. package/coverage/lcov-report/db/linkedRows/index.js.html +31 -31
  125. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +15 -15
  126. package/coverage/lcov-report/db/newid.js.html +4 -4
  127. package/coverage/lcov-report/db/utils.js.html +85 -85
  128. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  129. package/coverage/lcov-report/events/index.html +1 -1
  130. package/coverage/lcov-report/events/index.js.html +5 -5
  131. package/coverage/lcov-report/events/utils.js.html +3 -3
  132. package/coverage/lcov-report/index.html +86 -116
  133. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  134. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  135. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  136. package/coverage/lcov-report/middleware/authorized.js.html +11 -11
  137. package/coverage/lcov-report/middleware/builder.js.html +8 -8
  138. package/coverage/lcov-report/middleware/currentapp.js.html +29 -29
  139. package/coverage/lcov-report/middleware/index.html +20 -20
  140. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  141. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  142. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  143. package/coverage/lcov-report/middleware/usageQuota.js.html +41 -275
  144. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  145. package/coverage/lcov-report/threads/automation.js.html +1 -1
  146. package/coverage/lcov-report/threads/index.html +15 -15
  147. package/coverage/lcov-report/threads/index.js.html +10 -10
  148. package/coverage/lcov-report/threads/query.js.html +8 -23
  149. package/coverage/lcov-report/threads/utils.js.html +14 -14
  150. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  151. package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
  152. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  153. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  154. package/coverage/lcov-report/utilities/global.js.html +26 -26
  155. package/coverage/lcov-report/utilities/index.html +19 -19
  156. package/coverage/lcov-report/utilities/index.js.html +25 -25
  157. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
  158. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  159. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  160. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  161. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  162. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +53 -53
  163. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +10 -10
  164. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  165. package/coverage/lcov-report/utilities/security.js.html +8 -8
  166. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  167. package/coverage/lcov-report/utilities/users.js.html +5 -5
  168. package/coverage/lcov-report/utilities/workerRequests.js.html +108 -39
  169. package/coverage/lcov.info +2332 -2599
  170. package/dist/api/controllers/application.js +20 -49
  171. package/dist/api/controllers/datasource.js +0 -11
  172. package/dist/api/controllers/hosting.js +30 -0
  173. package/dist/api/controllers/row/ExternalRequest.js +2 -1
  174. package/dist/api/controllers/row/utils.js +8 -6
  175. package/dist/api/controllers/static/index.js +10 -59
  176. package/dist/api/controllers/table/index.js +4 -10
  177. package/dist/api/controllers/table/internal.js +0 -2
  178. package/dist/api/controllers/table/utils.js +17 -11
  179. package/dist/api/routes/hosting.js +11 -0
  180. package/dist/api/routes/index.js +2 -0
  181. package/dist/api/routes/static.js +1 -2
  182. package/dist/automations/steps/createRow.js +4 -2
  183. package/dist/automations/steps/deleteRow.js +4 -1
  184. package/dist/constants/index.js +5 -8
  185. package/dist/definitions/datasource.js +0 -1
  186. package/dist/environment.js +0 -1
  187. package/dist/integrations/base/sql.js +6 -13
  188. package/dist/integrations/index.js +0 -3
  189. package/dist/integrations/utils.js +9 -56
  190. package/dist/middleware/usageQuota.js +13 -82
  191. package/dist/package.json +5 -8
  192. package/dist/tests/utilities/TestConfiguration.js +1 -3
  193. package/dist/threads/query.js +0 -4
  194. package/dist/tsconfig.tsbuildinfo +1 -1
  195. package/dist/utilities/{usageQuota/index.js → usageQuota.js} +31 -44
  196. package/dist/utilities/workerRequests.js +20 -0
  197. package/nodemon.json +1 -1
  198. package/package.json +6 -9
  199. package/src/api/controllers/application.js +24 -52
  200. package/src/api/controllers/datasource.js +0 -12
  201. package/src/api/controllers/hosting.js +22 -0
  202. package/src/api/controllers/row/ExternalRequest.ts +1 -1
  203. package/src/api/controllers/row/utils.js +12 -6
  204. package/src/api/controllers/static/index.js +10 -63
  205. package/src/api/controllers/table/index.js +9 -15
  206. package/src/api/controllers/table/internal.js +0 -2
  207. package/src/api/controllers/table/utils.js +24 -11
  208. package/src/api/routes/hosting.js +13 -0
  209. package/src/api/routes/index.js +2 -0
  210. package/src/api/routes/static.js +0 -5
  211. package/src/api/routes/tests/application.spec.js +2 -2
  212. package/src/api/routes/tests/hosting.spec.js +36 -0
  213. package/src/automations/steps/createRow.js +4 -2
  214. package/src/automations/steps/deleteRow.js +4 -1
  215. package/src/constants/index.js +8 -9
  216. package/src/definitions/datasource.ts +0 -3
  217. package/src/environment.js +0 -1
  218. package/src/integrations/base/sql.ts +7 -14
  219. package/src/integrations/index.ts +0 -3
  220. package/src/integrations/tests/sql.spec.js +0 -16
  221. package/src/integrations/utils.ts +11 -70
  222. package/src/middleware/tests/usageQuota.spec.js +24 -18
  223. package/src/middleware/usageQuota.js +15 -93
  224. package/src/tests/utilities/TestConfiguration.js +1 -3
  225. package/src/threads/query.js +0 -5
  226. package/src/utilities/usageQuota.js +73 -0
  227. package/src/utilities/workerRequests.js +23 -0
  228. package/coverage/lcov-report/migrations/usageQuotas/index.html +0 -141
  229. package/coverage/lcov-report/migrations/usageQuotas/index.js.html +0 -152
  230. package/coverage/lcov-report/utilities/usageQuota/index.html +0 -141
  231. package/coverage/lcov-report/utilities/usageQuota/index.js.html +0 -356
  232. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +0 -302
  233. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +0 -134
  234. package/dist/integrations/googlesheets.js +0 -340
  235. package/dist/migrations/usageQuotas/index.js +0 -24
  236. package/dist/migrations/usageQuotas/syncApps.js +0 -26
  237. package/dist/migrations/usageQuotas/syncRows.js +0 -29
  238. package/dist/utilities/usageQuota/rows.js +0 -77
  239. package/dist/utilities/usageQuota/usageQuoteReset.js +0 -16
  240. package/src/api/routes/tests/static.spec.js +0 -98
  241. package/src/integrations/googlesheets.ts +0 -353
  242. package/src/migrations/tests/usageQuotas/index.spec.js +0 -27
  243. package/src/migrations/tests/usageQuotas/syncApps.spec.js +0 -37
  244. package/src/migrations/tests/usageQuotas/syncRows.spec.js +0 -43
  245. package/src/migrations/usageQuotas/index.js +0 -24
  246. package/src/migrations/usageQuotas/syncApps.js +0 -18
  247. package/src/migrations/usageQuotas/syncRows.js +0 -21
  248. package/src/utilities/tests/usageQuota/usageQuota.spec.js +0 -72
  249. package/src/utilities/usageQuota/index.js +0 -92
  250. package/src/utilities/usageQuota/rows.js +0 -74
  251. package/src/utilities/usageQuota/usageQuoteReset.js +0 -18
@@ -8,24 +8,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- const env = require("../../environment");
12
- const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy");
11
+ const env = require("../environment");
12
+ const { getGlobalDB } = require("@budibase/backend-core/tenancy");
13
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
- };
14
+ function getNewQuotaReset() {
15
+ return Date.now() + 2592000000;
16
+ }
29
17
  exports.Properties = {
30
18
  ROW: "rows",
31
19
  UPLOAD: "storage",
@@ -33,21 +21,21 @@ exports.Properties = {
33
21
  USER: "users",
34
22
  AUTOMATION: "automationRuns",
35
23
  APPS: "apps",
36
- EMAILS: "emails", // doesn't work yet
24
+ EMAILS: "emails",
37
25
  };
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
- });
26
+ function getUsageQuotaDoc(db) {
27
+ return __awaiter(this, void 0, void 0, function* () {
28
+ let quota;
29
+ try {
30
+ quota = yield db.get(StaticDatabases.PLATFORM_INFO.docs.usageQuota);
31
+ }
32
+ catch (err) {
33
+ // doc doesn't exist. Create it
34
+ quota = yield db.post(generateNewUsageQuotaDoc());
35
+ }
36
+ return quota;
37
+ });
38
+ }
51
39
  /**
52
40
  * Given a specified tenantId this will add to the usage object for the specified property.
53
41
  * @param {string} property The property which is to be added to (within the nested usageQuota object).
@@ -55,28 +43,27 @@ exports.getUsageQuotaDoc = (db) => __awaiter(void 0, void 0, void 0, function* (
55
43
  * @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
56
44
  * also been reset after this call.
57
45
  */
58
- exports.update = (property, usage, opts = { dryRun: false }) => __awaiter(void 0, void 0, void 0, function* () {
59
- if (!exports.useQuotas()) {
46
+ exports.update = (property, usage) => __awaiter(void 0, void 0, void 0, function* () {
47
+ if (!env.USE_QUOTAS) {
60
48
  return;
61
49
  }
62
50
  try {
63
51
  const db = getGlobalDB();
64
- const quota = yield exports.getUsageQuotaDoc(db);
52
+ const quota = yield getUsageQuotaDoc(db);
53
+ // Check if the quota needs reset
54
+ if (Date.now() >= quota.quotaReset) {
55
+ quota.quotaReset = getNewQuotaReset();
56
+ for (let prop of Object.keys(quota.usageQuota)) {
57
+ quota.usageQuota[prop] = 0;
58
+ }
59
+ }
65
60
  // increment the quota
66
61
  quota.usageQuota[property] += usage;
67
- if (quota.usageQuota[property] > quota.usageLimits[property] &&
68
- usage > 0 // allow for decrementing usage when the quota is already exceeded
69
- ) {
62
+ if (quota.usageQuota[property] > quota.usageLimits[property]) {
70
63
  throw new Error(`You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`);
71
64
  }
72
- if (quota.usageQuota[property] < 0) {
73
- // never go negative if the quota has previously been exceeded
74
- quota.usageQuota[property] = 0;
75
- }
76
65
  // update the usage quotas
77
- if (!opts.dryRun) {
78
- yield db.put(quota);
79
- }
66
+ yield db.put(quota);
80
67
  }
81
68
  catch (err) {
82
69
  console.error(`Error updating usage quotas for ${property}`, err);
@@ -61,6 +61,26 @@ exports.sendSmtpEmail = (to, from, subject, contents, automation) => __awaiter(v
61
61
  }
62
62
  return response.json();
63
63
  });
64
+ exports.getDeployedApps = () => __awaiter(void 0, void 0, void 0, function* () {
65
+ try {
66
+ const response = yield fetch(checkSlashesInUrl(env.WORKER_URL + `/api/apps`), request(null, {
67
+ method: "GET",
68
+ }));
69
+ const json = yield response.json();
70
+ const apps = {};
71
+ for (let [key, value] of Object.entries(json)) {
72
+ if (value.url) {
73
+ value.url = value.url.toLowerCase();
74
+ apps[key.toLowerCase()] = value;
75
+ }
76
+ }
77
+ return apps;
78
+ }
79
+ catch (err) {
80
+ // error, cannot determine deployed apps, don't stop app creation - sort this later
81
+ return {};
82
+ }
83
+ });
64
84
  exports.getGlobalSelf = (ctx, appId = null) => __awaiter(void 0, void 0, void 0, function* () {
65
85
  const endpoint = `/api/global/users/self`;
66
86
  const response = yield fetch(checkSlashesInUrl(env.WORKER_URL + endpoint),
package/nodemon.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "watch": ["src", "../backend-core"],
2
+ "watch": ["src", "../auth"],
3
3
  "ext": "js,ts,json",
4
4
  "ignore": ["src/**/*.spec.ts", "src/**/*.spec.js"],
5
5
  "exec": "ts-node src/index.ts"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "1.0.46-alpha.7",
4
+ "version": "1.0.48",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -70,9 +70,9 @@
70
70
  "license": "GPL-3.0",
71
71
  "dependencies": {
72
72
  "@apidevtools/swagger-parser": "^10.0.3",
73
- "@budibase/backend-core": "^1.0.46-alpha.7",
74
- "@budibase/client": "^1.0.46-alpha.7",
75
- "@budibase/string-templates": "^1.0.46-alpha.7",
73
+ "@budibase/backend-core": "^1.0.48",
74
+ "@budibase/client": "^1.0.48",
75
+ "@budibase/string-templates": "^1.0.48",
76
76
  "@bull-board/api": "^3.7.0",
77
77
  "@bull-board/koa": "^3.7.0",
78
78
  "@elastic/elasticsearch": "7.10.0",
@@ -92,8 +92,6 @@
92
92
  "fix-path": "3.0.0",
93
93
  "form-data": "^4.0.0",
94
94
  "fs-extra": "8.1.0",
95
- "google-auth-library": "^7.11.0",
96
- "google-spreadsheet": "^3.2.0",
97
95
  "jimp": "0.16.1",
98
96
  "joi": "17.2.1",
99
97
  "js-yaml": "^4.1.0",
@@ -112,7 +110,7 @@
112
110
  "mongodb": "3.6.3",
113
111
  "mssql": "6.2.3",
114
112
  "mysql2": "^2.3.1",
115
- "node-fetch": "2.6.7",
113
+ "node-fetch": "2.6.0",
116
114
  "open": "^8.4.0",
117
115
  "pg": "8.5.1",
118
116
  "pino-pretty": "4.0.0",
@@ -141,7 +139,6 @@
141
139
  "@jest/test-sequencer": "^24.8.0",
142
140
  "@types/apidoc": "^0.50.0",
143
141
  "@types/bull": "^3.15.1",
144
- "@types/google-spreadsheet": "^3.1.5",
145
142
  "@types/jest": "^26.0.23",
146
143
  "@types/koa": "^2.13.3",
147
144
  "@types/koa-router": "^7.4.2",
@@ -168,5 +165,5 @@
168
165
  "optionalDependencies": {
169
166
  "oracledb": "^5.3.0"
170
167
  },
171
- "gitHead": "5718d4925a31131daadf694e7f0ba837084a61f2"
168
+ "gitHead": "a5f51d83ba37e2361daf4ff579bb039a2247dd5e"
172
169
  }
@@ -33,7 +33,10 @@ const {
33
33
  Replication,
34
34
  } = require("@budibase/backend-core/db")
35
35
  const { USERS_TABLE_SCHEMA } = require("../../constants")
36
- const { removeAppFromUserRoles } = require("../../utilities/workerRequests")
36
+ const {
37
+ getDeployedApps,
38
+ removeAppFromUserRoles,
39
+ } = require("../../utilities/workerRequests")
37
40
  const { clientLibraryPath, stringToReadStream } = require("../../utilities")
38
41
  const { getAllLocks } = require("../../utilities/redis")
39
42
  const {
@@ -75,42 +78,29 @@ function getUserRoleId(ctx) {
75
78
  : ctx.user.role._id
76
79
  }
77
80
 
78
- async function getAppUrl(ctx) {
79
- // construct the url
81
+ async function getAppUrlIfNotInUse(ctx) {
80
82
  let url
81
83
  if (ctx.request.body.url) {
82
- // if the url is provided, use that
83
84
  url = encodeURI(ctx.request.body.url)
84
85
  } else if (ctx.request.body.name) {
85
- // otherwise use the name
86
86
  url = encodeURI(`${ctx.request.body.name}`)
87
87
  }
88
88
  if (url) {
89
89
  url = `/${url.replace(URL_REGEX_SLASH, "")}`.toLowerCase()
90
90
  }
91
- return url
92
- }
93
-
94
- const checkAppUrl = (ctx, apps, url, currentAppId) => {
95
- if (currentAppId) {
96
- apps = apps.filter(app => app.appId !== currentAppId)
97
- }
98
- if (apps.some(app => app.url === url)) {
99
- ctx.throw(400, "App URL is already in use.")
100
- }
101
- }
102
-
103
- const checkAppName = (ctx, apps, name, currentAppId) => {
104
- // TODO: Replace with Joi
105
- if (!name) {
106
- ctx.throw(400, "Name is required")
91
+ if (!env.SELF_HOSTED) {
92
+ return url
107
93
  }
108
- if (currentAppId) {
109
- apps = apps.filter(app => app.appId !== currentAppId)
110
- }
111
- if (apps.some(app => app.name === name)) {
112
- ctx.throw(400, "App name is already in use.")
94
+ const deployedApps = await getDeployedApps()
95
+ if (
96
+ url &&
97
+ deployedApps[url] != null &&
98
+ ctx.params != null &&
99
+ deployedApps[url].appId !== ctx.params.appId
100
+ ) {
101
+ ctx.throw(400, "App name/URL is already in use.")
113
102
  }
103
+ return url
114
104
  }
115
105
 
116
106
  async function createInstance(template) {
@@ -216,12 +206,6 @@ exports.fetchAppPackage = async ctx => {
216
206
  }
217
207
 
218
208
  exports.create = async ctx => {
219
- const apps = await getAllApps(CouchDB, { dev: true })
220
- const name = ctx.request.body.name
221
- checkAppName(ctx, apps, name)
222
- const url = await getAppUrl(ctx)
223
- checkAppUrl(ctx, apps, url)
224
-
225
209
  const { useTemplate, templateKey, templateString } = ctx.request.body
226
210
  const instanceConfig = {
227
211
  useTemplate,
@@ -234,6 +218,7 @@ exports.create = async ctx => {
234
218
  const instance = await createInstance(instanceConfig)
235
219
  const appId = instance._id
236
220
 
221
+ const url = await getAppUrlIfNotInUse(ctx)
237
222
  const db = new CouchDB(appId)
238
223
  let _rev
239
224
  try {
@@ -250,7 +235,7 @@ exports.create = async ctx => {
250
235
  type: "app",
251
236
  version: packageJson.version,
252
237
  componentLibraries: ["@budibase/standard-components"],
253
- name: name,
238
+ name: ctx.request.body.name,
254
239
  url: url,
255
240
  template: ctx.request.body.template,
256
241
  instance: instance,
@@ -277,22 +262,8 @@ exports.create = async ctx => {
277
262
  ctx.body = newApplication
278
263
  }
279
264
 
280
- // This endpoint currently operates as a PATCH rather than a PUT
281
- // Thus name and url fields are handled only if present
282
265
  exports.update = async ctx => {
283
- const apps = await getAllApps(CouchDB, { dev: true })
284
- // validation
285
- const name = ctx.request.body.name
286
- if (name) {
287
- checkAppName(ctx, apps, name, ctx.params.appId)
288
- }
289
- const url = await getAppUrl(ctx)
290
- if (url) {
291
- checkAppUrl(ctx, apps, url, ctx.params.appId)
292
- ctx.request.body.url = url
293
- }
294
-
295
- const data = await updateAppPackage(ctx.request.body, ctx.params.appId)
266
+ const data = await updateAppPackage(ctx, ctx.request.body, ctx.params.appId)
296
267
  ctx.status = 200
297
268
  ctx.body = data
298
269
  }
@@ -314,7 +285,7 @@ exports.updateClient = async ctx => {
314
285
  version: packageJson.version,
315
286
  revertableVersion: currentVersion,
316
287
  }
317
- const data = await updateAppPackage(appPackageUpdates, ctx.params.appId)
288
+ const data = await updateAppPackage(ctx, appPackageUpdates, ctx.params.appId)
318
289
  ctx.status = 200
319
290
  ctx.body = data
320
291
  }
@@ -337,7 +308,7 @@ exports.revertClient = async ctx => {
337
308
  version: application.revertableVersion,
338
309
  revertableVersion: null,
339
310
  }
340
- const data = await updateAppPackage(appPackageUpdates, ctx.params.appId)
311
+ const data = await updateAppPackage(ctx, appPackageUpdates, ctx.params.appId)
341
312
  ctx.status = 200
342
313
  ctx.body = data
343
314
  }
@@ -410,11 +381,12 @@ exports.sync = async (ctx, next) => {
410
381
  }
411
382
  }
412
383
 
413
- const updateAppPackage = async (appPackage, appId) => {
384
+ const updateAppPackage = async (ctx, appPackage, appId) => {
385
+ const url = await getAppUrlIfNotInUse(ctx)
414
386
  const db = new CouchDB(appId)
415
387
  const application = await db.get(DocumentTypes.APP_METADATA)
416
388
 
417
- const newAppPackage = { ...application, ...appPackage }
389
+ const newAppPackage = { ...application, ...appPackage, url }
418
390
  if (appPackage._rev !== application._rev) {
419
391
  newAppPackage._rev = application._rev
420
392
  }
@@ -38,13 +38,6 @@ exports.fetch = async function (ctx) {
38
38
  )
39
39
  ).rows.map(row => row.doc)
40
40
 
41
- for (let datasource of datasources) {
42
- if (datasource.config && datasource.config.auth) {
43
- // strip secrets from response so they don't show in the network request
44
- delete datasource.config.auth
45
- }
46
- }
47
-
48
41
  ctx.body = [bbInternalDb, ...datasources]
49
42
  }
50
43
 
@@ -101,13 +94,8 @@ exports.update = async function (ctx) {
101
94
  const db = new CouchDB(ctx.appId)
102
95
  const datasourceId = ctx.params.datasourceId
103
96
  let datasource = await db.get(datasourceId)
104
- const auth = datasource.config.auth
105
97
  await invalidateVariables(datasource, ctx.request.body)
106
98
  datasource = { ...datasource, ...ctx.request.body }
107
- if (auth && !ctx.request.body.auth) {
108
- // don't strip auth config from DB
109
- datasource.config.auth = auth
110
- }
111
99
 
112
100
  const response = await db.put(datasource)
113
101
  datasource._rev = response.rev
@@ -0,0 +1,22 @@
1
+ const CouchDB = require("../../db")
2
+ const { getDeployedApps } = require("../../utilities/workerRequests")
3
+ const { getScopedConfig } = require("@budibase/backend-core/db")
4
+ const { Configs } = require("@budibase/backend-core/constants")
5
+ const { checkSlashesInUrl } = require("../../utilities")
6
+
7
+ exports.fetchUrls = async ctx => {
8
+ const appId = ctx.appId
9
+ const db = new CouchDB(appId)
10
+ const settings = await getScopedConfig(db, { type: Configs.SETTINGS })
11
+ let appUrl = "http://localhost:10000/app"
12
+ if (settings && settings["platformUrl"]) {
13
+ appUrl = checkSlashesInUrl(`${settings["platformUrl"]}/app`)
14
+ }
15
+ ctx.body = {
16
+ app: appUrl,
17
+ }
18
+ }
19
+
20
+ exports.getDeployedApps = async ctx => {
21
+ ctx.body = await getDeployedApps()
22
+ }
@@ -525,7 +525,7 @@ module External {
525
525
  const linkTable = this.getTable(tableId)
526
526
  // @ts-ignore
527
527
  const linkPrimary = linkTable.primary[0]
528
- const rows = related[key].rows || []
528
+ const rows = related[key]?.rows || []
529
529
  const found = rows.find(
530
530
  (row: { [key: string]: any }) =>
531
531
  row[linkPrimary] === relationship.id ||
@@ -58,16 +58,22 @@ exports.validate = async ({ appId, tableId, row, table }) => {
58
58
  let res
59
59
 
60
60
  // Validate.js doesn't seem to handle array
61
- if (type === FieldTypes.ARRAY && row[fieldName]) {
62
- if (row[fieldName].length) {
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) {
63
67
  row[fieldName].map(val => {
64
68
  if (!constraints.inclusion.includes(val)) {
65
- errors[fieldName] = "Field not in list"
69
+ errors[fieldName] = "Value not in list"
66
70
  }
67
71
  })
68
- } else if (constraints.presence && row[fieldName].length === 0) {
69
- // non required MultiSelect creates an empty array, which should not throw errors
70
- errors[fieldName] = [`${fieldName} is required`]
72
+ }
73
+
74
+ // Check for required constraint
75
+ if (constraints.presence === true && !hasValues) {
76
+ errors[fieldName] = "Required field"
71
77
  }
72
78
  } else if (type === FieldTypes.JSON && typeof row[fieldName] === "string") {
73
79
  // this should only happen if there is an error
@@ -5,7 +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 { getAllApps } = require("@budibase/backend-core/db")
8
+ const { getDeployedApps } = require("../../../utilities/workerRequests")
9
9
  const CouchDB = require("../../../db")
10
10
  const {
11
11
  loadHandlebarsFile,
@@ -17,8 +17,6 @@ const { clientLibraryPath } = require("../../../utilities")
17
17
  const { upload } = require("../../../utilities/fileSystem")
18
18
  const { attachmentsRelativeURL } = require("../../../utilities")
19
19
  const { DocumentTypes } = require("../../../db/utils")
20
- const AWS = require("aws-sdk")
21
- const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
22
20
 
23
21
  async function prepareUpload({ s3Key, bucket, metadata, file }) {
24
22
  const response = await upload({
@@ -39,18 +37,12 @@ async function prepareUpload({ s3Key, bucket, metadata, file }) {
39
37
  }
40
38
  }
41
39
 
42
- async function getAppIdFromUrl(ctx) {
43
- // the "appId" component of the URL can be the id or the custom url
40
+ async function checkForSelfHostedURL(ctx) {
41
+ // the "appId" component of the URL may actually be a specific self hosted URL
44
42
  let possibleAppUrl = `/${encodeURI(ctx.params.appId).toLowerCase()}`
45
-
46
- // search prod apps for a url that matches, exclude dev where id is always used
47
- const apps = await getAllApps(CouchDB, { dev: false })
48
- const app = apps.filter(
49
- a => a.url && a.url.toLowerCase() === possibleAppUrl
50
- )[0]
51
-
52
- if (app && app.appId) {
53
- return app.appId
43
+ const apps = await getDeployedApps()
44
+ if (apps[possibleAppUrl] && apps[possibleAppUrl].appId) {
45
+ return apps[possibleAppUrl].appId
54
46
  } else {
55
47
  return ctx.params.appId
56
48
  }
@@ -83,7 +75,10 @@ exports.uploadFile = async function (ctx) {
83
75
  }
84
76
 
85
77
  exports.serveApp = async function (ctx) {
86
- let appId = await getAppIdFromUrl(ctx)
78
+ let appId = ctx.params.appId
79
+ if (env.SELF_HOSTED) {
80
+ appId = await checkForSelfHostedURL(ctx)
81
+ }
87
82
  const App = require("./templates/BudibaseApp.svelte").default
88
83
  const db = new CouchDB(appId, { skip_setup: true })
89
84
  const appInfo = await db.get(DocumentTypes.APP_METADATA)
@@ -109,51 +104,3 @@ exports.serveClientLibrary = async function (ctx) {
109
104
  root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"),
110
105
  })
111
106
  }
112
-
113
- exports.getSignedUploadURL = async function (ctx) {
114
- const database = new CouchDB(ctx.appId)
115
-
116
- // Ensure datasource is valid
117
- let datasource
118
- try {
119
- const { datasourceId } = ctx.params
120
- datasource = await database.get(datasourceId)
121
- if (!datasource) {
122
- ctx.throw(400, "The specified datasource could not be found")
123
- }
124
- } catch (error) {
125
- ctx.throw(400, "The specified datasource could not be found")
126
- }
127
-
128
- // Ensure we aren't using a custom endpoint
129
- if (datasource?.config?.endpoint) {
130
- ctx.throw(400, "S3 datasources with custom endpoints are not supported")
131
- }
132
-
133
- // Determine type of datasource and generate signed URL
134
- let signedUrl
135
- let publicUrl
136
- if (datasource.source === "S3") {
137
- const { bucket, key } = ctx.request.body || {}
138
- if (!bucket || !key) {
139
- ctx.throw(400, "bucket and key values are required")
140
- return
141
- }
142
- try {
143
- const s3 = new AWS.S3({
144
- region: AWS_REGION,
145
- accessKeyId: datasource?.config?.accessKeyId,
146
- secretAccessKey: datasource?.config?.secretAccessKey,
147
- apiVersion: "2006-03-01",
148
- signatureVersion: "v4",
149
- })
150
- const params = { Bucket: bucket, Key: key }
151
- signedUrl = s3.getSignedUrl("putObject", params)
152
- publicUrl = `https://${bucket}.s3.${AWS_REGION}.amazonaws.com/${key}`
153
- } catch (error) {
154
- ctx.throw(400, error)
155
- }
156
- }
157
-
158
- ctx.body = { signedUrl, publicUrl }
159
- }
@@ -2,7 +2,7 @@ const CouchDB = require("../../../db")
2
2
  const internal = require("./internal")
3
3
  const external = require("./external")
4
4
  const csvParser = require("../../../utilities/csvParser")
5
- const { isExternalTable, isSQL } = require("../../../integrations/utils")
5
+ const { isExternalTable } = require("../../../integrations/utils")
6
6
  const {
7
7
  getTableParams,
8
8
  getDatasourceParams,
@@ -32,8 +32,8 @@ exports.fetch = async function (ctx) {
32
32
  })
33
33
  )
34
34
 
35
- const internal = internalTables.rows.map(tableDoc => ({
36
- ...tableDoc.doc,
35
+ const internal = internalTables.rows.map(row => ({
36
+ ...row.doc,
37
37
  type: "internal",
38
38
  sourceId: BudibaseInternalDB._id,
39
39
  }))
@@ -44,18 +44,12 @@ exports.fetch = async function (ctx) {
44
44
  })
45
45
  )
46
46
 
47
- const external = externalTables.rows.flatMap(tableDoc => {
48
- let entities = tableDoc.doc.entities
49
- if (entities) {
50
- return Object.values(entities).map(entity => ({
51
- ...entity,
52
- type: "external",
53
- sourceId: tableDoc.doc._id,
54
- sql: isSQL(tableDoc.doc),
55
- }))
56
- } else {
57
- return []
58
- }
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
+ }))
59
53
  })
60
54
 
61
55
  ctx.body = [...internal, ...external]
@@ -8,7 +8,6 @@ const {
8
8
  getTable,
9
9
  handleDataImport,
10
10
  } = require("./utils")
11
- const usageQuota = require("../../../utilities/usageQuota")
12
11
 
13
12
  exports.save = async function (ctx) {
14
13
  const appId = ctx.appId
@@ -120,7 +119,6 @@ exports.destroy = async function (ctx) {
120
119
  })
121
120
  )
122
121
  await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
123
- await usageQuota.update(usageQuota.Properties.ROW, -rows.rows.length)
124
122
 
125
123
  // update linked rows
126
124
  await linkRows.updateLinks({