@budibase/server 1.0.46-alpha.2 → 1.0.46-alpha.3
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.6eae2fa0.js} +28 -28
- package/builder/index.html +1 -1
- package/coverage/clover.xml +1412 -1236
- package/coverage/coverage-final.json +89 -83
- 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 +90 -90
- 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 +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/hosting.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +1 -1
- 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 +1 -1
- 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 +25 -25
- 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 +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/application.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +1 -1
- package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +1 -1
- package/coverage/lcov-report/api/routes/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +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 +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +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 +1 -1
- package/coverage/lcov-report/constants/index.js.html +22 -22
- 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 +83 -83
- 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 +68 -38
- 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 +1 -1
- package/coverage/lcov-report/middleware/builder.js.html +1 -1
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +20 -20
- 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 +1 -1
- 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/migrations/usageQuotas/syncApps.js.html +134 -0
- package/coverage/lcov-report/migrations/usageQuotas/syncRows.js.html +143 -0
- package/coverage/lcov-report/threads/automation.js.html +1 -1
- package/coverage/lcov-report/threads/index.html +1 -1
- package/coverage/lcov-report/threads/index.js.html +10 -10
- package/coverage/lcov-report/threads/query.js.html +1 -1
- 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 +14 -14
- package/coverage/lcov-report/utilities/index.html +1 -1
- 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 +31 -31
- package/coverage/lcov.info +1900 -1602
- package/dist/api/controllers/table/internal.js +2 -0
- package/dist/api/controllers/table/utils.js +5 -0
- package/dist/automations/steps/createRow.js +2 -4
- package/dist/automations/steps/deleteRow.js +1 -4
- package/dist/environment.js +1 -0
- 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 +4 -4
- 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/package.json +5 -5
- package/src/api/controllers/table/internal.js +2 -0
- package/src/api/controllers/table/utils.js +5 -0
- package/src/automations/steps/createRow.js +2 -4
- package/src/automations/steps/deleteRow.js +1 -4
- package/src/environment.js +1 -0
- 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/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/usageQuota.js +0 -73
|
@@ -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
|
+
}
|
|
@@ -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
|
+
})
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
* @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
|
|
56
|
+
* also been reset after this call.
|
|
57
|
+
*/
|
|
58
|
+
exports.update = async (property, usage, opts = { dryRun: false }) => {
|
|
59
|
+
if (!exports.useQuotas()) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const db = getGlobalDB()
|
|
65
|
+
const quota = await exports.getUsageQuotaDoc(db)
|
|
66
|
+
|
|
67
|
+
// increment the quota
|
|
68
|
+
quota.usageQuota[property] += usage
|
|
69
|
+
|
|
70
|
+
if (
|
|
71
|
+
quota.usageQuota[property] > quota.usageLimits[property] &&
|
|
72
|
+
usage > 0 // allow for decrementing usage when the quota is already exceeded
|
|
73
|
+
) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (quota.usageQuota[property] < 0) {
|
|
80
|
+
// never go negative if the quota has previously been exceeded
|
|
81
|
+
quota.usageQuota[property] = 0
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// update the usage quotas
|
|
85
|
+
if (!opts.dryRun) {
|
|
86
|
+
await db.put(quota)
|
|
87
|
+
}
|
|
88
|
+
} catch (err) {
|
|
89
|
+
console.error(`Error updating usage quotas for ${property}`, err)
|
|
90
|
+
throw err
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const { getRowParams, USER_METDATA_PREFIX } = require("../../db/utils")
|
|
2
|
+
const CouchDB = require("../../db")
|
|
3
|
+
const { isDevAppID, getDevelopmentAppID } = require("@budibase/backend-core/db")
|
|
4
|
+
|
|
5
|
+
const ROW_EXCLUSIONS = [USER_METDATA_PREFIX]
|
|
6
|
+
|
|
7
|
+
const getAppPairs = appIds => {
|
|
8
|
+
// collect the app ids into dev / prod pairs
|
|
9
|
+
// keyed by the dev app id
|
|
10
|
+
const pairs = {}
|
|
11
|
+
for (let appId of appIds) {
|
|
12
|
+
const devId = getDevelopmentAppID(appId)
|
|
13
|
+
if (!pairs[devId]) {
|
|
14
|
+
pairs[devId] = {}
|
|
15
|
+
}
|
|
16
|
+
if (isDevAppID(appId)) {
|
|
17
|
+
pairs[devId].devId = appId
|
|
18
|
+
} else {
|
|
19
|
+
pairs[devId].prodId = appId
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return pairs
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const getAppRows = async appId => {
|
|
26
|
+
const appDb = new CouchDB(appId)
|
|
27
|
+
const response = await appDb.allDocs(
|
|
28
|
+
getRowParams(null, null, {
|
|
29
|
+
include_docs: false,
|
|
30
|
+
})
|
|
31
|
+
)
|
|
32
|
+
return response.rows
|
|
33
|
+
.map(r => r.id)
|
|
34
|
+
.filter(id => {
|
|
35
|
+
for (let exclusion of ROW_EXCLUSIONS) {
|
|
36
|
+
if (id.startsWith(exclusion)) {
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return true
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Return a set of all rows in the given app ids.
|
|
46
|
+
* The returned rows will be unique on a per dev/prod app basis.
|
|
47
|
+
* Rows duplicates may exist across apps due to data import so they are not filtered out.
|
|
48
|
+
*/
|
|
49
|
+
exports.getUniqueRows = async appIds => {
|
|
50
|
+
let uniqueRows = []
|
|
51
|
+
const pairs = getAppPairs(appIds)
|
|
52
|
+
|
|
53
|
+
for (let pair of Object.values(pairs)) {
|
|
54
|
+
let appRows = []
|
|
55
|
+
for (let appId of [pair.devId, pair.prodId]) {
|
|
56
|
+
if (!appId) {
|
|
57
|
+
continue
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
appRows.push(await getAppRows(appId))
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error(e)
|
|
63
|
+
// don't error out if we can't count the app rows, just continue
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ensure uniqueness on a per app pair basis
|
|
68
|
+
// this can't be done on all rows because app import results in
|
|
69
|
+
// duplicate row ids across apps
|
|
70
|
+
uniqueRows = uniqueRows.concat(...new Set(appRows))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return uniqueRows
|
|
74
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// UNUSED CODE
|
|
2
|
+
// Preserved for future use
|
|
3
|
+
|
|
4
|
+
/* eslint-disable no-unused-vars */
|
|
5
|
+
|
|
6
|
+
function getNewQuotaReset() {
|
|
7
|
+
return Date.now() + 2592000000
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function resetQuotasIfRequired(quota) {
|
|
11
|
+
// Check if the quota needs reset
|
|
12
|
+
if (Date.now() >= quota.quotaReset) {
|
|
13
|
+
quota.quotaReset = getNewQuotaReset()
|
|
14
|
+
for (let prop of Object.keys(quota.usageQuota)) {
|
|
15
|
+
quota.usageQuota[prop] = 0
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
const env = require("../environment")
|
|
2
|
-
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
3
|
-
const {
|
|
4
|
-
StaticDatabases,
|
|
5
|
-
generateNewUsageQuotaDoc,
|
|
6
|
-
} = require("@budibase/backend-core/db")
|
|
7
|
-
|
|
8
|
-
function getNewQuotaReset() {
|
|
9
|
-
return Date.now() + 2592000000
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
exports.Properties = {
|
|
13
|
-
ROW: "rows",
|
|
14
|
-
UPLOAD: "storage",
|
|
15
|
-
VIEW: "views",
|
|
16
|
-
USER: "users",
|
|
17
|
-
AUTOMATION: "automationRuns",
|
|
18
|
-
APPS: "apps",
|
|
19
|
-
EMAILS: "emails",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function getUsageQuotaDoc(db) {
|
|
23
|
-
let quota
|
|
24
|
-
try {
|
|
25
|
-
quota = await db.get(StaticDatabases.PLATFORM_INFO.docs.usageQuota)
|
|
26
|
-
} catch (err) {
|
|
27
|
-
// doc doesn't exist. Create it
|
|
28
|
-
quota = await db.post(generateNewUsageQuotaDoc())
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return quota
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Given a specified tenantId this will add to the usage object for the specified property.
|
|
36
|
-
* @param {string} property The property which is to be added to (within the nested usageQuota object).
|
|
37
|
-
* @param {number} usage The amount (this can be negative) to adjust the number by.
|
|
38
|
-
* @returns {Promise<void>} When this completes the API key will now be up to date - the quota period may have
|
|
39
|
-
* also been reset after this call.
|
|
40
|
-
*/
|
|
41
|
-
exports.update = async (property, usage) => {
|
|
42
|
-
if (!env.USE_QUOTAS) {
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
const db = getGlobalDB()
|
|
48
|
-
const quota = await getUsageQuotaDoc(db)
|
|
49
|
-
|
|
50
|
-
// Check if the quota needs reset
|
|
51
|
-
if (Date.now() >= quota.quotaReset) {
|
|
52
|
-
quota.quotaReset = getNewQuotaReset()
|
|
53
|
-
for (let prop of Object.keys(quota.usageQuota)) {
|
|
54
|
-
quota.usageQuota[prop] = 0
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// increment the quota
|
|
59
|
-
quota.usageQuota[property] += usage
|
|
60
|
-
|
|
61
|
-
if (quota.usageQuota[property] > quota.usageLimits[property]) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`You have exceeded your usage quota of ${quota.usageLimits[property]} ${property}.`
|
|
64
|
-
)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// update the usage quotas
|
|
68
|
-
await db.put(quota)
|
|
69
|
-
} catch (err) {
|
|
70
|
-
console.error(`Error updating usage quotas for ${property}`, err)
|
|
71
|
-
throw err
|
|
72
|
-
}
|
|
73
|
-
}
|