@budibase/server 1.0.123 → 1.0.125
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.3d890df7.js +1299 -0
- package/builder/assets/index.89795487.css +6 -0
- package/builder/assets/{vendor.8e34a169.js → vendor.5240f480.js} +1 -1
- package/builder/index.html +3 -3
- package/coverage/clover.xml +695 -1678
- package/coverage/coverage-final.json +28 -43
- package/coverage/lcov-report/api/controllers/analytics.js.html +8 -3
- package/coverage/lcov-report/api/controllers/apikeys.js.html +9 -4
- package/coverage/lcov-report/api/controllers/auth.js.html +8 -3
- package/coverage/lcov-report/api/controllers/automation.js.html +8 -3
- package/coverage/lcov-report/api/controllers/backup.js.html +8 -3
- package/coverage/lcov-report/api/controllers/cloud.js.html +8 -3
- package/coverage/lcov-report/api/controllers/component.js.html +8 -3
- package/coverage/lcov-report/api/controllers/datasource.js.html +11 -6
- package/coverage/lcov-report/api/controllers/dev.js.html +8 -3
- package/coverage/lcov-report/api/controllers/index.html +16 -26
- package/coverage/lcov-report/api/controllers/integration.js.html +8 -3
- package/coverage/lcov-report/api/controllers/layout.js.html +8 -3
- package/coverage/lcov-report/api/controllers/metadata.js.html +8 -3
- package/coverage/lcov-report/api/controllers/migrations.js.html +8 -3
- package/coverage/lcov-report/api/controllers/permission.js.html +8 -3
- package/coverage/lcov-report/api/controllers/query/index.html +16 -26
- package/coverage/lcov-report/api/controllers/query/validation.js.html +8 -3
- package/coverage/lcov-report/api/controllers/role.js.html +10 -5
- package/coverage/lcov-report/api/controllers/routing.js.html +9 -4
- package/coverage/lcov-report/api/controllers/row/external.js.html +8 -3
- package/coverage/lcov-report/api/controllers/row/index.html +25 -35
- package/coverage/lcov-report/api/controllers/row/internal.js.html +32 -24
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +21 -16
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +24 -19
- package/coverage/lcov-report/api/controllers/row/utils.js.html +33 -19
- package/coverage/lcov-report/api/controllers/screen.js.html +9 -4
- package/coverage/lcov-report/api/controllers/script.js.html +8 -3
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +55 -50
- package/coverage/lcov-report/api/controllers/table/external.js.html +8 -3
- package/coverage/lcov-report/api/controllers/table/index.html +19 -44
- package/coverage/lcov-report/api/controllers/table/index.js.html +20 -15
- package/coverage/lcov-report/api/controllers/templates.js.html +8 -3
- package/coverage/lcov-report/api/controllers/user.js.html +8 -3
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +8 -3
- package/coverage/lcov-report/api/controllers/view/index.html +8 -3
- package/coverage/lcov-report/api/controllers/view/index.js.html +10 -5
- package/coverage/lcov-report/api/controllers/view/utils.js.html +8 -3
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +8 -3
- package/coverage/lcov-report/api/controllers/webhook.js.html +10 -5
- package/coverage/lcov-report/api/index.html +18 -13
- package/coverage/lcov-report/api/index.js.html +28 -8
- package/coverage/lcov-report/api/routes/analytics.js.html +8 -3
- package/coverage/lcov-report/api/routes/apikeys.js.html +8 -3
- package/coverage/lcov-report/api/routes/auth.js.html +8 -3
- package/coverage/lcov-report/api/routes/automation.js.html +8 -3
- package/coverage/lcov-report/api/routes/backup.js.html +8 -3
- package/coverage/lcov-report/api/routes/cloud.js.html +8 -3
- package/coverage/lcov-report/api/routes/component.js.html +8 -3
- package/coverage/lcov-report/api/routes/datasource.js.html +8 -3
- package/coverage/lcov-report/api/routes/deploy.js.html +8 -3
- package/coverage/lcov-report/api/routes/dev.js.html +9 -4
- package/coverage/lcov-report/api/routes/index.html +13 -68
- package/coverage/lcov-report/api/routes/integration.js.html +8 -3
- package/coverage/lcov-report/api/routes/layout.js.html +8 -3
- package/coverage/lcov-report/api/routes/metadata.js.html +8 -3
- package/coverage/lcov-report/api/routes/migrations.js.html +8 -3
- package/coverage/lcov-report/api/routes/permission.js.html +8 -3
- package/coverage/lcov-report/api/routes/query.js.html +8 -3
- package/coverage/lcov-report/api/routes/role.js.html +8 -3
- package/coverage/lcov-report/api/routes/routing.js.html +8 -3
- package/coverage/lcov-report/api/routes/screen.js.html +8 -3
- package/coverage/lcov-report/api/routes/script.js.html +8 -3
- package/coverage/lcov-report/api/routes/table.js.html +8 -3
- package/coverage/lcov-report/api/routes/templates.js.html +8 -3
- package/coverage/lcov-report/api/routes/user.js.html +8 -3
- package/coverage/lcov-report/api/routes/utils/index.html +8 -3
- package/coverage/lcov-report/api/routes/utils/validators.js.html +8 -3
- package/coverage/lcov-report/api/routes/view.js.html +8 -3
- package/coverage/lcov-report/api/routes/webhook.js.html +8 -3
- package/coverage/lcov-report/automations/actions.js.html +21 -7
- package/coverage/lcov-report/automations/automationUtils.js.html +64 -23
- package/coverage/lcov-report/automations/bullboard.js.html +8 -3
- package/coverage/lcov-report/automations/index.html +27 -37
- package/coverage/lcov-report/automations/index.js.html +8 -3
- package/coverage/lcov-report/automations/steps/bash.js.html +8 -3
- package/coverage/lcov-report/automations/steps/delay.js.html +8 -3
- package/coverage/lcov-report/automations/steps/discord.js.html +8 -3
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +8 -3
- package/coverage/lcov-report/automations/steps/executeScript.js.html +8 -3
- package/coverage/lcov-report/automations/steps/filter.js.html +8 -3
- package/coverage/lcov-report/automations/steps/index.html +31 -41
- package/coverage/lcov-report/automations/steps/integromat.js.html +8 -3
- package/coverage/lcov-report/{api/routes/static.js.html → automations/steps/loop.js.html} +70 -80
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +9 -4
- package/coverage/lcov-report/automations/steps/queryRows.js.html +9 -4
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +8 -3
- package/coverage/lcov-report/automations/steps/serverLog.js.html +8 -3
- package/coverage/lcov-report/automations/steps/slack.js.html +8 -3
- package/coverage/lcov-report/automations/steps/updateRow.js.html +8 -3
- package/coverage/lcov-report/automations/steps/utils.js.html +14 -9
- package/coverage/lcov-report/automations/steps/zapier.js.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/index.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +8 -3
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +8 -3
- package/coverage/lcov-report/automations/triggers.js.html +16 -11
- package/coverage/lcov-report/block-navigation.js +8 -0
- package/coverage/lcov-report/constants/index.html +12 -7
- package/coverage/lcov-report/constants/index.js.html +55 -32
- package/coverage/lcov-report/constants/layouts.js.html +8 -3
- package/coverage/lcov-report/constants/screens.js.html +8 -3
- package/coverage/lcov-report/db/inMemoryView.js.html +8 -3
- package/coverage/lcov-report/db/index.html +8 -3
- package/coverage/lcov-report/db/index.js.html +9 -4
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +20 -15
- package/coverage/lcov-report/db/linkedRows/index.html +8 -3
- package/coverage/lcov-report/db/linkedRows/index.js.html +22 -17
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +12 -7
- package/coverage/lcov-report/db/newid.js.html +11 -6
- package/coverage/lcov-report/db/utils.js.html +84 -79
- package/coverage/lcov-report/events/AutomationEmitter.js.html +14 -9
- package/coverage/lcov-report/events/index.html +8 -3
- package/coverage/lcov-report/events/index.js.html +9 -4
- package/coverage/lcov-report/events/utils.js.html +18 -13
- package/coverage/lcov-report/index.html +125 -120
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +8 -3
- package/coverage/lcov-report/integrations/tests/index.html +8 -3
- package/coverage/lcov-report/middleware/appInfo.js.html +8 -3
- package/coverage/lcov-report/middleware/builder.js.html +8 -3
- package/coverage/lcov-report/middleware/currentapp.js.html +65 -15
- package/coverage/lcov-report/middleware/index.html +25 -50
- package/coverage/lcov-report/middleware/joi-validator.js.html +9 -4
- package/coverage/lcov-report/middleware/publicApi.js.html +8 -3
- package/coverage/lcov-report/middleware/resourceId.js.html +8 -3
- package/coverage/lcov-report/middleware/selfhost.js.html +9 -4
- package/coverage/lcov-report/middleware/utils.js.html +8 -3
- package/coverage/lcov-report/sorter.js +26 -0
- package/coverage/lcov-report/threads/automation.js.html +581 -90
- package/coverage/lcov-report/threads/index.html +30 -40
- package/coverage/lcov-report/threads/query.js.html +9 -4
- package/coverage/lcov-report/threads/utils.js.html +17 -9
- package/coverage/lcov-report/utilities/bcrypt.js.html +8 -3
- package/coverage/lcov-report/utilities/budibaseDir.js.html +8 -3
- package/coverage/lcov-report/utilities/centralPath.js.html +8 -3
- package/coverage/lcov-report/utilities/csvParser.js.html +10 -5
- package/coverage/lcov-report/utilities/global.js.html +9 -4
- package/coverage/lcov-report/utilities/index.html +8 -3
- package/coverage/lcov-report/utilities/index.js.html +11 -6
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +32 -9
- package/coverage/lcov-report/utilities/queue/index.html +12 -7
- package/coverage/lcov-report/utilities/routing/index.html +8 -3
- package/coverage/lcov-report/utilities/routing/index.js.html +8 -3
- package/coverage/lcov-report/utilities/rowProcessor/index.html +8 -3
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +48 -43
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +18 -13
- package/coverage/lcov-report/utilities/scriptRunner.js.html +8 -3
- package/coverage/lcov-report/utilities/security.js.html +9 -4
- package/coverage/lcov-report/utilities/statusCodes.js.html +8 -3
- package/coverage/lcov-report/utilities/usageQuota/index.html +24 -34
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +44 -39
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +8 -3
- package/coverage/lcov-report/utilities/users.js.html +8 -3
- package/coverage/lcov-report/utilities/workerRequests.js.html +9 -4
- package/coverage/lcov.info +1144 -2875
- package/dist/api/controllers/application.js +145 -73
- package/dist/api/controllers/deploy/index.js +68 -36
- package/dist/api/controllers/public/applications.js +29 -9
- package/dist/api/controllers/public/queries.js +27 -7
- package/dist/api/controllers/public/rows.js +32 -12
- package/dist/api/controllers/public/tables.js +2 -2
- package/dist/api/controllers/public/users.js +8 -8
- package/dist/api/controllers/public/utils.js +1 -1
- package/dist/api/controllers/query/import/index.js +3 -3
- package/dist/api/controllers/query/index.js +57 -44
- package/dist/api/controllers/row/ExternalRequest.js +27 -27
- package/dist/api/controllers/row/index.js +83 -60
- package/dist/api/controllers/row/internal.js +2 -1
- package/dist/api/controllers/row/utils.js +2 -1
- package/dist/api/controllers/static/templates/BudibaseApp.svelte +3 -0
- package/dist/api/controllers/table/bulkFormula.js +2 -1
- package/dist/api/controllers/table/internal.js +41 -35
- package/dist/api/controllers/table/utils.js +271 -229
- package/dist/api/index.js +5 -0
- package/dist/api/routes/application.js +39 -13
- package/dist/api/routes/index.js +61 -56
- package/dist/api/routes/public/index.js +6 -9
- package/dist/api/routes/public/queries.js +1 -1
- package/dist/api/routes/public/rows.js +1 -1
- package/dist/api/routes/public/tables.js +3 -3
- package/dist/api/routes/public/users.js +1 -1
- package/dist/api/routes/row.js +43 -17
- package/dist/api/routes/static.js +40 -13
- package/dist/api/routes/tests/utilities/TestFunctions.js +75 -33
- package/dist/app.js +8 -4
- package/dist/automations/actions.js +3 -0
- package/dist/automations/automationUtils.js +10 -0
- package/dist/automations/steps/createRow.js +12 -12
- package/dist/automations/steps/deleteRow.js +13 -16
- package/dist/automations/steps/loop.js +51 -0
- package/dist/automations/tests/utilities/index.js +13 -11
- package/dist/automations/utils.js +187 -133
- package/dist/constants/index.js +5 -0
- package/dist/definitions/datasource.js +1 -0
- package/dist/environment.js +2 -3
- package/dist/index.js +4 -0
- package/dist/integrations/base/sql.js +2 -2
- package/dist/integrations/base/sqlTable.js +2 -2
- package/dist/integrations/googlesheets.js +1 -1
- package/dist/integrations/index.js +4 -0
- package/dist/integrations/microsoftSqlServer.js +8 -8
- package/dist/integrations/mysql.js +9 -9
- package/dist/integrations/oracle.js +7 -7
- package/dist/integrations/postgres.js +7 -7
- package/dist/integrations/queries/sql.js +2 -2
- package/dist/integrations/redis.js +158 -0
- package/dist/integrations/rest.js +1 -1
- package/dist/middleware/authorized.js +51 -51
- package/dist/middleware/currentapp.js +15 -1
- package/dist/migrations/functions/appUrls.js +1 -1
- package/dist/migrations/functions/developerQuota.js +49 -0
- package/dist/migrations/functions/publishedAppsQuota.js +47 -0
- package/dist/migrations/functions/quotas1.js +6 -2
- package/dist/migrations/functions/usageQuotas/index.js +0 -4
- package/dist/migrations/functions/usageQuotas/syncApps.js +4 -7
- package/dist/migrations/functions/usageQuotas/syncDevelopers.js +24 -0
- package/dist/migrations/functions/usageQuotas/syncPublishedApps.js +26 -0
- package/dist/migrations/functions/usageQuotas/syncRows.js +5 -8
- package/dist/migrations/index.js +17 -1
- package/dist/package.json +14 -8
- package/dist/threads/automation.js +149 -27
- package/dist/threads/index.js +36 -10
- package/dist/threads/utils.js +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/utilities/queue/inMemoryQueue.js +6 -1
- package/nodemon.json +1 -1
- package/package.json +15 -9
- package/scripts/dev/manage.js +2 -0
- package/src/api/controllers/{application.js → application.ts} +118 -51
- package/src/api/controllers/deploy/{index.js → index.ts} +53 -29
- package/src/api/controllers/public/applications.ts +2 -2
- package/src/api/controllers/public/queries.ts +1 -1
- package/src/api/controllers/public/rows.ts +1 -1
- package/src/api/controllers/query/{index.js → index.ts} +51 -48
- package/src/api/controllers/row/ExternalRequest.ts +1 -1
- package/src/api/controllers/row/{index.js → index.ts} +24 -17
- package/src/api/controllers/row/internal.js +2 -1
- package/src/api/controllers/row/utils.js +4 -1
- package/src/api/controllers/static/templates/BudibaseApp.svelte +3 -0
- package/src/api/controllers/table/bulkFormula.js +1 -1
- package/src/api/controllers/table/{internal.js → internal.ts} +30 -26
- package/src/api/controllers/table/{utils.js → utils.ts} +86 -69
- package/src/api/index.js +5 -0
- package/src/api/routes/{application.js → application.ts} +8 -14
- package/src/api/routes/index.ts +60 -0
- package/src/api/routes/public/index.ts +1 -4
- package/src/api/routes/{row.js → row.ts} +7 -15
- package/src/api/routes/{static.js → static.ts} +11 -11
- package/src/api/routes/tests/misc.spec.js +39 -37
- package/src/api/routes/tests/utilities/{TestFunctions.js → TestFunctions.ts} +57 -33
- package/src/app.ts +1 -2
- package/src/automations/actions.js +3 -0
- package/src/automations/automationUtils.js +12 -0
- package/src/automations/steps/{createRow.js → createRow.ts} +9 -15
- package/src/automations/steps/{deleteRow.js → deleteRow.ts} +10 -16
- package/src/automations/steps/loop.js +50 -0
- package/src/automations/tests/automation.spec.js +0 -1
- package/src/automations/tests/{createRow.spec.js → createRow.spec.ts} +4 -15
- package/src/automations/tests/{deleteRow.spec.js → deleteRow.spec.ts} +3 -5
- package/src/automations/tests/utilities/index.js +12 -10
- package/src/automations/{utils.js → utils.ts} +39 -28
- package/src/constants/index.js +6 -0
- package/src/definitions/common.ts +1 -0
- package/src/definitions/datasource.ts +1 -0
- package/src/environment.js +2 -3
- package/src/index.ts +3 -0
- package/src/integrations/index.ts +4 -0
- package/src/integrations/redis.ts +152 -0
- package/src/integrations/tests/redis.spec.js +60 -0
- package/src/middleware/{authorized.js → authorized.ts} +20 -14
- package/src/middleware/currentapp.js +16 -1
- package/src/middleware/tests/currentapp.spec.js +8 -4
- package/src/migrations/functions/developerQuota.ts +15 -0
- package/src/migrations/functions/publishedAppsQuota.ts +13 -0
- package/src/migrations/functions/tests/quotas1.spec.js +0 -2
- package/src/migrations/functions/usageQuotas/index.ts +0 -5
- package/src/migrations/functions/usageQuotas/syncApps.ts +3 -6
- package/src/migrations/functions/usageQuotas/syncDevelopers.ts +19 -0
- package/src/migrations/functions/usageQuotas/syncPublishedApps.ts +21 -0
- package/src/migrations/functions/usageQuotas/syncRows.ts +3 -6
- package/src/migrations/functions/usageQuotas/tests/syncApps.spec.ts +34 -0
- package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +40 -0
- package/src/migrations/index.ts +13 -1
- package/src/threads/automation.js +196 -34
- package/src/threads/{index.js → index.ts} +18 -14
- package/src/threads/utils.js +1 -0
- package/src/utilities/queue/inMemoryQueue.js +7 -1
- package/tsconfig.build.json +10 -0
- package/tsconfig.json +2 -2
- package/builder/assets/index.68a7f4e3.css +0 -6
- package/builder/assets/index.8d4a5b33.js +0 -1291
- package/coverage/lcov-report/api/controllers/application.js.html +0 -1436
- package/coverage/lcov-report/api/controllers/query/index.js.html +0 -713
- package/coverage/lcov-report/api/controllers/row/index.js.html +0 -524
- package/coverage/lcov-report/api/controllers/table/internal.js.html +0 -620
- package/coverage/lcov-report/api/controllers/table/utils.js.html +0 -1331
- package/coverage/lcov-report/api/routes/application.js.html +0 -179
- package/coverage/lcov-report/api/routes/index.js.html +0 -266
- package/coverage/lcov-report/api/routes/row.js.html +0 -908
- package/coverage/lcov-report/automations/steps/createRow.js.html +0 -380
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +0 -347
- package/coverage/lcov-report/automations/utils.js.html +0 -665
- package/coverage/lcov-report/middleware/authorized.js.html +0 -458
- package/coverage/lcov-report/middleware/usageQuota.js.html +0 -572
- package/coverage/lcov-report/threads/index.js.html +0 -296
- package/coverage/lcov-report/utilities/usageQuota/index.js.html +0 -359
- package/dist/middleware/usageQuota.js +0 -154
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/dist/utilities/usageQuota/index.js +0 -86
- package/src/api/routes/index.js +0 -62
- package/src/middleware/tests/usageQuota.spec.js +0 -120
- package/src/middleware/usageQuota.js +0 -164
- package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +0 -41
- package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +0 -45
- package/src/utilities/tests/usageQuota/usageQuota.spec.js +0 -72
- package/src/utilities/usageQuota/index.js +0 -93
|
@@ -1,86 +0,0 @@
|
|
|
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 env = require("../../environment");
|
|
12
|
-
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy");
|
|
13
|
-
const { StaticDatabases, generateNewUsageQuotaDoc, } = require("@budibase/backend-core/db");
|
|
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
|
-
};
|
|
29
|
-
exports.Properties = {
|
|
30
|
-
ROW: "rows",
|
|
31
|
-
UPLOAD: "storage",
|
|
32
|
-
VIEW: "views",
|
|
33
|
-
USER: "users",
|
|
34
|
-
AUTOMATION: "automationRuns",
|
|
35
|
-
APPS: "apps",
|
|
36
|
-
EMAILS: "emails", // doesn't work yet
|
|
37
|
-
};
|
|
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
|
-
});
|
|
51
|
-
/**
|
|
52
|
-
* Given a specified tenantId this will add to the usage object for the specified property.
|
|
53
|
-
* @param {string} property The property which is to be added to (within the nested usageQuota object).
|
|
54
|
-
* @param {number} usage The amount (this can be negative) to adjust the number by.
|
|
55
|
-
* @param {object} opts optional - options such as dryRun, to check what update will do.
|
|
56
|
-
* @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
|
|
57
|
-
* also been reset after this call.
|
|
58
|
-
*/
|
|
59
|
-
exports.update = (property, usage, opts = { dryRun: false }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
-
if (!exports.useQuotas()) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
try {
|
|
64
|
-
const db = getGlobalDB();
|
|
65
|
-
const quota = yield exports.getUsageQuotaDoc(db);
|
|
66
|
-
// increment the quota
|
|
67
|
-
quota.usageQuota[property] += usage;
|
|
68
|
-
if (quota.usageQuota[property] > quota.usageLimits[property] &&
|
|
69
|
-
usage > 0 // allow for decrementing usage when the quota is already exceeded
|
|
70
|
-
) {
|
|
71
|
-
throw new Error(`You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`);
|
|
72
|
-
}
|
|
73
|
-
if (quota.usageQuota[property] < 0) {
|
|
74
|
-
// never go negative if the quota has previously been exceeded
|
|
75
|
-
quota.usageQuota[property] = 0;
|
|
76
|
-
}
|
|
77
|
-
// update the usage quotas
|
|
78
|
-
if (!opts.dryRun) {
|
|
79
|
-
yield db.put(quota);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
console.error(`Error updating usage quotas for ${property}`, err);
|
|
84
|
-
throw err;
|
|
85
|
-
}
|
|
86
|
-
});
|
package/src/api/routes/index.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
const authRoutes = require("./auth")
|
|
2
|
-
const layoutRoutes = require("./layout")
|
|
3
|
-
const screenRoutes = require("./screen")
|
|
4
|
-
const userRoutes = require("./user")
|
|
5
|
-
const applicationRoutes = require("./application")
|
|
6
|
-
const tableRoutes = require("./table")
|
|
7
|
-
const rowRoutes = require("./row")
|
|
8
|
-
const viewRoutes = require("./view")
|
|
9
|
-
const staticRoutes = require("./static")
|
|
10
|
-
const componentRoutes = require("./component")
|
|
11
|
-
const automationRoutes = require("./automation")
|
|
12
|
-
const webhookRoutes = require("./webhook")
|
|
13
|
-
const roleRoutes = require("./role")
|
|
14
|
-
const deployRoutes = require("./deploy")
|
|
15
|
-
const apiKeysRoutes = require("./apikeys")
|
|
16
|
-
const templatesRoutes = require("./templates")
|
|
17
|
-
const analyticsRoutes = require("./analytics")
|
|
18
|
-
const routingRoutes = require("./routing")
|
|
19
|
-
const integrationRoutes = require("./integration")
|
|
20
|
-
const permissionRoutes = require("./permission")
|
|
21
|
-
const datasourceRoutes = require("./datasource")
|
|
22
|
-
const queryRoutes = require("./query")
|
|
23
|
-
const backupRoutes = require("./backup")
|
|
24
|
-
const metadataRoutes = require("./metadata")
|
|
25
|
-
const devRoutes = require("./dev")
|
|
26
|
-
const cloudRoutes = require("./cloud")
|
|
27
|
-
const migrationRoutes = require("./migrations")
|
|
28
|
-
const publicRoutes = require("./public")
|
|
29
|
-
|
|
30
|
-
exports.mainRoutes = [
|
|
31
|
-
authRoutes,
|
|
32
|
-
deployRoutes,
|
|
33
|
-
layoutRoutes,
|
|
34
|
-
screenRoutes,
|
|
35
|
-
userRoutes,
|
|
36
|
-
applicationRoutes,
|
|
37
|
-
automationRoutes,
|
|
38
|
-
viewRoutes,
|
|
39
|
-
componentRoutes,
|
|
40
|
-
roleRoutes,
|
|
41
|
-
apiKeysRoutes,
|
|
42
|
-
templatesRoutes,
|
|
43
|
-
analyticsRoutes,
|
|
44
|
-
webhookRoutes,
|
|
45
|
-
routingRoutes,
|
|
46
|
-
integrationRoutes,
|
|
47
|
-
permissionRoutes,
|
|
48
|
-
datasourceRoutes,
|
|
49
|
-
queryRoutes,
|
|
50
|
-
backupRoutes,
|
|
51
|
-
metadataRoutes,
|
|
52
|
-
devRoutes,
|
|
53
|
-
cloudRoutes,
|
|
54
|
-
// these need to be handled last as they still use /api/:tableId
|
|
55
|
-
// this could be breaking as koa may recognise other routes as this
|
|
56
|
-
tableRoutes,
|
|
57
|
-
rowRoutes,
|
|
58
|
-
migrationRoutes,
|
|
59
|
-
]
|
|
60
|
-
|
|
61
|
-
exports.publicRoutes = publicRoutes
|
|
62
|
-
exports.staticRoutes = staticRoutes
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
jest.mock("../../db")
|
|
2
|
-
jest.mock("../../utilities/usageQuota")
|
|
3
|
-
jest.mock("@budibase/backend-core/tenancy", () => ({
|
|
4
|
-
getTenantId: () => "testing123"
|
|
5
|
-
}))
|
|
6
|
-
|
|
7
|
-
const usageQuotaMiddleware = require("../usageQuota")
|
|
8
|
-
const usageQuota = require("../../utilities/usageQuota")
|
|
9
|
-
|
|
10
|
-
jest.mock("@budibase/backend-core/db")
|
|
11
|
-
const { dangerousGetDB } = require("@budibase/backend-core/db")
|
|
12
|
-
|
|
13
|
-
const env = require("../../environment")
|
|
14
|
-
|
|
15
|
-
class TestConfiguration {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.throw = jest.fn()
|
|
18
|
-
this.next = jest.fn()
|
|
19
|
-
this.middleware = usageQuotaMiddleware
|
|
20
|
-
this.ctx = {
|
|
21
|
-
throw: this.throw,
|
|
22
|
-
next: this.next,
|
|
23
|
-
appId: "test",
|
|
24
|
-
request: {
|
|
25
|
-
body: {}
|
|
26
|
-
},
|
|
27
|
-
req: {
|
|
28
|
-
method: "POST",
|
|
29
|
-
url: "/applications"
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
usageQuota.useQuotas = () => true
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
executeMiddleware() {
|
|
36
|
-
return this.middleware(this.ctx, this.next)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
setProd(bool) {
|
|
40
|
-
if (bool) {
|
|
41
|
-
env.isDev = () => false
|
|
42
|
-
env.isProd = () => true
|
|
43
|
-
this.ctx.user = { tenantId: "test" }
|
|
44
|
-
} else {
|
|
45
|
-
env.isDev = () => true
|
|
46
|
-
env.isProd = () => false
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
setMethod(method) {
|
|
51
|
-
this.ctx.req.method = method
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
setUrl(url) {
|
|
55
|
-
this.ctx.req.url = url
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
setBody(body) {
|
|
59
|
-
this.ctx.request.body = body
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
setFiles(files) {
|
|
63
|
-
this.ctx.request.files = { file: files }
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
describe("usageQuota middleware", () => {
|
|
68
|
-
let config
|
|
69
|
-
|
|
70
|
-
beforeEach(() => {
|
|
71
|
-
config = new TestConfiguration()
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it("skips the middleware if there is no usage property or method", async () => {
|
|
75
|
-
await config.executeMiddleware()
|
|
76
|
-
expect(config.next).toHaveBeenCalled()
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it("passes through to next middleware if document already exists", async () => {
|
|
80
|
-
config.setProd(true)
|
|
81
|
-
config.setBody({
|
|
82
|
-
_id: "test",
|
|
83
|
-
_rev: "test",
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
dangerousGetDB.mockImplementationOnce(() => ({
|
|
87
|
-
get: async () => true
|
|
88
|
-
}))
|
|
89
|
-
|
|
90
|
-
await config.executeMiddleware()
|
|
91
|
-
|
|
92
|
-
expect(config.next).toHaveBeenCalled()
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
it("throws if request has _id, but the document no longer exists", async () => {
|
|
96
|
-
config.setBody({
|
|
97
|
-
_id: "123",
|
|
98
|
-
_rev: "test",
|
|
99
|
-
})
|
|
100
|
-
config.setProd(true)
|
|
101
|
-
|
|
102
|
-
dangerousGetDB.mockImplementationOnce(() => ({
|
|
103
|
-
get: async () => {
|
|
104
|
-
throw new Error()
|
|
105
|
-
}
|
|
106
|
-
}))
|
|
107
|
-
|
|
108
|
-
await config.executeMiddleware()
|
|
109
|
-
expect(config.throw).toHaveBeenCalledWith(404, `${config.ctx.request.body._id} does not exist`)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
it("calculates and persists the correct usage quota for the relevant action", async () => {
|
|
113
|
-
config.setUrl("/rows")
|
|
114
|
-
|
|
115
|
-
await config.executeMiddleware()
|
|
116
|
-
|
|
117
|
-
expect(usageQuota.update).toHaveBeenCalledWith("rows", 1)
|
|
118
|
-
expect(config.next).toHaveBeenCalled()
|
|
119
|
-
})
|
|
120
|
-
})
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
const usageQuota = require("../utilities/usageQuota")
|
|
2
|
-
const { getUniqueRows } = require("../utilities/usageQuota/rows")
|
|
3
|
-
const {
|
|
4
|
-
isExternalTable,
|
|
5
|
-
isRowId: isExternalRowId,
|
|
6
|
-
} = require("../integrations/utils")
|
|
7
|
-
const { getAppDB } = require("@budibase/backend-core/context")
|
|
8
|
-
|
|
9
|
-
// currently only counting new writes and deletes
|
|
10
|
-
const METHOD_MAP = {
|
|
11
|
-
POST: 1,
|
|
12
|
-
DELETE: -1,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const DOMAIN_MAP = {
|
|
16
|
-
rows: usageQuota.Properties.ROW,
|
|
17
|
-
// upload: usageQuota.Properties.UPLOAD, // doesn't work yet
|
|
18
|
-
// views: usageQuota.Properties.VIEW, // doesn't work yet
|
|
19
|
-
// users: usageQuota.Properties.USER, // doesn't work yet
|
|
20
|
-
applications: usageQuota.Properties.APPS,
|
|
21
|
-
// this will not be updated by endpoint calls
|
|
22
|
-
// instead it will be updated by triggerInfo
|
|
23
|
-
// automationRuns: usageQuota.Properties.AUTOMATION, // doesn't work yet
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function getProperty(url) {
|
|
27
|
-
for (let domain of Object.keys(DOMAIN_MAP)) {
|
|
28
|
-
if (url.indexOf(domain) !== -1) {
|
|
29
|
-
return DOMAIN_MAP[domain]
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
module.exports = async (ctx, next) => {
|
|
35
|
-
if (!usageQuota.useQuotas()) {
|
|
36
|
-
return next()
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let usage = METHOD_MAP[ctx.req.method]
|
|
40
|
-
const property = getProperty(ctx.req.url)
|
|
41
|
-
if (usage == null || property == null) {
|
|
42
|
-
return next()
|
|
43
|
-
}
|
|
44
|
-
// post request could be a save of a pre-existing entry
|
|
45
|
-
if (ctx.request.body && ctx.request.body._id && ctx.request.body._rev) {
|
|
46
|
-
const usageId = ctx.request.body._id
|
|
47
|
-
try {
|
|
48
|
-
if (ctx.appId) {
|
|
49
|
-
const db = getAppDB()
|
|
50
|
-
await db.get(usageId)
|
|
51
|
-
}
|
|
52
|
-
return next()
|
|
53
|
-
} catch (err) {
|
|
54
|
-
if (
|
|
55
|
-
isExternalTable(usageId) ||
|
|
56
|
-
(ctx.request.body.tableId &&
|
|
57
|
-
isExternalTable(ctx.request.body.tableId)) ||
|
|
58
|
-
isExternalRowId(usageId)
|
|
59
|
-
) {
|
|
60
|
-
return next()
|
|
61
|
-
} else {
|
|
62
|
-
ctx.throw(404, `${usageId} does not exist`)
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// update usage for uploads to be the total size
|
|
68
|
-
if (property === usageQuota.Properties.UPLOAD) {
|
|
69
|
-
const files =
|
|
70
|
-
ctx.request.files.file.length > 1
|
|
71
|
-
? Array.from(ctx.request.files.file)
|
|
72
|
-
: [ctx.request.files.file]
|
|
73
|
-
usage = files.map(file => file.size).reduce((total, size) => total + size)
|
|
74
|
-
}
|
|
75
|
-
try {
|
|
76
|
-
await performRequest(ctx, next, property, usage)
|
|
77
|
-
} catch (err) {
|
|
78
|
-
ctx.throw(400, err)
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const performRequest = async (ctx, next, property, usage) => {
|
|
83
|
-
const usageContext = {
|
|
84
|
-
skipNext: false,
|
|
85
|
-
skipUsage: false,
|
|
86
|
-
[usageQuota.Properties.APPS]: {},
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (usage === -1) {
|
|
90
|
-
if (PRE_DELETE[property]) {
|
|
91
|
-
await PRE_DELETE[property](ctx, usageContext)
|
|
92
|
-
}
|
|
93
|
-
} else {
|
|
94
|
-
if (PRE_CREATE[property]) {
|
|
95
|
-
await PRE_CREATE[property](ctx, usageContext)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// run the request
|
|
100
|
-
if (!usageContext.skipNext) {
|
|
101
|
-
await usageQuota.update(property, usage, { dryRun: true })
|
|
102
|
-
await next()
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (usage === -1) {
|
|
106
|
-
if (POST_DELETE[property]) {
|
|
107
|
-
await POST_DELETE[property](ctx, usageContext)
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
if (POST_CREATE[property]) {
|
|
111
|
-
await POST_CREATE[property](ctx, usageContext)
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// update the usage
|
|
116
|
-
if (!usageContext.skipUsage) {
|
|
117
|
-
await usageQuota.update(property, usage)
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const appPreDelete = async (ctx, usageContext) => {
|
|
122
|
-
if (ctx.query.unpublish) {
|
|
123
|
-
// don't run usage decrement for unpublish
|
|
124
|
-
usageContext.skipUsage = true
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// store the row count to delete
|
|
129
|
-
const rows = await getUniqueRows([ctx.appId])
|
|
130
|
-
if (rows.length) {
|
|
131
|
-
usageContext[usageQuota.Properties.APPS] = { rowCount: rows.length }
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const appPostDelete = async (ctx, usageContext) => {
|
|
136
|
-
// delete the app rows from usage
|
|
137
|
-
const rowCount = usageContext[usageQuota.Properties.APPS].rowCount
|
|
138
|
-
if (rowCount) {
|
|
139
|
-
await usageQuota.update(usageQuota.Properties.ROW, -rowCount)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const appPostCreate = async ctx => {
|
|
144
|
-
// app import & template creation
|
|
145
|
-
if (ctx.request.body.useTemplate === "true") {
|
|
146
|
-
const rows = await getUniqueRows([ctx.response.body.appId])
|
|
147
|
-
const rowCount = rows ? rows.length : 0
|
|
148
|
-
await usageQuota.update(usageQuota.Properties.ROW, rowCount)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const PRE_DELETE = {
|
|
153
|
-
[usageQuota.Properties.APPS]: appPreDelete,
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const POST_DELETE = {
|
|
157
|
-
[usageQuota.Properties.APPS]: appPostDelete,
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const PRE_CREATE = {}
|
|
161
|
-
|
|
162
|
-
const POST_CREATE = {
|
|
163
|
-
[usageQuota.Properties.APPS]: appPostCreate,
|
|
164
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
2
|
-
const TestConfig = require("../../../../tests/utilities/TestConfiguration")
|
|
3
|
-
const { TENANT_ID } = require("../../../../tests/utilities/structures")
|
|
4
|
-
const { getUsageQuotaDoc, update, Properties } = require("../../../../utilities/usageQuota")
|
|
5
|
-
const syncApps = require("../syncApps")
|
|
6
|
-
const env = require("../../../../environment")
|
|
7
|
-
|
|
8
|
-
describe("syncApps", () => {
|
|
9
|
-
|
|
10
|
-
let config = new TestConfig(false)
|
|
11
|
-
|
|
12
|
-
beforeEach(async () => {
|
|
13
|
-
await config.init()
|
|
14
|
-
env._set("USE_QUOTAS", 1)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
afterAll(config.end)
|
|
18
|
-
|
|
19
|
-
it("runs successfully", async () => {
|
|
20
|
-
await doInTenant(TENANT_ID, async () => {
|
|
21
|
-
const db = getGlobalDB()
|
|
22
|
-
// create the usage quota doc and mock usages
|
|
23
|
-
await getUsageQuotaDoc(db)
|
|
24
|
-
await update(Properties.APPS, 3)
|
|
25
|
-
|
|
26
|
-
let usageDoc = await getUsageQuotaDoc(db)
|
|
27
|
-
expect(usageDoc.usageQuota.apps).toEqual(3)
|
|
28
|
-
|
|
29
|
-
// create an extra app to test the migration
|
|
30
|
-
await config.createApp("quota-test")
|
|
31
|
-
|
|
32
|
-
// migrate
|
|
33
|
-
await syncApps.run()
|
|
34
|
-
|
|
35
|
-
// assert the migration worked
|
|
36
|
-
usageDoc = await getUsageQuotaDoc(db)
|
|
37
|
-
expect(usageDoc.usageQuota.apps).toEqual(2)
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
})
|
|
41
|
-
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
const { doInTenant, getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
2
|
-
const TestConfig = require("../../../../tests/utilities/TestConfiguration")
|
|
3
|
-
const { TENANT_ID } = require("../../../../tests/utilities/structures")
|
|
4
|
-
const { getUsageQuotaDoc, update, Properties } = require("../../../../utilities/usageQuota")
|
|
5
|
-
const syncRows = require("../syncRows")
|
|
6
|
-
const env = require("../../../../environment")
|
|
7
|
-
|
|
8
|
-
describe("syncRows", () => {
|
|
9
|
-
let config = new TestConfig(false)
|
|
10
|
-
|
|
11
|
-
beforeEach(async () => {
|
|
12
|
-
await config.init()
|
|
13
|
-
env._set("USE_QUOTAS", 1)
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
afterAll(config.end)
|
|
17
|
-
|
|
18
|
-
it("runs successfully", async () => {
|
|
19
|
-
await doInTenant(TENANT_ID, async () => {
|
|
20
|
-
const db = getGlobalDB()
|
|
21
|
-
await getUsageQuotaDoc(db)
|
|
22
|
-
await update(Properties.ROW, 300)
|
|
23
|
-
|
|
24
|
-
let usageDoc = await getUsageQuotaDoc(db)
|
|
25
|
-
expect(usageDoc.usageQuota.rows).toEqual(300)
|
|
26
|
-
|
|
27
|
-
// app 1
|
|
28
|
-
await config.createTable()
|
|
29
|
-
await config.createRow()
|
|
30
|
-
// app 2
|
|
31
|
-
await config.createApp("second-app")
|
|
32
|
-
await config.createTable()
|
|
33
|
-
await config.createRow()
|
|
34
|
-
await config.createRow()
|
|
35
|
-
|
|
36
|
-
// migrate
|
|
37
|
-
await syncRows.run()
|
|
38
|
-
|
|
39
|
-
// assert the migration worked
|
|
40
|
-
usageDoc = await getUsageQuotaDoc(db)
|
|
41
|
-
expect(usageDoc.usageQuota.rows).toEqual(3)
|
|
42
|
-
})
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
|
|
@@ -1,72 +0,0 @@
|
|
|
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
|
-
})
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
const env = require("../../environment")
|
|
2
|
-
const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy")
|
|
3
|
-
const {
|
|
4
|
-
StaticDatabases,
|
|
5
|
-
generateNewUsageQuotaDoc,
|
|
6
|
-
} = require("@budibase/backend-core/db")
|
|
7
|
-
|
|
8
|
-
exports.useQuotas = () => {
|
|
9
|
-
// check if quotas are enabled
|
|
10
|
-
if (env.USE_QUOTAS) {
|
|
11
|
-
// check if there are any tenants without limits
|
|
12
|
-
if (env.EXCLUDE_QUOTAS_TENANTS) {
|
|
13
|
-
const excludedTenants = env.EXCLUDE_QUOTAS_TENANTS.replace(
|
|
14
|
-
/\s/g,
|
|
15
|
-
""
|
|
16
|
-
).split(",")
|
|
17
|
-
const tenantId = getTenantId()
|
|
18
|
-
if (excludedTenants.includes(tenantId)) {
|
|
19
|
-
return false
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
return true
|
|
23
|
-
}
|
|
24
|
-
return false
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
exports.Properties = {
|
|
28
|
-
ROW: "rows",
|
|
29
|
-
UPLOAD: "storage", // doesn't work yet
|
|
30
|
-
VIEW: "views", // doesn't work yet
|
|
31
|
-
USER: "users", // doesn't work yet
|
|
32
|
-
AUTOMATION: "automationRuns", // doesn't work yet
|
|
33
|
-
APPS: "apps",
|
|
34
|
-
EMAILS: "emails", // doesn't work yet
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
exports.getUsageQuotaDoc = async db => {
|
|
38
|
-
let quota
|
|
39
|
-
try {
|
|
40
|
-
quota = await db.get(StaticDatabases.GLOBAL.docs.usageQuota)
|
|
41
|
-
} catch (err) {
|
|
42
|
-
// doc doesn't exist. Create it
|
|
43
|
-
quota = generateNewUsageQuotaDoc()
|
|
44
|
-
const response = await db.put(quota)
|
|
45
|
-
quota._rev = response.rev
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return quota
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Given a specified tenantId this will add to the usage object for the specified property.
|
|
53
|
-
* @param {string} property The property which is to be added to (within the nested usageQuota object).
|
|
54
|
-
* @param {number} usage The amount (this can be negative) to adjust the number by.
|
|
55
|
-
* @param {object} opts optional - options such as dryRun, to check what update will do.
|
|
56
|
-
* @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
|
|
57
|
-
* also been reset after this call.
|
|
58
|
-
*/
|
|
59
|
-
exports.update = async (property, usage, opts = { dryRun: false }) => {
|
|
60
|
-
if (!exports.useQuotas()) {
|
|
61
|
-
return
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
const db = getGlobalDB()
|
|
66
|
-
const quota = await exports.getUsageQuotaDoc(db)
|
|
67
|
-
|
|
68
|
-
// increment the quota
|
|
69
|
-
quota.usageQuota[property] += usage
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
quota.usageQuota[property] > quota.usageLimits[property] &&
|
|
73
|
-
usage > 0 // allow for decrementing usage when the quota is already exceeded
|
|
74
|
-
) {
|
|
75
|
-
throw new Error(
|
|
76
|
-
`You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (quota.usageQuota[property] < 0) {
|
|
81
|
-
// never go negative if the quota has previously been exceeded
|
|
82
|
-
quota.usageQuota[property] = 0
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// update the usage quotas
|
|
86
|
-
if (!opts.dryRun) {
|
|
87
|
-
await db.put(quota)
|
|
88
|
-
}
|
|
89
|
-
} catch (err) {
|
|
90
|
-
console.error(`Error updating usage quotas for ${property}`, err)
|
|
91
|
-
throw err
|
|
92
|
-
}
|
|
93
|
-
}
|