@budibase/server 1.0.217 → 1.0.219-alpha.1

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 (257) hide show
  1. package/__mocks__/node-fetch.ts +9 -0
  2. package/builder/assets/index.7786f497.css +6 -0
  3. package/builder/assets/index.832d3790.js +977 -0
  4. package/builder/assets/{vendor.9bf2fcb4.js → vendor.001dcf8c.js} +163 -163
  5. package/builder/index.html +3 -3
  6. package/coverage/clover.xml +866 -792
  7. package/coverage/coverage-final.json +26 -26
  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 +9 -6
  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 +21 -21
  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 +47 -17
  27. package/coverage/lcov-report/api/controllers/row/index.html +34 -34
  28. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +95 -11
  30. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/row/utils.js.html +17 -8
  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 +57 -12
  78. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  79. package/coverage/lcov-report/automations/index.html +17 -17
  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 +4 -4
  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 +27 -51
  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 +74 -74
  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 +18 -9
  137. package/coverage/lcov-report/threads/index.html +25 -25
  138. package/coverage/lcov-report/threads/query.js.html +280 -76
  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 +1554 -1422
  162. package/dist/api/controllers/application.js +18 -15
  163. package/dist/api/controllers/automation.js +28 -2
  164. package/dist/api/controllers/backup.js +3 -2
  165. package/dist/api/controllers/query/index.js +25 -0
  166. package/dist/api/controllers/row/external.js +19 -7
  167. package/dist/api/controllers/row/internalSearch.js +22 -1
  168. package/dist/api/controllers/row/utils.js +3 -0
  169. package/dist/api/index.js +4 -1
  170. package/dist/api/routes/automation.js +2 -0
  171. package/dist/automations/automationUtils.js +16 -4
  172. package/dist/automations/logging/index.js +70 -0
  173. package/dist/automations/steps/filter.js +38 -29
  174. package/dist/automations/triggers.js +1 -1
  175. package/dist/db/linkedRows/index.js +1 -0
  176. package/dist/db/utils.js +4 -31
  177. package/dist/definitions/datasource.js +1 -0
  178. package/dist/environment.js +1 -0
  179. package/dist/integrations/airtable.js +1 -0
  180. package/dist/integrations/arangodb.js +1 -0
  181. package/dist/integrations/base/sql.js +20 -3
  182. package/dist/integrations/couchdb.js +1 -0
  183. package/dist/integrations/dynamodb.js +1 -0
  184. package/dist/integrations/elasticsearch.js +1 -0
  185. package/dist/integrations/firebase.js +1 -0
  186. package/dist/integrations/googlesheets.js +1 -0
  187. package/dist/integrations/index.js +4 -0
  188. package/dist/integrations/microsoftSqlServer.js +2 -1
  189. package/dist/integrations/mongodb.js +1 -0
  190. package/dist/integrations/mysql.js +2 -1
  191. package/dist/integrations/oracle.js +1 -0
  192. package/dist/integrations/postgres.js +2 -1
  193. package/dist/integrations/queries/sql.js +3 -0
  194. package/dist/integrations/redis.js +1 -0
  195. package/dist/integrations/rest.js +2 -1
  196. package/dist/integrations/s3.js +1 -0
  197. package/dist/integrations/snowflake.js +102 -0
  198. package/dist/package.json +7 -6
  199. package/dist/tests/utilities/TestConfiguration.js +19 -6
  200. package/dist/threads/automation.js +6 -3
  201. package/dist/threads/index.js +15 -1
  202. package/dist/threads/query.js +53 -8
  203. package/dist/tsconfig.build.tsbuildinfo +1 -1
  204. package/dist/utilities/fileSystem/index.js +16 -6
  205. package/package.json +8 -7
  206. package/scripts/integrations/oracle/instantclient/linux/arm64/basiclite-19.10.zip +0 -0
  207. package/scripts/integrations/oracle/instantclient/linux/arm64/install.sh +23 -0
  208. package/scripts/integrations/oracle/instantclient/linux/install.sh +10 -0
  209. package/src/api/controllers/application.ts +18 -14
  210. package/src/api/controllers/automation.js +35 -2
  211. package/src/api/controllers/backup.js +3 -2
  212. package/src/api/controllers/query/index.ts +29 -1
  213. package/src/api/controllers/row/external.js +19 -9
  214. package/src/api/controllers/row/internalSearch.js +28 -0
  215. package/src/api/controllers/row/utils.js +3 -0
  216. package/src/api/index.js +4 -1
  217. package/src/api/routes/automation.js +10 -0
  218. package/src/api/routes/tests/query.spec.js +166 -0
  219. package/src/automations/automationUtils.js +19 -4
  220. package/src/automations/logging/index.ts +35 -0
  221. package/src/automations/steps/filter.js +36 -28
  222. package/src/automations/tests/filter.spec.js +2 -1
  223. package/src/automations/triggers.js +1 -1
  224. package/src/db/linkedRows/index.js +1 -0
  225. package/src/db/utils.js +5 -13
  226. package/src/definitions/common.ts +1 -0
  227. package/src/definitions/datasource.ts +2 -0
  228. package/src/environment.js +1 -0
  229. package/src/integrations/airtable.ts +1 -0
  230. package/src/integrations/arangodb.ts +1 -0
  231. package/src/integrations/base/sql.ts +25 -11
  232. package/src/integrations/couchdb.ts +1 -0
  233. package/src/integrations/dynamodb.ts +1 -0
  234. package/src/integrations/elasticsearch.ts +1 -0
  235. package/src/integrations/firebase.ts +1 -0
  236. package/src/integrations/googlesheets.ts +1 -0
  237. package/src/integrations/index.ts +4 -0
  238. package/src/integrations/microsoftSqlServer.ts +2 -0
  239. package/src/integrations/mongodb.ts +1 -0
  240. package/src/integrations/mysql.ts +2 -0
  241. package/src/integrations/oracle.ts +1 -0
  242. package/src/integrations/postgres.ts +2 -0
  243. package/src/integrations/queries/sql.ts +3 -1
  244. package/src/integrations/redis.ts +1 -0
  245. package/src/integrations/rest.ts +2 -1
  246. package/src/integrations/s3.ts +1 -0
  247. package/src/integrations/snowflake.ts +99 -0
  248. package/src/integrations/tests/rest.spec.js +16 -1
  249. package/src/migrations/tests/index.spec.ts +18 -2
  250. package/src/module.d.ts +2 -0
  251. package/src/tests/utilities/TestConfiguration.js +22 -3
  252. package/src/threads/automation.js +6 -3
  253. package/src/threads/index.ts +5 -1
  254. package/src/threads/query.js +78 -10
  255. package/src/utilities/fileSystem/index.js +22 -8
  256. package/builder/assets/index.24307ca0.css +0 -6
  257. package/builder/assets/index.cc2e9cbe.js +0 -1316
@@ -17,7 +17,7 @@ const { ObjectStoreBuckets } = require("../../constants");
17
17
  const { upload, retrieve, retrieveToTmp, streamUpload, deleteFolder, downloadTarball, } = require("./utilities");
18
18
  const { updateClientLibrary } = require("./clientLibrary");
19
19
  const env = require("../../environment");
20
- const { USER_METDATA_PREFIX, LINK_USER_METADATA_PREFIX, } = require("../../db/utils");
20
+ const { USER_METDATA_PREFIX, LINK_USER_METADATA_PREFIX, TABLE_ROW_PREFIX, } = require("../../db/utils");
21
21
  const MemoryStream = require("memorystream");
22
22
  const { getAppId } = require("@budibase/backend-core/context");
23
23
  const TOP_LEVEL_PATH = join(__dirname, "..", "..", "..");
@@ -98,6 +98,17 @@ exports.apiFileReturn = contents => {
98
98
  fs.writeFileSync(path, contents);
99
99
  return fs.createReadStream(path);
100
100
  };
101
+ exports.defineFilter = excludeRows => {
102
+ if (excludeRows) {
103
+ return doc => !(doc._id.includes(USER_METDATA_PREFIX) ||
104
+ doc._id.includes(LINK_USER_METADATA_PREFIX) ||
105
+ doc._id.includes(TABLE_ROW_PREFIX));
106
+ }
107
+ else if (!excludeRows) {
108
+ return doc => !(doc._id.includes(USER_METDATA_PREFIX) ||
109
+ doc._id.includes(LINK_USER_METADATA_PREFIX));
110
+ }
111
+ };
101
112
  /**
102
113
  * Local utility to back up the database state for an app, excluding global user
103
114
  * data or user relationships.
@@ -105,9 +116,8 @@ exports.apiFileReturn = contents => {
105
116
  * @param {object} config Config to send to export DB
106
117
  * @returns {*} either a string or a stream of the backup
107
118
  */
108
- const backupAppData = (appId, config) => __awaiter(void 0, void 0, void 0, function* () {
109
- return yield exports.exportDB(appId, Object.assign(Object.assign({}, config), { filter: doc => !(doc._id.includes(USER_METDATA_PREFIX) ||
110
- doc._id.includes(LINK_USER_METADATA_PREFIX)) }));
119
+ const backupAppData = (appId, config, includeRows) => __awaiter(void 0, void 0, void 0, function* () {
120
+ return yield exports.exportDB(appId, Object.assign(Object.assign({}, config), { filter: exports.defineFilter(includeRows) }));
111
121
  });
112
122
  /**
113
123
  * Takes a copy of the database state for an app to the object store.
@@ -123,8 +133,8 @@ exports.performBackup = (appId, backupName) => __awaiter(void 0, void 0, void 0,
123
133
  * @param {string} appId The ID of the app which is to be backed up.
124
134
  * @returns {*} a readable stream of the backup which is written in real time
125
135
  */
126
- exports.streamBackup = (appId) => __awaiter(void 0, void 0, void 0, function* () {
127
- return yield backupAppData(appId, { stream: true });
136
+ exports.streamBackup = (appId, includeRows) => __awaiter(void 0, void 0, void 0, function* () {
137
+ return yield backupAppData(appId, { stream: true }, includeRows);
128
138
  });
129
139
  /**
130
140
  * Exports a DB to either file or a variable (memory).
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.217",
4
+ "version": "1.0.219-alpha.1",
5
5
  "description": "Budibase Web Server",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -77,10 +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.217",
81
- "@budibase/client": "^1.0.217",
82
- "@budibase/pro": "1.0.216",
83
- "@budibase/string-templates": "^1.0.217",
80
+ "@budibase/backend-core": "^1.0.219-alpha.1",
81
+ "@budibase/client": "^1.0.219-alpha.1",
82
+ "@budibase/pro": "1.0.219-alpha.0",
83
+ "@budibase/string-templates": "^1.0.219-alpha.1",
84
+ "@budibase/types": "^1.0.219-alpha.1",
84
85
  "@bull-board/api": "3.7.0",
85
86
  "@bull-board/koa": "3.9.4",
86
87
  "@elastic/elasticsearch": "7.10.0",
@@ -135,6 +136,7 @@
135
136
  "pouchdb-replication-stream": "1.2.9",
136
137
  "redis": "4",
137
138
  "server-destroy": "1.0.1",
139
+ "snowflake-promise": "^4.5.0",
138
140
  "svelte": "3.44.1",
139
141
  "swagger-parser": "10.0.3",
140
142
  "to-json-schema": "0.2.5",
@@ -150,7 +152,6 @@
150
152
  "@babel/core": "7.17.4",
151
153
  "@babel/preset-env": "7.16.11",
152
154
  "@budibase/standard-components": "^0.9.139",
153
- "@budibase/types": "^1.0.217",
154
155
  "@jest/test-sequencer": "24.9.0",
155
156
  "@types/apidoc": "0.50.0",
156
157
  "@types/bson": "4.2.0",
@@ -194,5 +195,5 @@
194
195
  "optionalDependencies": {
195
196
  "oracledb": "5.3.0"
196
197
  },
197
- "gitHead": "8bc247cbba648c3c52b8a71ae7e5517f284f4bea"
198
+ "gitHead": "58d9fc1384c304fb9c442b7605745512ba4c70d9"
198
199
  }
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ # Must be root to continue
4
+ if [[ $(id -u) -ne 0 ]] ; then echo "Please run as root" ; exit 1 ; fi
5
+
6
+ # Allow for re-runs
7
+ rm -rf /opt/oracle
8
+
9
+ echo "Installing oracle instant client"
10
+
11
+ # copy and unzip package
12
+ mkdir -p /opt/oracle
13
+ cp scripts/integrations/oracle/instantclient/linux/arm64/basiclite-19.10.zip /opt/oracle
14
+ cd /opt/oracle
15
+ unzip -qq basiclite-19.10.zip -d .
16
+ rm *.zip
17
+ mv instantclient* instantclient
18
+
19
+ # update runtime link path
20
+ sh -c "echo /opt/oracle/instantclient > /etc/ld.so.conf.d/oracle-instantclient.conf"
21
+ ldconfig /etc/ld.so.conf.d
22
+
23
+ echo "Installation complete"
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}"; )" &> /dev/null && pwd 2> /dev/null; )"
3
+ if [[ $TARGETARCH == arm* ]] ;
4
+ then
5
+ echo "Installing ARM Oracle instant client..."
6
+ $SCRIPT_DIR/arm64/install.sh
7
+ else
8
+ echo "Installing x86-64 Oracle instant client..."
9
+ $SCRIPT_DIR/x86-64/install.sh
10
+ fi
@@ -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
  }
@@ -3,11 +3,12 @@ const { events, context } = require("@budibase/backend-core")
3
3
  const { DocumentTypes } = require("../../db/utils")
4
4
 
5
5
  exports.exportAppDump = async function (ctx) {
6
- const { appId } = ctx.query
6
+ let { appId, excludeRows } = ctx.query
7
7
  const appName = decodeURI(ctx.query.appname)
8
+ excludeRows = excludeRows === "true"
8
9
  const backupIdentifier = `${appName}-export-${new Date().getTime()}.txt`
9
10
  ctx.attachment(backupIdentifier)
10
- ctx.body = await streamBackup(appId)
11
+ ctx.body = await streamBackup(appId, excludeRows)
11
12
 
12
13
  await context.doInAppContext(appId, async () => {
13
14
  const appDb = context.getAppDB()
@@ -8,6 +8,8 @@ import { QUERY_THREAD_TIMEOUT } from "../../../environment"
8
8
  import { getAppDB } from "@budibase/backend-core/context"
9
9
  import { quotas } from "@budibase/pro"
10
10
  import { events } from "@budibase/backend-core"
11
+ import { getCookie } from "@budibase/backend-core/utils"
12
+ import { Cookies, Configs } from "@budibase/backend-core/constants"
11
13
 
12
14
  const Runner = new Thread(ThreadType.QUERY, {
13
15
  timeoutMs: QUERY_THREAD_TIMEOUT || 10000,
@@ -110,6 +112,21 @@ export async function find(ctx: any) {
110
112
  ctx.body = query
111
113
  }
112
114
 
115
+ //Required to discern between OIDC OAuth config entries
116
+ function getOAuthConfigCookieId(ctx: any) {
117
+ if (ctx.user.providerType === Configs.OIDC) {
118
+ return getCookie(ctx, Cookies.OIDC_CONFIG)
119
+ }
120
+ }
121
+
122
+ function getAuthConfig(ctx: any) {
123
+ const authCookie = getCookie(ctx, Cookies.Auth)
124
+ let authConfigCtx: any = {}
125
+ authConfigCtx["configId"] = getOAuthConfigCookieId(ctx)
126
+ authConfigCtx["sessionId"] = authCookie ? authCookie.sessionId : null
127
+ return authConfigCtx
128
+ }
129
+
113
130
  export async function preview(ctx: any) {
114
131
  const db = getAppDB()
115
132
 
@@ -119,6 +136,8 @@ export async function preview(ctx: any) {
119
136
  // this stops dynamic variables from calling the same query
120
137
  const { fields, parameters, queryVerb, transformer, queryId } = query
121
138
 
139
+ const authConfigCtx: any = getAuthConfig(ctx)
140
+
122
141
  try {
123
142
  const runFn = () =>
124
143
  Runner.run({
@@ -129,8 +148,11 @@ export async function preview(ctx: any) {
129
148
  parameters,
130
149
  transformer,
131
150
  queryId,
151
+ ctx: {
152
+ user: ctx.user,
153
+ auth: { ...authConfigCtx },
154
+ },
132
155
  })
133
-
134
156
  const { rows, keys, info, extra } = await quotas.addQuery(runFn)
135
157
  await events.query.previewed(datasource, query)
136
158
  ctx.body = {
@@ -150,6 +172,8 @@ async function execute(ctx: any, opts = { rowsOnly: false }) {
150
172
  const query = await db.get(ctx.params.queryId)
151
173
  const datasource = await db.get(query.datasourceId)
152
174
 
175
+ const authConfigCtx: any = getAuthConfig(ctx)
176
+
153
177
  const enrichedParameters = ctx.request.body.parameters || {}
154
178
  // make sure parameters are fully enriched with defaults
155
179
  if (query && query.parameters) {
@@ -172,6 +196,10 @@ async function execute(ctx: any, opts = { rowsOnly: false }) {
172
196
  parameters: enrichedParameters,
173
197
  transformer: query.transformer,
174
198
  queryId: ctx.params.queryId,
199
+ ctx: {
200
+ user: ctx.user,
201
+ auth: { ...authConfigCtx },
202
+ },
175
203
  })
176
204
 
177
205
  const { rows, pagination, extra } = await quotas.addQuery(runFn)
@@ -155,34 +155,44 @@ exports.validate = async () => {
155
155
  }
156
156
 
157
157
  exports.exportRows = async ctx => {
158
- const { datasourceId, tableName } = breakExternalTableId(ctx.params.tableId)
158
+ const { datasourceId } = breakExternalTableId(ctx.params.tableId)
159
159
  const db = getAppDB()
160
- let format = ctx.query.format
160
+ const format = ctx.query.format
161
+ const { columns } = ctx.request.body
161
162
  const datasource = await db.get(datasourceId)
162
163
  if (!datasource || !datasource.entities) {
163
164
  ctx.throw(400, "Datasource has not been configured for plus API.")
164
165
  }
165
- const tables = datasource.entities
166
- const table = tables[tableName]
167
166
  ctx.request.body = {
168
167
  query: {
169
168
  oneOf: {
170
- [table.primaryDisplay]: ctx.request.body.rows.map(
171
- id => breakRowIdField(id)[0]
172
- ),
169
+ _id: ctx.request.body.rows.map(row => JSON.parse(decodeURI(row))[0]),
173
170
  },
174
171
  },
175
172
  }
176
173
 
177
174
  let result = await exports.search(ctx)
175
+ let rows = []
176
+
177
+ // Filter data to only specified columns if required
178
+ if (columns && columns.length) {
179
+ for (let i = 0; i < result.rows.length; i++) {
180
+ rows[i] = {}
181
+ for (let column of columns) {
182
+ rows[i][column] = result.rows[i][column]
183
+ }
184
+ }
185
+ } else {
186
+ rows = result.rows
187
+ }
178
188
 
179
- let headers = Object.keys(result.rows[0])
189
+ let headers = Object.keys(rows[0])
180
190
  const exporter = exporters[format]
181
191
  const filename = `export.${format}`
182
192
 
183
193
  // send down the file
184
194
  ctx.attachment(filename)
185
- return apiFileReturn(exporter(headers, result.rows))
195
+ return apiFileReturn(exporter(headers, rows))
186
196
  }
187
197
 
188
198
  exports.fetchEnrichedRow = async ctx => {
@@ -17,6 +17,7 @@ class QueryBuilder {
17
17
  notEqual: {},
18
18
  empty: {},
19
19
  notEmpty: {},
20
+ oneOf: {},
20
21
  ...base,
21
22
  }
22
23
  this.limit = 50
@@ -112,6 +113,11 @@ class QueryBuilder {
112
113
  return this
113
114
  }
114
115
 
116
+ addOneOf(key, value) {
117
+ this.query.oneOf[key] = value
118
+ return this
119
+ }
120
+
115
121
  /**
116
122
  * Preprocesses a value before going into a lucene search.
117
123
  * Transforms strings to lowercase and wraps strings and bools in quotes.
@@ -220,6 +226,28 @@ class QueryBuilder {
220
226
  if (this.query.notEmpty) {
221
227
  build(this.query.notEmpty, key => `${key}:["" TO *]`)
222
228
  }
229
+ if (this.query.oneOf) {
230
+ build(this.query.oneOf, (key, value) => {
231
+ if (!Array.isArray(value)) {
232
+ if (typeof value === "string") {
233
+ value = value.split(",")
234
+ } else {
235
+ return ""
236
+ }
237
+ }
238
+ let orStatement = `${builder.preprocess(
239
+ value[0],
240
+ allPreProcessingOpts
241
+ )}`
242
+ for (let i = 1; i < value.length; i++) {
243
+ orStatement += ` OR ${builder.preprocess(
244
+ value[i],
245
+ allPreProcessingOpts
246
+ )}`
247
+ }
248
+ return `${key}:(${orStatement})`
249
+ })
250
+ }
223
251
  return query
224
252
  }
225
253
 
@@ -64,6 +64,9 @@ exports.validate = async ({ tableId, row, table }) => {
64
64
  // Validate.js doesn't seem to handle array
65
65
  if (type === FieldTypes.ARRAY && row[fieldName]) {
66
66
  if (row[fieldName].length) {
67
+ if (!Array.isArray(row[fieldName])) {
68
+ row[fieldName] = row[fieldName].split(",")
69
+ }
67
70
  row[fieldName].map(val => {
68
71
  if (
69
72
  !constraints.inclusion.includes(val) &&
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
  })