@budibase/server 1.0.48 → 1.0.49-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/builder/assets/{index.e083dcaf.js → index.21e57eb4.js} +234 -231
  2. package/builder/assets/index.83c0944f.css +1 -0
  3. package/builder/assets/{vendor.f9faf6ab.js → vendor.d526bfe8.js} +12 -12
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +2338 -2028
  6. package/coverage/coverage-final.json +100 -95
  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 +210 -126
  10. package/coverage/lcov-report/api/controllers/auth.js.html +18 -6
  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 +72 -36
  16. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/index.html +53 -53
  18. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
  20. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/migrations.js.html +119 -0
  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 +48 -33
  30. package/coverage/lcov-report/api/controllers/row/index.js.html +26 -26
  31. package/coverage/lcov-report/api/controllers/row/internal.js.html +95 -158
  32. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +41 -17
  33. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +551 -0
  34. package/coverage/lcov-report/api/controllers/row/utils.js.html +39 -57
  35. package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
  36. package/coverage/lcov-report/api/controllers/script.js.html +4 -4
  37. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +629 -0
  38. package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
  39. package/coverage/lcov-report/api/controllers/table/index.html +46 -31
  40. package/coverage/lcov-report/api/controllers/table/index.js.html +53 -77
  41. package/coverage/lcov-report/api/controllers/table/internal.js.html +59 -35
  42. package/coverage/lcov-report/api/controllers/table/utils.js.html +217 -73
  43. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/user.js.html +30 -24
  45. package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
  46. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  47. package/coverage/lcov-report/api/controllers/view/index.js.html +14 -14
  48. package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
  49. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
  50. package/coverage/lcov-report/api/controllers/webhook.js.html +15 -15
  51. package/coverage/lcov-report/api/index.html +1 -1
  52. package/coverage/lcov-report/api/index.js.html +8 -8
  53. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/application.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/index.html +18 -18
  65. package/coverage/lcov-report/api/routes/index.js.html +3 -3
  66. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/{hosting.js.html → migrations.js.html} +17 -14
  70. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  73. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/row.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  76. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  77. package/coverage/lcov-report/api/routes/static.js.html +17 -2
  78. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  79. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  80. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  81. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  82. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  83. package/coverage/lcov-report/automations/actions.js.html +24 -24
  84. package/coverage/lcov-report/automations/automationUtils.js.html +5 -5
  85. package/coverage/lcov-report/automations/bullboard.js.html +16 -16
  86. package/coverage/lcov-report/automations/index.html +1 -1
  87. package/coverage/lcov-report/automations/index.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
  89. package/coverage/lcov-report/automations/steps/createRow.js.html +13 -19
  90. package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
  91. package/coverage/lcov-report/automations/steps/deleteRow.js.html +11 -20
  92. package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
  93. package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
  94. package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
  95. package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
  96. package/coverage/lcov-report/automations/steps/index.html +13 -13
  97. package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
  98. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
  99. package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
  100. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
  101. package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
  102. package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
  103. package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
  104. package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
  105. package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
  106. package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
  107. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
  108. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  109. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
  110. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
  111. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
  112. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
  113. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
  114. package/coverage/lcov-report/automations/triggers.js.html +18 -18
  115. package/coverage/lcov-report/automations/utils.js.html +32 -32
  116. package/coverage/lcov-report/constants/index.html +5 -5
  117. package/coverage/lcov-report/constants/index.js.html +53 -26
  118. package/coverage/lcov-report/constants/layouts.js.html +5 -5
  119. package/coverage/lcov-report/constants/screens.js.html +4 -4
  120. package/coverage/lcov-report/db/client.js.html +18 -18
  121. package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
  122. package/coverage/lcov-report/db/index.html +15 -15
  123. package/coverage/lcov-report/db/index.js.html +3 -3
  124. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +18 -18
  125. package/coverage/lcov-report/db/linkedRows/index.html +10 -10
  126. package/coverage/lcov-report/db/linkedRows/index.js.html +38 -41
  127. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +15 -15
  128. package/coverage/lcov-report/db/newid.js.html +4 -4
  129. package/coverage/lcov-report/db/utils.js.html +86 -86
  130. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  131. package/coverage/lcov-report/events/index.html +1 -1
  132. package/coverage/lcov-report/events/index.js.html +5 -5
  133. package/coverage/lcov-report/events/utils.js.html +3 -3
  134. package/coverage/lcov-report/index.html +114 -99
  135. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  136. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  137. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  138. package/coverage/lcov-report/middleware/authorized.js.html +166 -64
  139. package/coverage/lcov-report/middleware/builder.js.html +8 -8
  140. package/coverage/lcov-report/middleware/currentapp.js.html +29 -29
  141. package/coverage/lcov-report/middleware/index.html +30 -30
  142. package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
  143. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  144. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  145. package/coverage/lcov-report/middleware/usageQuota.js.html +270 -42
  146. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  147. package/coverage/lcov-report/threads/automation.js.html +1 -1
  148. package/coverage/lcov-report/threads/index.html +15 -15
  149. package/coverage/lcov-report/threads/index.js.html +10 -10
  150. package/coverage/lcov-report/threads/query.js.html +23 -8
  151. package/coverage/lcov-report/threads/utils.js.html +14 -14
  152. package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
  153. package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
  154. package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
  155. package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
  156. package/coverage/lcov-report/utilities/global.js.html +26 -26
  157. package/coverage/lcov-report/utilities/index.html +19 -19
  158. package/coverage/lcov-report/utilities/index.js.html +25 -25
  159. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
  160. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  161. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  162. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  163. package/coverage/lcov-report/utilities/rowProcessor/index.html +27 -27
  164. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +115 -79
  165. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +75 -27
  166. package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
  167. package/coverage/lcov-report/utilities/security.js.html +8 -8
  168. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  169. package/coverage/lcov-report/utilities/usageQuota/index.html +141 -0
  170. package/coverage/lcov-report/utilities/usageQuota/index.js.html +356 -0
  171. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +302 -0
  172. package/coverage/lcov-report/{api/controllers/hosting.js.html → utilities/usageQuota/usageQuoteReset.js.html} +36 -48
  173. package/coverage/lcov-report/utilities/users.js.html +5 -5
  174. package/coverage/lcov-report/utilities/workerRequests.js.html +39 -108
  175. package/coverage/lcov.info +3656 -3057
  176. package/dist/api/controllers/application.js +61 -34
  177. package/dist/api/controllers/auth.js +4 -0
  178. package/dist/api/controllers/datasource.js +11 -0
  179. package/dist/api/controllers/migrations.js +21 -0
  180. package/dist/api/controllers/row/internal.js +30 -53
  181. package/dist/api/controllers/row/internalSearch.js +12 -4
  182. package/dist/api/controllers/row/staticFormula.js +147 -0
  183. package/dist/api/controllers/row/utils.js +6 -8
  184. package/dist/api/controllers/static/index.js +59 -10
  185. package/dist/api/controllers/table/bulkFormula.js +160 -0
  186. package/dist/api/controllers/table/index.js +12 -9
  187. package/dist/api/controllers/table/internal.js +9 -0
  188. package/dist/api/controllers/table/utils.js +41 -12
  189. package/dist/api/controllers/user.js +2 -0
  190. package/dist/api/routes/index.js +2 -2
  191. package/dist/api/routes/migrations.js +9 -0
  192. package/dist/api/routes/static.js +2 -1
  193. package/dist/app.js +35 -5
  194. package/dist/automations/steps/createRow.js +2 -4
  195. package/dist/automations/steps/deleteRow.js +1 -4
  196. package/dist/constants/index.js +7 -0
  197. package/dist/db/linkedRows/index.js +4 -5
  198. package/dist/definitions/datasource.js +1 -0
  199. package/dist/environment.js +2 -0
  200. package/dist/integrations/base/sql.js +13 -6
  201. package/dist/integrations/googlesheets.js +340 -0
  202. package/dist/integrations/index.js +3 -0
  203. package/dist/integrations/utils.js +57 -9
  204. package/dist/middleware/authorized.js +55 -30
  205. package/dist/middleware/usageQuota.js +80 -13
  206. package/dist/migrations/functions/appUrls.js +46 -0
  207. package/dist/migrations/functions/quotas1.js +50 -0
  208. package/dist/migrations/functions/usageQuotas/index.js +20 -0
  209. package/dist/migrations/functions/usageQuotas/syncApps.js +32 -0
  210. package/dist/migrations/functions/usageQuotas/syncRows.js +35 -0
  211. package/dist/migrations/functions/userEmailViewCasing.js +24 -0
  212. package/dist/migrations/index.js +62 -0
  213. package/dist/package.json +8 -5
  214. package/dist/tests/utilities/TestConfiguration.js +13 -6
  215. package/dist/threads/query.js +4 -0
  216. package/dist/tsconfig.tsbuildinfo +1 -1
  217. package/dist/utilities/rowProcessor/index.js +18 -11
  218. package/dist/utilities/rowProcessor/utils.js +14 -4
  219. package/dist/utilities/{usageQuota.js → usageQuota/index.js} +44 -31
  220. package/dist/utilities/usageQuota/rows.js +77 -0
  221. package/dist/utilities/usageQuota/usageQuoteReset.js +16 -0
  222. package/dist/utilities/workerRequests.js +0 -20
  223. package/nodemon.json +1 -1
  224. package/package.json +9 -6
  225. package/src/api/controllers/application.js +52 -24
  226. package/src/api/controllers/auth.js +4 -0
  227. package/src/api/controllers/datasource.js +12 -0
  228. package/src/api/controllers/migrations.js +13 -0
  229. package/src/api/controllers/row/internal.js +29 -50
  230. package/src/api/controllers/row/internalSearch.js +12 -4
  231. package/src/api/controllers/row/staticFormula.js +157 -0
  232. package/src/api/controllers/row/utils.js +6 -12
  233. package/src/api/controllers/static/index.js +63 -10
  234. package/src/api/controllers/table/bulkFormula.js +183 -0
  235. package/src/api/controllers/table/index.js +16 -24
  236. package/src/api/controllers/table/internal.js +9 -1
  237. package/src/api/controllers/table/utils.js +57 -9
  238. package/src/api/controllers/user.js +2 -0
  239. package/src/api/routes/index.js +2 -2
  240. package/src/api/routes/migrations.js +14 -0
  241. package/src/api/routes/static.js +5 -0
  242. package/src/api/routes/tests/application.spec.js +2 -2
  243. package/src/api/routes/tests/auth.spec.js +1 -2
  244. package/src/api/routes/tests/static.spec.js +98 -0
  245. package/src/app.ts +18 -5
  246. package/src/automations/steps/createRow.js +2 -4
  247. package/src/automations/steps/deleteRow.js +1 -4
  248. package/src/constants/index.js +9 -0
  249. package/src/db/linkedRows/index.js +4 -5
  250. package/src/definitions/common.ts +3 -0
  251. package/src/definitions/datasource.ts +3 -0
  252. package/src/environment.js +2 -0
  253. package/src/integrations/base/sql.ts +14 -7
  254. package/src/integrations/googlesheets.ts +353 -0
  255. package/src/integrations/index.ts +3 -0
  256. package/src/integrations/tests/sql.spec.js +16 -0
  257. package/src/integrations/utils.ts +71 -11
  258. package/src/middleware/authorized.js +64 -30
  259. package/src/middleware/tests/authorized.spec.js +6 -4
  260. package/src/middleware/tests/usageQuota.spec.js +18 -24
  261. package/src/middleware/usageQuota.js +91 -15
  262. package/src/migrations/functions/appUrls.ts +34 -0
  263. package/src/migrations/functions/quotas1.ts +20 -0
  264. package/src/migrations/functions/tests/appUrls.spec.js +29 -0
  265. package/src/migrations/functions/tests/quotas1.spec.js +27 -0
  266. package/src/migrations/functions/tests/userEmailViewCasing.spec.js +25 -0
  267. package/src/migrations/functions/usageQuotas/index.ts +8 -0
  268. package/src/migrations/functions/usageQuotas/syncApps.ts +18 -0
  269. package/src/migrations/functions/usageQuotas/syncRows.ts +21 -0
  270. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +37 -0
  271. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +43 -0
  272. package/src/migrations/functions/userEmailViewCasing.ts +13 -0
  273. package/src/migrations/index.ts +56 -0
  274. package/src/tests/utilities/TestConfiguration.js +14 -6
  275. package/src/threads/query.js +5 -0
  276. package/src/utilities/rowProcessor/index.js +24 -12
  277. package/src/utilities/rowProcessor/utils.js +23 -7
  278. package/src/utilities/tests/usageQuota/usageQuota.spec.js +72 -0
  279. package/src/utilities/usageQuota/index.js +92 -0
  280. package/src/utilities/usageQuota/rows.js +74 -0
  281. package/src/utilities/usageQuota/usageQuoteReset.js +18 -0
  282. package/src/utilities/workerRequests.js +0 -23
  283. package/builder/assets/index.39e01193.css +0 -1
  284. package/dist/api/controllers/hosting.js +0 -30
  285. package/dist/api/routes/hosting.js +0 -11
  286. package/src/api/controllers/hosting.js +0 -22
  287. package/src/api/routes/hosting.js +0 -13
  288. package/src/api/routes/tests/hosting.spec.js +0 -36
  289. package/src/utilities/usageQuota.js +0 -73
@@ -20,7 +20,7 @@ const { cloneDeep } = require("lodash/fp");
20
20
  const { processObject } = require("@budibase/string-templates");
21
21
  const { getAllApps, isDevAppID, getDeployedAppID, Replication, } = require("@budibase/backend-core/db");
22
22
  const { USERS_TABLE_SCHEMA } = require("../../constants");
23
- const { getDeployedApps, removeAppFromUserRoles, } = require("../../utilities/workerRequests");
23
+ const { removeAppFromUserRoles } = require("../../utilities/workerRequests");
24
24
  const { clientLibraryPath, stringToReadStream } = require("../../utilities");
25
25
  const { getAllLocks } = require("../../utilities/redis");
26
26
  const { updateClientLibrary, backupClientLibrary, revertClientLibrary, } = require("../../utilities/fileSystem/clientLibrary");
@@ -49,31 +49,42 @@ function getUserRoleId(ctx) {
49
49
  ? BUILTIN_ROLE_IDS.PUBLIC
50
50
  : ctx.user.role._id;
51
51
  }
52
- function getAppUrlIfNotInUse(ctx) {
53
- return __awaiter(this, void 0, void 0, function* () {
54
- let url;
55
- if (ctx.request.body.url) {
56
- url = encodeURI(ctx.request.body.url);
57
- }
58
- else if (ctx.request.body.name) {
59
- url = encodeURI(`${ctx.request.body.name}`);
60
- }
61
- if (url) {
62
- url = `/${url.replace(URL_REGEX_SLASH, "")}`.toLowerCase();
63
- }
64
- if (!env.SELF_HOSTED) {
65
- return url;
66
- }
67
- const deployedApps = yield getDeployedApps();
68
- if (url &&
69
- deployedApps[url] != null &&
70
- ctx.params != null &&
71
- deployedApps[url].appId !== ctx.params.appId) {
72
- ctx.throw(400, "App name/URL is already in use.");
73
- }
74
- return url;
75
- });
76
- }
52
+ exports.getAppUrl = ctx => {
53
+ // construct the url
54
+ let url;
55
+ if (ctx.request.body.url) {
56
+ // if the url is provided, use that
57
+ url = encodeURI(ctx.request.body.url);
58
+ }
59
+ else if (ctx.request.body.name) {
60
+ // otherwise use the name
61
+ url = encodeURI(`${ctx.request.body.name}`);
62
+ }
63
+ if (url) {
64
+ url = `/${url.replace(URL_REGEX_SLASH, "")}`.toLowerCase();
65
+ }
66
+ return url;
67
+ };
68
+ const checkAppUrl = (ctx, apps, url, currentAppId) => {
69
+ if (currentAppId) {
70
+ apps = apps.filter(app => app.appId !== currentAppId);
71
+ }
72
+ if (apps.some(app => app.url === url)) {
73
+ ctx.throw(400, "App URL is already in use.");
74
+ }
75
+ };
76
+ const checkAppName = (ctx, apps, name, currentAppId) => {
77
+ // TODO: Replace with Joi
78
+ if (!name) {
79
+ ctx.throw(400, "Name is required");
80
+ }
81
+ if (currentAppId) {
82
+ apps = apps.filter(app => app.appId !== currentAppId);
83
+ }
84
+ if (apps.some(app => app.name === name)) {
85
+ ctx.throw(400, "App name is already in use.");
86
+ }
87
+ };
77
88
  function createInstance(template) {
78
89
  return __awaiter(this, void 0, void 0, function* () {
79
90
  const tenantId = isMultiTenant() ? getTenantId() : null;
@@ -167,6 +178,11 @@ exports.fetchAppPackage = (ctx) => __awaiter(void 0, void 0, void 0, function* (
167
178
  };
168
179
  });
169
180
  exports.create = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
181
+ const apps = yield getAllApps(CouchDB, { dev: true });
182
+ const name = ctx.request.body.name;
183
+ checkAppName(ctx, apps, name);
184
+ const url = exports.getAppUrl(ctx);
185
+ checkAppUrl(ctx, apps, url);
170
186
  const { useTemplate, templateKey, templateString } = ctx.request.body;
171
187
  const instanceConfig = {
172
188
  useTemplate,
@@ -178,7 +194,6 @@ exports.create = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
178
194
  }
179
195
  const instance = yield createInstance(instanceConfig);
180
196
  const appId = instance._id;
181
- const url = yield getAppUrlIfNotInUse(ctx);
182
197
  const db = new CouchDB(appId);
183
198
  let _rev;
184
199
  try {
@@ -196,7 +211,7 @@ exports.create = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
196
211
  type: "app",
197
212
  version: packageJson.version,
198
213
  componentLibraries: ["@budibase/standard-components"],
199
- name: ctx.request.body.name,
214
+ name: name,
200
215
  url: url,
201
216
  template: ctx.request.body.template,
202
217
  instance: instance,
@@ -219,8 +234,21 @@ exports.create = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
219
234
  ctx.status = 200;
220
235
  ctx.body = newApplication;
221
236
  });
237
+ // This endpoint currently operates as a PATCH rather than a PUT
238
+ // Thus name and url fields are handled only if present
222
239
  exports.update = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
223
- const data = yield updateAppPackage(ctx, ctx.request.body, ctx.params.appId);
240
+ const apps = yield getAllApps(CouchDB, { dev: true });
241
+ // validation
242
+ const name = ctx.request.body.name;
243
+ if (name) {
244
+ checkAppName(ctx, apps, name, ctx.params.appId);
245
+ }
246
+ const url = yield exports.getAppUrl(ctx);
247
+ if (url) {
248
+ checkAppUrl(ctx, apps, url, ctx.params.appId);
249
+ ctx.request.body.url = url;
250
+ }
251
+ const data = yield updateAppPackage(ctx.request.body, ctx.params.appId);
224
252
  ctx.status = 200;
225
253
  ctx.body = data;
226
254
  });
@@ -239,7 +267,7 @@ exports.updateClient = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
239
267
  version: packageJson.version,
240
268
  revertableVersion: currentVersion,
241
269
  };
242
- const data = yield updateAppPackage(ctx, appPackageUpdates, ctx.params.appId);
270
+ const data = yield updateAppPackage(appPackageUpdates, ctx.params.appId);
243
271
  ctx.status = 200;
244
272
  ctx.body = data;
245
273
  });
@@ -259,7 +287,7 @@ exports.revertClient = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
259
287
  version: application.revertableVersion,
260
288
  revertableVersion: null,
261
289
  };
262
- const data = yield updateAppPackage(ctx, appPackageUpdates, ctx.params.appId);
290
+ const data = yield updateAppPackage(appPackageUpdates, ctx.params.appId);
263
291
  ctx.status = 200;
264
292
  ctx.body = data;
265
293
  });
@@ -326,11 +354,10 @@ exports.sync = (ctx, next) => __awaiter(void 0, void 0, void 0, function* () {
326
354
  };
327
355
  }
328
356
  });
329
- const updateAppPackage = (ctx, appPackage, appId) => __awaiter(void 0, void 0, void 0, function* () {
330
- const url = yield getAppUrlIfNotInUse(ctx);
357
+ const updateAppPackage = (appPackage, appId) => __awaiter(void 0, void 0, void 0, function* () {
331
358
  const db = new CouchDB(appId);
332
359
  const application = yield db.get(DocumentTypes.APP_METADATA);
333
- const newAppPackage = Object.assign(Object.assign(Object.assign({}, application), appPackage), { url });
360
+ const newAppPackage = Object.assign(Object.assign({}, application), appPackage);
334
361
  if (appPackage._rev !== application._rev) {
335
362
  newAppPackage._rev = application._rev;
336
363
  }
@@ -24,6 +24,8 @@ exports.fetchSelf = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
24
24
  const user = yield getFullUser(ctx, userId);
25
25
  // this shouldn't be returned by the app self
26
26
  delete user.roles;
27
+ // forward the csrf token from the session
28
+ user.csrfToken = ctx.user.csrfToken;
27
29
  if (appId) {
28
30
  const db = new CouchDB(appId);
29
31
  // remove the full roles structure
@@ -31,6 +33,8 @@ exports.fetchSelf = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
31
33
  try {
32
34
  const userTable = yield db.get(InternalTables.USER_METADATA);
33
35
  const metadata = yield db.get(userId);
36
+ // make sure there is never a stale csrf token
37
+ delete metadata.csrfToken;
34
38
  // specifically needs to make sure is enriched
35
39
  ctx.body = yield outputProcessing(ctx, userTable, Object.assign(Object.assign({}, user), metadata));
36
40
  }
@@ -28,6 +28,12 @@ exports.fetch = function (ctx) {
28
28
  const datasources = (yield database.allDocs(getDatasourceParams(null, {
29
29
  include_docs: true,
30
30
  }))).rows.map(row => row.doc);
31
+ for (let datasource of datasources) {
32
+ if (datasource.config && datasource.config.auth) {
33
+ // strip secrets from response so they don't show in the network request
34
+ delete datasource.config.auth;
35
+ }
36
+ }
31
37
  ctx.body = [bbInternalDb, ...datasources];
32
38
  });
33
39
  };
@@ -78,8 +84,13 @@ exports.update = function (ctx) {
78
84
  const db = new CouchDB(ctx.appId);
79
85
  const datasourceId = ctx.params.datasourceId;
80
86
  let datasource = yield db.get(datasourceId);
87
+ const auth = datasource.config.auth;
81
88
  yield invalidateVariables(datasource, ctx.request.body);
82
89
  datasource = Object.assign(Object.assign({}, datasource), ctx.request.body);
90
+ if (auth && !ctx.request.body.auth) {
91
+ // don't strip auth config from DB
92
+ datasource.config.auth = auth;
93
+ }
83
94
  const response = yield db.put(datasource);
84
95
  datasource._rev = response.rev;
85
96
  // Drain connection pools when configuration is changed
@@ -0,0 +1,21 @@
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 { migrate, MIGRATIONS } = require("../../migrations");
12
+ exports.migrate = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
13
+ const options = ctx.request.body;
14
+ // don't await as can take a while, just return
15
+ migrate(options);
16
+ ctx.status = 200;
17
+ });
18
+ exports.fetchDefinitions = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
19
+ ctx.body = MIGRATIONS;
20
+ ctx.status = 200;
21
+ });
@@ -21,11 +21,10 @@ var __rest = (this && this.__rest) || function (s, e) {
21
21
  };
22
22
  const CouchDB = require("../../../db");
23
23
  const linkRows = require("../../../db/linkedRows");
24
- const { getRowParams, generateRowID, DocumentTypes, InternalTables, } = require("../../../db/utils");
24
+ const { generateRowID, getRowParams, DocumentTypes, InternalTables, } = require("../../../db/utils");
25
25
  const userController = require("../user");
26
- const { inputProcessing, outputProcessing, processAutoColumn, cleanupAttachments, } = require("../../../utilities/rowProcessor");
26
+ const { inputProcessing, outputProcessing, cleanupAttachments, } = require("../../../utilities/rowProcessor");
27
27
  const { FieldTypes } = require("../../../constants");
28
- const { isEqual } = require("lodash");
29
28
  const { validate, findRow } = require("./utils");
30
29
  const { fullSearch, paginatedSearch } = require("./internalSearch");
31
30
  const { getGlobalUsersFromMetadata } = require("../../../utilities/global");
@@ -33,59 +32,12 @@ const inMemoryViews = require("../../../db/inMemoryView");
33
32
  const env = require("../../../environment");
34
33
  const { migrateToInMemoryView, migrateToDesignView, getFromDesignDoc, getFromMemoryDoc, } = require("../view/utils");
35
34
  const { cloneDeep } = require("lodash/fp");
35
+ const { finaliseRow, updateRelatedFormula } = require("./staticFormula");
36
36
  const CALCULATION_TYPES = {
37
37
  SUM: "sum",
38
38
  COUNT: "count",
39
39
  STATS: "stats",
40
40
  };
41
- function storeResponse(ctx, db, row, oldTable, table) {
42
- return __awaiter(this, void 0, void 0, function* () {
43
- row.type = "row";
44
- // don't worry about rev, tables handle rev/lastID updates
45
- // if another row has been written since processing this will
46
- // handle the auto ID clash
47
- if (!isEqual(oldTable, table)) {
48
- try {
49
- yield db.put(table);
50
- }
51
- catch (err) {
52
- if (err.status === 409) {
53
- const updatedTable = yield db.get(table._id);
54
- let response = processAutoColumn(null, updatedTable, row, {
55
- reprocessing: true,
56
- });
57
- yield db.put(response.table);
58
- row = response.row;
59
- }
60
- else {
61
- throw err;
62
- }
63
- }
64
- }
65
- const response = yield db.put(row);
66
- row._rev = response.rev;
67
- // process the row before return, to include relationships
68
- row = yield outputProcessing(ctx, table, row, { squash: false });
69
- return { row, table };
70
- });
71
- }
72
- // doesn't do the outputProcessing
73
- function getRawTableData(ctx, db, tableId) {
74
- return __awaiter(this, void 0, void 0, function* () {
75
- let rows;
76
- if (tableId === InternalTables.USER_METADATA) {
77
- yield userController.fetchMetadata(ctx);
78
- rows = ctx.body;
79
- }
80
- else {
81
- const response = yield db.allDocs(getRowParams(tableId, null, {
82
- include_docs: true,
83
- }));
84
- rows = response.rows.map(row => row.doc);
85
- }
86
- return rows;
87
- });
88
- }
89
41
  function getView(db, viewName) {
90
42
  return __awaiter(this, void 0, void 0, function* () {
91
43
  let mainGetter = env.SELF_HOSTED ? getFromDesignDoc : getFromMemoryDoc;
@@ -114,6 +66,22 @@ function getView(db, viewName) {
114
66
  return viewInfo;
115
67
  });
116
68
  }
69
+ function getRawTableData(ctx, db, tableId) {
70
+ return __awaiter(this, void 0, void 0, function* () {
71
+ let rows;
72
+ if (tableId === InternalTables.USER_METADATA) {
73
+ yield userController.fetchMetadata(ctx);
74
+ rows = ctx.body;
75
+ }
76
+ else {
77
+ const response = yield db.allDocs(getRowParams(tableId, null, {
78
+ include_docs: true,
79
+ }));
80
+ rows = response.rows.map(row => row.doc);
81
+ }
82
+ return rows;
83
+ });
84
+ }
117
85
  exports.patch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
118
86
  const appId = ctx.appId;
119
87
  const db = new CouchDB(appId);
@@ -169,7 +137,10 @@ exports.patch = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
169
137
  yield userController.updateMetadata(ctx);
170
138
  return { row: ctx.body, table };
171
139
  }
172
- return storeResponse(ctx, db, row, dbTable, table);
140
+ return finaliseRow(ctx.appId, table, row, {
141
+ oldTable: dbTable,
142
+ updateFormula: true,
143
+ });
173
144
  });
174
145
  exports.save = function (ctx) {
175
146
  return __awaiter(this, void 0, void 0, function* () {
@@ -198,7 +169,10 @@ exports.save = function (ctx) {
198
169
  tableId: row.tableId,
199
170
  table,
200
171
  });
201
- return storeResponse(ctx, db, row, dbTable, table);
172
+ return finaliseRow(ctx.appId, table, row, {
173
+ oldTable: dbTable,
174
+ updateFormula: true,
175
+ });
202
176
  });
203
177
  };
204
178
  exports.fetchView = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
@@ -290,6 +264,8 @@ exports.destroy = function (ctx) {
290
264
  });
291
265
  // remove any attachments that were on the row from object storage
292
266
  yield cleanupAttachments(appId, table, { row });
267
+ // remove any static formula
268
+ yield updateRelatedFormula(appId, table, row);
293
269
  let response;
294
270
  if (ctx.params.tableId === InternalTables.USER_METADATA) {
295
271
  ctx.params = {
@@ -333,6 +309,7 @@ exports.bulkDestroy = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
333
309
  }
334
310
  // remove any attachments that were on the rows from object storage
335
311
  yield cleanupAttachments(appId, table, { rows });
312
+ yield updateRelatedFormula(appId, table, rows);
336
313
  yield Promise.all(updates);
337
314
  return { response: { ok: true }, rows };
338
315
  });
@@ -34,19 +34,27 @@ class QueryBuilder {
34
34
  return this;
35
35
  }
36
36
  setLimit(limit) {
37
- this.limit = limit;
37
+ if (limit != null) {
38
+ this.limit = limit;
39
+ }
38
40
  return this;
39
41
  }
40
42
  setSort(sort) {
41
- this.sort = sort;
43
+ if (sort != null) {
44
+ this.sort = sort;
45
+ }
42
46
  return this;
43
47
  }
44
48
  setSortOrder(sortOrder) {
45
- this.sortOrder = sortOrder;
49
+ if (sortOrder != null) {
50
+ this.sortOrder = sortOrder;
51
+ }
46
52
  return this;
47
53
  }
48
54
  setSortType(sortType) {
49
- this.sortType = sortType;
55
+ if (sortType != null) {
56
+ this.sortType = sortType;
57
+ }
50
58
  return this;
51
59
  }
52
60
  setBookmark(bookmark) {
@@ -0,0 +1,147 @@
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 CouchDB = require("../../../db");
12
+ const { getRowParams } = require("../../../db/utils");
13
+ const { outputProcessing, processAutoColumn, processFormulas, } = require("../../../utilities/rowProcessor");
14
+ const { FieldTypes, FormulaTypes } = require("../../../constants");
15
+ const { isEqual } = require("lodash");
16
+ const { cloneDeep } = require("lodash/fp");
17
+ /**
18
+ * This function runs through a list of enriched rows, looks at the rows which
19
+ * are related and then checks if they need the state of their formulas
20
+ * updated.
21
+ * NOTE: this will only for affect static formulas.
22
+ */
23
+ exports.updateRelatedFormula = (appId, table, enrichedRows) => __awaiter(void 0, void 0, void 0, function* () {
24
+ const db = new CouchDB(appId);
25
+ // no formula to update, we're done
26
+ if (!table.relatedFormula) {
27
+ return;
28
+ }
29
+ let promises = [];
30
+ for (let enrichedRow of Array.isArray(enrichedRows)
31
+ ? enrichedRows
32
+ : [enrichedRows]) {
33
+ // the related rows by tableId
34
+ let relatedRows = {};
35
+ for (let [key, field] of Object.entries(enrichedRow)) {
36
+ const columnDefinition = table.schema[key];
37
+ if (columnDefinition && columnDefinition.type === FieldTypes.LINK) {
38
+ const relatedTableId = columnDefinition.tableId;
39
+ if (!relatedRows[relatedTableId]) {
40
+ relatedRows[relatedTableId] = [];
41
+ }
42
+ relatedRows[relatedTableId] = relatedRows[relatedTableId].concat(field);
43
+ }
44
+ }
45
+ for (let tableId of table.relatedFormula) {
46
+ let relatedTable;
47
+ try {
48
+ // no rows to update, skip
49
+ if (!relatedRows[tableId] || relatedRows[tableId].length === 0) {
50
+ continue;
51
+ }
52
+ relatedTable = yield db.get(tableId);
53
+ }
54
+ catch (err) {
55
+ // no error scenario, table doesn't seem to exist anymore, ignore
56
+ }
57
+ for (let column of Object.values(relatedTable.schema)) {
58
+ // needs updated in related rows
59
+ if (column.type === FieldTypes.FORMULA &&
60
+ column.formulaType === FormulaTypes.STATIC) {
61
+ // re-enrich rows for all the related, don't update the related formula for them
62
+ promises = promises.concat(relatedRows[tableId].map(related => exports.finaliseRow(appId, relatedTable, related, {
63
+ updateFormula: false,
64
+ })));
65
+ }
66
+ }
67
+ }
68
+ }
69
+ yield Promise.all(promises);
70
+ });
71
+ exports.updateAllFormulasInTable = (appId, table) => __awaiter(void 0, void 0, void 0, function* () {
72
+ const db = new CouchDB(appId);
73
+ // start by getting the raw rows (which will be written back to DB after update)
74
+ let rows = (yield db.allDocs(getRowParams(table._id, null, {
75
+ include_docs: true,
76
+ }))).rows.map(row => row.doc);
77
+ // now enrich the rows, note the clone so that we have the base state of the
78
+ // rows so that we don't write any of the enriched information back
79
+ let enrichedRows = yield outputProcessing({ appId }, table, cloneDeep(rows), {
80
+ squash: false,
81
+ });
82
+ const updatedRows = [];
83
+ for (let row of rows) {
84
+ // find the enriched row, if found process the formulas
85
+ const enrichedRow = enrichedRows.find(enriched => enriched._id === row._id);
86
+ if (enrichedRow) {
87
+ const processed = processFormulas(table, cloneDeep(row), {
88
+ dynamic: false,
89
+ contextRows: enrichedRow,
90
+ });
91
+ // values have changed, need to add to bulk docs to update
92
+ if (!isEqual(processed, row)) {
93
+ updatedRows.push(processed);
94
+ }
95
+ }
96
+ }
97
+ yield db.bulkDocs(updatedRows);
98
+ });
99
+ /**
100
+ * This function runs at the end of the save/patch functions of the row controller, all this
101
+ * really does is enrich the row, handle any static formula processing, then return the enriched
102
+ * row. The reason we need to return the enriched row is that the automation row created trigger
103
+ * expects the row to be totally enriched/contain all relationships.
104
+ */
105
+ exports.finaliseRow = (appId, table, row, { oldTable, updateFormula } = { updateFormula: true }) => __awaiter(void 0, void 0, void 0, function* () {
106
+ const db = new CouchDB(appId);
107
+ row.type = "row";
108
+ // process the row before return, to include relationships
109
+ let enrichedRow = yield outputProcessing({ appId }, table, cloneDeep(row), {
110
+ squash: false,
111
+ });
112
+ // use enriched row to generate formulas for saving, specifically only use as context
113
+ row = processFormulas(table, row, {
114
+ dynamic: false,
115
+ contextRows: enrichedRow,
116
+ });
117
+ // don't worry about rev, tables handle rev/lastID updates
118
+ // if another row has been written since processing this will
119
+ // handle the auto ID clash
120
+ if (oldTable && !isEqual(oldTable, table)) {
121
+ try {
122
+ yield db.put(table);
123
+ }
124
+ catch (err) {
125
+ if (err.status === 409) {
126
+ const updatedTable = yield db.get(table._id);
127
+ let response = processAutoColumn(null, updatedTable, row, {
128
+ reprocessing: true,
129
+ });
130
+ yield db.put(response.table);
131
+ row = response.row;
132
+ }
133
+ else {
134
+ throw err;
135
+ }
136
+ }
137
+ }
138
+ const response = yield db.put(row);
139
+ // for response, calculate the formulas for the enriched row
140
+ enrichedRow._rev = response.rev;
141
+ enrichedRow = yield processFormulas(table, enrichedRow, { dynamic: false });
142
+ // this updates the related formulas in other rows based on the relations to this row
143
+ if (updateFormula) {
144
+ yield exports.updateRelatedFormula(appId, table, enrichedRow);
145
+ }
146
+ return { row: enrichedRow, table };
147
+ });
@@ -64,19 +64,17 @@ exports.validate = ({ appId, tableId, row, table }) => __awaiter(void 0, void 0,
64
64
  }
65
65
  let res;
66
66
  // Validate.js doesn't seem to handle array
67
- if (type === FieldTypes.ARRAY) {
68
- const hasValues = Array.isArray(row[fieldName]) && row[fieldName].length > 0;
69
- // Check values are valid if values are specified
70
- if (hasValues) {
67
+ if (type === FieldTypes.ARRAY && row[fieldName]) {
68
+ if (row[fieldName].length) {
71
69
  row[fieldName].map(val => {
72
70
  if (!constraints.inclusion.includes(val)) {
73
- errors[fieldName] = "Value not in list";
71
+ errors[fieldName] = "Field not in list";
74
72
  }
75
73
  });
76
74
  }
77
- // Check for required constraint
78
- if (constraints.presence === true && !hasValues) {
79
- errors[fieldName] = "Required field";
75
+ else if (constraints.presence && row[fieldName].length === 0) {
76
+ // non required MultiSelect creates an empty array, which should not throw errors
77
+ errors[fieldName] = [`${fieldName} is required`];
80
78
  }
81
79
  }
82
80
  else if (type === FieldTypes.JSON && typeof row[fieldName] === "string") {