@budibase/server 1.0.25 → 1.0.27-alpha.2
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.
- package/__mocks__/node-fetch.ts +3 -0
- package/builder/assets/bb-spaceship.8f6e81e1.svg +227 -0
- package/builder/assets/{index.4fb3f887.css → index.5522fcd5.css} +1 -1
- package/builder/assets/index.e9e2c4d7.js +1343 -0
- package/builder/assets/{vendor.470042a4.js → vendor.f9faf6ab.js} +88 -88
- package/builder/index.html +3 -3
- package/coverage/clover.xml +736 -649
- package/coverage/coverage-final.json +24 -23
- package/coverage/lcov-report/api/controllers/analytics.js.html +1 -1
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/application.js.html +1 -1
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +22 -10
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +4 -4
- package/coverage/lcov-report/api/controllers/datasource.js.html +14 -14
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +28 -43
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
- package/coverage/lcov-report/api/controllers/query/index.html +126 -0
- package/coverage/lcov-report/api/controllers/{query.js.html → query/index.js.html} +159 -27
- package/coverage/lcov-report/api/controllers/query/validation.js.html +203 -0
- package/coverage/lcov-report/api/controllers/role.js.html +1 -1
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/index.html +16 -16
- package/coverage/lcov-report/api/controllers/row/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +7 -4
- package/coverage/lcov-report/api/controllers/row/utils.js.html +29 -20
- package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +108 -9
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +18 -6
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/application.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +1 -1
- package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +9 -9
- package/coverage/lcov-report/api/routes/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +11 -98
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/row.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/static.js.html +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +32 -2
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +1 -1
- package/coverage/lcov-report/automations/index.html +20 -20
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +5 -8
- package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +1 -1
- package/coverage/lcov-report/automations/utils.js.html +44 -11
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +22 -22
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/client.js.html +18 -18
- package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
- package/coverage/lcov-report/db/index.html +15 -15
- package/coverage/lcov-report/db/index.js.html +3 -3
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
- package/coverage/lcov-report/db/newid.js.html +4 -4
- package/coverage/lcov-report/db/utils.js.html +91 -64
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +1 -1
- package/coverage/lcov-report/index.html +92 -77
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
- package/coverage/lcov-report/middleware/authorized.js.html +2 -2
- package/coverage/lcov-report/middleware/builder.js.html +1 -1
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +1 -1
- package/coverage/lcov-report/middleware/joi-validator.js.html +3 -3
- package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/usageQuota.js.html +1 -1
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/threads/automation.js.html +1 -1
- package/coverage/lcov-report/threads/index.html +19 -19
- package/coverage/lcov-report/threads/index.js.html +1 -1
- package/coverage/lcov-report/threads/query.js.html +63 -12
- package/coverage/lcov-report/threads/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +1 -1
- package/coverage/lcov-report/utilities/index.html +19 -19
- package/coverage/lcov-report/utilities/index.js.html +66 -33
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +19 -19
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +46 -10
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +2 -2
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
- package/coverage/lcov.info +1220 -1083
- package/dist/api/controllers/automation.js +7 -5
- package/dist/api/controllers/query/import/index.js +79 -0
- package/dist/api/controllers/query/import/sources/base/index.js +63 -0
- package/dist/api/controllers/query/import/sources/base/openapi.js +42 -0
- package/dist/api/controllers/query/import/sources/curl.js +90 -0
- package/dist/api/controllers/query/import/sources/openapi2.js +139 -0
- package/dist/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
- package/dist/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
- package/dist/api/controllers/{query.js → query/index.js} +42 -6
- package/dist/api/controllers/query/validation.js +37 -0
- package/dist/api/controllers/row/internalSearch.js +2 -1
- package/dist/api/controllers/row/utils.js +13 -6
- package/dist/api/controllers/user.js +37 -1
- package/dist/api/controllers/webhook.js +4 -0
- package/dist/api/routes/query.js +2 -32
- package/dist/api/routes/user.js +3 -1
- package/dist/automations/steps/outgoingWebhook.js +2 -3
- package/dist/automations/utils.js +10 -0
- package/dist/db/utils.js +8 -0
- package/dist/definitions/datasource.js +6 -1
- package/dist/integrations/rest.js +207 -117
- package/dist/package.json +10 -4
- package/dist/threads/query.js +14 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/index.js +10 -0
- package/dist/utilities/rowProcessor/index.js +13 -0
- package/package.json +11 -5
- package/src/api/controllers/automation.js +8 -4
- package/src/api/controllers/query/import/index.ts +85 -0
- package/src/api/controllers/query/import/sources/base/index.ts +85 -0
- package/src/api/controllers/query/import/sources/base/openapi.ts +24 -0
- package/src/api/controllers/query/import/sources/curl.ts +94 -0
- package/src/api/controllers/query/import/sources/openapi2.ts +159 -0
- package/src/api/controllers/query/import/sources/tests/curl/curl.spec.js +104 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/delete.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/empty-body.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/get.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/headers.txt +3 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/patch.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/path.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/post.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/put.txt +2 -0
- package/src/api/controllers/query/import/sources/tests/curl/data/query.txt +1 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.json +253 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/crud/crud.yaml +160 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.json +1054 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/data/petstore/petstore.yaml +711 -0
- package/src/api/controllers/query/import/sources/tests/openapi2/openapi2.spec.js +239 -0
- package/src/api/controllers/query/import/tests/index.spec.js +115 -0
- package/src/api/controllers/{query.js → query/index.js} +50 -6
- package/src/api/controllers/query/validation.js +41 -0
- package/src/api/controllers/row/internalSearch.js +2 -1
- package/src/api/controllers/row/utils.js +11 -8
- package/src/api/controllers/user.js +33 -0
- package/src/api/controllers/webhook.js +4 -0
- package/src/api/routes/query.js +5 -34
- package/src/api/routes/user.js +10 -0
- package/src/automations/steps/outgoingWebhook.js +2 -3
- package/src/automations/utils.js +11 -0
- package/src/db/utils.js +9 -0
- package/src/definitions/common.ts +2 -16
- package/src/definitions/datasource.ts +73 -1
- package/src/integrations/base/IntegrationBase.ts +4 -4
- package/src/integrations/oracle.ts +1 -1
- package/src/integrations/rest.ts +227 -137
- package/src/integrations/tests/rest.spec.js +167 -19
- package/src/threads/query.js +19 -2
- package/src/utilities/index.js +11 -0
- package/src/utilities/rowProcessor/index.js +12 -0
- package/builder/assets/index.f01106f0.js +0 -1316
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
const { OpenAPI2 } = require("../../openapi2")
|
|
2
|
+
const fs = require("fs")
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
5
|
+
const getData = (file, extension) => {
|
|
6
|
+
return fs.readFileSync(path.join(__dirname, `./data/${file}/${file}.${extension}`), "utf8")
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
describe("OpenAPI2 Import", () => {
|
|
10
|
+
let openapi2
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
openapi2 = new OpenAPI2()
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it("validates unsupported data", async () => {
|
|
17
|
+
let data
|
|
18
|
+
let supported
|
|
19
|
+
|
|
20
|
+
// non json / yaml
|
|
21
|
+
data = "curl http://example.com"
|
|
22
|
+
supported = await openapi2.isSupported(data)
|
|
23
|
+
expect(supported).toBe(false)
|
|
24
|
+
|
|
25
|
+
// Empty
|
|
26
|
+
data = ""
|
|
27
|
+
supported = await openapi2.isSupported(data)
|
|
28
|
+
expect(supported).toBe(false)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const init = async (file, extension) => {
|
|
32
|
+
await openapi2.isSupported(getData(file, extension))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const runTests = async (filename, test, assertions) => {
|
|
36
|
+
for (let extension of ["json", "yaml"]) {
|
|
37
|
+
await test(filename, extension, assertions)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const testImportInfo = async (file, extension) => {
|
|
42
|
+
await init(file, extension)
|
|
43
|
+
const info = await openapi2.getInfo()
|
|
44
|
+
expect(info.url).toBe("https://petstore.swagger.io/v2")
|
|
45
|
+
expect(info.name).toBe("Swagger Petstore")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
it("returns import info", async () => {
|
|
49
|
+
await runTests("petstore", testImportInfo)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe("Returns queries", () => {
|
|
53
|
+
const indexQueries = (queries) => {
|
|
54
|
+
return queries.reduce((acc, query) => {
|
|
55
|
+
acc[query.name] = query
|
|
56
|
+
return acc
|
|
57
|
+
}, {})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const getQueries = async (file, extension) => {
|
|
61
|
+
await init(file, extension)
|
|
62
|
+
const queries = await openapi2.getQueries()
|
|
63
|
+
expect(queries.length).toBe(6)
|
|
64
|
+
return indexQueries(queries)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const testVerb = async (file, extension, assertions) => {
|
|
68
|
+
const queries = await getQueries(file, extension)
|
|
69
|
+
for (let [operationId, method] of Object.entries(assertions)) {
|
|
70
|
+
expect(queries[operationId].queryVerb).toBe(method)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
it("populates verb", async () => {
|
|
75
|
+
const assertions = {
|
|
76
|
+
"createEntity" : "create",
|
|
77
|
+
"getEntities" : "read",
|
|
78
|
+
"getEntity" : "read",
|
|
79
|
+
"updateEntity" : "update",
|
|
80
|
+
"patchEntity" : "patch",
|
|
81
|
+
"deleteEntity" : "delete"
|
|
82
|
+
}
|
|
83
|
+
await runTests("crud", testVerb, assertions)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const testPath = async (file, extension, assertions) => {
|
|
87
|
+
const queries = await getQueries(file, extension)
|
|
88
|
+
for (let [operationId, urlPath] of Object.entries(assertions)) {
|
|
89
|
+
expect(queries[operationId].fields.path).toBe(urlPath)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
it("populates path", async () => {
|
|
94
|
+
const assertions = {
|
|
95
|
+
"createEntity" : "entities",
|
|
96
|
+
"getEntities" : "entities",
|
|
97
|
+
"getEntity" : "entities/{{entityId}}",
|
|
98
|
+
"updateEntity" : "entities/{{entityId}}",
|
|
99
|
+
"patchEntity" : "entities/{{entityId}}",
|
|
100
|
+
"deleteEntity" : "entities/{{entityId}}"
|
|
101
|
+
}
|
|
102
|
+
await runTests("crud", testPath, assertions)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const testHeaders = async (file, extension, assertions) => {
|
|
106
|
+
const queries = await getQueries(file, extension)
|
|
107
|
+
for (let [operationId, headers] of Object.entries(assertions)) {
|
|
108
|
+
expect(queries[operationId].fields.headers).toStrictEqual(headers)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const contentTypeHeader = {
|
|
113
|
+
"Content-Type" : "application/json",
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
it("populates headers", async () => {
|
|
117
|
+
const assertions = {
|
|
118
|
+
"createEntity" : {
|
|
119
|
+
...contentTypeHeader
|
|
120
|
+
},
|
|
121
|
+
"getEntities" : {
|
|
122
|
+
},
|
|
123
|
+
"getEntity" : {
|
|
124
|
+
},
|
|
125
|
+
"updateEntity" : {
|
|
126
|
+
...contentTypeHeader
|
|
127
|
+
},
|
|
128
|
+
"patchEntity" : {
|
|
129
|
+
...contentTypeHeader
|
|
130
|
+
},
|
|
131
|
+
"deleteEntity" : {
|
|
132
|
+
"x-api-key" : "{{x-api-key}}",
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
await runTests("crud", testHeaders, assertions)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const testQuery = async (file, extension, assertions) => {
|
|
140
|
+
const queries = await getQueries(file, extension)
|
|
141
|
+
for (let [operationId, queryString] of Object.entries(assertions)) {
|
|
142
|
+
expect(queries[operationId].fields.queryString).toStrictEqual(queryString)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
it("populates query", async () => {
|
|
147
|
+
const assertions = {
|
|
148
|
+
"createEntity" : "",
|
|
149
|
+
"getEntities" : "page={{page}}&size={{size}}",
|
|
150
|
+
"getEntity" : "",
|
|
151
|
+
"updateEntity" : "",
|
|
152
|
+
"patchEntity" : "",
|
|
153
|
+
"deleteEntity" : ""
|
|
154
|
+
}
|
|
155
|
+
await runTests("crud", testQuery, assertions)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
const testParameters = async (file, extension, assertions) => {
|
|
159
|
+
const queries = await getQueries(file, extension)
|
|
160
|
+
for (let [operationId, parameters] of Object.entries(assertions)) {
|
|
161
|
+
expect(queries[operationId].parameters).toStrictEqual(parameters)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
it("populates parameters", async () => {
|
|
166
|
+
const assertions = {
|
|
167
|
+
"createEntity" : [],
|
|
168
|
+
"getEntities" : [
|
|
169
|
+
{
|
|
170
|
+
"name" : "page",
|
|
171
|
+
"default" : "",
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"name" : "size",
|
|
175
|
+
"default" : "",
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"getEntity" : [
|
|
179
|
+
{
|
|
180
|
+
"name" : "entityId",
|
|
181
|
+
"default" : "",
|
|
182
|
+
}
|
|
183
|
+
],
|
|
184
|
+
"updateEntity" : [
|
|
185
|
+
{
|
|
186
|
+
"name" : "entityId",
|
|
187
|
+
"default" : "",
|
|
188
|
+
}
|
|
189
|
+
],
|
|
190
|
+
"patchEntity" : [
|
|
191
|
+
{
|
|
192
|
+
"name" : "entityId",
|
|
193
|
+
"default" : "",
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
"deleteEntity" : [
|
|
197
|
+
{
|
|
198
|
+
"name" : "entityId",
|
|
199
|
+
"default" : "",
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"name" : "x-api-key",
|
|
203
|
+
"default" : "",
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
await runTests("crud", testParameters, assertions)
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
const testBody = async (file, extension, assertions) => {
|
|
211
|
+
const queries = await getQueries(file, extension)
|
|
212
|
+
for (let [operationId, body] of Object.entries(assertions)) {
|
|
213
|
+
expect(queries[operationId].fields.requestBody).toStrictEqual(JSON.stringify(body, null, 2))
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
it("populates body", async () => {
|
|
217
|
+
const assertions = {
|
|
218
|
+
"createEntity" : {
|
|
219
|
+
"name" : "name",
|
|
220
|
+
"type" : "type",
|
|
221
|
+
},
|
|
222
|
+
"getEntities" : undefined,
|
|
223
|
+
"getEntity" : undefined,
|
|
224
|
+
"updateEntity" : {
|
|
225
|
+
"id": 1,
|
|
226
|
+
"name" : "name",
|
|
227
|
+
"type" : "type",
|
|
228
|
+
},
|
|
229
|
+
"patchEntity" : {
|
|
230
|
+
"id": 1,
|
|
231
|
+
"name" : "name",
|
|
232
|
+
"type" : "type",
|
|
233
|
+
},
|
|
234
|
+
"deleteEntity" : undefined
|
|
235
|
+
}
|
|
236
|
+
await runTests("crud", testBody, assertions)
|
|
237
|
+
})
|
|
238
|
+
})
|
|
239
|
+
})
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
|
|
2
|
+
const bulkDocs = jest.fn()
|
|
3
|
+
const db = jest.fn(() => {
|
|
4
|
+
return {
|
|
5
|
+
bulkDocs
|
|
6
|
+
}
|
|
7
|
+
})
|
|
8
|
+
jest.mock("../../../../../db", () => db)
|
|
9
|
+
|
|
10
|
+
const { RestImporter } = require("../index")
|
|
11
|
+
|
|
12
|
+
const fs = require("fs")
|
|
13
|
+
const path = require('path')
|
|
14
|
+
|
|
15
|
+
const getData = (file) => {
|
|
16
|
+
return fs.readFileSync(path.join(__dirname, `../sources/tests/${file}`), "utf8")
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// openapi2 (swagger)
|
|
20
|
+
const oapi2CrudJson = getData("openapi2/data/crud/crud.json")
|
|
21
|
+
const oapi2CrudYaml = getData("openapi2/data/crud/crud.json")
|
|
22
|
+
const oapi2PetstoreJson = getData("openapi2/data/petstore/petstore.json")
|
|
23
|
+
const oapi2PetstoreYaml = getData("openapi2/data/petstore/petstore.json")
|
|
24
|
+
|
|
25
|
+
// curl
|
|
26
|
+
const curl = getData("curl/data/post.txt")
|
|
27
|
+
|
|
28
|
+
const datasets = {
|
|
29
|
+
oapi2CrudJson,
|
|
30
|
+
oapi2CrudYaml,
|
|
31
|
+
oapi2PetstoreJson,
|
|
32
|
+
oapi2PetstoreYaml,
|
|
33
|
+
curl
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("Rest Importer", () => {
|
|
37
|
+
let restImporter
|
|
38
|
+
|
|
39
|
+
const init = async (data) => {
|
|
40
|
+
restImporter = new RestImporter(data)
|
|
41
|
+
await restImporter.init()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const runTest = async (test, assertions) => {
|
|
45
|
+
for (let [key, data] of Object.entries(datasets)) {
|
|
46
|
+
await test(key, data, assertions)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const testGetInfo = async (key, data, assertions) => {
|
|
51
|
+
await init(data)
|
|
52
|
+
const info = await restImporter.getInfo()
|
|
53
|
+
expect(info.name).toBe(assertions[key].name)
|
|
54
|
+
expect(info.url).toBe(assertions[key].url)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
it("gets info", async () => {
|
|
58
|
+
const assertions = {
|
|
59
|
+
"oapi2CrudJson" : {
|
|
60
|
+
name: "CRUD",
|
|
61
|
+
url: "http://example.com"
|
|
62
|
+
},
|
|
63
|
+
"oapi2CrudYaml" : {
|
|
64
|
+
name: "CRUD",
|
|
65
|
+
url: "http://example.com"
|
|
66
|
+
},
|
|
67
|
+
"oapi2PetstoreJson" : {
|
|
68
|
+
name: "Swagger Petstore",
|
|
69
|
+
url: "https://petstore.swagger.io/v2"
|
|
70
|
+
},
|
|
71
|
+
"oapi2PetstoreYaml" :{
|
|
72
|
+
name: "Swagger Petstore",
|
|
73
|
+
url: "https://petstore.swagger.io/v2"
|
|
74
|
+
},
|
|
75
|
+
"curl": {
|
|
76
|
+
name: "example.com",
|
|
77
|
+
url: "http://example.com"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
await runTest(testGetInfo, assertions)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
const testImportQueries = async (key, data, assertions) => {
|
|
84
|
+
await init(data)
|
|
85
|
+
bulkDocs.mockReturnValue([])
|
|
86
|
+
const importResult = await restImporter.importQueries("appId", "datasourceId")
|
|
87
|
+
expect(importResult.errorQueries.length).toBe(0)
|
|
88
|
+
expect(importResult.queries.length).toBe(assertions[key].count)
|
|
89
|
+
expect(bulkDocs).toHaveBeenCalledTimes(1)
|
|
90
|
+
jest.clearAllMocks()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
it("imports queries", async () => {
|
|
94
|
+
// simple sanity assertions that the whole dataset
|
|
95
|
+
// makes it through the importer
|
|
96
|
+
const assertions = {
|
|
97
|
+
"oapi2CrudJson" : {
|
|
98
|
+
count: 6,
|
|
99
|
+
},
|
|
100
|
+
"oapi2CrudYaml" :{
|
|
101
|
+
count: 6,
|
|
102
|
+
},
|
|
103
|
+
"oapi2PetstoreJson" : {
|
|
104
|
+
count: 20,
|
|
105
|
+
},
|
|
106
|
+
"oapi2PetstoreYaml" :{
|
|
107
|
+
count: 20,
|
|
108
|
+
},
|
|
109
|
+
"curl": {
|
|
110
|
+
count: 1
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
await runTest(testImportQueries, assertions)
|
|
114
|
+
})
|
|
115
|
+
})
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
const { processString } = require("@budibase/string-templates")
|
|
2
|
-
const CouchDB = require("
|
|
2
|
+
const CouchDB = require("../../../db")
|
|
3
3
|
const {
|
|
4
4
|
generateQueryID,
|
|
5
5
|
getQueryParams,
|
|
6
6
|
isProdAppID,
|
|
7
|
-
} = require("
|
|
8
|
-
const { BaseQueryVerbs } = require("
|
|
9
|
-
const { Thread, ThreadType } = require("
|
|
7
|
+
} = require("../../../db/utils")
|
|
8
|
+
const { BaseQueryVerbs } = require("../../../constants")
|
|
9
|
+
const { Thread, ThreadType } = require("../../../threads")
|
|
10
|
+
const { save: saveDatasource } = require("../datasource")
|
|
11
|
+
const { RestImporter } = require("./import")
|
|
10
12
|
|
|
11
13
|
const Runner = new Thread(ThreadType.QUERY, { timeoutMs: 10000 })
|
|
12
14
|
|
|
@@ -30,9 +32,49 @@ exports.fetch = async function (ctx) {
|
|
|
30
32
|
include_docs: true,
|
|
31
33
|
})
|
|
32
34
|
)
|
|
35
|
+
|
|
33
36
|
ctx.body = enrichQueries(body.rows.map(row => row.doc))
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
exports.import = async ctx => {
|
|
40
|
+
const body = ctx.request.body
|
|
41
|
+
const data = body.data
|
|
42
|
+
|
|
43
|
+
const importer = new RestImporter(data)
|
|
44
|
+
await importer.init()
|
|
45
|
+
|
|
46
|
+
let datasourceId
|
|
47
|
+
if (!body.datasourceId) {
|
|
48
|
+
// construct new datasource
|
|
49
|
+
const info = await importer.getInfo()
|
|
50
|
+
let datasource = {
|
|
51
|
+
type: "datasource",
|
|
52
|
+
source: "REST",
|
|
53
|
+
config: {
|
|
54
|
+
url: info.url,
|
|
55
|
+
defaultHeaders: [],
|
|
56
|
+
},
|
|
57
|
+
name: info.name,
|
|
58
|
+
}
|
|
59
|
+
// save the datasource
|
|
60
|
+
const datasourceCtx = { ...ctx }
|
|
61
|
+
datasourceCtx.request.body.datasource = datasource
|
|
62
|
+
await saveDatasource(datasourceCtx)
|
|
63
|
+
datasourceId = datasourceCtx.body.datasource._id
|
|
64
|
+
} else {
|
|
65
|
+
// use existing datasource
|
|
66
|
+
datasourceId = body.datasourceId
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const importResult = await importer.importQueries(ctx.appId, datasourceId)
|
|
70
|
+
|
|
71
|
+
ctx.body = {
|
|
72
|
+
...importResult,
|
|
73
|
+
datasourceId,
|
|
74
|
+
}
|
|
75
|
+
ctx.status = 200
|
|
76
|
+
}
|
|
77
|
+
|
|
36
78
|
exports.save = async function (ctx) {
|
|
37
79
|
const db = new CouchDB(ctx.appId)
|
|
38
80
|
const query = ctx.request.body
|
|
@@ -81,7 +123,7 @@ async function enrichQueryFields(fields, parameters = {}) {
|
|
|
81
123
|
enrichedQuery.requestBody
|
|
82
124
|
)
|
|
83
125
|
} catch (err) {
|
|
84
|
-
|
|
126
|
+
// no json found, ignore
|
|
85
127
|
}
|
|
86
128
|
delete enrichedQuery.customData
|
|
87
129
|
}
|
|
@@ -109,7 +151,7 @@ exports.preview = async function (ctx) {
|
|
|
109
151
|
const enrichedQuery = await enrichQueryFields(fields, parameters)
|
|
110
152
|
|
|
111
153
|
try {
|
|
112
|
-
const { rows, keys } = await Runner.run({
|
|
154
|
+
const { rows, keys, info, extra } = await Runner.run({
|
|
113
155
|
datasource,
|
|
114
156
|
queryVerb,
|
|
115
157
|
query: enrichedQuery,
|
|
@@ -119,6 +161,8 @@ exports.preview = async function (ctx) {
|
|
|
119
161
|
ctx.body = {
|
|
120
162
|
rows,
|
|
121
163
|
schemaFields: [...new Set(keys)],
|
|
164
|
+
info,
|
|
165
|
+
extra,
|
|
122
166
|
}
|
|
123
167
|
} catch (err) {
|
|
124
168
|
ctx.throw(400, err)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const joiValidator = require("../../../middleware/joi-validator")
|
|
2
|
+
const Joi = require("joi")
|
|
3
|
+
|
|
4
|
+
exports.queryValidation = () => {
|
|
5
|
+
return Joi.object({
|
|
6
|
+
_id: Joi.string(),
|
|
7
|
+
_rev: Joi.string(),
|
|
8
|
+
name: Joi.string().required(),
|
|
9
|
+
fields: Joi.object().required(),
|
|
10
|
+
datasourceId: Joi.string().required(),
|
|
11
|
+
readable: Joi.boolean(),
|
|
12
|
+
parameters: Joi.array().items(
|
|
13
|
+
Joi.object({
|
|
14
|
+
name: Joi.string(),
|
|
15
|
+
default: Joi.string().allow(""),
|
|
16
|
+
})
|
|
17
|
+
),
|
|
18
|
+
queryVerb: Joi.string().allow().required(),
|
|
19
|
+
extra: Joi.object().optional(),
|
|
20
|
+
schema: Joi.object({}).required().unknown(true),
|
|
21
|
+
transformer: Joi.string().optional(),
|
|
22
|
+
flags: Joi.object().optional(),
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
exports.generateQueryValidation = () => {
|
|
27
|
+
// prettier-ignore
|
|
28
|
+
return joiValidator.body(exports.queryValidation())
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
exports.generateQueryPreviewValidation = () => {
|
|
32
|
+
// prettier-ignore
|
|
33
|
+
return joiValidator.body(Joi.object({
|
|
34
|
+
fields: Joi.object().required(),
|
|
35
|
+
queryVerb: Joi.string().allow().required(),
|
|
36
|
+
extra: Joi.object().optional(),
|
|
37
|
+
datasourceId: Joi.string().required(),
|
|
38
|
+
transformer: Joi.string().optional(),
|
|
39
|
+
parameters: Joi.object({}).required().unknown(true)
|
|
40
|
+
}))
|
|
41
|
+
}
|
|
@@ -191,7 +191,8 @@ class QueryBuilder {
|
|
|
191
191
|
}
|
|
192
192
|
if (this.query.equal) {
|
|
193
193
|
build(this.query.equal, (key, value) => {
|
|
194
|
-
if
|
|
194
|
+
// 0 evaluates to false, which means we would return all rows if we don't check it
|
|
195
|
+
if (!value && value !== 0) {
|
|
195
196
|
return null
|
|
196
197
|
}
|
|
197
198
|
return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`
|
|
@@ -50,10 +50,10 @@ exports.validate = async ({ appId, tableId, row, table }) => {
|
|
|
50
50
|
const errors = {}
|
|
51
51
|
for (let fieldName of Object.keys(table.schema)) {
|
|
52
52
|
const constraints = cloneDeep(table.schema[fieldName].constraints)
|
|
53
|
+
const type = table.schema[fieldName].type
|
|
53
54
|
// special case for options, need to always allow unselected (null)
|
|
54
55
|
if (
|
|
55
|
-
|
|
56
|
-
(FieldTypes.OPTIONS || FieldTypes.ARRAY) &&
|
|
56
|
+
(type === FieldTypes.OPTIONS || type === FieldTypes.ARRAY) &&
|
|
57
57
|
constraints.inclusion
|
|
58
58
|
) {
|
|
59
59
|
constraints.inclusion.push(null)
|
|
@@ -61,17 +61,20 @@ exports.validate = async ({ appId, tableId, row, table }) => {
|
|
|
61
61
|
let res
|
|
62
62
|
|
|
63
63
|
// Validate.js doesn't seem to handle array
|
|
64
|
-
if (
|
|
65
|
-
table.schema[fieldName].type === FieldTypes.ARRAY &&
|
|
66
|
-
row[fieldName] &&
|
|
67
|
-
row[fieldName].length
|
|
68
|
-
) {
|
|
64
|
+
if (type === FieldTypes.ARRAY && row[fieldName] && row[fieldName].length) {
|
|
69
65
|
row[fieldName].map(val => {
|
|
70
66
|
if (!constraints.inclusion.includes(val)) {
|
|
71
67
|
errors[fieldName] = "Field not in list"
|
|
72
68
|
}
|
|
73
69
|
})
|
|
74
|
-
} else if (
|
|
70
|
+
} else if (type === FieldTypes.JSON && typeof row[fieldName] === "string") {
|
|
71
|
+
// this should only happen if there is an error
|
|
72
|
+
try {
|
|
73
|
+
JSON.parse(row[fieldName])
|
|
74
|
+
} catch (err) {
|
|
75
|
+
errors[fieldName] = [`Contains invalid JSON`]
|
|
76
|
+
}
|
|
77
|
+
} else if (type === FieldTypes.FORMULA) {
|
|
75
78
|
res = validateJs.single(
|
|
76
79
|
processStringSync(table.schema[fieldName].formula, row),
|
|
77
80
|
constraints
|
|
@@ -2,6 +2,7 @@ const CouchDB = require("../../db")
|
|
|
2
2
|
const {
|
|
3
3
|
generateUserMetadataID,
|
|
4
4
|
getUserMetadataParams,
|
|
5
|
+
generateUserFlagID,
|
|
5
6
|
} = require("../../db/utils")
|
|
6
7
|
const { InternalTables } = require("../../db/utils")
|
|
7
8
|
const { getGlobalUsers, getRawGlobalUser } = require("../../utilities/global")
|
|
@@ -195,3 +196,35 @@ exports.destroyMetadata = async function (ctx) {
|
|
|
195
196
|
exports.findMetadata = async function (ctx) {
|
|
196
197
|
ctx.body = await getFullUser(ctx, ctx.params.id)
|
|
197
198
|
}
|
|
199
|
+
|
|
200
|
+
exports.setFlag = async function (ctx) {
|
|
201
|
+
const userId = ctx.user._id
|
|
202
|
+
const { flag, value } = ctx.request.body
|
|
203
|
+
if (!flag) {
|
|
204
|
+
ctx.throw(400, "Must supply a 'flag' field in request body.")
|
|
205
|
+
}
|
|
206
|
+
const flagDocId = generateUserFlagID(userId)
|
|
207
|
+
const db = new CouchDB(ctx.appId)
|
|
208
|
+
let doc
|
|
209
|
+
try {
|
|
210
|
+
doc = await db.get(flagDocId)
|
|
211
|
+
} catch (err) {
|
|
212
|
+
doc = { _id: flagDocId }
|
|
213
|
+
}
|
|
214
|
+
doc[flag] = value || true
|
|
215
|
+
await db.put(doc)
|
|
216
|
+
ctx.body = { message: "Flag set successfully" }
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
exports.getFlags = async function (ctx) {
|
|
220
|
+
const userId = ctx.user._id
|
|
221
|
+
const docId = generateUserFlagID(userId)
|
|
222
|
+
const db = new CouchDB(ctx.appId)
|
|
223
|
+
let doc
|
|
224
|
+
try {
|
|
225
|
+
doc = await db.get(docId)
|
|
226
|
+
} catch (err) {
|
|
227
|
+
doc = { _id: docId }
|
|
228
|
+
}
|
|
229
|
+
ctx.body = doc
|
|
230
|
+
}
|
|
@@ -65,6 +65,10 @@ exports.buildSchema = async ctx => {
|
|
|
65
65
|
let automation = await db.get(webhook.action.target)
|
|
66
66
|
const autoOutputs = automation.definition.trigger.schema.outputs
|
|
67
67
|
let properties = webhook.bodySchema.properties
|
|
68
|
+
// reset webhook outputs
|
|
69
|
+
autoOutputs.properties = {
|
|
70
|
+
body: autoOutputs.properties.body,
|
|
71
|
+
}
|
|
68
72
|
for (let prop of Object.keys(properties)) {
|
|
69
73
|
autoOutputs.properties[prop] = {
|
|
70
74
|
type: properties[prop].type,
|
package/src/api/routes/query.js
CHANGED
|
@@ -1,53 +1,23 @@
|
|
|
1
1
|
const Router = require("@koa/router")
|
|
2
2
|
const queryController = require("../controllers/query")
|
|
3
3
|
const authorized = require("../../middleware/authorized")
|
|
4
|
-
const Joi = require("joi")
|
|
5
4
|
const {
|
|
6
5
|
PermissionLevels,
|
|
7
6
|
PermissionTypes,
|
|
8
7
|
BUILDER,
|
|
9
8
|
} = require("@budibase/auth/permissions")
|
|
10
|
-
const joiValidator = require("../../middleware/joi-validator")
|
|
11
9
|
const {
|
|
12
10
|
bodyResource,
|
|
13
11
|
bodySubResource,
|
|
14
12
|
paramResource,
|
|
15
13
|
} = require("../../middleware/resourceId")
|
|
14
|
+
const {
|
|
15
|
+
generateQueryPreviewValidation,
|
|
16
|
+
generateQueryValidation,
|
|
17
|
+
} = require("../controllers/query/validation")
|
|
16
18
|
|
|
17
19
|
const router = Router()
|
|
18
20
|
|
|
19
|
-
function generateQueryValidation() {
|
|
20
|
-
// prettier-ignore
|
|
21
|
-
return joiValidator.body(Joi.object({
|
|
22
|
-
_id: Joi.string(),
|
|
23
|
-
_rev: Joi.string(),
|
|
24
|
-
name: Joi.string().required(),
|
|
25
|
-
fields: Joi.object().required(),
|
|
26
|
-
datasourceId: Joi.string().required(),
|
|
27
|
-
readable: Joi.boolean(),
|
|
28
|
-
parameters: Joi.array().items(Joi.object({
|
|
29
|
-
name: Joi.string(),
|
|
30
|
-
default: Joi.string().allow(""),
|
|
31
|
-
})),
|
|
32
|
-
queryVerb: Joi.string().allow().required(),
|
|
33
|
-
extra: Joi.object().optional(),
|
|
34
|
-
schema: Joi.object({}).required().unknown(true),
|
|
35
|
-
transformer: Joi.string().optional(),
|
|
36
|
-
}))
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function generateQueryPreviewValidation() {
|
|
40
|
-
// prettier-ignore
|
|
41
|
-
return joiValidator.body(Joi.object({
|
|
42
|
-
fields: Joi.object().required(),
|
|
43
|
-
queryVerb: Joi.string().allow().required(),
|
|
44
|
-
extra: Joi.object().optional(),
|
|
45
|
-
datasourceId: Joi.string().required(),
|
|
46
|
-
transformer: Joi.string().optional(),
|
|
47
|
-
parameters: Joi.object({}).required().unknown(true)
|
|
48
|
-
}))
|
|
49
|
-
}
|
|
50
|
-
|
|
51
21
|
router
|
|
52
22
|
.get("/api/queries", authorized(BUILDER), queryController.fetch)
|
|
53
23
|
.post(
|
|
@@ -57,6 +27,7 @@ router
|
|
|
57
27
|
generateQueryValidation(),
|
|
58
28
|
queryController.save
|
|
59
29
|
)
|
|
30
|
+
.post("/api/queries/import", authorized(BUILDER), queryController.import)
|
|
60
31
|
.post(
|
|
61
32
|
"/api/queries/preview",
|
|
62
33
|
bodyResource("datasourceId"),
|
package/src/api/routes/user.js
CHANGED
|
@@ -39,5 +39,15 @@ router
|
|
|
39
39
|
authorized(PermissionTypes.USER, PermissionLevels.WRITE),
|
|
40
40
|
controller.syncUser
|
|
41
41
|
)
|
|
42
|
+
.post(
|
|
43
|
+
"/api/users/flags",
|
|
44
|
+
authorized(PermissionTypes.USER, PermissionLevels.WRITE),
|
|
45
|
+
controller.setFlag
|
|
46
|
+
)
|
|
47
|
+
.get(
|
|
48
|
+
"/api/users/flags",
|
|
49
|
+
authorized(PermissionTypes.USER, PermissionLevels.READ),
|
|
50
|
+
controller.getFlags
|
|
51
|
+
)
|
|
42
52
|
|
|
43
53
|
module.exports = router
|
|
@@ -13,12 +13,11 @@ const RequestType = {
|
|
|
13
13
|
const BODY_REQUESTS = [RequestType.POST, RequestType.PUT, RequestType.PATCH]
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
* is complex and maybe better to be opinionated here.
|
|
18
|
-
* GET/DELETE requests cannot handle body elements so they will not be sent if configured.
|
|
16
|
+
* NOTE: this functionality is deprecated - it no longer should be used.
|
|
19
17
|
*/
|
|
20
18
|
|
|
21
19
|
exports.definition = {
|
|
20
|
+
deprecated: true,
|
|
22
21
|
name: "Outgoing webhook",
|
|
23
22
|
tagline: "Send a {{inputs.requestMethod}} request",
|
|
24
23
|
icon: "Send",
|