@budibase/server 1.0.212-alpha.11 → 1.0.212-alpha.14

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 (202) hide show
  1. package/__mocks__/node-fetch.ts +9 -0
  2. package/builder/assets/index.1f366fcc.js +977 -0
  3. package/builder/assets/{index.969c2236.css → index.7786f497.css} +2 -2
  4. package/builder/assets/{vendor.9bf2fcb4.js → vendor.001dcf8c.js} +163 -163
  5. package/builder/index.html +3 -3
  6. package/coverage/clover.xml +616 -588
  7. package/coverage/coverage-final.json +20 -20
  8. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/automation.js.html +111 -12
  11. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
  15. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/index.html +19 -19
  17. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  23. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  37. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  45. package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
  46. package/coverage/lcov-report/api/index.html +15 -15
  47. package/coverage/lcov-report/api/index.js.html +22 -13
  48. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/automation.js.html +32 -2
  52. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/index.html +1 -1
  59. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  72. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  73. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  75. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  76. package/coverage/lcov-report/automations/actions.js.html +1 -1
  77. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  78. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  79. package/coverage/lcov-report/automations/index.html +1 -1
  80. package/coverage/lcov-report/automations/index.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/filter.js.html +58 -34
  87. package/coverage/lcov-report/automations/steps/index.html +11 -11
  88. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  97. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  106. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  107. package/coverage/lcov-report/constants/index.html +1 -1
  108. package/coverage/lcov-report/constants/index.js.html +1 -1
  109. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  110. package/coverage/lcov-report/constants/screens.js.html +1 -1
  111. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  112. package/coverage/lcov-report/db/index.html +14 -14
  113. package/coverage/lcov-report/db/index.js.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/index.html +13 -13
  116. package/coverage/lcov-report/db/linkedRows/index.js.html +10 -7
  117. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  118. package/coverage/lcov-report/db/newid.js.html +2 -2
  119. package/coverage/lcov-report/db/utils.js.html +25 -52
  120. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  121. package/coverage/lcov-report/events/index.html +1 -1
  122. package/coverage/lcov-report/events/index.js.html +1 -1
  123. package/coverage/lcov-report/events/utils.js.html +1 -1
  124. package/coverage/lcov-report/index.html +56 -56
  125. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  126. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  127. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  128. package/coverage/lcov-report/middleware/builder.js.html +12 -12
  129. package/coverage/lcov-report/middleware/currentapp.js.html +33 -33
  130. package/coverage/lcov-report/middleware/index.html +1 -1
  131. package/coverage/lcov-report/middleware/joi-validator.js.html +10 -10
  132. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  133. package/coverage/lcov-report/middleware/resourceId.js.html +7 -7
  134. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  135. package/coverage/lcov-report/middleware/utils.js.html +2 -2
  136. package/coverage/lcov-report/threads/automation.js.html +17 -8
  137. package/coverage/lcov-report/threads/index.html +25 -25
  138. package/coverage/lcov-report/threads/query.js.html +143 -68
  139. package/coverage/lcov-report/threads/utils.js.html +4 -4
  140. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  141. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  142. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  143. package/coverage/lcov-report/utilities/global.js.html +14 -14
  144. package/coverage/lcov-report/utilities/index.html +1 -1
  145. package/coverage/lcov-report/utilities/index.js.html +9 -9
  146. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
  147. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  148. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  149. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  150. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  151. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  152. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  153. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  154. package/coverage/lcov-report/utilities/security.js.html +2 -2
  155. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  156. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  157. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  158. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  159. package/coverage/lcov-report/utilities/users.js.html +1 -1
  160. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  161. package/coverage/lcov.info +1094 -1046
  162. package/dist/api/controllers/application.js +18 -15
  163. package/dist/api/controllers/automation.js +28 -2
  164. package/dist/api/controllers/query/index.js +6 -0
  165. package/dist/api/index.js +4 -1
  166. package/dist/api/routes/automation.js +2 -0
  167. package/dist/automations/logging/index.js +70 -0
  168. package/dist/automations/steps/filter.js +38 -29
  169. package/dist/db/linkedRows/index.js +1 -0
  170. package/dist/db/utils.js +3 -31
  171. package/dist/environment.js +1 -0
  172. package/dist/integrations/queries/sql.js +3 -0
  173. package/dist/integrations/rest.js +1 -1
  174. package/dist/package.json +6 -6
  175. package/dist/tests/utilities/TestConfiguration.js +19 -6
  176. package/dist/threads/automation.js +5 -2
  177. package/dist/threads/index.js +15 -1
  178. package/dist/threads/query.js +18 -3
  179. package/dist/tsconfig.build.tsbuildinfo +1 -1
  180. package/package.json +7 -7
  181. package/src/api/controllers/application.ts +18 -14
  182. package/src/api/controllers/automation.js +35 -2
  183. package/src/api/controllers/query/index.ts +6 -0
  184. package/src/api/index.js +4 -1
  185. package/src/api/routes/automation.js +10 -0
  186. package/src/api/routes/tests/query.spec.js +166 -0
  187. package/src/automations/logging/index.ts +35 -0
  188. package/src/automations/steps/filter.js +36 -28
  189. package/src/automations/tests/filter.spec.js +2 -1
  190. package/src/db/linkedRows/index.js +1 -0
  191. package/src/db/utils.js +4 -13
  192. package/src/environment.js +1 -0
  193. package/src/integrations/queries/sql.ts +3 -1
  194. package/src/integrations/rest.ts +1 -1
  195. package/src/integrations/tests/rest.spec.js +16 -1
  196. package/src/migrations/tests/index.spec.ts +18 -2
  197. package/src/module.d.ts +1 -0
  198. package/src/tests/utilities/TestConfiguration.js +22 -3
  199. package/src/threads/automation.js +5 -2
  200. package/src/threads/index.ts +5 -1
  201. package/src/threads/query.js +28 -3
  202. package/builder/assets/index.a7550206.js +0 -978
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.212-alpha.11",
4
+ "version": "1.0.212-alpha.14",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -77,11 +77,11 @@
77
77
  "license": "GPL-3.0",
78
78
  "dependencies": {
79
79
  "@apidevtools/swagger-parser": "10.0.3",
80
- "@budibase/backend-core": "^1.0.212-alpha.11",
81
- "@budibase/client": "^1.0.212-alpha.11",
82
- "@budibase/pro": "1.0.212-alpha.10",
83
- "@budibase/string-templates": "^1.0.212-alpha.11",
84
- "@budibase/types": "^1.0.212-alpha.11",
80
+ "@budibase/backend-core": "^1.0.212-alpha.14",
81
+ "@budibase/client": "^1.0.212-alpha.14",
82
+ "@budibase/pro": "1.0.212-alpha.13",
83
+ "@budibase/string-templates": "^1.0.212-alpha.14",
84
+ "@budibase/types": "^1.0.212-alpha.14",
85
85
  "@bull-board/api": "3.7.0",
86
86
  "@bull-board/koa": "3.9.4",
87
87
  "@elastic/elasticsearch": "7.10.0",
@@ -195,5 +195,5 @@
195
195
  "optionalDependencies": {
196
196
  "oracledb": "5.3.0"
197
197
  },
198
- "gitHead": "d123d0b4fd3a7b449f759f8841645987c4acc013"
198
+ "gitHead": "5147929cb55fe0ad5fa21adf64774458b7176c7e"
199
199
  }
@@ -45,10 +45,12 @@ const { getTenantId, isMultiTenant } = require("@budibase/backend-core/tenancy")
45
45
  import { syncGlobalUsers } from "./user"
46
46
  const { app: appCache } = require("@budibase/backend-core/cache")
47
47
  import { cleanupAutomations } from "../../automations/utils"
48
+ import { checkAppMetadata } from "../../automations/logging"
48
49
  const {
49
50
  getAppDB,
50
51
  getProdAppDB,
51
52
  updateAppId,
53
+ doInAppContext,
52
54
  } = require("@budibase/backend-core/context")
53
55
  import { getUniqueRows } from "../../utilities/usageQuota/rows"
54
56
  import { quotas } from "@budibase/pro"
@@ -192,7 +194,7 @@ export const fetch = async (ctx: any) => {
192
194
  }
193
195
  }
194
196
 
195
- ctx.body = apps
197
+ ctx.body = await checkAppMetadata(apps)
196
198
  }
197
199
 
198
200
  export const fetchAppDefinition = async (ctx: any) => {
@@ -548,22 +550,24 @@ export const sync = async (ctx: any, next: any) => {
548
550
  }
549
551
 
550
552
  const updateAppPackage = async (appPackage: any, appId: any) => {
551
- const db = getAppDB()
552
- const application = await db.get(DocumentTypes.APP_METADATA)
553
+ return doInAppContext(appId, async () => {
554
+ const db = getAppDB()
555
+ const application = await db.get(DocumentTypes.APP_METADATA)
553
556
 
554
- const newAppPackage = { ...application, ...appPackage }
555
- if (appPackage._rev !== application._rev) {
556
- newAppPackage._rev = application._rev
557
- }
557
+ const newAppPackage = { ...application, ...appPackage }
558
+ if (appPackage._rev !== application._rev) {
559
+ newAppPackage._rev = application._rev
560
+ }
558
561
 
559
- // the locked by property is attached by server but generated from
560
- // Redis, shouldn't ever store it
561
- delete newAppPackage.lockedBy
562
+ // the locked by property is attached by server but generated from
563
+ // Redis, shouldn't ever store it
564
+ delete newAppPackage.lockedBy
562
565
 
563
- await db.put(newAppPackage)
564
- // remove any cached metadata, so that it will be updated
565
- await appCache.invalidateAppMetadata(appId)
566
- return newAppPackage
566
+ await db.put(newAppPackage)
567
+ // remove any cached metadata, so that it will be updated
568
+ await appCache.invalidateAppMetadata(appId)
569
+ return newAppPackage
570
+ })
567
571
  }
568
572
 
569
573
  const createEmptyAppPackage = async (ctx: any, app: any) => {
@@ -1,6 +1,10 @@
1
1
  const actions = require("../../automations/actions")
2
2
  const triggers = require("../../automations/triggers")
3
- const { getAutomationParams, generateAutomationID } = require("../../db/utils")
3
+ const {
4
+ getAutomationParams,
5
+ generateAutomationID,
6
+ DocumentTypes,
7
+ } = require("../../db/utils")
4
8
  const {
5
9
  checkForWebhooks,
6
10
  updateTestHistory,
@@ -9,8 +13,14 @@ const {
9
13
  const { deleteEntityMetadata } = require("../../utilities")
10
14
  const { MetadataTypes } = require("../../constants")
11
15
  const { setTestFlag, clearTestFlag } = require("../../utilities/redis")
12
- const { getAppDB } = require("@budibase/backend-core/context")
16
+ const {
17
+ getAppDB,
18
+ getProdAppDB,
19
+ doInAppContext,
20
+ } = require("@budibase/backend-core/context")
13
21
  const { events } = require("@budibase/backend-core")
22
+ const { app } = require("@budibase/backend-core/cache")
23
+ const { automations } = require("@budibase/pro")
14
24
 
15
25
  const ACTION_DEFS = removeDeprecated(actions.ACTION_DEFINITIONS)
16
26
  const TRIGGER_DEFS = removeDeprecated(triggers.TRIGGER_DEFINITIONS)
@@ -183,6 +193,29 @@ exports.destroy = async function (ctx) {
183
193
  await events.automation.deleted(oldAutomation)
184
194
  }
185
195
 
196
+ exports.logSearch = async function (ctx) {
197
+ ctx.body = await automations.logs.logSearch(ctx.request.body)
198
+ }
199
+
200
+ exports.clearLogError = async function (ctx) {
201
+ const { automationId, appId } = ctx.request.body
202
+ await doInAppContext(appId, async () => {
203
+ const db = getProdAppDB()
204
+ const metadata = await db.get(DocumentTypes.APP_METADATA)
205
+ if (!automationId) {
206
+ delete metadata.automationErrors
207
+ } else if (
208
+ metadata.automationErrors &&
209
+ metadata.automationErrors[automationId]
210
+ ) {
211
+ delete metadata.automationErrors[automationId]
212
+ }
213
+ await db.put(metadata)
214
+ await app.invalidateAppMetadata(metadata.appId, metadata)
215
+ ctx.body = { message: `Error logs cleared.` }
216
+ })
217
+ }
218
+
186
219
  exports.getActionList = async function (ctx) {
187
220
  ctx.body = ACTION_DEFS
188
221
  }
@@ -129,6 +129,9 @@ export async function preview(ctx: any) {
129
129
  parameters,
130
130
  transformer,
131
131
  queryId,
132
+ ctx: {
133
+ user: ctx.user,
134
+ },
132
135
  })
133
136
 
134
137
  const { rows, keys, info, extra } = await quotas.addQuery(runFn)
@@ -172,6 +175,9 @@ async function execute(ctx: any, opts = { rowsOnly: false }) {
172
175
  parameters: enrichedParameters,
173
176
  transformer: query.transformer,
174
177
  queryId: ctx.params.queryId,
178
+ ctx: {
179
+ user: ctx.user,
180
+ },
175
181
  })
176
182
 
177
183
  const { rows, pagination, extra } = await quotas.addQuery(runFn)
package/src/api/index.js CHANGED
@@ -72,7 +72,10 @@ router.use(async (ctx, next) => {
72
72
  error,
73
73
  }
74
74
  ctx.log.error(err)
75
- console.trace(err)
75
+ // unauthorised errors don't provide a useful trace
76
+ if (!env.isTest()) {
77
+ console.trace(err)
78
+ }
76
79
  }
77
80
  })
78
81
 
@@ -51,6 +51,16 @@ router
51
51
  automationValidator(false),
52
52
  controller.create
53
53
  )
54
+ .post(
55
+ "/api/automations/logs/search",
56
+ authorized(BUILDER),
57
+ controller.logSearch
58
+ )
59
+ .delete(
60
+ "/api/automations/logs",
61
+ authorized(BUILDER),
62
+ controller.clearLogError
63
+ )
54
64
  .delete(
55
65
  "/api/automations/:id/:rev",
56
66
  paramResource("id"),
@@ -346,4 +346,170 @@ describe("/queries", () => {
346
346
  expect(contents).toBe(null)
347
347
  })
348
348
  })
349
+
350
+ describe("Current User Request Mapping", () => {
351
+
352
+ async function previewGet(datasource, fields, params) {
353
+ return config.previewQuery(request, config, datasource, fields, params)
354
+ }
355
+
356
+ async function previewPost(datasource, fields, params) {
357
+ return config.previewQuery(request, config, datasource, fields, params, "create")
358
+ }
359
+
360
+ it("should parse global and query level header mappings", async () => {
361
+ const userDetails = config.getUserDetails()
362
+
363
+ const datasource = await config.restDatasource({
364
+ defaultHeaders: {
365
+ "test": "headerVal",
366
+ "emailHdr": "{{[user].[email]}}"
367
+ }
368
+ })
369
+ const res = await previewGet(datasource, {
370
+ path: "www.google.com",
371
+ queryString: "email={{[user].[email]}}",
372
+ headers: {
373
+ queryHdr : "{{[user].[firstName]}}",
374
+ secondHdr : "1234"
375
+ }
376
+ })
377
+
378
+ const parsedRequest = JSON.parse(res.body.extra.raw)
379
+ expect(parsedRequest.opts.headers).toEqual({
380
+ "test": "headerVal",
381
+ "emailHdr": userDetails.email,
382
+ "queryHdr": userDetails.firstName,
383
+ "secondHdr" : "1234"
384
+ })
385
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?email=" + userDetails.email)
386
+ })
387
+
388
+ it("should bind the current user to query parameters", async () => {
389
+ const userDetails = config.getUserDetails()
390
+
391
+ const datasource = await config.restDatasource()
392
+
393
+ const res = await previewGet(datasource, {
394
+ path: "www.google.com",
395
+ queryString: "test={{myEmail}}&testName={{myName}}&testParam={{testParam}}",
396
+ }, {
397
+ "myEmail" : "{{[user].[email]}}",
398
+ "myName" : "{{[user].[firstName]}}",
399
+ "testParam" : "1234"
400
+ })
401
+
402
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?test=" + userDetails.email +
403
+ "&testName=" + userDetails.firstName + "&testParam=1234")
404
+ })
405
+
406
+ it("should bind the current user the request body - plain text", async () => {
407
+ const userDetails = config.getUserDetails()
408
+ const datasource = await config.restDatasource()
409
+
410
+ const res = await previewPost(datasource, {
411
+ path: "www.google.com",
412
+ queryString: "testParam={{testParam}}",
413
+ requestBody: "This is plain text and this is my email: {{[user].[email]}}. This is a test param: {{testParam}}",
414
+ bodyType: "text"
415
+ }, {
416
+ "testParam" : "1234"
417
+ })
418
+
419
+ const parsedRequest = JSON.parse(res.body.extra.raw)
420
+ expect(parsedRequest.opts.body).toEqual(`This is plain text and this is my email: ${userDetails.email}. This is a test param: 1234`)
421
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
422
+ })
423
+
424
+ it("should bind the current user the request body - json", async () => {
425
+ const userDetails = config.getUserDetails()
426
+ const datasource = await config.restDatasource()
427
+
428
+ const res = await previewPost(datasource, {
429
+ path: "www.google.com",
430
+ queryString: "testParam={{testParam}}",
431
+ requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
432
+ bodyType: "json"
433
+ }, {
434
+ "testParam" : "1234",
435
+ "userRef" : "{{[user].[firstName]}}"
436
+ })
437
+
438
+ const parsedRequest = JSON.parse(res.body.extra.raw)
439
+ const test = `{"email":"${userDetails.email}","queryCode":1234,"userRef":"${userDetails.firstName}"}`
440
+ expect(parsedRequest.opts.body).toEqual(test)
441
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
442
+ })
443
+
444
+ it("should bind the current user the request body - xml", async () => {
445
+ const userDetails = config.getUserDetails()
446
+ const datasource = await config.restDatasource()
447
+
448
+ const res = await previewPost(datasource, {
449
+ path: "www.google.com",
450
+ queryString: "testParam={{testParam}}",
451
+ requestBody: "<note> <email>{{[user].[email]}}</email> <code>{{testParam}}</code> " +
452
+ "<ref>{{userId}}</ref> <somestring>testing</somestring> </note>",
453
+ bodyType: "xml"
454
+ }, {
455
+ "testParam" : "1234",
456
+ "userId" : "{{[user].[firstName]}}"
457
+ })
458
+
459
+ const parsedRequest = JSON.parse(res.body.extra.raw)
460
+ const test = `<note> <email>${userDetails.email}</email> <code>1234</code> <ref>${userDetails.firstName}</ref> <somestring>testing</somestring> </note>`
461
+
462
+ expect(parsedRequest.opts.body).toEqual(test)
463
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
464
+ })
465
+
466
+ it("should bind the current user the request body - form-data", async () => {
467
+ const userDetails = config.getUserDetails()
468
+ const datasource = await config.restDatasource()
469
+
470
+ const res = await previewPost(datasource, {
471
+ path: "www.google.com",
472
+ queryString: "testParam={{testParam}}",
473
+ requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
474
+ bodyType: "form"
475
+ }, {
476
+ "testParam" : "1234",
477
+ "userRef" : "{{[user].[firstName]}}"
478
+ })
479
+
480
+ const parsedRequest = JSON.parse(res.body.extra.raw)
481
+
482
+ const emailData = parsedRequest.opts.body._streams[1]
483
+ expect(emailData).toEqual(userDetails.email)
484
+
485
+ const queryCodeData = parsedRequest.opts.body._streams[4]
486
+ expect(queryCodeData).toEqual("1234")
487
+
488
+ const userRef = parsedRequest.opts.body._streams[7]
489
+ expect(userRef).toEqual(userDetails.firstName)
490
+
491
+ expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
492
+ })
493
+
494
+ it("should bind the current user the request body - encoded", async () => {
495
+ const userDetails = config.getUserDetails()
496
+ const datasource = await config.restDatasource()
497
+
498
+ const res = await previewPost(datasource, {
499
+ path: "www.google.com",
500
+ queryString: "testParam={{testParam}}",
501
+ requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
502
+ bodyType: "encoded"
503
+ }, {
504
+ "testParam" : "1234",
505
+ "userRef" : "{{[user].[firstName]}}"
506
+ })
507
+ const parsedRequest = JSON.parse(res.body.extra.raw)
508
+
509
+ expect(parsedRequest.opts.body.email).toEqual(userDetails.email)
510
+ expect(parsedRequest.opts.body.queryCode).toEqual("1234")
511
+ expect(parsedRequest.opts.body.userRef).toEqual(userDetails.firstName)
512
+ })
513
+
514
+ });
349
515
  })
@@ -0,0 +1,35 @@
1
+ import * as env from "../../environment"
2
+ import { AutomationResults, Automation, App } from "@budibase/types"
3
+ import { automations } from "@budibase/pro"
4
+ import { db as dbUtils } from "@budibase/backend-core"
5
+
6
+ export async function storeLog(
7
+ automation: Automation,
8
+ results: AutomationResults
9
+ ) {
10
+ // can disable this if un-needed in self-host, also only do this for prod apps
11
+ if (env.DISABLE_AUTOMATION_LOGS) {
12
+ return
13
+ }
14
+ await automations.logs.storeLog(automation, results)
15
+ }
16
+
17
+ export async function checkAppMetadata(apps: App[]) {
18
+ const maxStartDate = await automations.logs.oldestLogDate()
19
+ for (let metadata of apps) {
20
+ if (!metadata.automationErrors) {
21
+ continue
22
+ }
23
+ for (let [key, errors] of Object.entries(metadata.automationErrors)) {
24
+ const updated = []
25
+ for (let error of errors) {
26
+ const startDate = error.split(dbUtils.SEPARATOR)[2]
27
+ if (startDate > maxStartDate) {
28
+ updated.push(error)
29
+ }
30
+ }
31
+ metadata.automationErrors[key] = updated
32
+ }
33
+ }
34
+ return apps
35
+ }
@@ -50,43 +50,51 @@ exports.definition = {
50
50
  outputs: {
51
51
  properties: {
52
52
  success: {
53
+ type: "boolean",
54
+ description: "Whether the action was successful",
55
+ },
56
+ result: {
53
57
  type: "boolean",
54
58
  description: "Whether the logic block passed",
55
59
  },
56
60
  },
57
- required: ["success"],
61
+ required: ["success", "result"],
58
62
  },
59
63
  },
60
64
  }
61
65
 
62
66
  exports.run = async function filter({ inputs }) {
63
- let { field, condition, value } = inputs
64
- // coerce types so that we can use them
65
- if (!isNaN(value) && !isNaN(field)) {
66
- value = parseFloat(value)
67
- field = parseFloat(field)
68
- } else if (!isNaN(Date.parse(value)) && !isNaN(Date.parse(field))) {
69
- value = Date.parse(value)
70
- field = Date.parse(field)
71
- }
72
- let success = false
73
- if (typeof field !== "object" && typeof value !== "object") {
74
- switch (condition) {
75
- case FilterConditions.EQUAL:
76
- success = field === value
77
- break
78
- case FilterConditions.NOT_EQUAL:
79
- success = field !== value
80
- break
81
- case FilterConditions.GREATER_THAN:
82
- success = field > value
83
- break
84
- case FilterConditions.LESS_THAN:
85
- success = field < value
86
- break
67
+ try {
68
+ let { field, condition, value } = inputs
69
+ // coerce types so that we can use them
70
+ if (!isNaN(value) && !isNaN(field)) {
71
+ value = parseFloat(value)
72
+ field = parseFloat(field)
73
+ } else if (!isNaN(Date.parse(value)) && !isNaN(Date.parse(field))) {
74
+ value = Date.parse(value)
75
+ field = Date.parse(field)
76
+ }
77
+ let result = false
78
+ if (typeof field !== "object" && typeof value !== "object") {
79
+ switch (condition) {
80
+ case FilterConditions.EQUAL:
81
+ result = field === value
82
+ break
83
+ case FilterConditions.NOT_EQUAL:
84
+ result = field !== value
85
+ break
86
+ case FilterConditions.GREATER_THAN:
87
+ result = field > value
88
+ break
89
+ case FilterConditions.LESS_THAN:
90
+ result = field < value
91
+ break
92
+ }
93
+ } else {
94
+ result = false
87
95
  }
88
- } else {
89
- success = false
96
+ return { success: true, result }
97
+ } catch (err) {
98
+ return { success: false, result: false }
90
99
  }
91
- return { success }
92
100
  }
@@ -6,7 +6,8 @@ describe("test the filter logic", () => {
6
6
  let res = await setup.runStep(setup.actions.FILTER.stepId,
7
7
  { field, condition, value }
8
8
  )
9
- expect(res.success).toEqual(pass)
9
+ expect(res.result).toEqual(pass)
10
+ expect(res.success).toEqual(true)
10
11
  }
11
12
 
12
13
  it("should be able test equality", async () => {
@@ -65,6 +65,7 @@ async function getLinksForRows(rows) {
65
65
  // return duplicates, could be querying for both tables in a relation
66
66
  return getUniqueByProp(
67
67
  responses
68
+ .filter(el => el != null)
68
69
  // create a unique ID which we can use for getting only unique ones
69
70
  .map(el => ({ ...el, unique: el.id + el.thisId + el.fieldName })),
70
71
  "unique"
package/src/db/utils.js CHANGED
@@ -11,6 +11,8 @@ const {
11
11
  isProdAppID,
12
12
  getDevelopmentAppID,
13
13
  generateAppID,
14
+ getQueryIndex,
15
+ ViewNames,
14
16
  } = require("@budibase/backend-core/db")
15
17
 
16
18
  const UNICODE_MAX = "\ufff0"
@@ -22,11 +24,7 @@ const AppStatus = {
22
24
  }
23
25
 
24
26
  const DocumentTypes = {
25
- APP: CoreDocTypes.APP,
26
- DEV: CoreDocTypes.DEV,
27
- APP_DEV: CoreDocTypes.APP_DEV,
28
- APP_METADATA: CoreDocTypes.APP_METADATA,
29
- ROLE: CoreDocTypes.ROLE,
27
+ ...CoreDocTypes,
30
28
  TABLE: "ta",
31
29
  ROW: "ro",
32
30
  USER: "us",
@@ -45,11 +43,6 @@ const DocumentTypes = {
45
43
  USER_FLAG: "flag",
46
44
  }
47
45
 
48
- const ViewNames = {
49
- LINK: "by_link",
50
- ROUTING: "screen_routes",
51
- }
52
-
53
46
  const InternalTables = {
54
47
  USER_METADATA: "ta_users",
55
48
  }
@@ -89,9 +82,7 @@ exports.generateDevAppID = getDevelopmentAppID
89
82
  exports.generateRoleID = generateRoleID
90
83
  exports.getRoleParams = getRoleParams
91
84
 
92
- exports.getQueryIndex = viewName => {
93
- return `database/${viewName}`
94
- }
85
+ exports.getQueryIndex = getQueryIndex
95
86
 
96
87
  /**
97
88
  * If creating DB allDocs/query params with only a single top level ID this can be used, this
@@ -78,6 +78,7 @@ module.exports = {
78
78
  ALLOW_DEV_AUTOMATIONS: process.env.ALLOW_DEV_AUTOMATIONS,
79
79
  DISABLE_THREADING: process.env.DISABLE_THREADING,
80
80
  DISABLE_DEVELOPER_LICENSE: process.env.DISABLE_DEVELOPER_LICENSE,
81
+ DISABLE_AUTOMATION_LOGS: process.env.DISABLE_AUTOMATION_LOGS,
81
82
  MULTI_TENANCY: process.env.MULTI_TENANCY,
82
83
  ENABLE_ANALYTICS: process.env.ENABLE_ANALYTICS,
83
84
  SELF_HOSTED: process.env.SELF_HOSTED,
@@ -9,7 +9,9 @@ export function enrichQueryFields(
9
9
  parameters = {}
10
10
  ) {
11
11
  const enrichedQuery: { [key: string]: any } = Array.isArray(fields) ? [] : {}
12
-
12
+ if (!fields || !parameters) {
13
+ return enrichedQuery
14
+ }
13
15
  // enrich the fields with dynamic parameters
14
16
  for (let key of Object.keys(fields)) {
15
17
  if (fields[key] == null) {
@@ -287,7 +287,7 @@ module RestModule {
287
287
  input.body = form
288
288
  break
289
289
  case BodyTypes.XML:
290
- if (object != null) {
290
+ if (object != null && Object.keys(object).length) {
291
291
  string = new XmlBuilder().buildObject(object)
292
292
  }
293
293
  input.body = string
@@ -155,12 +155,27 @@ describe("REST Integration", () => {
155
155
  expect(output.headers["Content-Type"]).toEqual("application/json")
156
156
  })
157
157
 
158
- it("should allow XML", () => {
158
+ it("should allow raw XML", () => {
159
+ const output = config.integration.addBody("xml", "<a>1</a><b>2</b>", {})
160
+ expect(output.body.includes("<a>1</a>")).toEqual(true)
161
+ expect(output.body.includes("<b>2</b>")).toEqual(true)
162
+ expect(output.headers["Content-Type"]).toEqual("application/xml")
163
+ })
164
+
165
+ it("should allow a valid js object and parse the contents to xml", () => {
159
166
  const output = config.integration.addBody("xml", input, {})
160
167
  expect(output.body.includes("<a>1</a>")).toEqual(true)
161
168
  expect(output.body.includes("<b>2</b>")).toEqual(true)
162
169
  expect(output.headers["Content-Type"]).toEqual("application/xml")
163
170
  })
171
+
172
+ it("should allow a valid json string and parse the contents to xml", () => {
173
+ const output = config.integration.addBody("xml", JSON.stringify(input), {})
174
+ expect(output.body.includes("<a>1</a>")).toEqual(true)
175
+ expect(output.body.includes("<b>2</b>")).toEqual(true)
176
+ expect(output.headers["Content-Type"]).toEqual("application/xml")
177
+ })
178
+
164
179
  })
165
180
 
166
181
  describe("response", () => {
@@ -93,8 +93,24 @@ describe("migrations", () => {
93
93
  await clearMigrations()
94
94
  const appId = config.prodAppId
95
95
  const roles = { [appId]: "role_12345" }
96
- await config.createUser(undefined, undefined, false, true, roles) // admin only
97
- await config.createUser(undefined, undefined, false, false, roles) // non admin non builder
96
+ await config.createUser(
97
+ undefined,
98
+ undefined,
99
+ undefined,
100
+ undefined,
101
+ false,
102
+ true,
103
+ roles
104
+ ) // admin only
105
+ await config.createUser(
106
+ undefined,
107
+ undefined,
108
+ undefined,
109
+ undefined,
110
+ false,
111
+ false,
112
+ roles
113
+ ) // non admin non builder
98
114
  await config.createTable()
99
115
  await config.createRow()
100
116
  await config.createRow()
package/src/module.d.ts CHANGED
@@ -8,3 +8,4 @@ declare module "@budibase/backend-core/constants"
8
8
  declare module "@budibase/backend-core/auth"
9
9
  declare module "@budibase/backend-core/sessions"
10
10
  declare module "@budibase/backend-core/encryption"
11
+ declare module "@budibase/backend-core/redis"