@budibase/server 1.0.46-alpha.2 → 1.0.46-alpha.6
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/builder/assets/{index.89280093.js → index.00221ff2.js} +244 -244
- package/builder/assets/{index.0df4f7ab.css → index.dd9e386f.css} +1 -1
- package/builder/assets/{vendor.10e2ad1b.js → vendor.3bd2f661.js} +1 -1
- package/builder/index.html +3 -3
- package/coverage/clover.xml +1802 -1639
- package/coverage/coverage-final.json +98 -94
- 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 +192 -129
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +21 -21
- 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 +72 -36
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +27 -42
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +6 -6
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +15 -15
- package/coverage/lcov-report/api/controllers/query/index.html +15 -15
- package/coverage/lcov-report/api/controllers/query/index.js.html +61 -28
- package/coverage/lcov-report/api/controllers/query/validation.js.html +6 -6
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +16 -16
- package/coverage/lcov-report/api/controllers/row/index.html +5 -5
- package/coverage/lcov-report/api/controllers/row/index.js.html +26 -26
- package/coverage/lcov-report/api/controllers/row/internal.js.html +44 -44
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +8 -8
- package/coverage/lcov-report/api/controllers/row/utils.js.html +29 -38
- package/coverage/lcov-report/api/controllers/screen.js.html +7 -7
- package/coverage/lcov-report/api/controllers/script.js.html +4 -4
- package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
- package/coverage/lcov-report/api/controllers/table/index.html +16 -16
- package/coverage/lcov-report/api/controllers/table/index.js.html +25 -25
- package/coverage/lcov-report/api/controllers/table/internal.js.html +40 -34
- package/coverage/lcov-report/api/controllers/table/utils.js.html +76 -61
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +20 -20
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +4 -4
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +14 -14
- package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +7 -7
- package/coverage/lcov-report/api/controllers/webhook.js.html +15 -15
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +10 -10
- 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/index.html +7 -22
- package/coverage/lcov-report/api/routes/index.js.html +4 -10
- 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 +1 -1
- 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 +17 -2
- 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 +1 -1
- 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 +24 -24
- package/coverage/lcov-report/automations/automationUtils.js.html +5 -5
- package/coverage/lcov-report/automations/bullboard.js.html +16 -16
- package/coverage/lcov-report/automations/index.html +1 -1
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +6 -6
- package/coverage/lcov-report/automations/steps/createRow.js.html +13 -19
- package/coverage/lcov-report/automations/steps/delay.js.html +4 -4
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +11 -20
- package/coverage/lcov-report/automations/steps/discord.js.html +7 -7
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +6 -6
- package/coverage/lcov-report/automations/steps/executeScript.js.html +6 -6
- package/coverage/lcov-report/automations/steps/filter.js.html +7 -7
- package/coverage/lcov-report/automations/steps/index.html +13 -13
- package/coverage/lcov-report/automations/steps/integromat.js.html +5 -5
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +8 -8
- package/coverage/lcov-report/automations/steps/queryRows.js.html +10 -10
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +5 -5
- package/coverage/lcov-report/automations/steps/serverLog.js.html +3 -3
- package/coverage/lcov-report/automations/steps/slack.js.html +5 -5
- package/coverage/lcov-report/automations/steps/updateRow.js.html +6 -6
- package/coverage/lcov-report/automations/steps/utils.js.html +3 -3
- package/coverage/lcov-report/automations/steps/zapier.js.html +5 -5
- 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 +18 -18
- package/coverage/lcov-report/automations/utils.js.html +32 -32
- package/coverage/lcov-report/constants/index.html +5 -5
- package/coverage/lcov-report/constants/index.js.html +36 -24
- package/coverage/lcov-report/constants/layouts.js.html +5 -5
- package/coverage/lcov-report/constants/screens.js.html +4 -4
- package/coverage/lcov-report/db/client.js.html +18 -18
- package/coverage/lcov-report/db/inMemoryView.js.html +7 -7
- 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 +18 -18
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +31 -31
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +15 -15
- package/coverage/lcov-report/db/newid.js.html +4 -4
- package/coverage/lcov-report/db/utils.js.html +85 -85
- 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 +5 -5
- package/coverage/lcov-report/events/utils.js.html +3 -3
- package/coverage/lcov-report/index.html +110 -80
- 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 +11 -11
- package/coverage/lcov-report/middleware/builder.js.html +8 -8
- package/coverage/lcov-report/middleware/currentapp.js.html +34 -61
- package/coverage/lcov-report/middleware/index.html +25 -25
- 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 +275 -41
- package/coverage/lcov-report/middleware/utils.js.html +2 -2
- package/coverage/lcov-report/migrations/usageQuotas/index.html +141 -0
- package/coverage/lcov-report/migrations/usageQuotas/index.js.html +152 -0
- package/coverage/lcov-report/{api/routes/hosting.js.html → migrations/usageQuotas/syncApps.js.html} +42 -27
- package/coverage/lcov-report/{api/controllers/hosting.js.html → migrations/usageQuotas/syncRows.js.html} +41 -44
- package/coverage/lcov-report/threads/automation.js.html +1 -1
- package/coverage/lcov-report/threads/index.html +15 -15
- package/coverage/lcov-report/threads/index.js.html +10 -10
- package/coverage/lcov-report/threads/query.js.html +23 -8
- package/coverage/lcov-report/threads/utils.js.html +14 -14
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +7 -7
- package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
- package/coverage/lcov-report/utilities/csvParser.js.html +6 -6
- package/coverage/lcov-report/utilities/global.js.html +26 -26
- package/coverage/lcov-report/utilities/index.html +19 -19
- package/coverage/lcov-report/utilities/index.js.html +25 -25
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +8 -8
- 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 +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +53 -53
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +10 -10
- package/coverage/lcov-report/utilities/scriptRunner.js.html +5 -5
- package/coverage/lcov-report/utilities/security.js.html +8 -8
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +141 -0
- package/coverage/lcov-report/utilities/usageQuota/index.js.html +356 -0
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +302 -0
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +134 -0
- package/coverage/lcov-report/utilities/users.js.html +5 -5
- package/coverage/lcov-report/utilities/workerRequests.js.html +39 -108
- package/coverage/lcov.info +2644 -2356
- package/dist/api/controllers/application.js +45 -24
- package/dist/api/controllers/datasource.js +11 -0
- package/dist/api/controllers/query/index.js +11 -3
- package/dist/api/controllers/row/utils.js +1 -2
- package/dist/api/controllers/static/index.js +59 -10
- package/dist/api/controllers/table/internal.js +2 -0
- package/dist/api/controllers/table/utils.js +5 -0
- package/dist/api/routes/index.js +0 -2
- package/dist/api/routes/static.js +2 -1
- package/dist/automations/steps/createRow.js +2 -4
- package/dist/automations/steps/deleteRow.js +1 -4
- package/dist/constants/index.js +3 -0
- package/dist/definitions/datasource.js +1 -0
- package/dist/environment.js +1 -0
- package/dist/integrations/googlesheets.js +340 -0
- package/dist/integrations/index.js +3 -0
- package/dist/integrations/utils.js +6 -3
- package/dist/middleware/currentapp.js +0 -9
- package/dist/middleware/usageQuota.js +82 -13
- package/dist/migrations/usageQuotas/index.js +24 -0
- package/dist/migrations/usageQuotas/syncApps.js +26 -0
- package/dist/migrations/usageQuotas/syncRows.js +29 -0
- package/dist/package.json +8 -5
- package/dist/tests/utilities/TestConfiguration.js +3 -1
- package/dist/threads/query.js +4 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/{usageQuota.js → usageQuota/index.js} +44 -31
- package/dist/utilities/usageQuota/rows.js +77 -0
- package/dist/utilities/usageQuota/usageQuoteReset.js +16 -0
- package/dist/utilities/workerRequests.js +0 -20
- package/nodemon.json +1 -1
- package/package.json +9 -6
- package/src/api/controllers/application.js +48 -27
- package/src/api/controllers/datasource.js +12 -0
- package/src/api/controllers/query/index.js +14 -3
- package/src/api/controllers/row/utils.js +1 -4
- package/src/api/controllers/static/index.js +63 -10
- package/src/api/controllers/table/internal.js +2 -0
- package/src/api/controllers/table/utils.js +5 -0
- package/src/api/routes/index.js +0 -2
- package/src/api/routes/static.js +5 -0
- package/src/api/routes/tests/application.spec.js +2 -2
- package/src/api/routes/tests/static.spec.js +98 -0
- package/src/automations/steps/createRow.js +2 -4
- package/src/automations/steps/deleteRow.js +1 -4
- package/src/constants/index.js +4 -0
- package/src/definitions/datasource.ts +3 -0
- package/src/environment.js +1 -0
- package/src/integrations/googlesheets.ts +353 -0
- package/src/integrations/index.ts +3 -0
- package/src/integrations/utils.ts +18 -5
- package/src/middleware/currentapp.js +0 -9
- package/src/middleware/tests/usageQuota.spec.js +18 -24
- package/src/middleware/usageQuota.js +93 -15
- package/src/migrations/tests/usageQuotas/index.spec.js +27 -0
- package/src/migrations/tests/usageQuotas/syncApps.spec.js +37 -0
- package/src/migrations/tests/usageQuotas/syncRows.spec.js +43 -0
- package/src/migrations/usageQuotas/index.js +24 -0
- package/src/migrations/usageQuotas/syncApps.js +18 -0
- package/src/migrations/usageQuotas/syncRows.js +21 -0
- package/src/tests/utilities/TestConfiguration.js +3 -1
- package/src/threads/query.js +5 -0
- package/src/utilities/tests/usageQuota/usageQuota.spec.js +72 -0
- package/src/utilities/usageQuota/index.js +92 -0
- package/src/utilities/usageQuota/rows.js +74 -0
- package/src/utilities/usageQuota/usageQuoteReset.js +18 -0
- package/src/utilities/workerRequests.js +0 -23
- package/dist/api/controllers/hosting.js +0 -30
- package/dist/api/routes/hosting.js +0 -11
- package/src/api/controllers/hosting.js +0 -22
- package/src/api/routes/hosting.js +0 -13
- package/src/api/routes/tests/hosting.spec.js +0 -36
- package/src/utilities/usageQuota.js +0 -73
|
@@ -8,12 +8,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
const env = require("
|
|
12
|
-
const { getGlobalDB } = require("@budibase/backend-core/tenancy");
|
|
11
|
+
const env = require("../../environment");
|
|
12
|
+
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy");
|
|
13
13
|
const { StaticDatabases, generateNewUsageQuotaDoc, } = require("@budibase/backend-core/db");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
exports.useQuotas = () => {
|
|
15
|
+
// check if quotas are enabled
|
|
16
|
+
if (env.USE_QUOTAS) {
|
|
17
|
+
// check if there are any tenants without limits
|
|
18
|
+
if (env.EXCLUDE_QUOTAS_TENANTS) {
|
|
19
|
+
const excludedTenants = env.EXCLUDE_QUOTAS_TENANTS.replace(/\s/g, "").split(",");
|
|
20
|
+
const tenantId = getTenantId();
|
|
21
|
+
if (excludedTenants.includes(tenantId)) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
return false;
|
|
28
|
+
};
|
|
17
29
|
exports.Properties = {
|
|
18
30
|
ROW: "rows",
|
|
19
31
|
UPLOAD: "storage",
|
|
@@ -21,21 +33,21 @@ exports.Properties = {
|
|
|
21
33
|
USER: "users",
|
|
22
34
|
AUTOMATION: "automationRuns",
|
|
23
35
|
APPS: "apps",
|
|
24
|
-
EMAILS: "emails",
|
|
36
|
+
EMAILS: "emails", // doesn't work yet
|
|
25
37
|
};
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
38
|
+
exports.getUsageQuotaDoc = (db) => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
let quota;
|
|
40
|
+
try {
|
|
41
|
+
quota = yield db.get(StaticDatabases.GLOBAL.docs.usageQuota);
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
// doc doesn't exist. Create it
|
|
45
|
+
quota = generateNewUsageQuotaDoc();
|
|
46
|
+
const response = yield db.put(quota);
|
|
47
|
+
quota._rev = response.rev;
|
|
48
|
+
}
|
|
49
|
+
return quota;
|
|
50
|
+
});
|
|
39
51
|
/**
|
|
40
52
|
* Given a specified tenantId this will add to the usage object for the specified property.
|
|
41
53
|
* @param {string} property The property which is to be added to (within the nested usageQuota object).
|
|
@@ -43,27 +55,28 @@ function getUsageQuotaDoc(db) {
|
|
|
43
55
|
* @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
|
|
44
56
|
* also been reset after this call.
|
|
45
57
|
*/
|
|
46
|
-
exports.update = (property, usage) => __awaiter(void 0, void 0, void 0, function* () {
|
|
47
|
-
if (!
|
|
58
|
+
exports.update = (property, usage, opts = { dryRun: false }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
|
+
if (!exports.useQuotas()) {
|
|
48
60
|
return;
|
|
49
61
|
}
|
|
50
62
|
try {
|
|
51
63
|
const db = getGlobalDB();
|
|
52
|
-
const quota = yield getUsageQuotaDoc(db);
|
|
53
|
-
// Check if the quota needs reset
|
|
54
|
-
if (Date.now() >= quota.quotaReset) {
|
|
55
|
-
quota.quotaReset = getNewQuotaReset();
|
|
56
|
-
for (let prop of Object.keys(quota.usageQuota)) {
|
|
57
|
-
quota.usageQuota[prop] = 0;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
64
|
+
const quota = yield exports.getUsageQuotaDoc(db);
|
|
60
65
|
// increment the quota
|
|
61
66
|
quota.usageQuota[property] += usage;
|
|
62
|
-
if (quota.usageQuota[property] > quota.usageLimits[property]
|
|
67
|
+
if (quota.usageQuota[property] > quota.usageLimits[property] &&
|
|
68
|
+
usage > 0 // allow for decrementing usage when the quota is already exceeded
|
|
69
|
+
) {
|
|
63
70
|
throw new Error(`You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`);
|
|
64
71
|
}
|
|
72
|
+
if (quota.usageQuota[property] < 0) {
|
|
73
|
+
// never go negative if the quota has previously been exceeded
|
|
74
|
+
quota.usageQuota[property] = 0;
|
|
75
|
+
}
|
|
65
76
|
// update the usage quotas
|
|
66
|
-
|
|
77
|
+
if (!opts.dryRun) {
|
|
78
|
+
yield db.put(quota);
|
|
79
|
+
}
|
|
67
80
|
}
|
|
68
81
|
catch (err) {
|
|
69
82
|
console.error(`Error updating usage quotas for ${property}`, err);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
const { getRowParams, USER_METDATA_PREFIX } = require("../../db/utils");
|
|
12
|
+
const CouchDB = require("../../db");
|
|
13
|
+
const { isDevAppID, getDevelopmentAppID } = require("@budibase/backend-core/db");
|
|
14
|
+
const ROW_EXCLUSIONS = [USER_METDATA_PREFIX];
|
|
15
|
+
const getAppPairs = appIds => {
|
|
16
|
+
// collect the app ids into dev / prod pairs
|
|
17
|
+
// keyed by the dev app id
|
|
18
|
+
const pairs = {};
|
|
19
|
+
for (let appId of appIds) {
|
|
20
|
+
const devId = getDevelopmentAppID(appId);
|
|
21
|
+
if (!pairs[devId]) {
|
|
22
|
+
pairs[devId] = {};
|
|
23
|
+
}
|
|
24
|
+
if (isDevAppID(appId)) {
|
|
25
|
+
pairs[devId].devId = appId;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
pairs[devId].prodId = appId;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return pairs;
|
|
32
|
+
};
|
|
33
|
+
const getAppRows = (appId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
const appDb = new CouchDB(appId);
|
|
35
|
+
const response = yield appDb.allDocs(getRowParams(null, null, {
|
|
36
|
+
include_docs: false,
|
|
37
|
+
}));
|
|
38
|
+
return response.rows
|
|
39
|
+
.map(r => r.id)
|
|
40
|
+
.filter(id => {
|
|
41
|
+
for (let exclusion of ROW_EXCLUSIONS) {
|
|
42
|
+
if (id.startsWith(exclusion)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
/**
|
|
50
|
+
* Return a set of all rows in the given app ids.
|
|
51
|
+
* The returned rows will be unique on a per dev/prod app basis.
|
|
52
|
+
* Rows duplicates may exist across apps due to data import so they are not filtered out.
|
|
53
|
+
*/
|
|
54
|
+
exports.getUniqueRows = (appIds) => __awaiter(void 0, void 0, void 0, function* () {
|
|
55
|
+
let uniqueRows = [];
|
|
56
|
+
const pairs = getAppPairs(appIds);
|
|
57
|
+
for (let pair of Object.values(pairs)) {
|
|
58
|
+
let appRows = [];
|
|
59
|
+
for (let appId of [pair.devId, pair.prodId]) {
|
|
60
|
+
if (!appId) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
appRows.push(yield getAppRows(appId));
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.error(e);
|
|
68
|
+
// don't error out if we can't count the app rows, just continue
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// ensure uniqueness on a per app pair basis
|
|
72
|
+
// this can't be done on all rows because app import results in
|
|
73
|
+
// duplicate row ids across apps
|
|
74
|
+
uniqueRows = uniqueRows.concat(...new Set(appRows));
|
|
75
|
+
}
|
|
76
|
+
return uniqueRows;
|
|
77
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// UNUSED CODE
|
|
3
|
+
// Preserved for future use
|
|
4
|
+
/* eslint-disable no-unused-vars */
|
|
5
|
+
function getNewQuotaReset() {
|
|
6
|
+
return Date.now() + 2592000000;
|
|
7
|
+
}
|
|
8
|
+
function resetQuotasIfRequired(quota) {
|
|
9
|
+
// Check if the quota needs reset
|
|
10
|
+
if (Date.now() >= quota.quotaReset) {
|
|
11
|
+
quota.quotaReset = getNewQuotaReset();
|
|
12
|
+
for (let prop of Object.keys(quota.usageQuota)) {
|
|
13
|
+
quota.usageQuota[prop] = 0;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -61,26 +61,6 @@ exports.sendSmtpEmail = (to, from, subject, contents, automation) => __awaiter(v
|
|
|
61
61
|
}
|
|
62
62
|
return response.json();
|
|
63
63
|
});
|
|
64
|
-
exports.getDeployedApps = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
-
try {
|
|
66
|
-
const response = yield fetch(checkSlashesInUrl(env.WORKER_URL + `/api/apps`), request(null, {
|
|
67
|
-
method: "GET",
|
|
68
|
-
}));
|
|
69
|
-
const json = yield response.json();
|
|
70
|
-
const apps = {};
|
|
71
|
-
for (let [key, value] of Object.entries(json)) {
|
|
72
|
-
if (value.url) {
|
|
73
|
-
value.url = value.url.toLowerCase();
|
|
74
|
-
apps[key.toLowerCase()] = value;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return apps;
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
// error, cannot determine deployed apps, don't stop app creation - sort this later
|
|
81
|
-
return {};
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
64
|
exports.getGlobalSelf = (ctx, appId = null) => __awaiter(void 0, void 0, void 0, function* () {
|
|
85
65
|
const endpoint = `/api/global/users/self`;
|
|
86
66
|
const response = yield fetch(checkSlashesInUrl(env.WORKER_URL + endpoint),
|
package/nodemon.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "1.0.46-alpha.
|
|
4
|
+
"version": "1.0.46-alpha.6",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
"license": "GPL-3.0",
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@apidevtools/swagger-parser": "^10.0.3",
|
|
73
|
-
"@budibase/backend-core": "^1.0.46-alpha.
|
|
74
|
-
"@budibase/client": "^1.0.46-alpha.
|
|
75
|
-
"@budibase/string-templates": "^1.0.46-alpha.
|
|
73
|
+
"@budibase/backend-core": "^1.0.46-alpha.6",
|
|
74
|
+
"@budibase/client": "^1.0.46-alpha.6",
|
|
75
|
+
"@budibase/string-templates": "^1.0.46-alpha.6",
|
|
76
76
|
"@bull-board/api": "^3.7.0",
|
|
77
77
|
"@bull-board/koa": "^3.7.0",
|
|
78
78
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -92,6 +92,8 @@
|
|
|
92
92
|
"fix-path": "3.0.0",
|
|
93
93
|
"form-data": "^4.0.0",
|
|
94
94
|
"fs-extra": "8.1.0",
|
|
95
|
+
"google-auth-library": "^7.11.0",
|
|
96
|
+
"google-spreadsheet": "^3.2.0",
|
|
95
97
|
"jimp": "0.16.1",
|
|
96
98
|
"joi": "17.2.1",
|
|
97
99
|
"js-yaml": "^4.1.0",
|
|
@@ -110,7 +112,7 @@
|
|
|
110
112
|
"mongodb": "3.6.3",
|
|
111
113
|
"mssql": "6.2.3",
|
|
112
114
|
"mysql2": "^2.3.1",
|
|
113
|
-
"node-fetch": "2.6.
|
|
115
|
+
"node-fetch": "2.6.7",
|
|
114
116
|
"open": "^8.4.0",
|
|
115
117
|
"pg": "8.5.1",
|
|
116
118
|
"pino-pretty": "4.0.0",
|
|
@@ -139,6 +141,7 @@
|
|
|
139
141
|
"@jest/test-sequencer": "^24.8.0",
|
|
140
142
|
"@types/apidoc": "^0.50.0",
|
|
141
143
|
"@types/bull": "^3.15.1",
|
|
144
|
+
"@types/google-spreadsheet": "^3.1.5",
|
|
142
145
|
"@types/jest": "^26.0.23",
|
|
143
146
|
"@types/koa": "^2.13.3",
|
|
144
147
|
"@types/koa-router": "^7.4.2",
|
|
@@ -165,5 +168,5 @@
|
|
|
165
168
|
"optionalDependencies": {
|
|
166
169
|
"oracledb": "^5.3.0"
|
|
167
170
|
},
|
|
168
|
-
"gitHead": "
|
|
171
|
+
"gitHead": "a3e5c5af7f047b46ba1d7875ad489f357632b267"
|
|
169
172
|
}
|
|
@@ -33,10 +33,7 @@ const {
|
|
|
33
33
|
Replication,
|
|
34
34
|
} = require("@budibase/backend-core/db")
|
|
35
35
|
const { USERS_TABLE_SCHEMA } = require("../../constants")
|
|
36
|
-
const {
|
|
37
|
-
getDeployedApps,
|
|
38
|
-
removeAppFromUserRoles,
|
|
39
|
-
} = require("../../utilities/workerRequests")
|
|
36
|
+
const { removeAppFromUserRoles } = require("../../utilities/workerRequests")
|
|
40
37
|
const { clientLibraryPath, stringToReadStream } = require("../../utilities")
|
|
41
38
|
const { getAllLocks } = require("../../utilities/redis")
|
|
42
39
|
const {
|
|
@@ -78,29 +75,41 @@ function getUserRoleId(ctx) {
|
|
|
78
75
|
: ctx.user.role._id
|
|
79
76
|
}
|
|
80
77
|
|
|
81
|
-
async function
|
|
78
|
+
async function getAppUrl(ctx) {
|
|
79
|
+
// construct the url
|
|
82
80
|
let url
|
|
83
81
|
if (ctx.request.body.url) {
|
|
82
|
+
// if the url is provided, use that
|
|
84
83
|
url = encodeURI(ctx.request.body.url)
|
|
85
|
-
} else
|
|
84
|
+
} else {
|
|
85
|
+
// otherwise use the name
|
|
86
86
|
url = encodeURI(`${ctx.request.body.name}`)
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
url = `/${url.replace(URL_REGEX_SLASH, "")}`.toLowerCase()
|
|
89
|
+
|
|
90
|
+
return url
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const checkAppUrl = (ctx, apps, url, currentAppId) => {
|
|
94
|
+
if (currentAppId) {
|
|
95
|
+
apps = apps.filter(app => app.appId !== currentAppId)
|
|
96
|
+
}
|
|
97
|
+
if (apps.some(app => app.url === url)) {
|
|
98
|
+
ctx.throw(400, "App URL is already in use.")
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const checkAppName = (ctx, apps, name, currentAppId) => {
|
|
103
|
+
// TODO: Replace with Joi
|
|
104
|
+
if (!name) {
|
|
105
|
+
ctx.throw(400, "Name is required")
|
|
90
106
|
}
|
|
91
|
-
if (
|
|
92
|
-
|
|
107
|
+
if (currentAppId) {
|
|
108
|
+
apps = apps.filter(app => app.appId !== currentAppId)
|
|
93
109
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
url &&
|
|
97
|
-
deployedApps[url] != null &&
|
|
98
|
-
ctx.params != null &&
|
|
99
|
-
deployedApps[url].appId !== ctx.params.appId
|
|
100
|
-
) {
|
|
101
|
-
ctx.throw(400, "App name/URL is already in use.")
|
|
110
|
+
if (apps.some(app => app.name === name)) {
|
|
111
|
+
ctx.throw(400, "App name is already in use.")
|
|
102
112
|
}
|
|
103
|
-
return url
|
|
104
113
|
}
|
|
105
114
|
|
|
106
115
|
async function createInstance(template) {
|
|
@@ -206,6 +215,12 @@ exports.fetchAppPackage = async ctx => {
|
|
|
206
215
|
}
|
|
207
216
|
|
|
208
217
|
exports.create = async ctx => {
|
|
218
|
+
const apps = await getAllApps(CouchDB, { dev: true })
|
|
219
|
+
const name = ctx.request.body.name
|
|
220
|
+
checkAppName(ctx, apps, name)
|
|
221
|
+
const url = await getAppUrl(ctx)
|
|
222
|
+
checkAppUrl(ctx, apps, url)
|
|
223
|
+
|
|
209
224
|
const { useTemplate, templateKey, templateString } = ctx.request.body
|
|
210
225
|
const instanceConfig = {
|
|
211
226
|
useTemplate,
|
|
@@ -218,7 +233,6 @@ exports.create = async ctx => {
|
|
|
218
233
|
const instance = await createInstance(instanceConfig)
|
|
219
234
|
const appId = instance._id
|
|
220
235
|
|
|
221
|
-
const url = await getAppUrlIfNotInUse(ctx)
|
|
222
236
|
const db = new CouchDB(appId)
|
|
223
237
|
let _rev
|
|
224
238
|
try {
|
|
@@ -235,7 +249,7 @@ exports.create = async ctx => {
|
|
|
235
249
|
type: "app",
|
|
236
250
|
version: packageJson.version,
|
|
237
251
|
componentLibraries: ["@budibase/standard-components"],
|
|
238
|
-
name:
|
|
252
|
+
name: name,
|
|
239
253
|
url: url,
|
|
240
254
|
template: ctx.request.body.template,
|
|
241
255
|
instance: instance,
|
|
@@ -263,7 +277,15 @@ exports.create = async ctx => {
|
|
|
263
277
|
}
|
|
264
278
|
|
|
265
279
|
exports.update = async ctx => {
|
|
266
|
-
const
|
|
280
|
+
const apps = await getAllApps(CouchDB, { dev: true })
|
|
281
|
+
// validation
|
|
282
|
+
const name = ctx.request.body.name
|
|
283
|
+
checkAppName(ctx, apps, name, ctx.params.appId)
|
|
284
|
+
const url = await getAppUrl(ctx)
|
|
285
|
+
checkAppUrl(ctx, apps, url, ctx.params.appId)
|
|
286
|
+
|
|
287
|
+
const appPackageUpdates = { name, url }
|
|
288
|
+
const data = await updateAppPackage(appPackageUpdates, ctx.params.appId)
|
|
267
289
|
ctx.status = 200
|
|
268
290
|
ctx.body = data
|
|
269
291
|
}
|
|
@@ -285,7 +307,7 @@ exports.updateClient = async ctx => {
|
|
|
285
307
|
version: packageJson.version,
|
|
286
308
|
revertableVersion: currentVersion,
|
|
287
309
|
}
|
|
288
|
-
const data = await updateAppPackage(
|
|
310
|
+
const data = await updateAppPackage(appPackageUpdates, ctx.params.appId)
|
|
289
311
|
ctx.status = 200
|
|
290
312
|
ctx.body = data
|
|
291
313
|
}
|
|
@@ -308,7 +330,7 @@ exports.revertClient = async ctx => {
|
|
|
308
330
|
version: application.revertableVersion,
|
|
309
331
|
revertableVersion: null,
|
|
310
332
|
}
|
|
311
|
-
const data = await updateAppPackage(
|
|
333
|
+
const data = await updateAppPackage(appPackageUpdates, ctx.params.appId)
|
|
312
334
|
ctx.status = 200
|
|
313
335
|
ctx.body = data
|
|
314
336
|
}
|
|
@@ -381,12 +403,11 @@ exports.sync = async (ctx, next) => {
|
|
|
381
403
|
}
|
|
382
404
|
}
|
|
383
405
|
|
|
384
|
-
const updateAppPackage = async (
|
|
385
|
-
const url = await getAppUrlIfNotInUse(ctx)
|
|
406
|
+
const updateAppPackage = async (appPackage, appId) => {
|
|
386
407
|
const db = new CouchDB(appId)
|
|
387
408
|
const application = await db.get(DocumentTypes.APP_METADATA)
|
|
388
409
|
|
|
389
|
-
const newAppPackage = { ...application, ...appPackage
|
|
410
|
+
const newAppPackage = { ...application, ...appPackage }
|
|
390
411
|
if (appPackage._rev !== application._rev) {
|
|
391
412
|
newAppPackage._rev = application._rev
|
|
392
413
|
}
|
|
@@ -38,6 +38,13 @@ exports.fetch = async function (ctx) {
|
|
|
38
38
|
)
|
|
39
39
|
).rows.map(row => row.doc)
|
|
40
40
|
|
|
41
|
+
for (let datasource of datasources) {
|
|
42
|
+
if (datasource.config && datasource.config.auth) {
|
|
43
|
+
// strip secrets from response so they don't show in the network request
|
|
44
|
+
delete datasource.config.auth
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
41
48
|
ctx.body = [bbInternalDb, ...datasources]
|
|
42
49
|
}
|
|
43
50
|
|
|
@@ -94,8 +101,13 @@ exports.update = async function (ctx) {
|
|
|
94
101
|
const db = new CouchDB(ctx.appId)
|
|
95
102
|
const datasourceId = ctx.params.datasourceId
|
|
96
103
|
let datasource = await db.get(datasourceId)
|
|
104
|
+
const auth = datasource.config.auth
|
|
97
105
|
await invalidateVariables(datasource, ctx.request.body)
|
|
98
106
|
datasource = { ...datasource, ...ctx.request.body }
|
|
107
|
+
if (auth && !ctx.request.body.auth) {
|
|
108
|
+
// don't strip auth config from DB
|
|
109
|
+
datasource.config.auth = auth
|
|
110
|
+
}
|
|
99
111
|
|
|
100
112
|
const response = await db.put(datasource)
|
|
101
113
|
datasource._rev = response.rev
|
|
@@ -141,6 +141,16 @@ async function execute(ctx, opts = { rowsOnly: false }) {
|
|
|
141
141
|
const query = await db.get(ctx.params.queryId)
|
|
142
142
|
const datasource = await db.get(query.datasourceId)
|
|
143
143
|
|
|
144
|
+
const enrichedParameters = ctx.request.body.parameters || {}
|
|
145
|
+
// make sure parameters are fully enriched with defaults
|
|
146
|
+
if (query && query.parameters) {
|
|
147
|
+
for (let parameter of query.parameters) {
|
|
148
|
+
if (!enrichedParameters[parameter.name]) {
|
|
149
|
+
enrichedParameters[parameter.name] = parameter.default
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
144
154
|
// call the relevant CRUD method on the integration class
|
|
145
155
|
try {
|
|
146
156
|
const { rows, pagination, extra } = await Runner.run({
|
|
@@ -149,7 +159,7 @@ async function execute(ctx, opts = { rowsOnly: false }) {
|
|
|
149
159
|
queryVerb: query.queryVerb,
|
|
150
160
|
fields: query.fields,
|
|
151
161
|
pagination: ctx.request.body.pagination,
|
|
152
|
-
parameters:
|
|
162
|
+
parameters: enrichedParameters,
|
|
153
163
|
transformer: query.transformer,
|
|
154
164
|
queryId: ctx.params.queryId,
|
|
155
165
|
})
|
|
@@ -178,8 +188,9 @@ const removeDynamicVariables = async (db, queryId) => {
|
|
|
178
188
|
|
|
179
189
|
if (dynamicVariables) {
|
|
180
190
|
// delete dynamic variables from the datasource
|
|
181
|
-
|
|
182
|
-
|
|
191
|
+
datasource.config.dynamicVariables = dynamicVariables.filter(
|
|
192
|
+
dv => dv.queryId !== queryId
|
|
193
|
+
)
|
|
183
194
|
await db.put(datasource)
|
|
184
195
|
|
|
185
196
|
// invalidate the deleted variables
|
|
@@ -52,10 +52,7 @@ exports.validate = async ({ appId, tableId, row, table }) => {
|
|
|
52
52
|
const constraints = cloneDeep(table.schema[fieldName].constraints)
|
|
53
53
|
const type = table.schema[fieldName].type
|
|
54
54
|
// special case for options, need to always allow unselected (null)
|
|
55
|
-
if (
|
|
56
|
-
(type === FieldTypes.OPTIONS || type === FieldTypes.ARRAY) &&
|
|
57
|
-
constraints.inclusion
|
|
58
|
-
) {
|
|
55
|
+
if (type === FieldTypes.OPTIONS && constraints.inclusion) {
|
|
59
56
|
constraints.inclusion.push(null)
|
|
60
57
|
}
|
|
61
58
|
let res
|
|
@@ -5,7 +5,7 @@ const { resolve, join } = require("../../../utilities/centralPath")
|
|
|
5
5
|
const uuid = require("uuid")
|
|
6
6
|
const { ObjectStoreBuckets } = require("../../../constants")
|
|
7
7
|
const { processString } = require("@budibase/string-templates")
|
|
8
|
-
const {
|
|
8
|
+
const { getAllApps } = require("@budibase/backend-core/db")
|
|
9
9
|
const CouchDB = require("../../../db")
|
|
10
10
|
const {
|
|
11
11
|
loadHandlebarsFile,
|
|
@@ -17,6 +17,8 @@ const { clientLibraryPath } = require("../../../utilities")
|
|
|
17
17
|
const { upload } = require("../../../utilities/fileSystem")
|
|
18
18
|
const { attachmentsRelativeURL } = require("../../../utilities")
|
|
19
19
|
const { DocumentTypes } = require("../../../db/utils")
|
|
20
|
+
const AWS = require("aws-sdk")
|
|
21
|
+
const AWS_REGION = env.AWS_REGION ? env.AWS_REGION : "eu-west-1"
|
|
20
22
|
|
|
21
23
|
async function prepareUpload({ s3Key, bucket, metadata, file }) {
|
|
22
24
|
const response = await upload({
|
|
@@ -37,12 +39,18 @@ async function prepareUpload({ s3Key, bucket, metadata, file }) {
|
|
|
37
39
|
}
|
|
38
40
|
}
|
|
39
41
|
|
|
40
|
-
async function
|
|
41
|
-
// the "appId" component of the URL
|
|
42
|
+
async function getAppIdFromUrl(ctx) {
|
|
43
|
+
// the "appId" component of the URL can be the id or the custom url
|
|
42
44
|
let possibleAppUrl = `/${encodeURI(ctx.params.appId).toLowerCase()}`
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
|
|
46
|
+
// search prod apps for a url that matches, exclude dev where id is always used
|
|
47
|
+
const apps = await getAllApps(CouchDB, { dev: false })
|
|
48
|
+
const app = apps.filter(
|
|
49
|
+
a => a.url && a.url.toLowerCase() === possibleAppUrl
|
|
50
|
+
)[0]
|
|
51
|
+
|
|
52
|
+
if (app && app.appId) {
|
|
53
|
+
return app.appId
|
|
46
54
|
} else {
|
|
47
55
|
return ctx.params.appId
|
|
48
56
|
}
|
|
@@ -75,10 +83,7 @@ exports.uploadFile = async function (ctx) {
|
|
|
75
83
|
}
|
|
76
84
|
|
|
77
85
|
exports.serveApp = async function (ctx) {
|
|
78
|
-
let appId = ctx
|
|
79
|
-
if (env.SELF_HOSTED) {
|
|
80
|
-
appId = await checkForSelfHostedURL(ctx)
|
|
81
|
-
}
|
|
86
|
+
let appId = await getAppIdFromUrl(ctx)
|
|
82
87
|
const App = require("./templates/BudibaseApp.svelte").default
|
|
83
88
|
const db = new CouchDB(appId, { skip_setup: true })
|
|
84
89
|
const appInfo = await db.get(DocumentTypes.APP_METADATA)
|
|
@@ -104,3 +109,51 @@ exports.serveClientLibrary = async function (ctx) {
|
|
|
104
109
|
root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"),
|
|
105
110
|
})
|
|
106
111
|
}
|
|
112
|
+
|
|
113
|
+
exports.getSignedUploadURL = async function (ctx) {
|
|
114
|
+
const database = new CouchDB(ctx.appId)
|
|
115
|
+
|
|
116
|
+
// Ensure datasource is valid
|
|
117
|
+
let datasource
|
|
118
|
+
try {
|
|
119
|
+
const { datasourceId } = ctx.params
|
|
120
|
+
datasource = await database.get(datasourceId)
|
|
121
|
+
if (!datasource) {
|
|
122
|
+
ctx.throw(400, "The specified datasource could not be found")
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
ctx.throw(400, "The specified datasource could not be found")
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Ensure we aren't using a custom endpoint
|
|
129
|
+
if (datasource?.config?.endpoint) {
|
|
130
|
+
ctx.throw(400, "S3 datasources with custom endpoints are not supported")
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Determine type of datasource and generate signed URL
|
|
134
|
+
let signedUrl
|
|
135
|
+
let publicUrl
|
|
136
|
+
if (datasource.source === "S3") {
|
|
137
|
+
const { bucket, key } = ctx.request.body || {}
|
|
138
|
+
if (!bucket || !key) {
|
|
139
|
+
ctx.throw(400, "bucket and key values are required")
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const s3 = new AWS.S3({
|
|
144
|
+
region: AWS_REGION,
|
|
145
|
+
accessKeyId: datasource?.config?.accessKeyId,
|
|
146
|
+
secretAccessKey: datasource?.config?.secretAccessKey,
|
|
147
|
+
apiVersion: "2006-03-01",
|
|
148
|
+
signatureVersion: "v4",
|
|
149
|
+
})
|
|
150
|
+
const params = { Bucket: bucket, Key: key }
|
|
151
|
+
signedUrl = s3.getSignedUrl("putObject", params)
|
|
152
|
+
publicUrl = `https://${bucket}.s3.${AWS_REGION}.amazonaws.com/${key}`
|
|
153
|
+
} catch (error) {
|
|
154
|
+
ctx.throw(400, error)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
ctx.body = { signedUrl, publicUrl }
|
|
159
|
+
}
|
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
getTable,
|
|
9
9
|
handleDataImport,
|
|
10
10
|
} = require("./utils")
|
|
11
|
+
const usageQuota = require("../../../utilities/usageQuota")
|
|
11
12
|
|
|
12
13
|
exports.save = async function (ctx) {
|
|
13
14
|
const appId = ctx.appId
|
|
@@ -119,6 +120,7 @@ exports.destroy = async function (ctx) {
|
|
|
119
120
|
})
|
|
120
121
|
)
|
|
121
122
|
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true })))
|
|
123
|
+
await usageQuota.update(usageQuota.Properties.ROW, -rows.rows.length)
|
|
122
124
|
|
|
123
125
|
// update linked rows
|
|
124
126
|
await linkRows.updateLinks({
|
|
@@ -16,6 +16,7 @@ const {
|
|
|
16
16
|
} = require("../../../integrations/utils")
|
|
17
17
|
const { getViews, saveView } = require("../view/utils")
|
|
18
18
|
const viewTemplate = require("../view/viewBuilder")
|
|
19
|
+
const usageQuota = require("../../../utilities/usageQuota")
|
|
19
20
|
|
|
20
21
|
exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
|
|
21
22
|
let updatedRows = []
|
|
@@ -112,7 +113,11 @@ exports.handleDataImport = async (appId, user, table, dataImport) => {
|
|
|
112
113
|
finalData.push(row)
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
await usageQuota.update(usageQuota.Properties.ROW, finalData.length, {
|
|
117
|
+
dryRun: true,
|
|
118
|
+
})
|
|
115
119
|
await db.bulkDocs(finalData)
|
|
120
|
+
await usageQuota.update(usageQuota.Properties.ROW, finalData.length)
|
|
116
121
|
let response = await db.put(table)
|
|
117
122
|
table._rev = response._rev
|
|
118
123
|
return table
|
package/src/api/routes/index.js
CHANGED
|
@@ -20,7 +20,6 @@ const integrationRoutes = require("./integration")
|
|
|
20
20
|
const permissionRoutes = require("./permission")
|
|
21
21
|
const datasourceRoutes = require("./datasource")
|
|
22
22
|
const queryRoutes = require("./query")
|
|
23
|
-
const hostingRoutes = require("./hosting")
|
|
24
23
|
const backupRoutes = require("./backup")
|
|
25
24
|
const metadataRoutes = require("./metadata")
|
|
26
25
|
const devRoutes = require("./dev")
|
|
@@ -46,7 +45,6 @@ exports.mainRoutes = [
|
|
|
46
45
|
permissionRoutes,
|
|
47
46
|
datasourceRoutes,
|
|
48
47
|
queryRoutes,
|
|
49
|
-
hostingRoutes,
|
|
50
48
|
backupRoutes,
|
|
51
49
|
metadataRoutes,
|
|
52
50
|
devRoutes,
|