@budibase/server 2.1.17 → 2.1.19-alpha.0

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 (166) hide show
  1. package/__mocks__/aws-sdk.ts +14 -0
  2. package/builder/assets/{index.20f98993.js → index.b14b0f23.js} +216 -216
  3. package/builder/index.html +1 -1
  4. package/coverage/clover.xml +69 -70
  5. package/coverage/coverage-final.json +3 -3
  6. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  7. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/index.html +1 -1
  12. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  16. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  18. package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  22. package/coverage/lcov-report/api/controllers/row/index.html +1 -1
  23. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  27. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  29. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  31. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  36. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  39. package/coverage/lcov-report/api/index.html +1 -1
  40. package/coverage/lcov-report/api/index.js.html +1 -1
  41. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  42. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  43. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  44. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  45. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  46. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/index.html +1 -1
  50. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  58. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  64. package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  66. package/coverage/lcov-report/automations/actions.js.html +1 -1
  67. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  68. package/coverage/lcov-report/automations/bullboard.js.html +1 -1
  69. package/coverage/lcov-report/automations/index.html +1 -1
  70. package/coverage/lcov-report/automations/index.js.html +1 -1
  71. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  72. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  73. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  74. package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
  75. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  76. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  77. package/coverage/lcov-report/automations/steps/index.html +15 -15
  78. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  79. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  84. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/utils.js.html +10 -10
  87. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  88. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  89. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  90. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  91. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  92. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  93. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  94. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  95. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  96. package/coverage/lcov-report/automations/triggers.js.html +1 -1
  97. package/coverage/lcov-report/constants/index.html +1 -1
  98. package/coverage/lcov-report/constants/index.js.html +1 -1
  99. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  100. package/coverage/lcov-report/constants/screens.js.html +1 -1
  101. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  102. package/coverage/lcov-report/db/index.html +1 -1
  103. package/coverage/lcov-report/db/index.js.html +1 -1
  104. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  105. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  106. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  107. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  108. package/coverage/lcov-report/db/newid.js.html +1 -1
  109. package/coverage/lcov-report/db/utils.js.html +1 -1
  110. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  111. package/coverage/lcov-report/events/index.html +1 -1
  112. package/coverage/lcov-report/events/index.js.html +1 -1
  113. package/coverage/lcov-report/events/utils.js.html +1 -1
  114. package/coverage/lcov-report/index.html +20 -20
  115. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  116. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  117. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  118. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  119. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  120. package/coverage/lcov-report/middleware/index.html +1 -1
  121. package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
  122. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  123. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  124. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  125. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  126. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  127. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  128. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  129. package/coverage/lcov-report/utilities/global.js.html +1 -1
  130. package/coverage/lcov-report/utilities/index.html +10 -10
  131. package/coverage/lcov-report/utilities/index.js.html +7 -13
  132. package/coverage/lcov-report/utilities/plugins.js.html +2 -2
  133. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
  134. package/coverage/lcov-report/utilities/queue/index.html +1 -1
  135. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  136. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  137. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  138. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  139. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  140. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  141. package/coverage/lcov-report/utilities/security.js.html +1 -1
  142. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  143. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  144. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  145. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  146. package/coverage/lcov-report/utilities/users.js.html +1 -1
  147. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  148. package/coverage/lcov.info +113 -114
  149. package/dist/api/controllers/row/ExternalRequest.js +6 -1
  150. package/dist/api/controllers/row/index.js +16 -7
  151. package/dist/environment.js +1 -0
  152. package/dist/integrations/elasticsearch.js +26 -2
  153. package/dist/integrations/s3.js +157 -1
  154. package/dist/package.json +6 -6
  155. package/dist/tsconfig.build.tsbuildinfo +1 -1
  156. package/dist/utilities/index.js +1 -2
  157. package/dist/utilities/plugins.js +1 -1
  158. package/package.json +7 -7
  159. package/src/api/controllers/row/ExternalRequest.ts +5 -3
  160. package/src/api/controllers/row/index.ts +17 -9
  161. package/src/environment.js +1 -0
  162. package/src/integrations/elasticsearch.ts +32 -2
  163. package/src/integrations/s3.ts +179 -3
  164. package/src/integrations/tests/s3.spec.ts +85 -1
  165. package/src/utilities/index.js +1 -3
  166. package/src/utilities/plugins.js +1 -1
@@ -14,7 +14,6 @@ const { sanitizeKey } = require("@budibase/backend-core/objectStore");
14
14
  const { generateMetadataID } = require("../db/utils");
15
15
  const Readable = require("stream").Readable;
16
16
  const { getAppDB } = require("@budibase/backend-core/context");
17
- const BB_CDN = "https://cdn.budi.live";
18
17
  exports.wait = ms => new Promise(resolve => setTimeout(resolve, ms));
19
18
  exports.isDev = env.isDev;
20
19
  exports.NUMBER_REGEX = /^[+-]?([0-9]*[.])?[0-9]+$/g;
@@ -44,7 +43,7 @@ exports.objectStoreUrl = () => {
44
43
  return OBJ_STORE_DIRECTORY;
45
44
  }
46
45
  else {
47
- return BB_CDN;
46
+ return env.CDN_URL;
48
47
  }
49
48
  };
50
49
  /**
@@ -12,7 +12,7 @@ exports.enrichPluginURLs = plugins => {
12
12
  const jsFileName = "plugin.min.js";
13
13
  // In self host we need to prefix the path, as the bucket name is not part
14
14
  // of the bucket path. In cloud, it's already part of the bucket path.
15
- let jsUrl = cloud ? "https://cdn.budi.live/" : `/${bucket}/`;
15
+ let jsUrl = cloud ? `${env.CDN_URL}/` : `/${bucket}/`;
16
16
  jsUrl += ProPlugins.getBucketPath(plugin.name);
17
17
  jsUrl += jsFileName;
18
18
  return Object.assign(Object.assign({}, plugin), { jsUrl });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/server",
3
3
  "email": "hi@budibase.com",
4
- "version": "2.1.17",
4
+ "version": "2.1.19-alpha.0",
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": "^2.1.17",
81
- "@budibase/client": "^2.1.17",
82
- "@budibase/pro": "2.1.16",
83
- "@budibase/string-templates": "^2.1.17",
84
- "@budibase/types": "^2.1.17",
80
+ "@budibase/backend-core": "2.1.19-alpha.0",
81
+ "@budibase/client": "2.1.19-alpha.0",
82
+ "@budibase/pro": "2.1.18",
83
+ "@budibase/string-templates": "2.1.19-alpha.0",
84
+ "@budibase/types": "2.1.19-alpha.0",
85
85
  "@bull-board/api": "3.7.0",
86
86
  "@bull-board/koa": "3.9.4",
87
87
  "@elastic/elasticsearch": "7.10.0",
@@ -199,5 +199,5 @@
199
199
  "optionalDependencies": {
200
200
  "oracledb": "5.3.0"
201
201
  },
202
- "gitHead": "f13fc9cd82db61af9474e1070071cafefdfed42d"
202
+ "gitHead": "8159f0503b4cfcf1a307ac221ccf5609239be71a"
203
203
  }
@@ -282,9 +282,11 @@ module External {
282
282
  const linkTablePrimary = linkTable.primary[0]
283
283
  // one to many
284
284
  if (isOneSide(field)) {
285
- newRow[field.foreignKey || linkTablePrimary] = breakRowIdField(
286
- row[key][0]
287
- )[0]
285
+ let id = row[key][0]
286
+ if (typeof row[key] === "string") {
287
+ id = decodeURIComponent(row[key]).match(/\[(.*?)\]/)?.[1]
288
+ }
289
+ newRow[field.foreignKey || linkTablePrimary] = breakRowIdField(id)[0]
288
290
  }
289
291
  // many to many
290
292
  else if (field.through) {
@@ -30,16 +30,24 @@ export async function patch(ctx: any): Promise<any> {
30
30
  if (body && !body._id) {
31
31
  return save(ctx)
32
32
  }
33
- const { row, table } = await quotas.addQuery(
34
- () => pickApi(tableId).patch(ctx),
35
- {
36
- datasourceId: tableId,
33
+ try {
34
+ const { row, table } = await quotas.addQuery(
35
+ () => pickApi(tableId).patch(ctx),
36
+ {
37
+ datasourceId: tableId,
38
+ }
39
+ )
40
+ if (!row) {
41
+ ctx.throw(404, "Row not found")
37
42
  }
38
- )
39
- ctx.status = 200
40
- ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:update`, appId, row, table)
41
- ctx.message = `${table.name} updated successfully.`
42
- ctx.body = row
43
+ ctx.status = 200
44
+ ctx.eventEmitter &&
45
+ ctx.eventEmitter.emitRow(`row:update`, appId, row, table)
46
+ ctx.message = `${table.name} updated successfully.`
47
+ ctx.body = row
48
+ } catch (err) {
49
+ ctx.throw(400, err)
50
+ }
43
51
  }
44
52
 
45
53
  export const save = async (ctx: any) => {
@@ -46,6 +46,7 @@ module.exports = {
46
46
  AWS_REGION: process.env.AWS_REGION,
47
47
  MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
48
48
  MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
49
+ CDN_URL: process.env.CDN_URL || "https://cdn.budi.live",
49
50
  REDIS_URL: process.env.REDIS_URL,
50
51
  REDIS_PASSWORD: process.env.REDIS_PASSWORD,
51
52
  INTERNAL_API_KEY: process.env.INTERNAL_API_KEY,
@@ -5,10 +5,13 @@ import {
5
5
  IntegrationBase,
6
6
  } from "@budibase/types"
7
7
 
8
- const { Client } = require("@elastic/elasticsearch")
8
+ import { Client, ClientOptions } from "@elastic/elasticsearch"
9
9
 
10
10
  interface ElasticsearchConfig {
11
11
  url: string
12
+ ssl?: boolean
13
+ ca?: string
14
+ rejectUnauthorized?: boolean
12
15
  }
13
16
 
14
17
  const SCHEMA: Integration = {
@@ -23,6 +26,21 @@ const SCHEMA: Integration = {
23
26
  required: true,
24
27
  default: "http://localhost:9200",
25
28
  },
29
+ ssl: {
30
+ type: DatasourceFieldType.BOOLEAN,
31
+ default: false,
32
+ required: false,
33
+ },
34
+ rejectUnauthorized: {
35
+ type: DatasourceFieldType.BOOLEAN,
36
+ default: true,
37
+ required: false,
38
+ },
39
+ ca: {
40
+ type: DatasourceFieldType.LONGFORM,
41
+ default: false,
42
+ required: false,
43
+ },
26
44
  },
27
45
  query: {
28
46
  create: {
@@ -81,7 +99,19 @@ class ElasticSearchIntegration implements IntegrationBase {
81
99
 
82
100
  constructor(config: ElasticsearchConfig) {
83
101
  this.config = config
84
- this.client = new Client({ node: config.url })
102
+
103
+ const clientConfig: ClientOptions = {
104
+ node: this.config.url,
105
+ }
106
+
107
+ if (this.config.ssl) {
108
+ clientConfig.ssl = {
109
+ rejectUnauthorized: this.config.rejectUnauthorized,
110
+ ca: this.config.ca || undefined,
111
+ }
112
+ }
113
+
114
+ this.client = new Client(clientConfig)
85
115
  }
86
116
 
87
117
  async create(query: { index: string; json: object }) {
@@ -1,5 +1,12 @@
1
- import { Integration, QueryType, IntegrationBase } from "@budibase/types"
1
+ import {
2
+ Integration,
3
+ QueryType,
4
+ IntegrationBase,
5
+ DatasourceFieldType,
6
+ } from "@budibase/types"
7
+
2
8
  const AWS = require("aws-sdk")
9
+ const csv = require("csvtojson")
3
10
 
4
11
  interface S3Config {
5
12
  region: string
@@ -40,16 +47,106 @@ const SCHEMA: Integration = {
40
47
  },
41
48
  },
42
49
  query: {
50
+ create: {
51
+ type: QueryType.FIELDS,
52
+ fields: {
53
+ bucket: {
54
+ display: "New Bucket",
55
+ type: DatasourceFieldType.STRING,
56
+ required: true,
57
+ },
58
+ location: {
59
+ required: true,
60
+ default: "us-east-1",
61
+ type: DatasourceFieldType.STRING,
62
+ },
63
+ grantFullControl: {
64
+ display: "Grant full control",
65
+ type: DatasourceFieldType.STRING,
66
+ },
67
+ grantRead: {
68
+ display: "Grant read",
69
+ type: DatasourceFieldType.STRING,
70
+ },
71
+ grantReadAcp: {
72
+ display: "Grant read ACP",
73
+ type: DatasourceFieldType.STRING,
74
+ },
75
+ grantWrite: {
76
+ display: "Grant write",
77
+ type: DatasourceFieldType.STRING,
78
+ },
79
+ grantWriteAcp: {
80
+ display: "Grant write ACP",
81
+ type: DatasourceFieldType.STRING,
82
+ },
83
+ },
84
+ },
43
85
  read: {
44
86
  type: QueryType.FIELDS,
45
87
  fields: {
46
88
  bucket: {
47
- type: "string",
89
+ type: DatasourceFieldType.STRING,
90
+ required: true,
91
+ },
92
+ delimiter: {
93
+ type: DatasourceFieldType.STRING,
94
+ },
95
+ marker: {
96
+ type: DatasourceFieldType.STRING,
97
+ },
98
+ maxKeys: {
99
+ type: DatasourceFieldType.NUMBER,
100
+ display: "Max Keys",
101
+ },
102
+ prefix: {
103
+ type: DatasourceFieldType.STRING,
104
+ },
105
+ },
106
+ },
107
+ readCsv: {
108
+ displayName: "Read CSV",
109
+ type: QueryType.FIELDS,
110
+ fields: {
111
+ bucket: {
112
+ type: DatasourceFieldType.STRING,
113
+ required: true,
114
+ },
115
+ key: {
116
+ type: DatasourceFieldType.STRING,
117
+ required: true,
118
+ },
119
+ },
120
+ },
121
+ delete: {
122
+ type: QueryType.FIELDS,
123
+ fields: {
124
+ bucket: {
125
+ type: DatasourceFieldType.STRING,
126
+ required: true,
127
+ },
128
+ delete: {
129
+ type: DatasourceFieldType.JSON,
48
130
  required: true,
49
131
  },
50
132
  },
51
133
  },
52
134
  },
135
+ extra: {
136
+ acl: {
137
+ required: false,
138
+ displayName: "ACL",
139
+ type: DatasourceFieldType.LIST,
140
+ data: {
141
+ create: [
142
+ "private",
143
+ "public-read",
144
+ "public-read-write",
145
+ "authenticated-read",
146
+ ],
147
+ },
148
+ },
149
+ },
53
150
  }
54
151
 
55
152
  class S3Integration implements IntegrationBase {
@@ -67,14 +164,93 @@ class S3Integration implements IntegrationBase {
67
164
  this.client = new AWS.S3(this.config)
68
165
  }
69
166
 
70
- async read(query: { bucket: string }) {
167
+ async create(query: {
168
+ bucket: string
169
+ location: string
170
+ grantFullControl: string
171
+ grantRead: string
172
+ grantReadAcp: string
173
+ grantWrite: string
174
+ grantWriteAcp: string
175
+ extra: {
176
+ acl: string
177
+ }
178
+ }) {
179
+ let params: any = {
180
+ Bucket: query.bucket,
181
+ ACL: query.extra?.acl,
182
+ GrantFullControl: query.grantFullControl,
183
+ GrantRead: query.grantRead,
184
+ GrantReadACP: query.grantReadAcp,
185
+ GrantWrite: query.grantWrite,
186
+ GrantWriteACP: query.grantWriteAcp,
187
+ }
188
+ if (query.location) {
189
+ params["CreateBucketConfiguration"] = {
190
+ LocationConstraint: query.location,
191
+ }
192
+ }
193
+ return await this.client.createBucket(params).promise()
194
+ }
195
+
196
+ async read(query: {
197
+ bucket: string
198
+ delimiter: string
199
+ expectedBucketOwner: string
200
+ marker: string
201
+ maxKeys: number
202
+ prefix: string
203
+ }) {
71
204
  const response = await this.client
72
205
  .listObjects({
73
206
  Bucket: query.bucket,
207
+ Delimiter: query.delimiter,
208
+ Marker: query.marker,
209
+ MaxKeys: query.maxKeys,
210
+ Prefix: query.prefix,
74
211
  })
75
212
  .promise()
76
213
  return response.Contents
77
214
  }
215
+
216
+ async readCsv(query: { bucket: string; key: string }) {
217
+ const stream = this.client
218
+ .getObject({
219
+ Bucket: query.bucket,
220
+ Key: query.key,
221
+ })
222
+ .createReadStream()
223
+
224
+ let csvError = false
225
+ return new Promise((resolve, reject) => {
226
+ stream.on("error", (err: Error) => {
227
+ reject(err)
228
+ })
229
+ const response = csv()
230
+ .fromStream(stream)
231
+ .on("error", () => {
232
+ csvError = true
233
+ })
234
+ stream.on("finish", () => {
235
+ resolve(response)
236
+ })
237
+ }).catch(err => {
238
+ if (csvError) {
239
+ throw new Error("Could not read CSV")
240
+ } else {
241
+ throw err
242
+ }
243
+ })
244
+ }
245
+
246
+ async delete(query: { bucket: string; delete: string }) {
247
+ return await this.client
248
+ .deleteObjects({
249
+ Bucket: query.bucket,
250
+ Delete: JSON.parse(query.delete),
251
+ })
252
+ .promise()
253
+ }
78
254
  }
79
255
 
80
256
  export default {
@@ -18,11 +18,95 @@ describe("S3 Integration", () => {
18
18
  })
19
19
 
20
20
  it("calls the read method with the correct params", async () => {
21
- const response = await config.integration.read({
21
+ await config.integration.read({
22
22
  bucket: "test",
23
+ delimiter: "/",
24
+ marker: "file.txt",
25
+ maxKeys: 999,
26
+ prefix: "directory/",
23
27
  })
24
28
  expect(config.integration.client.listObjects).toHaveBeenCalledWith({
25
29
  Bucket: "test",
30
+ Delimiter: "/",
31
+ Marker: "file.txt",
32
+ MaxKeys: 999,
33
+ Prefix: "directory/",
34
+ })
35
+ })
36
+
37
+ it("calls the create method with the correct params", async () => {
38
+ await config.integration.create({
39
+ bucket: "test",
40
+ location: "af-south-1",
41
+ grantFullControl: "me",
42
+ grantRead: "him",
43
+ grantReadAcp: "her",
44
+ grantWrite: "she",
45
+ grantWriteAcp: "he",
46
+ objectLockEnabledForBucket: true,
47
+ extra: {
48
+ acl: "private",
49
+ },
50
+ })
51
+ expect(config.integration.client.createBucket).toHaveBeenCalledWith({
52
+ Bucket: "test",
53
+ CreateBucketConfiguration: {
54
+ LocationConstraint: "af-south-1",
55
+ },
56
+ GrantFullControl: "me",
57
+ GrantRead: "him",
58
+ GrantReadACP: "her",
59
+ GrantWrite: "she",
60
+ GrantWriteACP: "he",
61
+ ACL: "private",
62
+ })
63
+ })
64
+
65
+ it("does not add undefined location constraint when calling the create method", async () => {
66
+ await config.integration.create({
67
+ bucket: "test",
68
+ })
69
+ expect(config.integration.client.createBucket).toHaveBeenCalledWith({
70
+ Bucket: "test",
71
+ GrantFullControl: undefined,
72
+ GrantRead: undefined,
73
+ GrantReadACP: undefined,
74
+ GrantWrite: undefined,
75
+ GrantWriteACP: undefined,
76
+ ACL: undefined,
77
+ })
78
+ })
79
+
80
+ it("calls the delete method with the correct params ", async () => {
81
+ await config.integration.delete({
82
+ bucket: "test",
83
+ delete: `{
84
+ "Objects": [
85
+ {
86
+ "Key": "HappyFace.jpg",
87
+ "VersionId": "2LWg7lQLnY41.maGB5Z6SWW.dcq0vx7b"
88
+ },
89
+ {
90
+ "Key": "HappyFace.jpg",
91
+ "VersionId": "yoz3HB.ZhCS_tKVEmIOr7qYyyAaZSKVd"
92
+ }
93
+ ]
94
+ }`,
95
+ })
96
+ expect(config.integration.client.deleteObjects).toHaveBeenCalledWith({
97
+ Bucket: "test",
98
+ Delete: {
99
+ Objects: [
100
+ {
101
+ Key: "HappyFace.jpg",
102
+ VersionId: "2LWg7lQLnY41.maGB5Z6SWW.dcq0vx7b",
103
+ },
104
+ {
105
+ Key: "HappyFace.jpg",
106
+ VersionId: "yoz3HB.ZhCS_tKVEmIOr7qYyyAaZSKVd",
107
+ },
108
+ ],
109
+ },
26
110
  })
27
111
  })
28
112
  })
@@ -5,8 +5,6 @@ const { generateMetadataID } = require("../db/utils")
5
5
  const Readable = require("stream").Readable
6
6
  const { getAppDB } = require("@budibase/backend-core/context")
7
7
 
8
- const BB_CDN = "https://cdn.budi.live"
9
-
10
8
  exports.wait = ms => new Promise(resolve => setTimeout(resolve, ms))
11
9
 
12
10
  exports.isDev = env.isDev
@@ -40,7 +38,7 @@ exports.objectStoreUrl = () => {
40
38
  // can use a relative url for this as all goes through the proxy (this is hosted in minio)
41
39
  return OBJ_STORE_DIRECTORY
42
40
  } else {
43
- return BB_CDN
41
+ return env.CDN_URL
44
42
  }
45
43
  }
46
44
 
@@ -13,7 +13,7 @@ exports.enrichPluginURLs = plugins => {
13
13
 
14
14
  // In self host we need to prefix the path, as the bucket name is not part
15
15
  // of the bucket path. In cloud, it's already part of the bucket path.
16
- let jsUrl = cloud ? "https://cdn.budi.live/" : `/${bucket}/`
16
+ let jsUrl = cloud ? `${env.CDN_URL}/` : `/${bucket}/`
17
17
  jsUrl += ProPlugins.getBucketPath(plugin.name)
18
18
  jsUrl += jsFileName
19
19
  return { ...plugin, jsUrl }