@budibase/server 1.0.46 → 1.0.49-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder/assets/index.ba78c49d.css +1 -0
- package/builder/assets/{index.e9bff1c6.js → index.ed1cf508.js} +237 -234
- package/builder/assets/{vendor.f9faf6ab.js → vendor.d526bfe8.js} +12 -12
- package/builder/index.html +3 -3
- package/coverage/clover.xml +2368 -2016
- package/coverage/coverage-final.json +101 -95
- 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 +210 -126
- package/coverage/lcov-report/api/controllers/auth.js.html +18 -6
- 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 +38 -53
- 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 +1 -1
- package/coverage/lcov-report/api/controllers/query/index.js.html +19 -19
- 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 +48 -33
- package/coverage/lcov-report/api/controllers/row/index.js.html +26 -26
- package/coverage/lcov-report/api/controllers/row/internal.js.html +95 -158
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +41 -17
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +551 -0
- package/coverage/lcov-report/api/controllers/row/utils.js.html +39 -57
- 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/bulkFormula.js.html +629 -0
- package/coverage/lcov-report/api/controllers/table/external.js.html +12 -12
- package/coverage/lcov-report/api/controllers/table/index.html +49 -34
- package/coverage/lcov-report/api/controllers/table/index.js.html +53 -77
- package/coverage/lcov-report/api/controllers/table/internal.js.html +59 -35
- package/coverage/lcov-report/api/controllers/table/utils.js.html +283 -76
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +30 -24
- 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 +11 -11
- package/coverage/lcov-report/constants/index.js.html +68 -32
- 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 +10 -10
- package/coverage/lcov-report/db/linkedRows/index.js.html +38 -41
- 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 +86 -86
- 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 +131 -101
- 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 +166 -64
- package/coverage/lcov-report/middleware/builder.js.html +8 -8
- package/coverage/lcov-report/middleware/currentapp.js.html +29 -29
- package/coverage/lcov-report/middleware/index.html +30 -30
- 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 +27 -27
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +115 -79
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +75 -27
- 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 +3719 -3046
- package/dist/api/controllers/application.js +49 -20
- package/dist/api/controllers/auth.js +4 -0
- package/dist/api/controllers/datasource.js +11 -0
- package/dist/api/controllers/row/ExternalRequest.js +2 -1
- package/dist/api/controllers/row/internal.js +30 -53
- package/dist/api/controllers/row/internalSearch.js +12 -4
- package/dist/api/controllers/row/staticFormula.js +147 -0
- package/dist/api/controllers/row/utils.js +6 -8
- package/dist/api/controllers/static/index.js +59 -10
- package/dist/api/controllers/table/bulkFormula.js +160 -0
- package/dist/api/controllers/table/index.js +12 -9
- package/dist/api/controllers/table/internal.js +9 -0
- package/dist/api/controllers/table/utils.js +56 -14
- package/dist/api/controllers/user.js +2 -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 +12 -5
- package/dist/db/linkedRows/index.js +4 -5
- package/dist/definitions/datasource.js +1 -0
- package/dist/environment.js +1 -0
- package/dist/integrations/base/sql.js +13 -6
- package/dist/integrations/googlesheets.js +340 -0
- package/dist/integrations/index.js +3 -0
- package/dist/integrations/utils.js +57 -8
- package/dist/middleware/authorized.js +55 -30
- 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 +10 -6
- package/dist/threads/query.js +4 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/rowProcessor/index.js +18 -11
- package/dist/utilities/rowProcessor/utils.js +14 -4
- 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 +52 -24
- package/src/api/controllers/auth.js +4 -0
- package/src/api/controllers/datasource.js +12 -0
- package/src/api/controllers/row/ExternalRequest.ts +1 -1
- package/src/api/controllers/row/internal.js +29 -50
- package/src/api/controllers/row/internalSearch.js +12 -4
- package/src/api/controllers/row/staticFormula.js +157 -0
- package/src/api/controllers/row/utils.js +6 -12
- package/src/api/controllers/static/index.js +63 -10
- package/src/api/controllers/table/bulkFormula.js +183 -0
- package/src/api/controllers/table/index.js +16 -24
- package/src/api/controllers/table/internal.js +9 -1
- package/src/api/controllers/table/utils.js +80 -11
- package/src/api/controllers/user.js +2 -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/auth.spec.js +1 -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 +17 -5
- package/src/db/linkedRows/index.js +4 -5
- package/src/definitions/common.ts +3 -0
- package/src/definitions/datasource.ts +3 -0
- package/src/environment.js +1 -0
- package/src/integrations/base/sql.ts +14 -7
- package/src/integrations/googlesheets.ts +353 -0
- package/src/integrations/index.ts +3 -0
- package/src/integrations/tests/sql.spec.js +16 -0
- package/src/integrations/utils.ts +71 -10
- package/src/middleware/authorized.js +64 -30
- package/src/middleware/tests/authorized.spec.js +6 -4
- 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 +10 -6
- package/src/threads/query.js +5 -0
- package/src/utilities/rowProcessor/index.js +24 -12
- package/src/utilities/rowProcessor/utils.js +23 -7
- 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/builder/assets/index.39e01193.css +0 -1
- 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
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
jest.mock("../../db")
|
|
2
2
|
jest.mock("../../utilities/usageQuota")
|
|
3
|
-
jest.mock("../../environment", () => ({
|
|
4
|
-
isTest: () => true,
|
|
5
|
-
isProd: () => false,
|
|
6
|
-
isDev: () => true,
|
|
7
|
-
_set: () => {},
|
|
8
|
-
}))
|
|
9
3
|
jest.mock("@budibase/backend-core/tenancy", () => ({
|
|
10
4
|
getTenantId: () => "testing123"
|
|
11
5
|
}))
|
|
@@ -29,9 +23,10 @@ class TestConfiguration {
|
|
|
29
23
|
},
|
|
30
24
|
req: {
|
|
31
25
|
method: "POST",
|
|
32
|
-
url: "/
|
|
26
|
+
url: "/applications"
|
|
33
27
|
}
|
|
34
28
|
}
|
|
29
|
+
usageQuota.useQuotas = () => true
|
|
35
30
|
}
|
|
36
31
|
|
|
37
32
|
executeMiddleware() {
|
|
@@ -113,7 +108,6 @@ describe("usageQuota middleware", () => {
|
|
|
113
108
|
|
|
114
109
|
it("calculates and persists the correct usage quota for the relevant action", async () => {
|
|
115
110
|
config.setUrl("/rows")
|
|
116
|
-
config.setProd(true)
|
|
117
111
|
|
|
118
112
|
await config.executeMiddleware()
|
|
119
113
|
|
|
@@ -121,20 +115,20 @@ describe("usageQuota middleware", () => {
|
|
|
121
115
|
expect(config.next).toHaveBeenCalled()
|
|
122
116
|
})
|
|
123
117
|
|
|
124
|
-
it("calculates the correct file size from a file upload call and adds it to quota", async () => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
})
|
|
118
|
+
// it("calculates the correct file size from a file upload call and adds it to quota", async () => {
|
|
119
|
+
// config.setUrl("/upload")
|
|
120
|
+
// config.setProd(true)
|
|
121
|
+
// config.setFiles([
|
|
122
|
+
// {
|
|
123
|
+
// size: 100
|
|
124
|
+
// },
|
|
125
|
+
// {
|
|
126
|
+
// size: 10000
|
|
127
|
+
// },
|
|
128
|
+
// ])
|
|
129
|
+
// await config.executeMiddleware()
|
|
130
|
+
|
|
131
|
+
// expect(usageQuota.update).toHaveBeenCalledWith("storage", 10100)
|
|
132
|
+
// expect(config.next).toHaveBeenCalled()
|
|
133
|
+
// })
|
|
140
134
|
})
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
const CouchDB = require("../db")
|
|
2
2
|
const usageQuota = require("../utilities/usageQuota")
|
|
3
|
-
const
|
|
4
|
-
const { getTenantId } = require("@budibase/backend-core/tenancy")
|
|
3
|
+
const { getUniqueRows } = require("../utilities/usageQuota/rows")
|
|
5
4
|
const {
|
|
6
5
|
isExternalTable,
|
|
7
6
|
isRowId: isExternalRowId,
|
|
8
7
|
} = require("../integrations/utils")
|
|
9
|
-
|
|
10
|
-
// tenants without limits
|
|
11
|
-
const EXCLUDED_TENANTS = ["bb", "default", "bbtest", "bbstaging"]
|
|
8
|
+
const migration = require("../migrations/usageQuotas")
|
|
12
9
|
|
|
13
10
|
// currently only counting new writes and deletes
|
|
14
11
|
const METHOD_MAP = {
|
|
@@ -18,13 +15,13 @@ const METHOD_MAP = {
|
|
|
18
15
|
|
|
19
16
|
const DOMAIN_MAP = {
|
|
20
17
|
rows: usageQuota.Properties.ROW,
|
|
21
|
-
upload: usageQuota.Properties.UPLOAD,
|
|
22
|
-
views: usageQuota.Properties.VIEW,
|
|
23
|
-
users: usageQuota.Properties.USER,
|
|
18
|
+
// upload: usageQuota.Properties.UPLOAD, // doesn't work yet
|
|
19
|
+
// views: usageQuota.Properties.VIEW, // doesn't work yet
|
|
20
|
+
// users: usageQuota.Properties.USER, // doesn't work yet
|
|
24
21
|
applications: usageQuota.Properties.APPS,
|
|
25
22
|
// this will not be updated by endpoint calls
|
|
26
23
|
// instead it will be updated by triggerInfo
|
|
27
|
-
automationRuns: usageQuota.Properties.AUTOMATION,
|
|
24
|
+
// automationRuns: usageQuota.Properties.AUTOMATION, // doesn't work yet
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
function getProperty(url) {
|
|
@@ -36,10 +33,7 @@ function getProperty(url) {
|
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
module.exports = async (ctx, next) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
// if in development or a self hosted cloud usage quotas should not be executed
|
|
42
|
-
if (env.isDev() || env.SELF_HOSTED || EXCLUDED_TENANTS.includes(tenantId)) {
|
|
36
|
+
if (!usageQuota.useQuotas()) {
|
|
43
37
|
return next()
|
|
44
38
|
}
|
|
45
39
|
|
|
@@ -80,9 +74,93 @@ module.exports = async (ctx, next) => {
|
|
|
80
74
|
usage = files.map(file => file.size).reduce((total, size) => total + size)
|
|
81
75
|
}
|
|
82
76
|
try {
|
|
83
|
-
await
|
|
84
|
-
|
|
77
|
+
await migration.run()
|
|
78
|
+
await performRequest(ctx, next, property, usage)
|
|
85
79
|
} catch (err) {
|
|
86
80
|
ctx.throw(400, err)
|
|
87
81
|
}
|
|
88
82
|
}
|
|
83
|
+
|
|
84
|
+
const performRequest = async (ctx, next, property, usage) => {
|
|
85
|
+
const usageContext = {
|
|
86
|
+
skipNext: false,
|
|
87
|
+
skipUsage: false,
|
|
88
|
+
[usageQuota.Properties.APPS]: {},
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (usage === -1) {
|
|
92
|
+
if (PRE_DELETE[property]) {
|
|
93
|
+
await PRE_DELETE[property](ctx, usageContext)
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
if (PRE_CREATE[property]) {
|
|
97
|
+
await PRE_CREATE[property](ctx, usageContext)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// run the request
|
|
102
|
+
if (!usageContext.skipNext) {
|
|
103
|
+
await usageQuota.update(property, usage, { dryRun: true })
|
|
104
|
+
await next()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (usage === -1) {
|
|
108
|
+
if (POST_DELETE[property]) {
|
|
109
|
+
await POST_DELETE[property](ctx, usageContext)
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
if (POST_CREATE[property]) {
|
|
113
|
+
await POST_CREATE[property](ctx, usageContext)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// update the usage
|
|
118
|
+
if (!usageContext.skipUsage) {
|
|
119
|
+
await usageQuota.update(property, usage)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const appPreDelete = async (ctx, usageContext) => {
|
|
124
|
+
if (ctx.query.unpublish) {
|
|
125
|
+
// don't run usage decrement for unpublish
|
|
126
|
+
usageContext.skipUsage = true
|
|
127
|
+
return
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// store the row count to delete
|
|
131
|
+
const rows = await getUniqueRows([ctx.appId])
|
|
132
|
+
if (rows.length) {
|
|
133
|
+
usageContext[usageQuota.Properties.APPS] = { rowCount: rows.length }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const appPostDelete = async (ctx, usageContext) => {
|
|
138
|
+
// delete the app rows from usage
|
|
139
|
+
const rowCount = usageContext[usageQuota.Properties.APPS].rowCount
|
|
140
|
+
if (rowCount) {
|
|
141
|
+
await usageQuota.update(usageQuota.Properties.ROW, -rowCount)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const appPostCreate = async ctx => {
|
|
146
|
+
// app import & template creation
|
|
147
|
+
if (ctx.request.body.useTemplate === "true") {
|
|
148
|
+
const rows = await getUniqueRows([ctx.response.body.appId])
|
|
149
|
+
const rowCount = rows ? rows.length : 0
|
|
150
|
+
await usageQuota.update(usageQuota.Properties.ROW, rowCount)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const PRE_DELETE = {
|
|
155
|
+
[usageQuota.Properties.APPS]: appPreDelete,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const POST_DELETE = {
|
|
159
|
+
[usageQuota.Properties.APPS]: appPostDelete,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const PRE_CREATE = {}
|
|
163
|
+
|
|
164
|
+
const POST_CREATE = {
|
|
165
|
+
[usageQuota.Properties.APPS]: appPostCreate,
|
|
166
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const env = require("../../../environment")
|
|
2
|
+
const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
3
|
+
|
|
4
|
+
const syncApps = jest.fn()
|
|
5
|
+
const syncRows = jest.fn()
|
|
6
|
+
|
|
7
|
+
jest.mock("../../usageQuotas/syncApps", () => ({ run: syncApps }) )
|
|
8
|
+
jest.mock("../../usageQuotas/syncRows", () => ({ run: syncRows }) )
|
|
9
|
+
|
|
10
|
+
const migrations = require("../../usageQuotas")
|
|
11
|
+
|
|
12
|
+
describe("run", () => {
|
|
13
|
+
let config = new TestConfig(false)
|
|
14
|
+
|
|
15
|
+
beforeEach(async () => {
|
|
16
|
+
await config.init()
|
|
17
|
+
env._set("USE_QUOTAS", 1)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
afterAll(config.end)
|
|
21
|
+
|
|
22
|
+
it("runs the required migrations", async () => {
|
|
23
|
+
await migrations.run()
|
|
24
|
+
expect(syncApps).toHaveBeenCalledTimes(1)
|
|
25
|
+
expect(syncRows).toHaveBeenCalledTimes(1)
|
|
26
|
+
})
|
|
27
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
2
|
+
const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
3
|
+
const { getUsageQuotaDoc, update, Properties } = require("../../../utilities/usageQuota")
|
|
4
|
+
const syncApps = require("../../usageQuotas/syncApps")
|
|
5
|
+
const env = require("../../../environment")
|
|
6
|
+
|
|
7
|
+
describe("syncApps", () => {
|
|
8
|
+
let config = new TestConfig(false)
|
|
9
|
+
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
await config.init()
|
|
12
|
+
env._set("USE_QUOTAS", 1)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
afterAll(config.end)
|
|
16
|
+
|
|
17
|
+
it("runs successfully", async () => {
|
|
18
|
+
// create the usage quota doc and mock usages
|
|
19
|
+
const db = getGlobalDB()
|
|
20
|
+
await getUsageQuotaDoc(db)
|
|
21
|
+
await update(Properties.APPS, 3)
|
|
22
|
+
|
|
23
|
+
let usageDoc = await getUsageQuotaDoc(db)
|
|
24
|
+
expect(usageDoc.usageQuota.apps).toEqual(3)
|
|
25
|
+
|
|
26
|
+
// create an extra app to test the migration
|
|
27
|
+
await config.createApp("quota-test")
|
|
28
|
+
|
|
29
|
+
// migrate
|
|
30
|
+
await syncApps.run()
|
|
31
|
+
|
|
32
|
+
// assert the migration worked
|
|
33
|
+
usageDoc = await getUsageQuotaDoc(db)
|
|
34
|
+
expect(usageDoc.usageQuota.apps).toEqual(2)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
2
|
+
const TestConfig = require("../../../tests/utilities/TestConfiguration")
|
|
3
|
+
const { getUsageQuotaDoc, update, Properties } = require("../../../utilities/usageQuota")
|
|
4
|
+
const syncRows = require("../../usageQuotas/syncRows")
|
|
5
|
+
const env = require("../../../environment")
|
|
6
|
+
|
|
7
|
+
describe("syncRows", () => {
|
|
8
|
+
let config = new TestConfig(false)
|
|
9
|
+
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
await config.init()
|
|
12
|
+
env._set("USE_QUOTAS", 1)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
afterAll(config.end)
|
|
16
|
+
|
|
17
|
+
it("runs successfully", async () => {
|
|
18
|
+
// create the usage quota doc and mock usages
|
|
19
|
+
const db = getGlobalDB()
|
|
20
|
+
await getUsageQuotaDoc(db)
|
|
21
|
+
await update(Properties.ROW, 300)
|
|
22
|
+
|
|
23
|
+
let usageDoc = await getUsageQuotaDoc(db)
|
|
24
|
+
expect(usageDoc.usageQuota.rows).toEqual(300)
|
|
25
|
+
|
|
26
|
+
// app 1
|
|
27
|
+
await config.createTable()
|
|
28
|
+
await config.createRow()
|
|
29
|
+
// app 2
|
|
30
|
+
await config.createApp("second-app")
|
|
31
|
+
await config.createTable()
|
|
32
|
+
await config.createRow()
|
|
33
|
+
await config.createRow()
|
|
34
|
+
|
|
35
|
+
// migrate
|
|
36
|
+
await syncRows.run()
|
|
37
|
+
|
|
38
|
+
// assert the migration worked
|
|
39
|
+
usageDoc = await getUsageQuotaDoc(db)
|
|
40
|
+
expect(usageDoc.usageQuota.rows).toEqual(3)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const {
|
|
2
|
+
MIGRATIONS,
|
|
3
|
+
MIGRATION_DBS,
|
|
4
|
+
migrateIfRequired,
|
|
5
|
+
} = require("@budibase/backend-core/migrations")
|
|
6
|
+
const { useQuotas } = require("../../utilities/usageQuota")
|
|
7
|
+
const syncApps = require("./syncApps")
|
|
8
|
+
const syncRows = require("./syncRows")
|
|
9
|
+
|
|
10
|
+
exports.run = async () => {
|
|
11
|
+
if (!useQuotas()) {
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Jan 2022
|
|
16
|
+
await migrateIfRequired(
|
|
17
|
+
MIGRATION_DBS.GLOBAL_DB,
|
|
18
|
+
MIGRATIONS.QUOTAS_1,
|
|
19
|
+
async () => {
|
|
20
|
+
await syncApps.run()
|
|
21
|
+
await syncRows.run()
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
|
2
|
+
const { getAllApps } = require("@budibase/backend-core/db")
|
|
3
|
+
const CouchDB = require("../../db")
|
|
4
|
+
const { getUsageQuotaDoc } = require("../../utilities/usageQuota")
|
|
5
|
+
|
|
6
|
+
exports.run = async () => {
|
|
7
|
+
const db = getGlobalDB()
|
|
8
|
+
// get app count
|
|
9
|
+
const devApps = await getAllApps(CouchDB, { dev: true })
|
|
10
|
+
const appCount = devApps ? devApps.length : 0
|
|
11
|
+
|
|
12
|
+
// sync app count
|
|
13
|
+
const tenantId = getTenantId()
|
|
14
|
+
console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`)
|
|
15
|
+
const usageDoc = await getUsageQuotaDoc(db)
|
|
16
|
+
usageDoc.usageQuota.apps = appCount
|
|
17
|
+
await db.put(usageDoc)
|
|
18
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
|
2
|
+
const { getAllApps } = require("@budibase/backend-core/db")
|
|
3
|
+
const CouchDB = require("../../db")
|
|
4
|
+
const { getUsageQuotaDoc } = require("../../utilities/usageQuota")
|
|
5
|
+
const { getUniqueRows } = require("../../utilities/usageQuota/rows")
|
|
6
|
+
|
|
7
|
+
exports.run = async () => {
|
|
8
|
+
const db = getGlobalDB()
|
|
9
|
+
// get all rows in all apps
|
|
10
|
+
const allApps = await getAllApps(CouchDB, { all: true })
|
|
11
|
+
const appIds = allApps ? allApps.map(app => app.appId) : []
|
|
12
|
+
const rows = await getUniqueRows(appIds)
|
|
13
|
+
const rowCount = rows ? rows.length : 0
|
|
14
|
+
|
|
15
|
+
// sync row count
|
|
16
|
+
const tenantId = getTenantId()
|
|
17
|
+
console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`)
|
|
18
|
+
const usageDoc = await getUsageQuotaDoc(db)
|
|
19
|
+
usageDoc.usageQuota.rows = rowCount
|
|
20
|
+
await db.put(usageDoc)
|
|
21
|
+
}
|
|
@@ -22,10 +22,12 @@ const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
|
22
22
|
const { createASession } = require("@budibase/backend-core/sessions")
|
|
23
23
|
const { user: userCache } = require("@budibase/backend-core/cache")
|
|
24
24
|
const CouchDB = require("../../db")
|
|
25
|
+
const newid = require("../../db/newid")
|
|
25
26
|
core.init(CouchDB)
|
|
26
27
|
|
|
27
28
|
const GLOBAL_USER_ID = "us_uuid1"
|
|
28
29
|
const EMAIL = "babs@babs.com"
|
|
30
|
+
const CSRF_TOKEN = "e3727778-7af0-4226-b5eb-f43cbe60a306"
|
|
29
31
|
|
|
30
32
|
class TestConfiguration {
|
|
31
33
|
constructor(openServer = true) {
|
|
@@ -85,7 +87,11 @@ class TestConfiguration {
|
|
|
85
87
|
roles: roles || {},
|
|
86
88
|
tenantId: TENANT_ID,
|
|
87
89
|
}
|
|
88
|
-
await createASession(id, {
|
|
90
|
+
await createASession(id, {
|
|
91
|
+
sessionId: "sessionid",
|
|
92
|
+
tenantId: TENANT_ID,
|
|
93
|
+
csrfToken: CSRF_TOKEN,
|
|
94
|
+
})
|
|
89
95
|
if (builder) {
|
|
90
96
|
user.builder = { global: true }
|
|
91
97
|
} else {
|
|
@@ -98,7 +104,8 @@ class TestConfiguration {
|
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
|
|
101
|
-
|
|
107
|
+
// use a new id as the name to avoid name collisions
|
|
108
|
+
async init(appName = newid()) {
|
|
102
109
|
await this.globalUser()
|
|
103
110
|
return this.createApp(appName)
|
|
104
111
|
}
|
|
@@ -131,6 +138,7 @@ class TestConfiguration {
|
|
|
131
138
|
`${Cookies.Auth}=${authToken}`,
|
|
132
139
|
`${Cookies.CurrentApp}=${appToken}`,
|
|
133
140
|
],
|
|
141
|
+
[Headers.CSRF_TOKEN]: CSRF_TOKEN,
|
|
134
142
|
}
|
|
135
143
|
if (this.appId) {
|
|
136
144
|
headers[Headers.APP_ID] = this.appId
|
|
@@ -424,10 +432,6 @@ class TestConfiguration {
|
|
|
424
432
|
roles: { [this.prodAppId]: roleId },
|
|
425
433
|
})
|
|
426
434
|
}
|
|
427
|
-
await createASession(userId, {
|
|
428
|
-
sessionId: "sessionid",
|
|
429
|
-
tenantId: TENANT_ID,
|
|
430
|
-
})
|
|
431
435
|
// have to fake this
|
|
432
436
|
const auth = {
|
|
433
437
|
userId,
|
package/src/threads/query.js
CHANGED
|
@@ -180,6 +180,8 @@ function processAutoColumn(
|
|
|
180
180
|
}
|
|
181
181
|
exports.processAutoColumn = processAutoColumn
|
|
182
182
|
|
|
183
|
+
exports.processFormulas = processFormulas
|
|
184
|
+
|
|
183
185
|
/**
|
|
184
186
|
* This will coerce a value to the correct types based on the type transform map
|
|
185
187
|
* @param {object} row The value to coerce
|
|
@@ -229,11 +231,12 @@ exports.inputProcessing = (
|
|
|
229
231
|
}
|
|
230
232
|
continue
|
|
231
233
|
}
|
|
232
|
-
//
|
|
233
|
-
// type coercion cannot completely remove the field, so have to do it here
|
|
234
|
+
// remove any formula values, they are to be generated
|
|
234
235
|
if (field.type === FieldTypes.FORMULA) {
|
|
235
236
|
delete clonedRow[key]
|
|
236
|
-
}
|
|
237
|
+
}
|
|
238
|
+
// otherwise coerce what is there to correct types
|
|
239
|
+
else {
|
|
237
240
|
clonedRow[key] = exports.coerce(value, field.type)
|
|
238
241
|
}
|
|
239
242
|
}
|
|
@@ -250,7 +253,7 @@ exports.inputProcessing = (
|
|
|
250
253
|
/**
|
|
251
254
|
* This function enriches the input rows with anything they are supposed to contain, for example
|
|
252
255
|
* link records or attachment links.
|
|
253
|
-
* @param {
|
|
256
|
+
* @param {string} appId the app in which the request is looking for enriched rows.
|
|
254
257
|
* @param {object} table the table from which these rows came from originally, this is used to determine
|
|
255
258
|
* the schema of the rows and then enrich.
|
|
256
259
|
* @param {object[]|object} rows the rows which are to be enriched.
|
|
@@ -258,22 +261,21 @@ exports.inputProcessing = (
|
|
|
258
261
|
* @returns {object[]|object} the enriched rows will be returned.
|
|
259
262
|
*/
|
|
260
263
|
exports.outputProcessing = async (
|
|
261
|
-
|
|
264
|
+
{ appId },
|
|
262
265
|
table,
|
|
263
266
|
rows,
|
|
264
267
|
opts = { squash: true }
|
|
265
268
|
) => {
|
|
266
|
-
const appId = ctx.appId
|
|
267
269
|
let wasArray = true
|
|
268
270
|
if (!(rows instanceof Array)) {
|
|
269
271
|
rows = [rows]
|
|
270
272
|
wasArray = false
|
|
271
273
|
}
|
|
272
274
|
// attach any linked row information
|
|
273
|
-
let enriched = await linkRows.attachFullLinkedDocs(
|
|
275
|
+
let enriched = await linkRows.attachFullLinkedDocs(appId, table, rows)
|
|
274
276
|
|
|
275
277
|
// process formulas
|
|
276
|
-
enriched = processFormulas(table, enriched)
|
|
278
|
+
enriched = processFormulas(table, enriched, { dynamic: true })
|
|
277
279
|
|
|
278
280
|
// update the attachments URL depending on hosting
|
|
279
281
|
for (let [property, column] of Object.entries(table.schema)) {
|
|
@@ -305,9 +307,15 @@ exports.outputProcessing = async (
|
|
|
305
307
|
* @param {any} row optional - the row being removed.
|
|
306
308
|
* @param {any} rows optional - if multiple rows being deleted can do this in bulk.
|
|
307
309
|
* @param {any} oldRow optional - if updating a row this will determine the difference.
|
|
310
|
+
* @param {any} oldTable optional - if updating a table, can supply the old table to look for
|
|
311
|
+
* deleted attachment columns.
|
|
308
312
|
* @return {Promise<void>} When all attachments have been removed this will return.
|
|
309
313
|
*/
|
|
310
|
-
exports.cleanupAttachments = async (
|
|
314
|
+
exports.cleanupAttachments = async (
|
|
315
|
+
appId,
|
|
316
|
+
table,
|
|
317
|
+
{ row, rows, oldRow, oldTable }
|
|
318
|
+
) => {
|
|
311
319
|
if (!isProdAppID(appId)) {
|
|
312
320
|
const prodAppId = getDeployedAppID(appId)
|
|
313
321
|
// if prod exists, then don't allow deleting
|
|
@@ -322,12 +330,16 @@ exports.cleanupAttachments = async (appId, table, { row, rows, oldRow }) => {
|
|
|
322
330
|
files = files.concat(row[key].map(attachment => attachment.key))
|
|
323
331
|
}
|
|
324
332
|
}
|
|
325
|
-
|
|
333
|
+
const schemaToUse = oldTable ? oldTable.schema : table.schema
|
|
334
|
+
for (let [key, schema] of Object.entries(schemaToUse)) {
|
|
326
335
|
if (schema.type !== FieldTypes.ATTACHMENT) {
|
|
327
336
|
continue
|
|
328
337
|
}
|
|
329
|
-
//
|
|
330
|
-
if (
|
|
338
|
+
// old table had this column, new table doesn't - delete it
|
|
339
|
+
if (oldTable && !table.schema[key]) {
|
|
340
|
+
rows.forEach(row => addFiles(row, key))
|
|
341
|
+
} else if (oldRow && row) {
|
|
342
|
+
// if updating, need to manage the differences
|
|
331
343
|
files = files.concat(getRemovedAttachmentKeys(oldRow, row, key))
|
|
332
344
|
} else if (row) {
|
|
333
345
|
addFiles(row, key)
|
|
@@ -1,23 +1,39 @@
|
|
|
1
|
-
const { FieldTypes } = require("../../constants")
|
|
1
|
+
const { FieldTypes, FormulaTypes } = require("../../constants")
|
|
2
2
|
const { processStringSync } = require("@budibase/string-templates")
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Looks through the rows provided and finds formulas - which it then processes.
|
|
6
6
|
*/
|
|
7
|
-
exports.processFormulas = (
|
|
7
|
+
exports.processFormulas = (
|
|
8
|
+
table,
|
|
9
|
+
rows,
|
|
10
|
+
{ dynamic, contextRows } = { dynamic: true }
|
|
11
|
+
) => {
|
|
8
12
|
const single = !Array.isArray(rows)
|
|
9
13
|
if (single) {
|
|
10
14
|
rows = [rows]
|
|
15
|
+
contextRows = contextRows ? [contextRows] : contextRows
|
|
11
16
|
}
|
|
12
17
|
for (let [column, schema] of Object.entries(table.schema)) {
|
|
13
|
-
|
|
18
|
+
const isStatic = schema.formulaType === FormulaTypes.STATIC
|
|
19
|
+
if (
|
|
20
|
+
schema.type !== FieldTypes.FORMULA ||
|
|
21
|
+
(dynamic && isStatic) ||
|
|
22
|
+
(!dynamic && !isStatic)
|
|
23
|
+
) {
|
|
14
24
|
continue
|
|
15
25
|
}
|
|
16
26
|
// iterate through rows and process formula
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
27
|
+
for (let i = 0; i < rows.length; i++) {
|
|
28
|
+
if (schema.formula) {
|
|
29
|
+
let row = rows[i]
|
|
30
|
+
let context = contextRows ? contextRows[i] : row
|
|
31
|
+
rows[i] = {
|
|
32
|
+
...row,
|
|
33
|
+
[column]: processStringSync(schema.formula, context),
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
21
37
|
}
|
|
22
38
|
return single ? rows[0] : rows
|
|
23
39
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const getTenantId = jest.fn()
|
|
2
|
+
jest.mock("@budibase/backend-core/tenancy", () => ({
|
|
3
|
+
getTenantId
|
|
4
|
+
}))
|
|
5
|
+
const usageQuota = require("../../usageQuota")
|
|
6
|
+
const env = require("../../../environment")
|
|
7
|
+
|
|
8
|
+
class TestConfiguration {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.enableQuotas()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
enableQuotas = () => {
|
|
14
|
+
env.USE_QUOTAS = 1
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
disableQuotas = () => {
|
|
18
|
+
env.USE_QUOTAS = null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
setTenantId = (tenantId) => {
|
|
22
|
+
getTenantId.mockReturnValue(tenantId)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setExcludedTenants = (tenants) => {
|
|
26
|
+
env.EXCLUDE_QUOTAS_TENANTS = tenants
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
reset = () => {
|
|
30
|
+
this.disableQuotas()
|
|
31
|
+
this.setExcludedTenants(null)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
describe("usageQuota", () => {
|
|
36
|
+
let config
|
|
37
|
+
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
config = new TestConfiguration()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
config.reset()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe("useQuotas", () => {
|
|
47
|
+
it("works when no settings have been provided", () => {
|
|
48
|
+
config.reset()
|
|
49
|
+
expect(usageQuota.useQuotas()).toBe(false)
|
|
50
|
+
})
|
|
51
|
+
it("honours USE_QUOTAS setting", () => {
|
|
52
|
+
config.disableQuotas()
|
|
53
|
+
expect(usageQuota.useQuotas()).toBe(false)
|
|
54
|
+
|
|
55
|
+
config.enableQuotas()
|
|
56
|
+
expect(usageQuota.useQuotas()).toBe(true)
|
|
57
|
+
})
|
|
58
|
+
it("honours EXCLUDE_QUOTAS_TENANTS setting", () => {
|
|
59
|
+
config.setTenantId("test")
|
|
60
|
+
|
|
61
|
+
// tenantId is in the list
|
|
62
|
+
config.setExcludedTenants("test, test2, test2")
|
|
63
|
+
expect(usageQuota.useQuotas()).toBe(false)
|
|
64
|
+
config.setExcludedTenants("test,test2,test2")
|
|
65
|
+
expect(usageQuota.useQuotas()).toBe(false)
|
|
66
|
+
|
|
67
|
+
// tenantId is not in the list
|
|
68
|
+
config.setTenantId("other")
|
|
69
|
+
expect(usageQuota.useQuotas()).toBe(true)
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
})
|