@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,15 +8,17 @@ const {
8
8
  const { isEqual } = require("lodash/fp")
9
9
  const { AutoFieldSubTypes, FieldTypes } = require("../../../constants")
10
10
  const { inputProcessing } = require("../../../utilities/rowProcessor")
11
- const { USERS_TABLE_SCHEMA, SwitchableTypes } = require("../../../constants")
11
+ const {
12
+ USERS_TABLE_SCHEMA,
13
+ SwitchableTypes,
14
+ CanSwitchTypes,
15
+ } = require("../../../constants")
12
16
  const {
13
17
  isExternalTable,
14
18
  breakExternalTableId,
15
- isSQL,
16
19
  } = require("../../../integrations/utils")
17
20
  const { getViews, saveView } = require("../view/utils")
18
21
  const viewTemplate = require("../view/viewBuilder")
19
- const usageQuota = require("../../../utilities/usageQuota")
20
22
 
21
23
  exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
22
24
  let updatedRows = []
@@ -113,11 +115,7 @@ exports.handleDataImport = async (appId, user, table, dataImport) => {
113
115
  finalData.push(row)
114
116
  }
115
117
 
116
- await usageQuota.update(usageQuota.Properties.ROW, finalData.length, {
117
- dryRun: true,
118
- })
119
118
  await db.bulkDocs(finalData)
120
- await usageQuota.update(usageQuota.Properties.ROW, finalData.length)
121
119
  let response = await db.put(table)
122
120
  table._rev = response._rev
123
121
  return table
@@ -248,9 +246,7 @@ exports.getTable = async (appId, tableId) => {
248
246
  const db = new CouchDB(appId)
249
247
  if (isExternalTable(tableId)) {
250
248
  let { datasourceId, tableName } = breakExternalTableId(tableId)
251
- const datasource = await db.get(datasourceId)
252
- const table = await exports.getExternalTable(appId, datasourceId, tableName)
253
- return { ...table, sql: isSQL(datasource) }
249
+ return exports.getExternalTable(appId, datasourceId, tableName)
254
250
  } else {
255
251
  return db.get(tableId)
256
252
  }
@@ -348,6 +344,23 @@ exports.foreignKeyStructure = (keyName, meta = null) => {
348
344
  return structure
349
345
  }
350
346
 
347
+ exports.areSwitchableTypes = (type1, type2) => {
348
+ if (
349
+ SwitchableTypes.indexOf(type1) === -1 &&
350
+ SwitchableTypes.indexOf(type2) === -1
351
+ ) {
352
+ return false
353
+ }
354
+ for (let option of CanSwitchTypes) {
355
+ const index1 = option.indexOf(type1),
356
+ index2 = option.indexOf(type2)
357
+ if (index1 !== -1 && index2 !== -1 && index1 !== index2) {
358
+ return true
359
+ }
360
+ }
361
+ return false
362
+ }
363
+
351
364
  exports.hasTypeChanged = (table, oldTable) => {
352
365
  if (!oldTable) {
353
366
  return false
@@ -358,7 +371,7 @@ exports.hasTypeChanged = (table, oldTable) => {
358
371
  continue
359
372
  }
360
373
  const newType = table.schema[key].type
361
- if (oldType !== newType && SwitchableTypes.indexOf(oldType) === -1) {
374
+ if (oldType !== newType && !exports.areSwitchableTypes(oldType, newType)) {
362
375
  return true
363
376
  }
364
377
  }
@@ -0,0 +1,13 @@
1
+ const Router = require("@koa/router")
2
+ const controller = require("../controllers/hosting")
3
+ const authorized = require("../../middleware/authorized")
4
+ const { BUILDER } = require("@budibase/backend-core/permissions")
5
+
6
+ const router = Router()
7
+
8
+ router
9
+ .get("/api/hosting/urls", authorized(BUILDER), controller.fetchUrls)
10
+ // this isn't risky, doesn't return anything about apps other than names and URLs
11
+ .get("/api/hosting/apps", controller.getDeployedApps)
12
+
13
+ module.exports = router
@@ -20,6 +20,7 @@ const integrationRoutes = require("./integration")
20
20
  const permissionRoutes = require("./permission")
21
21
  const datasourceRoutes = require("./datasource")
22
22
  const queryRoutes = require("./query")
23
+ const hostingRoutes = require("./hosting")
23
24
  const backupRoutes = require("./backup")
24
25
  const metadataRoutes = require("./metadata")
25
26
  const devRoutes = require("./dev")
@@ -45,6 +46,7 @@ exports.mainRoutes = [
45
46
  permissionRoutes,
46
47
  datasourceRoutes,
47
48
  queryRoutes,
49
+ hostingRoutes,
48
50
  backupRoutes,
49
51
  metadataRoutes,
50
52
  devRoutes,
@@ -46,10 +46,5 @@ router
46
46
  )
47
47
  // TODO: this likely needs to be secured in some way
48
48
  .get("/:appId/:path*", controller.serveApp)
49
- .post(
50
- "/api/attachments/:datasourceId/url",
51
- authorized(PermissionTypes.TABLE, PermissionLevels.READ),
52
- controller.getSignedUploadURL
53
- )
54
49
 
55
50
  module.exports = router
@@ -53,8 +53,8 @@ describe("/applications", () => {
53
53
 
54
54
  describe("fetch", () => {
55
55
  it("lists all applications", async () => {
56
- await config.createApp("app1")
57
- await config.createApp("app2")
56
+ await config.createApp(request, "app1")
57
+ await config.createApp(request, "app2")
58
58
 
59
59
  const res = await request
60
60
  .get(`/api/applications?status=${AppStatus.DEV}`)
@@ -0,0 +1,36 @@
1
+ // mock out node fetch for this
2
+ jest.mock("node-fetch")
3
+
4
+ const { checkBuilderEndpoint } = require("./utilities/TestFunctions")
5
+ const setup = require("./utilities")
6
+
7
+ describe("/hosting", () => {
8
+ let request = setup.getRequest()
9
+ let config = setup.getConfig()
10
+ let app
11
+
12
+ afterAll(setup.afterAll)
13
+
14
+ beforeEach(async () => {
15
+ app = await config.init()
16
+ })
17
+
18
+ describe("fetchUrls", () => {
19
+ it("should be able to fetch current app URLs", async () => {
20
+ const res = await request
21
+ .get(`/api/hosting/urls`)
22
+ .set(config.defaultHeaders())
23
+ .expect("Content-Type", /json/)
24
+ .expect(200)
25
+ expect(res.body.app).toEqual(`http://localhost:10000/app`)
26
+ })
27
+
28
+ it("should apply authorization to endpoint", async () => {
29
+ await checkBuilderEndpoint({
30
+ config,
31
+ method: "GET",
32
+ url: `/api/hosting/urls`,
33
+ })
34
+ })
35
+ })
36
+ })
@@ -1,5 +1,6 @@
1
1
  const rowController = require("../../api/controllers/row")
2
2
  const automationUtils = require("../automationUtils")
3
+ const env = require("../../environment")
3
4
  const usage = require("../../utilities/usageQuota")
4
5
  const { buildCtx } = require("./utils")
5
6
 
@@ -82,9 +83,10 @@ exports.run = async function ({ inputs, appId, emitter }) {
82
83
  inputs.row.tableId,
83
84
  inputs.row
84
85
  )
85
- await usage.update(usage.Properties.ROW, 1, { dryRun: true })
86
+ if (env.USE_QUOTAS) {
87
+ await usage.update(usage.Properties.ROW, 1)
88
+ }
86
89
  await rowController.save(ctx)
87
- await usage.update(usage.Properties.ROW, 1)
88
90
  return {
89
91
  row: inputs.row,
90
92
  response: ctx.body,
@@ -1,4 +1,5 @@
1
1
  const rowController = require("../../api/controllers/row")
2
+ const env = require("../../environment")
2
3
  const usage = require("../../utilities/usageQuota")
3
4
  const { buildCtx } = require("./utils")
4
5
  const automationUtils = require("../automationUtils")
@@ -73,7 +74,9 @@ exports.run = async function ({ inputs, appId, emitter }) {
73
74
  })
74
75
 
75
76
  try {
76
- await usage.update(usage.Properties.ROW, -1)
77
+ if (env.isProd()) {
78
+ await usage.update(usage.Properties.ROW, -1)
79
+ }
77
80
  await rowController.destroy(ctx)
78
81
  return {
79
82
  response: ctx.body,
@@ -45,13 +45,16 @@ exports.FieldTypes = {
45
45
  INTERNAL: "internal",
46
46
  }
47
47
 
48
- exports.SwitchableTypes = [
49
- exports.FieldTypes.STRING,
50
- exports.FieldTypes.OPTIONS,
51
- exports.FieldTypes.NUMBER,
52
- exports.FieldTypes.BOOLEAN,
48
+ exports.CanSwitchTypes = [
49
+ [exports.FieldTypes.JSON, exports.FieldTypes.ARRAY],
50
+ [exports.FieldTypes.STRING, exports.FieldTypes.OPTIONS],
51
+ [exports.FieldTypes.BOOLEAN, exports.FieldTypes.NUMBER],
53
52
  ]
54
53
 
54
+ exports.SwitchableTypes = exports.CanSwitchTypes.reduce((prev, current) =>
55
+ prev ? prev.concat(current) : current
56
+ )
57
+
55
58
  exports.RelationshipTypes = {
56
59
  ONE_TO_MANY: "one-to-many",
57
60
  MANY_TO_ONE: "many-to-one",
@@ -75,10 +78,6 @@ exports.DataSourceOperation = {
75
78
  DELETE_TABLE: "DELETE_TABLE",
76
79
  }
77
80
 
78
- exports.DatasourceAuthTypes = {
79
- GOOGLE: "google",
80
- }
81
-
82
81
  exports.SortDirection = {
83
82
  ASCENDING: "ASCENDING",
84
83
  DESCENDING: "DESCENDING",
@@ -47,7 +47,6 @@ export enum SourceNames {
47
47
  ARANGODB = "ARANGODB",
48
48
  REST = "REST",
49
49
  ORACLE = "ORACLE",
50
- GOOGLE_SHEETS = "GOOGLE_SHEETS",
51
50
  }
52
51
 
53
52
  export enum IncludeRelationships {
@@ -87,8 +86,6 @@ export interface ExtraQueryConfig {
87
86
  export interface Integration {
88
87
  docs: string
89
88
  plus?: boolean
90
- auth?: { type: string }
91
- relationships?: boolean
92
89
  description: string
93
90
  friendlyName: string
94
91
  datasource: {}
@@ -38,7 +38,6 @@ module.exports = {
38
38
  MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
39
39
  MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
40
40
  USE_QUOTAS: process.env.USE_QUOTAS,
41
- EXCLUDE_QUOTAS_TENANTS: process.env.EXCLUDE_QUOTAS_TENANTS,
42
41
  REDIS_URL: process.env.REDIS_URL,
43
42
  REDIS_PASSWORD: process.env.REDIS_PASSWORD,
44
43
  INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
@@ -72,22 +72,16 @@ class InternalBuilder {
72
72
 
73
73
  // right now we only do filters on the specific table being queried
74
74
  addFilters(
75
+ tableName: string,
75
76
  query: KnexQuery,
76
- filters: SearchFilters | undefined,
77
- opts: { relationship?: boolean; tableName?: string }
77
+ filters: SearchFilters | undefined
78
78
  ): KnexQuery {
79
79
  function iterate(
80
80
  structure: { [key: string]: any },
81
81
  fn: (key: string, value: any) => void
82
82
  ) {
83
83
  for (let [key, value] of Object.entries(structure)) {
84
- const isRelationshipField = key.includes(".")
85
- if (!opts.relationship && !isRelationshipField) {
86
- fn(`${opts.tableName}.${key}`, value)
87
- }
88
- if (opts.relationship && isRelationshipField) {
89
- fn(key, value)
90
- }
84
+ fn(`${tableName}.${key}`, value)
91
85
  }
92
86
  }
93
87
  if (!filters) {
@@ -278,7 +272,7 @@ class InternalBuilder {
278
272
  if (foundOffset) {
279
273
  query = query.offset(foundOffset)
280
274
  }
281
- query = this.addFilters(query, filters, { tableName })
275
+ query = this.addFilters(tableName, query, filters)
282
276
  // add sorting to pre-query
283
277
  query = this.addSorting(query, json)
284
278
  // @ts-ignore
@@ -291,21 +285,20 @@ class InternalBuilder {
291
285
  preQuery = this.addSorting(preQuery, json)
292
286
  }
293
287
  // handle joins
294
- query = this.addRelationships(
288
+ return this.addRelationships(
295
289
  knex,
296
290
  preQuery,
297
291
  selectStatement,
298
292
  tableName,
299
293
  relationships
300
294
  )
301
- return this.addFilters(query, filters, { relationship: true })
302
295
  }
303
296
 
304
297
  update(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
305
298
  const { endpoint, body, filters } = json
306
299
  let query: KnexQuery = knex(endpoint.entityId)
307
300
  const parsedBody = parseBody(body)
308
- query = this.addFilters(query, filters, { tableName: endpoint.entityId })
301
+ query = this.addFilters(endpoint.entityId, query, filters)
309
302
  // mysql can't use returning
310
303
  if (opts.disableReturning) {
311
304
  return query.update(parsedBody)
@@ -317,7 +310,7 @@ class InternalBuilder {
317
310
  delete(knex: Knex, json: QueryJson, opts: QueryOptions): KnexQuery {
318
311
  const { endpoint, filters } = json
319
312
  let query: KnexQuery = knex(endpoint.entityId)
320
- query = this.addFilters(query, filters, { tableName: endpoint.entityId })
313
+ query = this.addFilters(endpoint.entityId, query, filters)
321
314
  // mysql can't use returning
322
315
  if (opts.disableReturning) {
323
316
  return query.delete()
@@ -9,7 +9,6 @@ const airtable = require("./airtable")
9
9
  const mysql = require("./mysql")
10
10
  const arangodb = require("./arangodb")
11
11
  const rest = require("./rest")
12
- const googlesheets = require("./googlesheets")
13
12
  const { SourceNames } = require("../definitions/datasource")
14
13
 
15
14
  const DEFINITIONS = {
@@ -24,7 +23,6 @@ const DEFINITIONS = {
24
23
  [SourceNames.MYSQL]: mysql.schema,
25
24
  [SourceNames.ARANGODB]: arangodb.schema,
26
25
  [SourceNames.REST]: rest.schema,
27
- [SourceNames.GOOGLE_SHEETS]: googlesheets.schema,
28
26
  }
29
27
 
30
28
  const INTEGRATIONS = {
@@ -39,7 +37,6 @@ const INTEGRATIONS = {
39
37
  [SourceNames.MYSQL]: mysql.integration,
40
38
  [SourceNames.ARANGODB]: arangodb.integration,
41
39
  [SourceNames.REST]: rest.integration,
42
- [SourceNames.GOOGLE_SHEETS]: googlesheets.integration,
43
40
  }
44
41
 
45
42
  // optionally add oracle integration if the oracle binary can be installed
@@ -119,22 +119,6 @@ describe("SQL query builder", () => {
119
119
  })
120
120
  })
121
121
 
122
- it("should allow filtering on a related field", () => {
123
- const query = sql._query(generateReadJson({
124
- filters: {
125
- equal: {
126
- age: 10,
127
- "task.name": "task 1",
128
- },
129
- },
130
- }))
131
- // order of bindings changes because relationship filters occur outside inner query
132
- expect(query).toEqual({
133
- bindings: [10, limit, "task 1"],
134
- sql: `select * from (select * from "${TABLE_NAME}" where "${TABLE_NAME}"."age" = $1 limit $2) as "${TABLE_NAME}" where "task"."name" = $3`
135
- })
136
- })
137
-
138
122
  it("should test an create statement", () => {
139
123
  const query = sql._query(generateCreateJson(TABLE_NAME, {
140
124
  name: "Michael",
@@ -1,5 +1,6 @@
1
- import { SourceNames, SqlQuery } from "../definitions/datasource"
1
+ import { SqlQuery } from "../definitions/datasource"
2
2
  import { Datasource, Table } from "../definitions/common"
3
+ import { SourceNames } from "../definitions/datasource"
3
4
  import { DocumentTypes, SEPARATOR } from "../db/utils"
4
5
  import { FieldTypes, BuildSchemaErrors, InvalidColumns } from "../constants"
5
6
 
@@ -126,12 +127,7 @@ export function isSQL(datasource: Datasource): boolean {
126
127
  if (!datasource || !datasource.source) {
127
128
  return false
128
129
  }
129
- const SQL = [
130
- SourceNames.POSTGRES,
131
- SourceNames.SQL_SERVER,
132
- SourceNames.MYSQL,
133
- SourceNames.ORACLE,
134
- ]
130
+ const SQL = [SourceNames.POSTGRES, SourceNames.SQL_SERVER, SourceNames.MYSQL]
135
131
  return SQL.indexOf(datasource.source) !== -1
136
132
  }
137
133
 
@@ -143,59 +139,11 @@ export function isIsoDateString(str: string) {
143
139
  return d.toISOString() === str
144
140
  }
145
141
 
146
- /**
147
- * This function will determine whether a column is a relationship and whether it
148
- * is currently valid. The reason for the validity check is that tables can be deleted
149
- * outside of Budibase control and if this is the case it will break Budibase relationships.
150
- * The tableIds is a list passed down from the main finalise tables function, which is
151
- * based on the tables that have just been fetched. This will only really be used on subsequent
152
- * fetches to the first one - if the user is periodically refreshing Budibase knowledge of tables.
153
- * @param column The column to check, to see if it is a valid relationship.
154
- * @param tableIds The IDs of the tables which currently exist.
155
- */
156
- function shouldCopyRelationship(
157
- column: { type: string; tableId?: string },
158
- tableIds: [string]
159
- ) {
160
- return (
161
- column.type === FieldTypes.LINK &&
162
- column.tableId &&
163
- tableIds.includes(column.tableId)
164
- )
165
- }
166
-
167
- /**
168
- * Similar function to the shouldCopyRelationship function, but instead this looks for options and boolean
169
- * types. It is possible to switch a string -> options and a number -> boolean (and vice versus) need to make
170
- * sure that these get copied over when tables are fetched. Also checks whether they are still valid, if a
171
- * column has changed type in the external database then copying it over may not be possible.
172
- * @param column The column to check for options or boolean type.
173
- * @param fetchedColumn The fetched column to check for the type in the external database.
174
- */
175
- function shouldCopySpecialColumn(
176
- column: { type: string },
177
- fetchedColumn: { type: string } | undefined
178
- ) {
179
- return (
180
- column.type === FieldTypes.OPTIONS ||
181
- ((!fetchedColumn || fetchedColumn.type === FieldTypes.NUMBER) &&
182
- column.type === FieldTypes.BOOLEAN)
183
- )
184
- }
185
-
186
- /**
187
- * Looks for columns which need to be copied over into the new table definitions, like relationships
188
- * and options types.
189
- * @param tableName The name of the table which is being checked.
190
- * @param table The specific table which is being checked.
191
- * @param entities All the tables that existed before - the old table definitions.
192
- * @param tableIds The IDs of the tables which exist now, to check if anything has been removed.
193
- */
142
+ // add the existing relationships from the entities if they exist, to prevent them from being overridden
194
143
  function copyExistingPropsOver(
195
144
  tableName: string,
196
145
  table: Table,
197
- entities: { [key: string]: any },
198
- tableIds: [string]
146
+ entities: { [key: string]: any }
199
147
  ) {
200
148
  if (entities && entities[tableName]) {
201
149
  if (entities[tableName].primaryDisplay) {
@@ -206,10 +154,12 @@ function copyExistingPropsOver(
206
154
  if (!existingTableSchema.hasOwnProperty(key)) {
207
155
  continue
208
156
  }
209
- const column = existingTableSchema[key]
210
157
  if (
211
- shouldCopyRelationship(column, tableIds) ||
212
- shouldCopySpecialColumn(column, table.schema[key])
158
+ existingTableSchema[key].type === FieldTypes.LINK ||
159
+ existingTableSchema[key].type === FieldTypes.OPTIONS ||
160
+ existingTableSchema[key].type === FieldTypes.ARRAY ||
161
+ ((!table.schema[key] || table.schema[key].type === FieldTypes.NUMBER) &&
162
+ existingTableSchema[key].type === FieldTypes.BOOLEAN)
213
163
  ) {
214
164
  table.schema[key] = existingTableSchema[key]
215
165
  }
@@ -218,13 +168,6 @@ function copyExistingPropsOver(
218
168
  return table
219
169
  }
220
170
 
221
- /**
222
- * Look through the final table definitions to see if anything needs to be
223
- * copied over from the old and if any errors have occurred mark them so
224
- * that the user can be made aware.
225
- * @param tables The list of tables that have been retrieved from the external database.
226
- * @param entities The old list of tables, if there was any to look for definitions in.
227
- */
228
171
  export function finaliseExternalTables(
229
172
  tables: { [key: string]: any },
230
173
  entities: { [key: string]: any }
@@ -232,8 +175,6 @@ export function finaliseExternalTables(
232
175
  const invalidColumns = Object.values(InvalidColumns)
233
176
  let finalTables: { [key: string]: any } = {}
234
177
  const errors: { [key: string]: string } = {}
235
- // @ts-ignore
236
- const tableIds: [string] = Object.values(tables).map(table => table._id)
237
178
  for (let [name, table] of Object.entries(tables)) {
238
179
  const schemaFields = Object.keys(table.schema)
239
180
  // make sure every table has a key
@@ -245,7 +186,7 @@ export function finaliseExternalTables(
245
186
  continue
246
187
  }
247
188
  // make sure all previous props have been added back
248
- finalTables[name] = copyExistingPropsOver(name, table, entities, tableIds)
189
+ finalTables[name] = copyExistingPropsOver(name, table, entities)
249
190
  }
250
191
  // sort the tables by name
251
192
  finalTables = Object.entries(finalTables)
@@ -1,5 +1,11 @@
1
1
  jest.mock("../../db")
2
2
  jest.mock("../../utilities/usageQuota")
3
+ jest.mock("../../environment", () => ({
4
+ isTest: () => true,
5
+ isProd: () => false,
6
+ isDev: () => true,
7
+ _set: () => {},
8
+ }))
3
9
  jest.mock("@budibase/backend-core/tenancy", () => ({
4
10
  getTenantId: () => "testing123"
5
11
  }))
@@ -23,10 +29,9 @@ class TestConfiguration {
23
29
  },
24
30
  req: {
25
31
  method: "POST",
26
- url: "/applications"
32
+ url: "/rows"
27
33
  }
28
34
  }
29
- usageQuota.useQuotas = () => true
30
35
  }
31
36
 
32
37
  executeMiddleware() {
@@ -108,6 +113,7 @@ describe("usageQuota middleware", () => {
108
113
 
109
114
  it("calculates and persists the correct usage quota for the relevant action", async () => {
110
115
  config.setUrl("/rows")
116
+ config.setProd(true)
111
117
 
112
118
  await config.executeMiddleware()
113
119
 
@@ -115,20 +121,20 @@ describe("usageQuota middleware", () => {
115
121
  expect(config.next).toHaveBeenCalled()
116
122
  })
117
123
 
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
- // })
124
+ it("calculates the correct file size from a file upload call and adds it to quota", async () => {
125
+ config.setUrl("/upload")
126
+ config.setProd(true)
127
+ config.setFiles([
128
+ {
129
+ size: 100
130
+ },
131
+ {
132
+ size: 10000
133
+ },
134
+ ])
135
+ await config.executeMiddleware()
136
+
137
+ expect(usageQuota.update).toHaveBeenCalledWith("storage", 10100)
138
+ expect(config.next).toHaveBeenCalled()
139
+ })
134
140
  })