@budibase/server 0.9.184 → 0.9.185-alpha.11
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/Dockerfile +1 -1
- package/__mocks__/mssql.ts +1 -1
- package/__mocks__/pg.ts +3 -0
- package/builder/assets/bb-space-man.5be51a45.svg +290 -0
- package/builder/assets/index.053c6f7a.js +1321 -0
- package/builder/assets/index.4a7c5636.css +1 -0
- package/builder/assets/vendor.470042a4.js +152 -0
- package/builder/assets/vendor.5e1fe644.css +1 -0
- package/builder/index.html +4 -4
- package/coverage/clover.xml +1357 -959
- package/coverage/coverage-final.json +91 -87
- package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
- package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
- package/coverage/lcov-report/api/controllers/application.js.html +65 -14
- package/coverage/lcov-report/api/controllers/auth.js.html +19 -10
- package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
- 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 +147 -27
- package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
- package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
- package/coverage/lcov-report/api/controllers/index.html +90 -90
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
- package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
- package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
- package/coverage/lcov-report/api/controllers/query.js.html +53 -209
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
- package/coverage/lcov-report/api/controllers/row/external.js.html +12 -6
- package/coverage/lcov-report/api/controllers/row/index.html +26 -26
- package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/utils.js.html +21 -30
- package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
- package/coverage/lcov-report/api/controllers/script.js.html +3 -3
- package/coverage/lcov-report/api/controllers/table/external.js.html +980 -0
- package/coverage/lcov-report/api/controllers/table/index.html +56 -26
- package/coverage/lcov-report/api/controllers/table/index.js.html +80 -350
- package/coverage/lcov-report/api/controllers/table/internal.js.html +545 -0
- package/coverage/lcov-report/api/controllers/table/utils.js.html +172 -49
- package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
- package/coverage/lcov-report/api/controllers/user.js.html +390 -33
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +9 -9
- package/coverage/lcov-report/api/controllers/view/index.js.html +5 -5
- package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
- package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
- 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 +2 -2
- package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +4 -4
- 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 +5 -2
- 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 +2 -2
- package/coverage/lcov-report/api/routes/table.js.html +35 -2
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +17 -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 +2 -2
- package/coverage/lcov-report/automations/automationUtils.js.html +3 -3
- package/coverage/lcov-report/automations/bullboard.js.html +71 -20
- package/coverage/lcov-report/automations/index.html +33 -48
- package/coverage/lcov-report/automations/index.js.html +2 -2
- 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 +3 -3
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +14 -14
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
- package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
- 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 +7 -7
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
- package/coverage/lcov-report/automations/triggers.js.html +22 -10
- package/coverage/lcov-report/automations/utils.js.html +42 -12
- package/coverage/lcov-report/constants/index.html +5 -5
- package/coverage/lcov-report/constants/index.js.html +49 -4
- 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 +2 -2
- package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
- package/coverage/lcov-report/db/index.html +2 -2
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
- package/coverage/lcov-report/db/linkedRows/index.html +10 -10
- package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
- package/coverage/lcov-report/db/newid.js.html +1 -1
- package/coverage/lcov-report/db/utils.js.html +1 -1
- package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
- package/coverage/lcov-report/events/index.html +6 -6
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +5 -5
- package/coverage/lcov-report/index.html +98 -83
- 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 +2 -2
- package/coverage/lcov-report/middleware/authorized.js.html +11 -8
- package/coverage/lcov-report/middleware/builder.js.html +16 -7
- package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
- package/coverage/lcov-report/middleware/index.html +23 -23
- package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
- package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
- package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
- package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +83 -32
- package/coverage/lcov-report/threads/index.html +141 -0
- package/coverage/lcov-report/threads/index.js.html +260 -0
- package/coverage/lcov-report/threads/query.js.html +269 -0
- 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 +144 -15
- package/coverage/lcov-report/utilities/global.js.html +26 -11
- package/coverage/lcov-report/utilities/index.html +49 -49
- package/coverage/lcov-report/utilities/index.js.html +65 -17
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
- package/coverage/lcov-report/utilities/queue/index.html +14 -14
- 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 +4 -4
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
- package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
- package/coverage/lcov-report/utilities/security.js.html +3 -3
- 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 +5 -5
- package/coverage/lcov.info +2301 -1599
- package/dist/api/controllers/application.js +16 -2
- package/dist/api/controllers/auth.js +3 -3
- package/dist/api/controllers/datasource.js +47 -16
- package/dist/api/controllers/deploy/index.js +2 -0
- package/dist/api/controllers/dev.js +4 -1
- package/dist/api/controllers/query.js +30 -58
- package/dist/api/controllers/row/ExternalRequest.js +37 -14
- package/dist/api/controllers/row/external.js +1 -0
- package/dist/api/controllers/row/utils.js +6 -12
- package/dist/api/controllers/static/index.js +1 -1
- package/dist/api/controllers/table/external.js +242 -0
- package/dist/api/controllers/table/index.js +49 -123
- package/dist/api/controllers/table/internal.js +150 -0
- package/dist/api/controllers/table/utils.js +62 -28
- package/dist/api/controllers/user.js +123 -11
- package/dist/api/routes/query.js +1 -1
- package/dist/api/routes/table.js +7 -1
- package/dist/api/routes/user.js +2 -1
- package/dist/app.js +2 -11
- package/dist/automations/bullboard.js +37 -10
- package/dist/automations/triggers.js +7 -3
- package/dist/automations/utils.js +11 -2
- package/dist/constants/index.js +13 -0
- package/dist/definitions/datasource.js +4 -0
- package/dist/integrations/base/IntegrationBase.js +2 -0
- package/dist/integrations/base/datasourcePlus.js +2 -0
- package/dist/integrations/base/sql.js +334 -180
- package/dist/integrations/base/sqlTable.js +143 -0
- package/dist/integrations/base/utils.js +30 -0
- package/dist/integrations/microsoftSqlServer.js +117 -9
- package/dist/integrations/mysql.js +14 -84
- package/dist/integrations/postgres.js +35 -28
- package/dist/integrations/utils.js +56 -9
- package/dist/middleware/authorized.js +2 -1
- package/dist/middleware/builder.js +4 -1
- package/dist/package.json +7 -6
- package/dist/tests/utilities/TestConfiguration.js +2 -1
- package/dist/{automations/thread.js → threads/automation.js} +23 -7
- package/dist/threads/index.js +58 -0
- package/dist/threads/query.js +61 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/csvParser.js +46 -5
- package/dist/utilities/global.js +6 -2
- package/dist/utilities/index.js +18 -2
- package/dist/utilities/queue/inMemoryQueue.js +8 -0
- package/dist/utilities/scriptRunner.js +4 -1
- package/package.json +8 -7
- package/scripts/integrations/mssql/data/Dockerfile +9 -0
- package/scripts/integrations/mssql/data/entrypoint.sh +24 -0
- package/scripts/integrations/mssql/data/setup.sql +54 -0
- package/scripts/integrations/mssql/docker-compose.yaml +12 -0
- package/scripts/integrations/mssql/reset.sh +3 -0
- package/scripts/likeCypress.ts +33 -0
- package/src/api/controllers/application.js +19 -2
- package/src/api/controllers/auth.js +3 -0
- package/src/api/controllers/datasource.js +56 -16
- package/src/api/controllers/deploy/index.js +2 -0
- package/src/api/controllers/dev.js +4 -1
- package/src/api/controllers/query.js +29 -81
- package/src/api/controllers/row/ExternalRequest.ts +47 -16
- package/src/api/controllers/row/external.js +2 -0
- package/src/api/controllers/row/utils.js +8 -11
- package/src/api/controllers/static/index.js +1 -1
- package/src/api/controllers/table/external.js +300 -0
- package/src/api/controllers/table/index.js +47 -137
- package/src/api/controllers/table/internal.js +155 -0
- package/src/api/controllers/table/utils.js +74 -33
- package/src/api/controllers/user.js +132 -13
- package/src/api/routes/query.js +1 -0
- package/src/api/routes/table.js +11 -0
- package/src/api/routes/tests/datasource.spec.js +2 -2
- package/src/api/routes/tests/misc.spec.js +5 -1
- package/src/api/routes/tests/query.spec.js +0 -1
- package/src/api/routes/user.js +5 -0
- package/src/app.ts +2 -10
- package/src/automations/bullboard.js +28 -11
- package/src/automations/tests/automation.spec.js +3 -4
- package/src/automations/triggers.js +7 -3
- package/src/automations/utils.js +12 -2
- package/src/constants/index.js +15 -0
- package/src/definitions/common.ts +7 -1
- package/src/definitions/datasource.ts +9 -3
- package/src/integrations/airtable.ts +2 -1
- package/src/integrations/arangodb.ts +2 -1
- package/src/integrations/base/IntegrationBase.ts +6 -0
- package/src/integrations/base/datasourcePlus.ts +9 -0
- package/src/integrations/base/sql.ts +359 -222
- package/src/integrations/base/sqlTable.ts +180 -0
- package/src/integrations/base/utils.ts +22 -0
- package/src/integrations/couchdb.ts +2 -1
- package/src/integrations/dynamodb.ts +2 -1
- package/src/integrations/elasticsearch.ts +2 -1
- package/src/integrations/microsoftSqlServer.ts +145 -13
- package/src/integrations/mongodb.ts +2 -1
- package/src/integrations/mysql.ts +20 -94
- package/src/integrations/postgres.ts +45 -35
- package/src/integrations/rest.ts +2 -1
- package/src/integrations/s3.ts +2 -1
- package/src/integrations/tests/microsoftSqlServer.spec.js +22 -15
- package/src/integrations/tests/postgres.spec.js +4 -0
- package/src/integrations/utils.ts +60 -8
- package/src/middleware/authorized.js +2 -1
- package/src/middleware/builder.js +4 -1
- package/src/tests/utilities/TestConfiguration.js +2 -1
- package/src/{automations/thread.js → threads/automation.js} +24 -7
- package/src/threads/index.js +60 -0
- package/src/threads/query.js +63 -0
- package/src/utilities/csvParser.js +48 -5
- package/src/utilities/global.js +7 -2
- package/src/utilities/index.js +18 -2
- package/src/utilities/queue/inMemoryQueue.js +7 -0
- package/src/utilities/scriptRunner.js +4 -1
- package/src/utilities/tests/__snapshots__/csvParser.spec.js.snap +0 -6
- package/src/utilities/tests/csvParser.spec.js +3 -0
- package/tsconfig.json +1 -1
- package/builder/assets/index.34964222.js +0 -201
- package/builder/assets/index.7469e1e4.css +0 -29
- package/builder/assets/vendor.278a305c.js +0 -9
- package/builder/assets/vendor.d75d5eb7.css +0 -1
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
const CouchDB = require("../../../db")
|
|
2
|
-
const
|
|
2
|
+
const internal = require("./internal")
|
|
3
|
+
const external = require("./external")
|
|
3
4
|
const csvParser = require("../../../utilities/csvParser")
|
|
5
|
+
const { isExternalTable } = require("../../../integrations/utils")
|
|
4
6
|
const {
|
|
5
|
-
getRowParams,
|
|
6
7
|
getTableParams,
|
|
7
|
-
generateTableID,
|
|
8
8
|
getDatasourceParams,
|
|
9
9
|
BudibaseInternalDB,
|
|
10
10
|
} = require("../../../db/utils")
|
|
11
|
-
const {
|
|
12
|
-
const { TableSaveFunctions, getTable } = require("./utils")
|
|
11
|
+
const { getTable } = require("./utils")
|
|
13
12
|
|
|
13
|
+
function pickApi({ tableId, table }) {
|
|
14
|
+
if (table && !tableId) {
|
|
15
|
+
tableId = table._id
|
|
16
|
+
}
|
|
17
|
+
if (table && table.type === "external") {
|
|
18
|
+
return external
|
|
19
|
+
} else if (tableId && isExternalTable(tableId)) {
|
|
20
|
+
return external
|
|
21
|
+
}
|
|
22
|
+
return internal
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// covers both internal and external
|
|
14
26
|
exports.fetch = async function (ctx) {
|
|
15
27
|
const db = new CouchDB(ctx.appId)
|
|
16
28
|
|
|
@@ -50,147 +62,45 @@ exports.find = async function (ctx) {
|
|
|
50
62
|
|
|
51
63
|
exports.save = async function (ctx) {
|
|
52
64
|
const appId = ctx.appId
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
let tableToSave = {
|
|
56
|
-
type: "table",
|
|
57
|
-
_id: generateTableID(),
|
|
58
|
-
views: {},
|
|
59
|
-
...rest,
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// if the table obj had an _id then it will have been retrieved
|
|
63
|
-
let oldTable
|
|
64
|
-
if (ctx.request.body && ctx.request.body._id) {
|
|
65
|
-
oldTable = await db.get(ctx.request.body._id)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// saving a table is a complex operation, involving many different steps, this
|
|
69
|
-
// has been broken out into a utility to make it more obvious/easier to manipulate
|
|
70
|
-
const tableSaveFunctions = new TableSaveFunctions({
|
|
71
|
-
db,
|
|
72
|
-
ctx,
|
|
73
|
-
oldTable,
|
|
74
|
-
dataImport,
|
|
75
|
-
})
|
|
76
|
-
tableToSave = await tableSaveFunctions.before(tableToSave)
|
|
77
|
-
|
|
78
|
-
// make sure that types don't change of a column, have to remove
|
|
79
|
-
// the column if you want to change the type
|
|
80
|
-
if (oldTable && oldTable.schema) {
|
|
81
|
-
for (let propKey of Object.keys(tableToSave.schema)) {
|
|
82
|
-
let column = tableToSave.schema[propKey]
|
|
83
|
-
let oldColumn = oldTable.schema[propKey]
|
|
84
|
-
if (oldColumn && oldColumn.type === "internal") {
|
|
85
|
-
oldColumn.type = "auto"
|
|
86
|
-
}
|
|
87
|
-
if (oldColumn && oldColumn.type !== column.type) {
|
|
88
|
-
ctx.throw(400, "Cannot change the type of a column")
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Don't rename if the name is the same
|
|
94
|
-
let { _rename } = tableToSave
|
|
95
|
-
/* istanbul ignore next */
|
|
96
|
-
if (_rename && _rename.old === _rename.updated) {
|
|
97
|
-
_rename = null
|
|
98
|
-
delete tableToSave._rename
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// rename row fields when table column is renamed
|
|
102
|
-
/* istanbul ignore next */
|
|
103
|
-
if (_rename && tableToSave.schema[_rename.updated].type === FieldTypes.LINK) {
|
|
104
|
-
ctx.throw(400, "Cannot rename a linked column.")
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
tableToSave = await tableSaveFunctions.mid(tableToSave)
|
|
108
|
-
|
|
109
|
-
// update schema of non-statistics views when new columns are added
|
|
110
|
-
for (let view in tableToSave.views) {
|
|
111
|
-
const tableView = tableToSave.views[view]
|
|
112
|
-
if (!tableView) continue
|
|
113
|
-
|
|
114
|
-
if (tableView.schema.group || tableView.schema.field) continue
|
|
115
|
-
tableView.schema = tableToSave.schema
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// update linked rows
|
|
119
|
-
try {
|
|
120
|
-
const linkResp = await linkRows.updateLinks({
|
|
121
|
-
appId,
|
|
122
|
-
eventType: oldTable
|
|
123
|
-
? linkRows.EventType.TABLE_UPDATED
|
|
124
|
-
: linkRows.EventType.TABLE_SAVE,
|
|
125
|
-
table: tableToSave,
|
|
126
|
-
oldTable: oldTable,
|
|
127
|
-
})
|
|
128
|
-
if (linkResp != null && linkResp._rev) {
|
|
129
|
-
tableToSave._rev = linkResp._rev
|
|
130
|
-
}
|
|
131
|
-
} catch (err) {
|
|
132
|
-
ctx.throw(400, err)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// don't perform any updates until relationships have been
|
|
136
|
-
// checked by the updateLinks function
|
|
137
|
-
const updatedRows = tableSaveFunctions.getUpdatedRows()
|
|
138
|
-
if (updatedRows && updatedRows.length !== 0) {
|
|
139
|
-
await db.bulkDocs(updatedRows)
|
|
140
|
-
}
|
|
141
|
-
const result = await db.put(tableToSave)
|
|
142
|
-
tableToSave._rev = result.rev
|
|
143
|
-
|
|
144
|
-
tableToSave = await tableSaveFunctions.after(tableToSave)
|
|
145
|
-
|
|
146
|
-
ctx.eventEmitter &&
|
|
147
|
-
ctx.eventEmitter.emitTable(`table:save`, appId, tableToSave)
|
|
148
|
-
|
|
65
|
+
const table = ctx.request.body
|
|
66
|
+
const savedTable = await pickApi({ table }).save(ctx)
|
|
149
67
|
ctx.status = 200
|
|
150
|
-
ctx.message = `Table ${
|
|
151
|
-
ctx.
|
|
68
|
+
ctx.message = `Table ${table.name} saved successfully.`
|
|
69
|
+
ctx.eventEmitter &&
|
|
70
|
+
ctx.eventEmitter.emitTable(`table:save`, appId, savedTable)
|
|
71
|
+
ctx.body = savedTable
|
|
152
72
|
}
|
|
153
73
|
|
|
154
74
|
exports.destroy = async function (ctx) {
|
|
155
75
|
const appId = ctx.appId
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
// Delete all rows for that table
|
|
160
|
-
const rows = await db.allDocs(
|
|
161
|
-
getRowParams(ctx.params.tableId, null, {
|
|
162
|
-
include_docs: true,
|
|
163
|
-
})
|
|
164
|
-
)
|
|
165
|
-
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
|
|
166
|
-
|
|
167
|
-
// update linked rows
|
|
168
|
-
await linkRows.updateLinks({
|
|
169
|
-
appId,
|
|
170
|
-
eventType: linkRows.EventType.TABLE_DELETE,
|
|
171
|
-
table: tableToDelete,
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
// don't remove the table itself until very end
|
|
175
|
-
await db.remove(tableToDelete)
|
|
176
|
-
|
|
177
|
-
// remove table search index
|
|
178
|
-
const currentIndexes = await db.getIndexes()
|
|
179
|
-
const existingIndex = currentIndexes.indexes.find(
|
|
180
|
-
existing => existing.name === `search:${ctx.params.tableId}`
|
|
181
|
-
)
|
|
182
|
-
if (existingIndex) {
|
|
183
|
-
await db.deleteIndex(existingIndex)
|
|
184
|
-
}
|
|
185
|
-
|
|
76
|
+
const tableId = ctx.params.tableId
|
|
77
|
+
const deletedTable = await pickApi({ tableId }).destroy(ctx)
|
|
186
78
|
ctx.eventEmitter &&
|
|
187
|
-
ctx.eventEmitter.emitTable(`table:delete`, appId,
|
|
79
|
+
ctx.eventEmitter.emitTable(`table:delete`, appId, deletedTable)
|
|
188
80
|
ctx.status = 200
|
|
189
|
-
ctx.body = { message: `Table ${
|
|
81
|
+
ctx.body = { message: `Table ${tableId} deleted.` }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
exports.bulkImport = async function (ctx) {
|
|
85
|
+
const tableId = ctx.params.tableId
|
|
86
|
+
await pickApi({ tableId }).bulkImport(ctx)
|
|
87
|
+
// right now we don't trigger anything for bulk import because it
|
|
88
|
+
// can only be done in the builder, but in the future we may need to
|
|
89
|
+
// think about events for bulk items
|
|
90
|
+
ctx.status = 200
|
|
91
|
+
ctx.body = { message: `Bulk rows created.` }
|
|
190
92
|
}
|
|
191
93
|
|
|
192
94
|
exports.validateCSVSchema = async function (ctx) {
|
|
193
|
-
|
|
194
|
-
const
|
|
95
|
+
// tableId being specified means its an import to an existing table
|
|
96
|
+
const { csvString, schema = {}, tableId } = ctx.request.body
|
|
97
|
+
let existingTable
|
|
98
|
+
if (tableId) {
|
|
99
|
+
existingTable = await getTable(ctx.appId, tableId)
|
|
100
|
+
}
|
|
101
|
+
let result = await csvParser.parse(csvString, schema)
|
|
102
|
+
if (existingTable) {
|
|
103
|
+
result = csvParser.updateSchema({ schema: result, existingTable })
|
|
104
|
+
}
|
|
195
105
|
ctx.body = { schema: result }
|
|
196
106
|
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
const CouchDB = require("../../../db")
|
|
2
|
+
const linkRows = require("../../../db/linkedRows")
|
|
3
|
+
const { getRowParams, generateTableID } = require("../../../db/utils")
|
|
4
|
+
const { FieldTypes } = require("../../../constants")
|
|
5
|
+
const {
|
|
6
|
+
TableSaveFunctions,
|
|
7
|
+
hasTypeChanged,
|
|
8
|
+
getTable,
|
|
9
|
+
handleDataImport,
|
|
10
|
+
} = require("./utils")
|
|
11
|
+
|
|
12
|
+
exports.save = async function (ctx) {
|
|
13
|
+
const appId = ctx.appId
|
|
14
|
+
const db = new CouchDB(appId)
|
|
15
|
+
const { dataImport, ...rest } = ctx.request.body
|
|
16
|
+
let tableToSave = {
|
|
17
|
+
type: "table",
|
|
18
|
+
_id: generateTableID(),
|
|
19
|
+
views: {},
|
|
20
|
+
...rest,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// if the table obj had an _id then it will have been retrieved
|
|
24
|
+
let oldTable
|
|
25
|
+
if (ctx.request.body && ctx.request.body._id) {
|
|
26
|
+
oldTable = await db.get(ctx.request.body._id)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (hasTypeChanged(tableToSave, oldTable)) {
|
|
30
|
+
ctx.throw(400, "A column type has changed.")
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// saving a table is a complex operation, involving many different steps, this
|
|
34
|
+
// has been broken out into a utility to make it more obvious/easier to manipulate
|
|
35
|
+
const tableSaveFunctions = new TableSaveFunctions({
|
|
36
|
+
db,
|
|
37
|
+
ctx,
|
|
38
|
+
oldTable,
|
|
39
|
+
dataImport,
|
|
40
|
+
})
|
|
41
|
+
tableToSave = await tableSaveFunctions.before(tableToSave)
|
|
42
|
+
|
|
43
|
+
// make sure that types don't change of a column, have to remove
|
|
44
|
+
// the column if you want to change the type
|
|
45
|
+
if (oldTable && oldTable.schema) {
|
|
46
|
+
for (let propKey of Object.keys(tableToSave.schema)) {
|
|
47
|
+
let column = tableToSave.schema[propKey]
|
|
48
|
+
let oldColumn = oldTable.schema[propKey]
|
|
49
|
+
if (oldColumn && oldColumn.type === "internal") {
|
|
50
|
+
oldColumn.type = "auto"
|
|
51
|
+
}
|
|
52
|
+
if (oldColumn && oldColumn.type !== column.type) {
|
|
53
|
+
ctx.throw(400, "Cannot change the type of a column")
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Don't rename if the name is the same
|
|
59
|
+
let { _rename } = tableToSave
|
|
60
|
+
/* istanbul ignore next */
|
|
61
|
+
if (_rename && _rename.old === _rename.updated) {
|
|
62
|
+
_rename = null
|
|
63
|
+
delete tableToSave._rename
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// rename row fields when table column is renamed
|
|
67
|
+
/* istanbul ignore next */
|
|
68
|
+
if (_rename && tableToSave.schema[_rename.updated].type === FieldTypes.LINK) {
|
|
69
|
+
ctx.throw(400, "Cannot rename a linked column.")
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
tableToSave = await tableSaveFunctions.mid(tableToSave)
|
|
73
|
+
|
|
74
|
+
// update schema of non-statistics views when new columns are added
|
|
75
|
+
for (let view in tableToSave.views) {
|
|
76
|
+
const tableView = tableToSave.views[view]
|
|
77
|
+
if (!tableView) continue
|
|
78
|
+
|
|
79
|
+
if (tableView.schema.group || tableView.schema.field) continue
|
|
80
|
+
tableView.schema = tableToSave.schema
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// update linked rows
|
|
84
|
+
try {
|
|
85
|
+
const linkResp = await linkRows.updateLinks({
|
|
86
|
+
appId,
|
|
87
|
+
eventType: oldTable
|
|
88
|
+
? linkRows.EventType.TABLE_UPDATED
|
|
89
|
+
: linkRows.EventType.TABLE_SAVE,
|
|
90
|
+
table: tableToSave,
|
|
91
|
+
oldTable: oldTable,
|
|
92
|
+
})
|
|
93
|
+
if (linkResp != null && linkResp._rev) {
|
|
94
|
+
tableToSave._rev = linkResp._rev
|
|
95
|
+
}
|
|
96
|
+
} catch (err) {
|
|
97
|
+
ctx.throw(400, err)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// don't perform any updates until relationships have been
|
|
101
|
+
// checked by the updateLinks function
|
|
102
|
+
const updatedRows = tableSaveFunctions.getUpdatedRows()
|
|
103
|
+
if (updatedRows && updatedRows.length !== 0) {
|
|
104
|
+
await db.bulkDocs(updatedRows)
|
|
105
|
+
}
|
|
106
|
+
const result = await db.put(tableToSave)
|
|
107
|
+
tableToSave._rev = result.rev
|
|
108
|
+
|
|
109
|
+
tableToSave = await tableSaveFunctions.after(tableToSave)
|
|
110
|
+
|
|
111
|
+
return tableToSave
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
exports.destroy = async function (ctx) {
|
|
115
|
+
const appId = ctx.appId
|
|
116
|
+
const db = new CouchDB(appId)
|
|
117
|
+
const tableToDelete = await db.get(ctx.params.tableId)
|
|
118
|
+
|
|
119
|
+
// Delete all rows for that table
|
|
120
|
+
const rows = await db.allDocs(
|
|
121
|
+
getRowParams(ctx.params.tableId, null, {
|
|
122
|
+
include_docs: true,
|
|
123
|
+
})
|
|
124
|
+
)
|
|
125
|
+
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
|
|
126
|
+
|
|
127
|
+
// update linked rows
|
|
128
|
+
await linkRows.updateLinks({
|
|
129
|
+
appId,
|
|
130
|
+
eventType: linkRows.EventType.TABLE_DELETE,
|
|
131
|
+
table: tableToDelete,
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
// don't remove the table itself until very end
|
|
135
|
+
await db.remove(tableToDelete)
|
|
136
|
+
|
|
137
|
+
// remove table search index
|
|
138
|
+
const currentIndexes = await db.getIndexes()
|
|
139
|
+
const existingIndex = currentIndexes.indexes.find(
|
|
140
|
+
existing => existing.name === `search:${ctx.params.tableId}`
|
|
141
|
+
)
|
|
142
|
+
if (existingIndex) {
|
|
143
|
+
await db.deleteIndex(existingIndex)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return tableToDelete
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
exports.bulkImport = async function (ctx) {
|
|
150
|
+
const appId = ctx.appId
|
|
151
|
+
const table = await getTable(appId, ctx.params.tableId)
|
|
152
|
+
const { dataImport } = ctx.request.body
|
|
153
|
+
await handleDataImport(appId, ctx.user, table, dataImport)
|
|
154
|
+
return table
|
|
155
|
+
}
|
|
@@ -8,7 +8,7 @@ const {
|
|
|
8
8
|
const { isEqual } = require("lodash/fp")
|
|
9
9
|
const { AutoFieldSubTypes, FieldTypes } = require("../../../constants")
|
|
10
10
|
const { inputProcessing } = require("../../../utilities/rowProcessor")
|
|
11
|
-
const { USERS_TABLE_SCHEMA } = require("../../../constants")
|
|
11
|
+
const { USERS_TABLE_SCHEMA, SwitchableTypes } = require("../../../constants")
|
|
12
12
|
const {
|
|
13
13
|
isExternalTable,
|
|
14
14
|
breakExternalTableId,
|
|
@@ -72,43 +72,47 @@ exports.makeSureTableUpToDate = (table, tableToSave) => {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
exports.handleDataImport = async (appId, user, table, dataImport) => {
|
|
75
|
+
if (!dataImport || !dataImport.csvString) {
|
|
76
|
+
return table
|
|
77
|
+
}
|
|
75
78
|
const db = new CouchDB(appId)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
// check whether the options need to be updated for inclusion as part of the data import
|
|
93
|
-
if (
|
|
94
|
-
schema.type === FieldTypes.OPTIONS &&
|
|
95
|
-
(!schema.constraints.inclusion ||
|
|
96
|
-
schema.constraints.inclusion.indexOf(row[fieldName]) === -1)
|
|
97
|
-
) {
|
|
98
|
-
schema.constraints.inclusion = [
|
|
99
|
-
...schema.constraints.inclusion,
|
|
100
|
-
row[fieldName],
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
}
|
|
79
|
+
// Populate the table with rows imported from CSV in a bulk update
|
|
80
|
+
const data = await csvParser.transform({
|
|
81
|
+
...dataImport,
|
|
82
|
+
existingTable: table,
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
let finalData = []
|
|
86
|
+
for (let i = 0; i < data.length; i++) {
|
|
87
|
+
let row = data[i]
|
|
88
|
+
row._id = generateRowID(table._id)
|
|
89
|
+
row.tableId = table._id
|
|
90
|
+
const processed = inputProcessing(user, table, row, {
|
|
91
|
+
noAutoRelationships: true,
|
|
92
|
+
})
|
|
93
|
+
table = processed.table
|
|
94
|
+
row = processed.row
|
|
104
95
|
|
|
105
|
-
|
|
96
|
+
for (let [fieldName, schema] of Object.entries(table.schema)) {
|
|
97
|
+
// check whether the options need to be updated for inclusion as part of the data import
|
|
98
|
+
if (
|
|
99
|
+
schema.type === FieldTypes.OPTIONS &&
|
|
100
|
+
(!schema.constraints.inclusion ||
|
|
101
|
+
schema.constraints.inclusion.indexOf(row[fieldName]) === -1)
|
|
102
|
+
) {
|
|
103
|
+
schema.constraints.inclusion = [
|
|
104
|
+
...schema.constraints.inclusion,
|
|
105
|
+
row[fieldName],
|
|
106
|
+
]
|
|
107
|
+
}
|
|
106
108
|
}
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
let response = await db.put(table)
|
|
110
|
-
table._rev = response._rev
|
|
110
|
+
finalData.push(row)
|
|
111
111
|
}
|
|
112
|
+
|
|
113
|
+
await db.bulkDocs(finalData)
|
|
114
|
+
let response = await db.put(table)
|
|
115
|
+
table._rev = response._rev
|
|
112
116
|
return table
|
|
113
117
|
}
|
|
114
118
|
|
|
@@ -315,4 +319,41 @@ exports.checkForViewUpdates = async (db, table, rename, deletedColumns) => {
|
|
|
315
319
|
}
|
|
316
320
|
}
|
|
317
321
|
|
|
322
|
+
exports.generateForeignKey = (column, relatedTable) => {
|
|
323
|
+
return `fk_${relatedTable.name}_${column.fieldName}`
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
exports.generateJunctionTableName = (column, table, relatedTable) => {
|
|
327
|
+
return `jt_${table.name}_${relatedTable.name}_${column.name}_${column.fieldName}`
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
exports.foreignKeyStructure = (keyName, meta = null) => {
|
|
331
|
+
const structure = {
|
|
332
|
+
type: FieldTypes.NUMBER,
|
|
333
|
+
constraints: {},
|
|
334
|
+
name: keyName,
|
|
335
|
+
}
|
|
336
|
+
if (meta) {
|
|
337
|
+
structure.meta = meta
|
|
338
|
+
}
|
|
339
|
+
return structure
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
exports.hasTypeChanged = (table, oldTable) => {
|
|
343
|
+
if (!oldTable) {
|
|
344
|
+
return false
|
|
345
|
+
}
|
|
346
|
+
for (let [key, field] of Object.entries(oldTable.schema)) {
|
|
347
|
+
const oldType = field.type
|
|
348
|
+
if (!table.schema[key]) {
|
|
349
|
+
continue
|
|
350
|
+
}
|
|
351
|
+
const newType = table.schema[key].type
|
|
352
|
+
if (oldType !== newType && SwitchableTypes.indexOf(oldType) === -1) {
|
|
353
|
+
return true
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
return false
|
|
357
|
+
}
|
|
358
|
+
|
|
318
359
|
exports.TableSaveFunctions = TableSaveFunctions
|
|
@@ -4,27 +4,144 @@ const {
|
|
|
4
4
|
getUserMetadataParams,
|
|
5
5
|
} = require("../../db/utils")
|
|
6
6
|
const { InternalTables } = require("../../db/utils")
|
|
7
|
-
const { getGlobalUsers } = require("../../utilities/global")
|
|
7
|
+
const { getGlobalUsers, getRawGlobalUser } = require("../../utilities/global")
|
|
8
8
|
const { getFullUser } = require("../../utilities/users")
|
|
9
|
+
const { isEqual } = require("lodash")
|
|
10
|
+
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
|
11
|
+
const { getDevelopmentAppID, getDeployedAppIDs } = require("@budibase/auth/db")
|
|
12
|
+
const { doesDatabaseExist } = require("../../utilities")
|
|
13
|
+
const { UserStatus } = require("@budibase/auth/constants")
|
|
9
14
|
|
|
10
|
-
function
|
|
11
|
-
|
|
15
|
+
async function rawMetadata(db) {
|
|
16
|
+
return (
|
|
17
|
+
await db.allDocs(
|
|
18
|
+
getUserMetadataParams(null, {
|
|
19
|
+
include_docs: true,
|
|
20
|
+
})
|
|
21
|
+
)
|
|
22
|
+
).rows.map(row => row.doc)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function combineMetadataAndUser(user, metadata) {
|
|
26
|
+
// skip users with no access
|
|
27
|
+
if (user.roleId === BUILTIN_ROLE_IDS.PUBLIC) {
|
|
28
|
+
return null
|
|
29
|
+
}
|
|
30
|
+
delete user._rev
|
|
31
|
+
const metadataId = generateUserMetadataID(user._id)
|
|
32
|
+
const newDoc = {
|
|
33
|
+
...user,
|
|
34
|
+
_id: metadataId,
|
|
35
|
+
tableId: InternalTables.USER_METADATA,
|
|
36
|
+
}
|
|
37
|
+
const found = Array.isArray(metadata)
|
|
38
|
+
? metadata.find(doc => doc._id === metadataId)
|
|
39
|
+
: metadata
|
|
40
|
+
// copy rev over for the purposes of equality check
|
|
41
|
+
if (found) {
|
|
42
|
+
newDoc._rev = found._rev
|
|
43
|
+
}
|
|
44
|
+
if (found == null || !isEqual(newDoc, found)) {
|
|
45
|
+
return {
|
|
46
|
+
...found,
|
|
47
|
+
...newDoc,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
exports.syncGlobalUsers = async appId => {
|
|
54
|
+
// sync user metadata
|
|
55
|
+
const db = new CouchDB(appId)
|
|
56
|
+
const [users, metadata] = await Promise.all([
|
|
57
|
+
getGlobalUsers(appId),
|
|
58
|
+
rawMetadata(db),
|
|
59
|
+
])
|
|
60
|
+
const toWrite = []
|
|
61
|
+
for (let user of users) {
|
|
62
|
+
const combined = await combineMetadataAndUser(user, metadata)
|
|
63
|
+
if (combined) {
|
|
64
|
+
toWrite.push(combined)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
await db.bulkDocs(toWrite)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
exports.syncUser = async function (ctx) {
|
|
71
|
+
let deleting = false,
|
|
72
|
+
user
|
|
73
|
+
const userId = ctx.params.id
|
|
74
|
+
try {
|
|
75
|
+
user = await getRawGlobalUser(userId)
|
|
76
|
+
} catch (err) {
|
|
77
|
+
if (err && err.status === 404) {
|
|
78
|
+
user = {}
|
|
79
|
+
deleting = true
|
|
80
|
+
} else {
|
|
81
|
+
throw err
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const roles = user.roles
|
|
85
|
+
// remove props which aren't useful to metadata
|
|
12
86
|
delete user.password
|
|
87
|
+
delete user.forceResetPassword
|
|
13
88
|
delete user.roles
|
|
14
|
-
|
|
15
|
-
|
|
89
|
+
// run through all production appIDs in the users roles
|
|
90
|
+
let prodAppIds
|
|
91
|
+
// if they are a builder then get all production app IDs
|
|
92
|
+
if ((user.builder && user.builder.global) || deleting) {
|
|
93
|
+
prodAppIds = await getDeployedAppIDs(CouchDB)
|
|
94
|
+
} else {
|
|
95
|
+
prodAppIds = Object.entries(roles)
|
|
96
|
+
.filter(entry => entry[1] !== BUILTIN_ROLE_IDS.PUBLIC)
|
|
97
|
+
.map(([appId]) => appId)
|
|
98
|
+
}
|
|
99
|
+
for (let prodAppId of prodAppIds) {
|
|
100
|
+
const roleId = roles[prodAppId]
|
|
101
|
+
const devAppId = getDevelopmentAppID(prodAppId)
|
|
102
|
+
for (let appId of [prodAppId, devAppId]) {
|
|
103
|
+
if (!(await doesDatabaseExist(appId))) {
|
|
104
|
+
continue
|
|
105
|
+
}
|
|
106
|
+
const db = new CouchDB(appId)
|
|
107
|
+
const metadataId = generateUserMetadataID(userId)
|
|
108
|
+
let metadata
|
|
109
|
+
try {
|
|
110
|
+
metadata = await db.get(metadataId)
|
|
111
|
+
} catch (err) {
|
|
112
|
+
if (deleting) {
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
metadata = {
|
|
116
|
+
tableId: InternalTables.USER_METADATA,
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// assign the roleId for the metadata doc
|
|
120
|
+
if (roleId) {
|
|
121
|
+
metadata.roleId = roleId
|
|
122
|
+
}
|
|
123
|
+
let combined = !deleting
|
|
124
|
+
? combineMetadataAndUser(user, metadata)
|
|
125
|
+
: {
|
|
126
|
+
...metadata,
|
|
127
|
+
status: UserStatus.INACTIVE,
|
|
128
|
+
metadata: BUILTIN_ROLE_IDS.PUBLIC,
|
|
129
|
+
}
|
|
130
|
+
// if its null then there was no updates required
|
|
131
|
+
if (combined) {
|
|
132
|
+
await db.put(combined)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
ctx.body = {
|
|
137
|
+
message: "User synced.",
|
|
138
|
+
}
|
|
16
139
|
}
|
|
17
140
|
|
|
18
141
|
exports.fetchMetadata = async function (ctx) {
|
|
19
142
|
const database = new CouchDB(ctx.appId)
|
|
20
143
|
const global = await getGlobalUsers(ctx.appId)
|
|
21
|
-
const metadata = (
|
|
22
|
-
await database.allDocs(
|
|
23
|
-
getUserMetadataParams(null, {
|
|
24
|
-
include_docs: true,
|
|
25
|
-
})
|
|
26
|
-
)
|
|
27
|
-
).rows.map(row => row.doc)
|
|
144
|
+
const metadata = await rawMetadata(database)
|
|
28
145
|
const users = []
|
|
29
146
|
for (let user of global) {
|
|
30
147
|
// find the metadata that matches up to the global ID
|
|
@@ -52,7 +169,9 @@ exports.updateSelfMetadata = async function (ctx) {
|
|
|
52
169
|
exports.updateMetadata = async function (ctx) {
|
|
53
170
|
const appId = ctx.appId
|
|
54
171
|
const db = new CouchDB(appId)
|
|
55
|
-
const user =
|
|
172
|
+
const user = ctx.request.body
|
|
173
|
+
// this isn't applicable to the user
|
|
174
|
+
delete user.roles
|
|
56
175
|
const metadata = {
|
|
57
176
|
tableId: InternalTables.USER_METADATA,
|
|
58
177
|
...user,
|
package/src/api/routes/query.js
CHANGED
package/src/api/routes/table.js
CHANGED
|
@@ -53,5 +53,16 @@ router
|
|
|
53
53
|
authorized(BUILDER),
|
|
54
54
|
tableController.destroy
|
|
55
55
|
)
|
|
56
|
+
// this is currently builder only, but in the future
|
|
57
|
+
// it could be carried out by an end user in app,
|
|
58
|
+
// however some thought will need to be had about
|
|
59
|
+
// implications for automations (triggers)
|
|
60
|
+
// new trigger type, bulk rows created
|
|
61
|
+
.post(
|
|
62
|
+
"/api/tables/:tableId/import",
|
|
63
|
+
paramResource("tableId"),
|
|
64
|
+
authorized(BUILDER),
|
|
65
|
+
tableController.bulkImport
|
|
66
|
+
)
|
|
56
67
|
|
|
57
68
|
module.exports = router
|
|
@@ -26,8 +26,8 @@ describe("/datasources", () => {
|
|
|
26
26
|
.expect('Content-Type', /json/)
|
|
27
27
|
.expect(200)
|
|
28
28
|
|
|
29
|
-
expect(res.
|
|
30
|
-
expect(res.body.
|
|
29
|
+
expect(res.body.datasource.name).toEqual("Test")
|
|
30
|
+
expect(res.body.errors).toBeUndefined()
|
|
31
31
|
})
|
|
32
32
|
})
|
|
33
33
|
|