@budibase/backend-core 2.9.40-alpha.6 → 2.10.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/dist/index.js +5 -4
- package/dist/index.js.map +2 -2
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +6 -6
- package/dist/src/cache/appMetadata.js +1 -1
- package/dist/src/cache/appMetadata.js.map +1 -1
- package/dist/src/constants/misc.d.ts +0 -2
- package/dist/src/constants/misc.js +0 -2
- package/dist/src/constants/misc.js.map +1 -1
- package/dist/src/environment.js +5 -4
- package/dist/src/environment.js.map +1 -1
- package/dist/src/logging/system.d.ts +1 -1
- package/dist/src/timers/timers.d.ts +1 -1
- package/package.json +6 -6
- package/src/accounts/accounts.ts +82 -0
- package/src/accounts/api.ts +59 -0
- package/src/accounts/index.ts +1 -0
- package/src/auth/auth.ts +208 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/tests/auth.spec.ts +14 -0
- package/src/blacklist/blacklist.ts +54 -0
- package/src/blacklist/index.ts +1 -0
- package/src/blacklist/tests/blacklist.spec.ts +46 -0
- package/src/cache/appMetadata.ts +88 -0
- package/src/cache/base/index.ts +92 -0
- package/src/cache/generic.ts +30 -0
- package/src/cache/index.ts +5 -0
- package/src/cache/tests/writethrough.spec.ts +138 -0
- package/src/cache/user.ts +83 -0
- package/src/cache/writethrough.ts +133 -0
- package/src/configs/configs.ts +257 -0
- package/src/configs/index.ts +1 -0
- package/src/configs/tests/configs.spec.ts +184 -0
- package/src/constants/db.ts +63 -0
- package/src/constants/index.ts +2 -0
- package/src/constants/misc.ts +50 -0
- package/src/context/Context.ts +14 -0
- package/src/context/identity.ts +58 -0
- package/src/context/index.ts +3 -0
- package/src/context/mainContext.ts +310 -0
- package/src/context/tests/index.spec.ts +147 -0
- package/src/context/types.ts +11 -0
- package/src/db/Replication.ts +84 -0
- package/src/db/constants.ts +10 -0
- package/src/db/couch/DatabaseImpl.ts +238 -0
- package/src/db/couch/connections.ts +77 -0
- package/src/db/couch/index.ts +5 -0
- package/src/db/couch/pouchDB.ts +97 -0
- package/src/db/couch/pouchDump.ts +0 -0
- package/src/db/couch/utils.ts +50 -0
- package/src/db/db.ts +43 -0
- package/src/db/errors.ts +14 -0
- package/src/db/index.ts +12 -0
- package/src/db/lucene.ts +750 -0
- package/src/db/searchIndexes/index.ts +1 -0
- package/src/db/searchIndexes/searchIndexes.ts +62 -0
- package/src/db/tests/index.spec.js +25 -0
- package/src/db/tests/lucene.spec.ts +368 -0
- package/src/db/tests/pouch.spec.js +62 -0
- package/src/db/tests/utils.spec.ts +63 -0
- package/src/db/utils.ts +207 -0
- package/src/db/views.ts +241 -0
- package/src/docIds/conversions.ts +59 -0
- package/src/docIds/ids.ts +113 -0
- package/src/docIds/index.ts +2 -0
- package/src/docIds/newid.ts +5 -0
- package/src/docIds/params.ts +174 -0
- package/src/docUpdates/index.ts +29 -0
- package/src/environment.ts +201 -0
- package/src/errors/errors.ts +119 -0
- package/src/errors/index.ts +1 -0
- package/src/events/analytics.ts +6 -0
- package/src/events/asyncEvents/index.ts +2 -0
- package/src/events/asyncEvents/publisher.ts +12 -0
- package/src/events/asyncEvents/queue.ts +22 -0
- package/src/events/backfill.ts +183 -0
- package/src/events/documentId.ts +56 -0
- package/src/events/events.ts +40 -0
- package/src/events/identification.ts +310 -0
- package/src/events/index.ts +14 -0
- package/src/events/processors/AnalyticsProcessor.ts +64 -0
- package/src/events/processors/AuditLogsProcessor.ts +93 -0
- package/src/events/processors/LoggingProcessor.ts +37 -0
- package/src/events/processors/Processors.ts +52 -0
- package/src/events/processors/async/DocumentUpdateProcessor.ts +43 -0
- package/src/events/processors/index.ts +19 -0
- package/src/events/processors/posthog/PosthogProcessor.ts +118 -0
- package/src/events/processors/posthog/index.ts +2 -0
- package/src/events/processors/posthog/rateLimiting.ts +106 -0
- package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +168 -0
- package/src/events/processors/types.ts +1 -0
- package/src/events/publishers/account.ts +35 -0
- package/src/events/publishers/app.ts +155 -0
- package/src/events/publishers/auditLog.ts +26 -0
- package/src/events/publishers/auth.ts +73 -0
- package/src/events/publishers/automation.ts +110 -0
- package/src/events/publishers/backfill.ts +74 -0
- package/src/events/publishers/backup.ts +42 -0
- package/src/events/publishers/datasource.ts +48 -0
- package/src/events/publishers/email.ts +17 -0
- package/src/events/publishers/environmentVariable.ts +38 -0
- package/src/events/publishers/group.ts +99 -0
- package/src/events/publishers/index.ts +24 -0
- package/src/events/publishers/installation.ts +38 -0
- package/src/events/publishers/layout.ts +26 -0
- package/src/events/publishers/license.ts +84 -0
- package/src/events/publishers/org.ts +37 -0
- package/src/events/publishers/plugin.ts +47 -0
- package/src/events/publishers/query.ts +88 -0
- package/src/events/publishers/role.ts +62 -0
- package/src/events/publishers/rows.ts +29 -0
- package/src/events/publishers/screen.ts +36 -0
- package/src/events/publishers/serve.ts +43 -0
- package/src/events/publishers/table.ts +70 -0
- package/src/events/publishers/user.ts +202 -0
- package/src/events/publishers/view.ts +107 -0
- package/src/features/index.ts +78 -0
- package/src/features/installation.ts +17 -0
- package/src/features/tests/featureFlags.spec.ts +85 -0
- package/src/helpers.ts +9 -0
- package/src/index.ts +54 -0
- package/src/installation.ts +107 -0
- package/src/logging/alerts.ts +26 -0
- package/src/logging/correlation/correlation.ts +13 -0
- package/src/logging/correlation/index.ts +1 -0
- package/src/logging/correlation/middleware.ts +17 -0
- package/src/logging/index.ts +4 -0
- package/src/logging/pino/logger.ts +232 -0
- package/src/logging/pino/middleware.ts +45 -0
- package/src/logging/system.ts +81 -0
- package/src/logging/tests/system.spec.ts +61 -0
- package/src/middleware/adminOnly.ts +9 -0
- package/src/middleware/auditLog.ts +6 -0
- package/src/middleware/authenticated.ts +193 -0
- package/src/middleware/builderOnly.ts +21 -0
- package/src/middleware/builderOrAdmin.ts +21 -0
- package/src/middleware/csrf.ts +81 -0
- package/src/middleware/errorHandling.ts +29 -0
- package/src/middleware/index.ts +21 -0
- package/src/middleware/internalApi.ts +23 -0
- package/src/middleware/joi-validator.ts +45 -0
- package/src/middleware/matchers.ts +47 -0
- package/src/middleware/passport/datasource/google.ts +95 -0
- package/src/middleware/passport/local.ts +54 -0
- package/src/middleware/passport/sso/google.ts +77 -0
- package/src/middleware/passport/sso/oidc.ts +154 -0
- package/src/middleware/passport/sso/sso.ts +165 -0
- package/src/middleware/passport/sso/tests/google.spec.ts +67 -0
- package/src/middleware/passport/sso/tests/oidc.spec.ts +152 -0
- package/src/middleware/passport/sso/tests/sso.spec.ts +197 -0
- package/src/middleware/passport/utils.ts +38 -0
- package/src/middleware/querystringToBody.ts +28 -0
- package/src/middleware/tenancy.ts +36 -0
- package/src/middleware/tests/builder.spec.ts +180 -0
- package/src/middleware/tests/matchers.spec.ts +134 -0
- package/src/migrations/definitions.ts +40 -0
- package/src/migrations/index.ts +2 -0
- package/src/migrations/migrations.ts +191 -0
- package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +11 -0
- package/src/migrations/tests/migrations.spec.ts +64 -0
- package/src/objectStore/buckets/app.ts +40 -0
- package/src/objectStore/buckets/global.ts +29 -0
- package/src/objectStore/buckets/index.ts +3 -0
- package/src/objectStore/buckets/plugins.ts +71 -0
- package/src/objectStore/buckets/tests/app.spec.ts +171 -0
- package/src/objectStore/buckets/tests/global.spec.ts +74 -0
- package/src/objectStore/buckets/tests/plugins.spec.ts +111 -0
- package/src/objectStore/cloudfront.ts +41 -0
- package/src/objectStore/index.ts +3 -0
- package/src/objectStore/objectStore.ts +440 -0
- package/src/objectStore/utils.ts +27 -0
- package/src/platform/index.ts +3 -0
- package/src/platform/platformDb.ts +6 -0
- package/src/platform/tenants.ts +101 -0
- package/src/platform/tests/tenants.spec.ts +26 -0
- package/src/platform/users.ts +90 -0
- package/src/plugin/index.ts +1 -0
- package/src/plugin/tests/validation.spec.ts +83 -0
- package/src/plugin/utils.ts +156 -0
- package/src/queue/constants.ts +6 -0
- package/src/queue/inMemoryQueue.ts +141 -0
- package/src/queue/index.ts +2 -0
- package/src/queue/listeners.ts +195 -0
- package/src/queue/queue.ts +54 -0
- package/src/redis/index.ts +6 -0
- package/src/redis/init.ts +86 -0
- package/src/redis/redis.ts +308 -0
- package/src/redis/redlockImpl.ts +139 -0
- package/src/redis/utils.ts +117 -0
- package/src/security/encryption.ts +179 -0
- package/src/security/permissions.ts +158 -0
- package/src/security/roles.ts +389 -0
- package/src/security/sessions.ts +120 -0
- package/src/security/tests/encryption.spec.ts +31 -0
- package/src/security/tests/permissions.spec.ts +145 -0
- package/src/security/tests/sessions.spec.ts +12 -0
- package/src/tenancy/db.ts +6 -0
- package/src/tenancy/index.ts +2 -0
- package/src/tenancy/tenancy.ts +140 -0
- package/src/tenancy/tests/tenancy.spec.ts +184 -0
- package/src/timers/index.ts +1 -0
- package/src/timers/timers.ts +22 -0
- package/src/users/db.ts +484 -0
- package/src/users/events.ts +176 -0
- package/src/users/index.ts +4 -0
- package/src/users/lookup.ts +102 -0
- package/src/users/users.ts +276 -0
- package/src/users/utils.ts +55 -0
- package/src/utils/hashing.ts +14 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/stringUtils.ts +8 -0
- package/src/utils/tests/utils.spec.ts +191 -0
- package/src/utils/utils.ts +239 -0
- package/tests/core/logging.ts +34 -0
- package/tests/core/utilities/index.ts +6 -0
- package/tests/core/utilities/jestUtils.ts +30 -0
- package/tests/core/utilities/mocks/alerts.ts +3 -0
- package/tests/core/utilities/mocks/date.ts +2 -0
- package/tests/core/utilities/mocks/events.ts +131 -0
- package/tests/core/utilities/mocks/fetch.ts +17 -0
- package/tests/core/utilities/mocks/index.ts +10 -0
- package/tests/core/utilities/mocks/licenses.ts +115 -0
- package/tests/core/utilities/mocks/posthog.ts +7 -0
- package/tests/core/utilities/structures/Chance.ts +20 -0
- package/tests/core/utilities/structures/accounts.ts +115 -0
- package/tests/core/utilities/structures/apps.ts +21 -0
- package/tests/core/utilities/structures/common.ts +7 -0
- package/tests/core/utilities/structures/db.ts +12 -0
- package/tests/core/utilities/structures/documents/index.ts +1 -0
- package/tests/core/utilities/structures/documents/platform/index.ts +1 -0
- package/tests/core/utilities/structures/documents/platform/installation.ts +12 -0
- package/tests/core/utilities/structures/generator.ts +2 -0
- package/tests/core/utilities/structures/index.ts +15 -0
- package/tests/core/utilities/structures/koa.ts +16 -0
- package/tests/core/utilities/structures/licenses.ts +167 -0
- package/tests/core/utilities/structures/plugins.ts +19 -0
- package/tests/core/utilities/structures/quotas.ts +67 -0
- package/tests/core/utilities/structures/scim.ts +80 -0
- package/tests/core/utilities/structures/shared.ts +19 -0
- package/tests/core/utilities/structures/sso.ts +119 -0
- package/tests/core/utilities/structures/tenants.ts +5 -0
- package/tests/core/utilities/structures/userGroups.ts +10 -0
- package/tests/core/utilities/structures/users.ts +73 -0
- package/tests/core/utilities/testContainerUtils.ts +85 -0
- package/tests/core/utilities/utils/index.ts +1 -0
- package/tests/core/utilities/utils/time.ts +3 -0
- package/tests/extra/DBTestConfiguration.ts +36 -0
- package/tests/extra/index.ts +2 -0
- package/tests/extra/testEnv.ts +95 -0
- package/tests/index.ts +1 -0
- package/tests/jestEnv.ts +6 -0
- package/tests/jestSetup.ts +28 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
// some test cases call functions directly, need to
|
|
2
|
+
// store an app ID to pretend there is a context
|
|
3
|
+
import env from "../environment"
|
|
4
|
+
import Context from "./Context"
|
|
5
|
+
import * as conversions from "../docIds/conversions"
|
|
6
|
+
import { getDB } from "../db/db"
|
|
7
|
+
import {
|
|
8
|
+
DocumentType,
|
|
9
|
+
SEPARATOR,
|
|
10
|
+
StaticDatabases,
|
|
11
|
+
DEFAULT_TENANT_ID,
|
|
12
|
+
} from "../constants"
|
|
13
|
+
import { Database, IdentityContext } from "@budibase/types"
|
|
14
|
+
import { ContextMap } from "./types"
|
|
15
|
+
|
|
16
|
+
let TEST_APP_ID: string | null = null
|
|
17
|
+
|
|
18
|
+
export function getGlobalDBName(tenantId?: string) {
|
|
19
|
+
// tenant ID can be set externally, for example user API where
|
|
20
|
+
// new tenants are being created, this may be the case
|
|
21
|
+
if (!tenantId) {
|
|
22
|
+
tenantId = getTenantId()
|
|
23
|
+
}
|
|
24
|
+
return baseGlobalDBName(tenantId)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function getAuditLogDBName(tenantId?: string) {
|
|
28
|
+
if (!tenantId) {
|
|
29
|
+
tenantId = getTenantId()
|
|
30
|
+
}
|
|
31
|
+
if (tenantId === DEFAULT_TENANT_ID) {
|
|
32
|
+
return StaticDatabases.AUDIT_LOGS.name
|
|
33
|
+
} else {
|
|
34
|
+
return `${tenantId}${SEPARATOR}${StaticDatabases.AUDIT_LOGS.name}`
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function baseGlobalDBName(tenantId: string | undefined | null) {
|
|
39
|
+
if (!tenantId || tenantId === DEFAULT_TENANT_ID) {
|
|
40
|
+
return StaticDatabases.GLOBAL.name
|
|
41
|
+
} else {
|
|
42
|
+
return `${tenantId}${SEPARATOR}${StaticDatabases.GLOBAL.name}`
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function getPlatformURL() {
|
|
47
|
+
return env.PLATFORM_URL
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function isMultiTenant() {
|
|
51
|
+
return !!env.MULTI_TENANCY
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function isTenantIdSet() {
|
|
55
|
+
const context = Context.get()
|
|
56
|
+
return !!context?.tenantId
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function isTenancyEnabled() {
|
|
60
|
+
return env.MULTI_TENANCY
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Given an app ID this will attempt to retrieve the tenant ID from it.
|
|
65
|
+
* @return {null|string} The tenant ID found within the app ID.
|
|
66
|
+
*/
|
|
67
|
+
export function getTenantIDFromAppID(appId: string) {
|
|
68
|
+
if (!appId) {
|
|
69
|
+
return undefined
|
|
70
|
+
}
|
|
71
|
+
if (!isMultiTenant()) {
|
|
72
|
+
return DEFAULT_TENANT_ID
|
|
73
|
+
}
|
|
74
|
+
const split = appId.split(SEPARATOR)
|
|
75
|
+
const hasDev = split[1] === DocumentType.DEV
|
|
76
|
+
if ((hasDev && split.length === 3) || (!hasDev && split.length === 2)) {
|
|
77
|
+
return undefined
|
|
78
|
+
}
|
|
79
|
+
if (hasDev) {
|
|
80
|
+
return split[2]
|
|
81
|
+
} else {
|
|
82
|
+
return split[1]
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function updateContext(updates: ContextMap): ContextMap {
|
|
87
|
+
let context: ContextMap
|
|
88
|
+
try {
|
|
89
|
+
context = Context.get()
|
|
90
|
+
} catch (err) {
|
|
91
|
+
// no context, start empty
|
|
92
|
+
context = {}
|
|
93
|
+
}
|
|
94
|
+
context = {
|
|
95
|
+
...context,
|
|
96
|
+
...updates,
|
|
97
|
+
}
|
|
98
|
+
return context
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function newContext(updates: ContextMap, task: any) {
|
|
102
|
+
// see if there already is a context setup
|
|
103
|
+
let context: ContextMap = updateContext(updates)
|
|
104
|
+
return Context.run(context, task)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export async function doInAutomationContext(params: {
|
|
108
|
+
appId: string
|
|
109
|
+
automationId: string
|
|
110
|
+
task: any
|
|
111
|
+
}): Promise<any> {
|
|
112
|
+
const tenantId = getTenantIDFromAppID(params.appId)
|
|
113
|
+
return newContext(
|
|
114
|
+
{
|
|
115
|
+
tenantId,
|
|
116
|
+
appId: params.appId,
|
|
117
|
+
automationId: params.automationId,
|
|
118
|
+
},
|
|
119
|
+
params.task
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export async function doInContext(appId: string, task: any): Promise<any> {
|
|
124
|
+
const tenantId = getTenantIDFromAppID(appId)
|
|
125
|
+
return newContext(
|
|
126
|
+
{
|
|
127
|
+
tenantId,
|
|
128
|
+
appId,
|
|
129
|
+
},
|
|
130
|
+
task
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export async function doInTenant<T>(
|
|
135
|
+
tenantId: string | null,
|
|
136
|
+
task: () => T
|
|
137
|
+
): Promise<T> {
|
|
138
|
+
// make sure default always selected in single tenancy
|
|
139
|
+
if (!env.MULTI_TENANCY) {
|
|
140
|
+
tenantId = tenantId || DEFAULT_TENANT_ID
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const updates = tenantId ? { tenantId } : {}
|
|
144
|
+
return newContext(updates, task)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export async function doInAppContext(
|
|
148
|
+
appId: string | null,
|
|
149
|
+
task: any
|
|
150
|
+
): Promise<any> {
|
|
151
|
+
if (!appId && !env.isTest()) {
|
|
152
|
+
throw new Error("appId is required")
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
let updates: ContextMap
|
|
156
|
+
if (!appId) {
|
|
157
|
+
updates = { appId: "" }
|
|
158
|
+
} else {
|
|
159
|
+
const tenantId = getTenantIDFromAppID(appId)
|
|
160
|
+
updates = { appId }
|
|
161
|
+
if (tenantId) {
|
|
162
|
+
updates.tenantId = tenantId
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return newContext(updates, task)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export async function doInIdentityContext(
|
|
169
|
+
identity: IdentityContext,
|
|
170
|
+
task: any
|
|
171
|
+
): Promise<any> {
|
|
172
|
+
if (!identity) {
|
|
173
|
+
throw new Error("identity is required")
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const context: ContextMap = {
|
|
177
|
+
identity,
|
|
178
|
+
}
|
|
179
|
+
if (identity.tenantId) {
|
|
180
|
+
context.tenantId = identity.tenantId
|
|
181
|
+
}
|
|
182
|
+
return newContext(context, task)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function getIdentity(): IdentityContext | undefined {
|
|
186
|
+
try {
|
|
187
|
+
const context = Context.get()
|
|
188
|
+
return context?.identity
|
|
189
|
+
} catch (e) {
|
|
190
|
+
// do nothing - identity is not in context
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function getTenantId(): string {
|
|
195
|
+
if (!isMultiTenant()) {
|
|
196
|
+
return DEFAULT_TENANT_ID
|
|
197
|
+
}
|
|
198
|
+
const context = Context.get()
|
|
199
|
+
const tenantId = context?.tenantId
|
|
200
|
+
if (!tenantId) {
|
|
201
|
+
throw new Error("Tenant id not found")
|
|
202
|
+
}
|
|
203
|
+
return tenantId
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function getAutomationId(): string | undefined {
|
|
207
|
+
const context = Context.get()
|
|
208
|
+
return context?.automationId
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function getAppId(): string | undefined {
|
|
212
|
+
const context = Context.get()
|
|
213
|
+
const foundId = context?.appId
|
|
214
|
+
if (!foundId && env.isTest() && TEST_APP_ID) {
|
|
215
|
+
return TEST_APP_ID
|
|
216
|
+
} else {
|
|
217
|
+
return foundId
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const getProdAppId = () => {
|
|
222
|
+
const appId = getAppId()
|
|
223
|
+
if (!appId) {
|
|
224
|
+
throw new Error("Could not get appId")
|
|
225
|
+
}
|
|
226
|
+
return conversions.getProdAppID(appId)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function doInEnvironmentContext(
|
|
230
|
+
values: Record<string, string>,
|
|
231
|
+
task: any
|
|
232
|
+
) {
|
|
233
|
+
if (!values) {
|
|
234
|
+
throw new Error("Must supply environment variables.")
|
|
235
|
+
}
|
|
236
|
+
const updates = {
|
|
237
|
+
environmentVariables: values,
|
|
238
|
+
}
|
|
239
|
+
return newContext(updates, task)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export function doInScimContext(task: any) {
|
|
243
|
+
const updates: ContextMap = {
|
|
244
|
+
isScim: true,
|
|
245
|
+
}
|
|
246
|
+
return newContext(updates, task)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export function getEnvironmentVariables() {
|
|
250
|
+
const context = Context.get()
|
|
251
|
+
if (!context.environmentVariables) {
|
|
252
|
+
return null
|
|
253
|
+
} else {
|
|
254
|
+
return context.environmentVariables
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function getGlobalDB(): Database {
|
|
259
|
+
const context = Context.get()
|
|
260
|
+
if (!context || (env.MULTI_TENANCY && !context.tenantId)) {
|
|
261
|
+
throw new Error("Global DB not found")
|
|
262
|
+
}
|
|
263
|
+
return getDB(baseGlobalDBName(context?.tenantId))
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function getAuditLogsDB(): Database {
|
|
267
|
+
if (!getTenantId()) {
|
|
268
|
+
throw new Error("No tenant ID found - cannot open audit log DB")
|
|
269
|
+
}
|
|
270
|
+
return getDB(getAuditLogDBName())
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Gets the app database based on whatever the request
|
|
275
|
+
* contained, dev or prod.
|
|
276
|
+
*/
|
|
277
|
+
export function getAppDB(opts?: any): Database {
|
|
278
|
+
const appId = getAppId()
|
|
279
|
+
return getDB(appId, opts)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* This specifically gets the prod app ID, if the request
|
|
284
|
+
* contained a development app ID, this will get the prod one.
|
|
285
|
+
*/
|
|
286
|
+
export function getProdAppDB(opts?: any): Database {
|
|
287
|
+
const appId = getAppId()
|
|
288
|
+
if (!appId) {
|
|
289
|
+
throw new Error("Unable to retrieve prod DB - no app ID.")
|
|
290
|
+
}
|
|
291
|
+
return getDB(conversions.getProdAppID(appId), opts)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* This specifically gets the dev app ID, if the request
|
|
296
|
+
* contained a prod app ID, this will get the dev one.
|
|
297
|
+
*/
|
|
298
|
+
export function getDevAppDB(opts?: any): Database {
|
|
299
|
+
const appId = getAppId()
|
|
300
|
+
if (!appId) {
|
|
301
|
+
throw new Error("Unable to retrieve dev DB - no app ID.")
|
|
302
|
+
}
|
|
303
|
+
return getDB(conversions.getDevelopmentAppID(appId), opts)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export function isScim(): boolean {
|
|
307
|
+
const context = Context.get()
|
|
308
|
+
const scimCall = context?.isScim
|
|
309
|
+
return !!scimCall
|
|
310
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { testEnv } from "../../../tests/extra"
|
|
2
|
+
import * as context from "../"
|
|
3
|
+
import { DEFAULT_TENANT_ID } from "../../constants"
|
|
4
|
+
|
|
5
|
+
describe("context", () => {
|
|
6
|
+
describe("doInTenant", () => {
|
|
7
|
+
describe("single-tenancy", () => {
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
testEnv.singleTenant()
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it("defaults to the default tenant", () => {
|
|
13
|
+
const tenantId = context.getTenantId()
|
|
14
|
+
expect(tenantId).toBe(DEFAULT_TENANT_ID)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it("defaults to the default tenant db", async () => {
|
|
18
|
+
await context.doInTenant(DEFAULT_TENANT_ID, () => {
|
|
19
|
+
const db = context.getGlobalDB()
|
|
20
|
+
expect(db.name).toBe("global-db")
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe("multi-tenancy", () => {
|
|
26
|
+
beforeAll(() => {
|
|
27
|
+
testEnv.multiTenant()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it("fails when no tenant id is set", () => {
|
|
31
|
+
const test = () => {
|
|
32
|
+
let error: any
|
|
33
|
+
try {
|
|
34
|
+
context.getTenantId()
|
|
35
|
+
} catch (e) {
|
|
36
|
+
error = e
|
|
37
|
+
}
|
|
38
|
+
expect(error.message).toBe("Tenant id not found")
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// test under no tenancy
|
|
42
|
+
test()
|
|
43
|
+
|
|
44
|
+
// test after tenancy has been accessed to ensure cleanup
|
|
45
|
+
context.doInTenant("test", () => {})
|
|
46
|
+
test()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it("fails when no tenant db is set", () => {
|
|
50
|
+
const test = () => {
|
|
51
|
+
let error: any
|
|
52
|
+
try {
|
|
53
|
+
context.getGlobalDB()
|
|
54
|
+
} catch (e) {
|
|
55
|
+
error = e
|
|
56
|
+
}
|
|
57
|
+
expect(error.message).toBe("Global DB not found")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// test under no tenancy
|
|
61
|
+
test()
|
|
62
|
+
|
|
63
|
+
// test after tenancy has been accessed to ensure cleanup
|
|
64
|
+
context.doInTenant("test", () => {})
|
|
65
|
+
test()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it("sets tenant id", () => {
|
|
69
|
+
context.doInTenant("test", () => {
|
|
70
|
+
const tenantId = context.getTenantId()
|
|
71
|
+
expect(tenantId).toBe("test")
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it("initialises the tenant db", async () => {
|
|
76
|
+
await context.doInTenant("test", () => {
|
|
77
|
+
const db = context.getGlobalDB()
|
|
78
|
+
expect(db.name).toBe("test_global-db")
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it("sets the tenant id when nested with same tenant id", async () => {
|
|
83
|
+
await context.doInTenant("test", async () => {
|
|
84
|
+
const tenantId = context.getTenantId()
|
|
85
|
+
expect(tenantId).toBe("test")
|
|
86
|
+
|
|
87
|
+
await context.doInTenant("test", async () => {
|
|
88
|
+
const tenantId = context.getTenantId()
|
|
89
|
+
expect(tenantId).toBe("test")
|
|
90
|
+
|
|
91
|
+
await context.doInTenant("test", () => {
|
|
92
|
+
const tenantId = context.getTenantId()
|
|
93
|
+
expect(tenantId).toBe("test")
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it("initialises the tenant db when nested with same tenant id", async () => {
|
|
100
|
+
await context.doInTenant("test", async () => {
|
|
101
|
+
const db = context.getGlobalDB()
|
|
102
|
+
expect(db.name).toBe("test_global-db")
|
|
103
|
+
|
|
104
|
+
await context.doInTenant("test", async () => {
|
|
105
|
+
const db = context.getGlobalDB()
|
|
106
|
+
expect(db.name).toBe("test_global-db")
|
|
107
|
+
|
|
108
|
+
await context.doInTenant("test", () => {
|
|
109
|
+
const db = context.getGlobalDB()
|
|
110
|
+
expect(db.name).toBe("test_global-db")
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it("sets different tenant id inside another context", () => {
|
|
117
|
+
context.doInTenant("test", () => {
|
|
118
|
+
const tenantId = context.getTenantId()
|
|
119
|
+
expect(tenantId).toBe("test")
|
|
120
|
+
|
|
121
|
+
context.doInTenant("nested", () => {
|
|
122
|
+
const tenantId = context.getTenantId()
|
|
123
|
+
expect(tenantId).toBe("nested")
|
|
124
|
+
|
|
125
|
+
context.doInTenant("double-nested", () => {
|
|
126
|
+
const tenantId = context.getTenantId()
|
|
127
|
+
expect(tenantId).toBe("double-nested")
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
describe("doInScimContext", () => {
|
|
136
|
+
it("returns true when set", () => {
|
|
137
|
+
context.doInScimContext(() => {
|
|
138
|
+
const isScim = context.isScim()
|
|
139
|
+
expect(isScim).toBe(true)
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
it("returns false when not set", () => {
|
|
143
|
+
const isScim = context.isScim()
|
|
144
|
+
expect(isScim).toBe(false)
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
})
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { IdentityContext } from "@budibase/types"
|
|
2
|
+
|
|
3
|
+
// keep this out of Budibase types, don't want to expose context info
|
|
4
|
+
export type ContextMap = {
|
|
5
|
+
tenantId?: string
|
|
6
|
+
appId?: string
|
|
7
|
+
identity?: IdentityContext
|
|
8
|
+
environmentVariables?: Record<string, string>
|
|
9
|
+
isScim?: boolean
|
|
10
|
+
automationId?: string
|
|
11
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { getPouchDB, closePouchDB } from "./couch"
|
|
2
|
+
import { DocumentType } from "../constants"
|
|
3
|
+
|
|
4
|
+
class Replication {
|
|
5
|
+
source: any
|
|
6
|
+
target: any
|
|
7
|
+
replication: any
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
*
|
|
11
|
+
* @param {String} source - the DB you want to replicate or rollback to
|
|
12
|
+
* @param {String} target - the DB you want to replicate to, or rollback from
|
|
13
|
+
*/
|
|
14
|
+
constructor({ source, target }: any) {
|
|
15
|
+
this.source = getPouchDB(source)
|
|
16
|
+
this.target = getPouchDB(target)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
close() {
|
|
20
|
+
return Promise.all([closePouchDB(this.source), closePouchDB(this.target)])
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
promisify(operation: any, opts = {}) {
|
|
24
|
+
return new Promise(resolve => {
|
|
25
|
+
operation(this.target, opts)
|
|
26
|
+
.on("denied", function (err: any) {
|
|
27
|
+
// a document failed to replicate (e.g. due to permissions)
|
|
28
|
+
throw new Error(`Denied: Document failed to replicate ${err}`)
|
|
29
|
+
})
|
|
30
|
+
.on("complete", function (info: any) {
|
|
31
|
+
return resolve(info)
|
|
32
|
+
})
|
|
33
|
+
.on("error", function (err: any) {
|
|
34
|
+
throw new Error(`Replication Error: ${err}`)
|
|
35
|
+
})
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Two way replication operation, intended to be promise based.
|
|
41
|
+
* @param {Object} opts - PouchDB replication options
|
|
42
|
+
*/
|
|
43
|
+
sync(opts = {}) {
|
|
44
|
+
this.replication = this.promisify(this.source.sync, opts)
|
|
45
|
+
return this.replication
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* One way replication operation, intended to be promise based.
|
|
50
|
+
* @param {Object} opts - PouchDB replication options
|
|
51
|
+
*/
|
|
52
|
+
replicate(opts = {}) {
|
|
53
|
+
this.replication = this.promisify(this.source.replicate.to, opts)
|
|
54
|
+
return this.replication
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
appReplicateOpts() {
|
|
58
|
+
return {
|
|
59
|
+
filter: (doc: any) => {
|
|
60
|
+
if (doc._id && doc._id.startsWith(DocumentType.AUTOMATION_LOG)) {
|
|
61
|
+
return false
|
|
62
|
+
}
|
|
63
|
+
return doc._id !== DocumentType.APP_METADATA
|
|
64
|
+
},
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Rollback the target DB back to the state of the source DB
|
|
70
|
+
*/
|
|
71
|
+
async rollback() {
|
|
72
|
+
await this.target.destroy()
|
|
73
|
+
// Recreate the DB again
|
|
74
|
+
this.target = getPouchDB(this.target.name)
|
|
75
|
+
// take the opportunity to remove deleted tombstones
|
|
76
|
+
await this.replicate()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
cancel() {
|
|
80
|
+
this.replication.cancel()
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export default Replication
|