@budibase/backend-core 2.9.19 → 2.9.20
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/package.json +19 -4
- package/dist/src/security/permissions.d.ts +1 -1
- package/package.json +19 -4
- package/dist/tsconfig.build.tsbuildinfo +0 -1
- package/src/accounts/accounts.ts +0 -82
- package/src/accounts/api.ts +0 -59
- package/src/accounts/index.ts +0 -1
- package/src/auth/auth.ts +0 -208
- package/src/auth/index.ts +0 -1
- package/src/auth/tests/auth.spec.ts +0 -14
- package/src/blacklist/blacklist.ts +0 -54
- package/src/blacklist/index.ts +0 -1
- package/src/blacklist/tests/blacklist.spec.ts +0 -46
- package/src/cache/appMetadata.ts +0 -88
- package/src/cache/base/index.ts +0 -92
- package/src/cache/generic.ts +0 -30
- package/src/cache/index.ts +0 -5
- package/src/cache/tests/writethrough.spec.ts +0 -138
- package/src/cache/user.ts +0 -69
- package/src/cache/writethrough.ts +0 -133
- package/src/configs/configs.ts +0 -257
- package/src/configs/index.ts +0 -1
- package/src/configs/tests/configs.spec.ts +0 -184
- package/src/constants/db.ts +0 -63
- package/src/constants/index.ts +0 -2
- package/src/constants/misc.ts +0 -50
- package/src/context/Context.ts +0 -14
- package/src/context/identity.ts +0 -58
- package/src/context/index.ts +0 -3
- package/src/context/mainContext.ts +0 -310
- package/src/context/tests/index.spec.ts +0 -147
- package/src/context/types.ts +0 -11
- package/src/db/Replication.ts +0 -84
- package/src/db/constants.ts +0 -10
- package/src/db/couch/DatabaseImpl.ts +0 -238
- package/src/db/couch/connections.ts +0 -77
- package/src/db/couch/index.ts +0 -5
- package/src/db/couch/pouchDB.ts +0 -97
- package/src/db/couch/pouchDump.ts +0 -0
- package/src/db/couch/utils.ts +0 -50
- package/src/db/db.ts +0 -39
- package/src/db/errors.ts +0 -14
- package/src/db/index.ts +0 -12
- package/src/db/lucene.ts +0 -732
- package/src/db/searchIndexes/index.ts +0 -1
- package/src/db/searchIndexes/searchIndexes.ts +0 -62
- package/src/db/tests/index.spec.js +0 -25
- package/src/db/tests/lucene.spec.ts +0 -298
- package/src/db/tests/pouch.spec.js +0 -62
- package/src/db/tests/utils.spec.ts +0 -63
- package/src/db/utils.ts +0 -207
- package/src/db/views.ts +0 -241
- package/src/docIds/conversions.ts +0 -59
- package/src/docIds/ids.ts +0 -113
- package/src/docIds/index.ts +0 -2
- package/src/docIds/newid.ts +0 -5
- package/src/docIds/params.ts +0 -174
- package/src/docUpdates/index.ts +0 -29
- package/src/environment.ts +0 -201
- package/src/errors/errors.ts +0 -119
- package/src/errors/index.ts +0 -1
- package/src/events/analytics.ts +0 -6
- package/src/events/asyncEvents/index.ts +0 -2
- package/src/events/asyncEvents/publisher.ts +0 -12
- package/src/events/asyncEvents/queue.ts +0 -22
- package/src/events/backfill.ts +0 -183
- package/src/events/documentId.ts +0 -56
- package/src/events/events.ts +0 -40
- package/src/events/identification.ts +0 -310
- package/src/events/index.ts +0 -14
- package/src/events/processors/AnalyticsProcessor.ts +0 -64
- package/src/events/processors/AuditLogsProcessor.ts +0 -93
- package/src/events/processors/LoggingProcessor.ts +0 -37
- package/src/events/processors/Processors.ts +0 -52
- package/src/events/processors/async/DocumentUpdateProcessor.ts +0 -43
- package/src/events/processors/index.ts +0 -19
- package/src/events/processors/posthog/PosthogProcessor.ts +0 -118
- package/src/events/processors/posthog/index.ts +0 -2
- package/src/events/processors/posthog/rateLimiting.ts +0 -106
- package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +0 -168
- package/src/events/processors/types.ts +0 -1
- package/src/events/publishers/account.ts +0 -35
- package/src/events/publishers/app.ts +0 -155
- package/src/events/publishers/auditLog.ts +0 -26
- package/src/events/publishers/auth.ts +0 -73
- package/src/events/publishers/automation.ts +0 -110
- package/src/events/publishers/backfill.ts +0 -74
- package/src/events/publishers/backup.ts +0 -42
- package/src/events/publishers/datasource.ts +0 -48
- package/src/events/publishers/email.ts +0 -17
- package/src/events/publishers/environmentVariable.ts +0 -38
- package/src/events/publishers/group.ts +0 -99
- package/src/events/publishers/index.ts +0 -24
- package/src/events/publishers/installation.ts +0 -38
- package/src/events/publishers/layout.ts +0 -26
- package/src/events/publishers/license.ts +0 -84
- package/src/events/publishers/org.ts +0 -37
- package/src/events/publishers/plugin.ts +0 -47
- package/src/events/publishers/query.ts +0 -88
- package/src/events/publishers/role.ts +0 -62
- package/src/events/publishers/rows.ts +0 -29
- package/src/events/publishers/screen.ts +0 -36
- package/src/events/publishers/serve.ts +0 -43
- package/src/events/publishers/table.ts +0 -70
- package/src/events/publishers/user.ts +0 -202
- package/src/events/publishers/view.ts +0 -107
- package/src/featureFlags/index.ts +0 -77
- package/src/featureFlags/tests/featureFlags.spec.ts +0 -85
- package/src/helpers.ts +0 -9
- package/src/index.ts +0 -53
- package/src/installation.ts +0 -107
- package/src/logging/alerts.ts +0 -26
- package/src/logging/correlation/correlation.ts +0 -13
- package/src/logging/correlation/index.ts +0 -1
- package/src/logging/correlation/middleware.ts +0 -17
- package/src/logging/index.ts +0 -4
- package/src/logging/pino/logger.ts +0 -232
- package/src/logging/pino/middleware.ts +0 -45
- package/src/logging/system.ts +0 -81
- package/src/logging/tests/system.spec.ts +0 -61
- package/src/middleware/adminOnly.ts +0 -9
- package/src/middleware/auditLog.ts +0 -6
- package/src/middleware/authenticated.ts +0 -193
- package/src/middleware/builderOnly.ts +0 -20
- package/src/middleware/builderOrAdmin.ts +0 -20
- package/src/middleware/csrf.ts +0 -81
- package/src/middleware/errorHandling.ts +0 -29
- package/src/middleware/index.ts +0 -21
- package/src/middleware/internalApi.ts +0 -23
- package/src/middleware/joi-validator.ts +0 -45
- package/src/middleware/matchers.ts +0 -47
- package/src/middleware/passport/datasource/google.ts +0 -95
- package/src/middleware/passport/local.ts +0 -54
- package/src/middleware/passport/sso/google.ts +0 -77
- package/src/middleware/passport/sso/oidc.ts +0 -154
- package/src/middleware/passport/sso/sso.ts +0 -165
- package/src/middleware/passport/sso/tests/google.spec.ts +0 -67
- package/src/middleware/passport/sso/tests/oidc.spec.ts +0 -152
- package/src/middleware/passport/sso/tests/sso.spec.ts +0 -197
- package/src/middleware/passport/utils.ts +0 -38
- package/src/middleware/querystringToBody.ts +0 -28
- package/src/middleware/tenancy.ts +0 -36
- package/src/middleware/tests/builder.spec.ts +0 -180
- package/src/middleware/tests/matchers.spec.ts +0 -134
- package/src/migrations/definitions.ts +0 -40
- package/src/migrations/index.ts +0 -2
- package/src/migrations/migrations.ts +0 -191
- package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +0 -11
- package/src/migrations/tests/migrations.spec.ts +0 -64
- package/src/objectStore/buckets/app.ts +0 -40
- package/src/objectStore/buckets/global.ts +0 -29
- package/src/objectStore/buckets/index.ts +0 -3
- package/src/objectStore/buckets/plugins.ts +0 -71
- package/src/objectStore/buckets/tests/app.spec.ts +0 -171
- package/src/objectStore/buckets/tests/global.spec.ts +0 -74
- package/src/objectStore/buckets/tests/plugins.spec.ts +0 -111
- package/src/objectStore/cloudfront.ts +0 -41
- package/src/objectStore/index.ts +0 -3
- package/src/objectStore/objectStore.ts +0 -440
- package/src/objectStore/utils.ts +0 -27
- package/src/platform/index.ts +0 -3
- package/src/platform/platformDb.ts +0 -6
- package/src/platform/tenants.ts +0 -101
- package/src/platform/tests/tenants.spec.ts +0 -26
- package/src/platform/users.ts +0 -90
- package/src/plugin/index.ts +0 -1
- package/src/plugin/tests/validation.spec.ts +0 -83
- package/src/plugin/utils.ts +0 -156
- package/src/queue/constants.ts +0 -6
- package/src/queue/inMemoryQueue.ts +0 -141
- package/src/queue/index.ts +0 -2
- package/src/queue/listeners.ts +0 -195
- package/src/queue/queue.ts +0 -54
- package/src/redis/index.ts +0 -6
- package/src/redis/init.ts +0 -86
- package/src/redis/redis.ts +0 -308
- package/src/redis/redlockImpl.ts +0 -139
- package/src/redis/utils.ts +0 -117
- package/src/security/encryption.ts +0 -179
- package/src/security/permissions.ts +0 -159
- package/src/security/roles.ts +0 -420
- package/src/security/sessions.ts +0 -120
- package/src/security/tests/encryption.spec.ts +0 -31
- package/src/security/tests/permissions.spec.ts +0 -145
- package/src/security/tests/sessions.spec.ts +0 -12
- package/src/tenancy/db.ts +0 -6
- package/src/tenancy/index.ts +0 -2
- package/src/tenancy/tenancy.ts +0 -140
- package/src/tenancy/tests/tenancy.spec.ts +0 -184
- package/src/timers/index.ts +0 -1
- package/src/timers/timers.ts +0 -22
- package/src/users/db.ts +0 -460
- package/src/users/events.ts +0 -176
- package/src/users/index.ts +0 -4
- package/src/users/lookup.ts +0 -102
- package/src/users/users.ts +0 -276
- package/src/users/utils.ts +0 -55
- package/src/utils/hashing.ts +0 -14
- package/src/utils/index.ts +0 -3
- package/src/utils/stringUtils.ts +0 -8
- package/src/utils/tests/utils.spec.ts +0 -191
- package/src/utils/utils.ts +0 -239
- package/tests/core/logging.ts +0 -34
- package/tests/core/utilities/index.ts +0 -6
- package/tests/core/utilities/jestUtils.ts +0 -30
- package/tests/core/utilities/mocks/alerts.ts +0 -3
- package/tests/core/utilities/mocks/date.ts +0 -2
- package/tests/core/utilities/mocks/events.ts +0 -131
- package/tests/core/utilities/mocks/fetch.ts +0 -17
- package/tests/core/utilities/mocks/index.ts +0 -10
- package/tests/core/utilities/mocks/licenses.ts +0 -107
- package/tests/core/utilities/mocks/posthog.ts +0 -7
- package/tests/core/utilities/structures/Chance.ts +0 -20
- package/tests/core/utilities/structures/accounts.ts +0 -115
- package/tests/core/utilities/structures/apps.ts +0 -21
- package/tests/core/utilities/structures/common.ts +0 -7
- package/tests/core/utilities/structures/db.ts +0 -12
- package/tests/core/utilities/structures/documents/index.ts +0 -1
- package/tests/core/utilities/structures/documents/platform/index.ts +0 -1
- package/tests/core/utilities/structures/documents/platform/installation.ts +0 -12
- package/tests/core/utilities/structures/generator.ts +0 -2
- package/tests/core/utilities/structures/index.ts +0 -15
- package/tests/core/utilities/structures/koa.ts +0 -16
- package/tests/core/utilities/structures/licenses.ts +0 -167
- package/tests/core/utilities/structures/plugins.ts +0 -19
- package/tests/core/utilities/structures/quotas.ts +0 -67
- package/tests/core/utilities/structures/scim.ts +0 -80
- package/tests/core/utilities/structures/shared.ts +0 -19
- package/tests/core/utilities/structures/sso.ts +0 -119
- package/tests/core/utilities/structures/tenants.ts +0 -5
- package/tests/core/utilities/structures/userGroups.ts +0 -10
- package/tests/core/utilities/structures/users.ts +0 -73
- package/tests/core/utilities/testContainerUtils.ts +0 -98
- package/tests/core/utilities/utils/index.ts +0 -1
- package/tests/core/utilities/utils/time.ts +0 -3
- package/tests/extra/DBTestConfiguration.ts +0 -36
- package/tests/extra/index.ts +0 -2
- package/tests/extra/testEnv.ts +0 -95
- package/tests/index.ts +0 -1
- package/tests/jestEnv.ts +0 -6
- package/tests/jestSetup.ts +0 -28
package/src/accounts/accounts.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import API from "./api"
|
|
2
|
-
import env from "../environment"
|
|
3
|
-
import { Header } from "../constants"
|
|
4
|
-
import { CloudAccount, HealthStatusResponse } from "@budibase/types"
|
|
5
|
-
|
|
6
|
-
const api = new API(env.ACCOUNT_PORTAL_URL)
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* This client is intended to be used in a cloud hosted deploy only.
|
|
10
|
-
* Rather than relying on each consumer to perform the necessary environmental checks
|
|
11
|
-
* we use the following check to exit early with a undefined response which should be
|
|
12
|
-
* handled by the caller.
|
|
13
|
-
*/
|
|
14
|
-
const EXIT_EARLY = env.SELF_HOSTED || env.DISABLE_ACCOUNT_PORTAL
|
|
15
|
-
|
|
16
|
-
export const getAccount = async (
|
|
17
|
-
email: string
|
|
18
|
-
): Promise<CloudAccount | undefined> => {
|
|
19
|
-
if (EXIT_EARLY) {
|
|
20
|
-
return
|
|
21
|
-
}
|
|
22
|
-
const payload = {
|
|
23
|
-
email,
|
|
24
|
-
}
|
|
25
|
-
const response = await api.post(`/api/accounts/search`, {
|
|
26
|
-
body: payload,
|
|
27
|
-
headers: {
|
|
28
|
-
[Header.API_KEY]: env.ACCOUNT_PORTAL_API_KEY,
|
|
29
|
-
},
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
if (response.status !== 200) {
|
|
33
|
-
throw new Error(`Error getting account by email ${email}`)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const json: CloudAccount[] = await response.json()
|
|
37
|
-
return json[0]
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const getAccountByTenantId = async (
|
|
41
|
-
tenantId: string
|
|
42
|
-
): Promise<CloudAccount | undefined> => {
|
|
43
|
-
if (EXIT_EARLY) {
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
const payload = {
|
|
47
|
-
tenantId,
|
|
48
|
-
}
|
|
49
|
-
const response = await api.post(`/api/accounts/search`, {
|
|
50
|
-
body: payload,
|
|
51
|
-
headers: {
|
|
52
|
-
[Header.API_KEY]: env.ACCOUNT_PORTAL_API_KEY,
|
|
53
|
-
},
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
if (response.status !== 200) {
|
|
57
|
-
throw new Error(`Error getting account by tenantId ${tenantId}`)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const json: CloudAccount[] = await response.json()
|
|
61
|
-
return json[0]
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export const getStatus = async (): Promise<
|
|
65
|
-
HealthStatusResponse | undefined
|
|
66
|
-
> => {
|
|
67
|
-
if (EXIT_EARLY) {
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
const response = await api.get(`/api/status`, {
|
|
71
|
-
headers: {
|
|
72
|
-
[Header.API_KEY]: env.ACCOUNT_PORTAL_API_KEY,
|
|
73
|
-
},
|
|
74
|
-
})
|
|
75
|
-
const json = await response.json()
|
|
76
|
-
|
|
77
|
-
if (response.status !== 200) {
|
|
78
|
-
throw new Error(`Error getting status`)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return json
|
|
82
|
-
}
|
package/src/accounts/api.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import fetch from "node-fetch"
|
|
2
|
-
import * as logging from "../logging"
|
|
3
|
-
|
|
4
|
-
export default class API {
|
|
5
|
-
host: string
|
|
6
|
-
|
|
7
|
-
constructor(host: string) {
|
|
8
|
-
this.host = host
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async apiCall(method: string, url: string, options?: any) {
|
|
12
|
-
if (!options.headers) {
|
|
13
|
-
options.headers = {}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (!options.headers["Content-Type"]) {
|
|
17
|
-
options.headers = {
|
|
18
|
-
"Content-Type": "application/json",
|
|
19
|
-
Accept: "application/json",
|
|
20
|
-
...options.headers,
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
let json = options.headers["Content-Type"] === "application/json"
|
|
25
|
-
|
|
26
|
-
// add x-budibase-correlation-id header
|
|
27
|
-
logging.correlation.setHeader(options.headers)
|
|
28
|
-
|
|
29
|
-
const requestOptions = {
|
|
30
|
-
method: method,
|
|
31
|
-
body: json ? JSON.stringify(options.body) : options.body,
|
|
32
|
-
headers: options.headers,
|
|
33
|
-
// TODO: See if this is necessary
|
|
34
|
-
credentials: "include",
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return await fetch(`${this.host}${url}`, requestOptions)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async post(url: string, options?: any) {
|
|
41
|
-
return this.apiCall("POST", url, options)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async get(url: string, options?: any) {
|
|
45
|
-
return this.apiCall("GET", url, options)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async patch(url: string, options?: any) {
|
|
49
|
-
return this.apiCall("PATCH", url, options)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async del(url: string, options?: any) {
|
|
53
|
-
return this.apiCall("DELETE", url, options)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async put(url: string, options?: any) {
|
|
57
|
-
return this.apiCall("PUT", url, options)
|
|
58
|
-
}
|
|
59
|
-
}
|
package/src/accounts/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./accounts"
|
package/src/auth/auth.ts
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
const _passport = require("koa-passport")
|
|
2
|
-
const LocalStrategy = require("passport-local").Strategy
|
|
3
|
-
import { getGlobalDB } from "../context"
|
|
4
|
-
import { Cookie } from "../constants"
|
|
5
|
-
import { getSessionsForUser, invalidateSessions } from "../security/sessions"
|
|
6
|
-
import {
|
|
7
|
-
authenticated,
|
|
8
|
-
csrf,
|
|
9
|
-
google,
|
|
10
|
-
local,
|
|
11
|
-
oidc,
|
|
12
|
-
tenancy,
|
|
13
|
-
} from "../middleware"
|
|
14
|
-
import * as userCache from "../cache/user"
|
|
15
|
-
import { invalidateUser } from "../cache/user"
|
|
16
|
-
import {
|
|
17
|
-
ConfigType,
|
|
18
|
-
GoogleInnerConfig,
|
|
19
|
-
OIDCInnerConfig,
|
|
20
|
-
PlatformLogoutOpts,
|
|
21
|
-
SSOProviderType,
|
|
22
|
-
} from "@budibase/types"
|
|
23
|
-
import * as events from "../events"
|
|
24
|
-
import * as configs from "../configs"
|
|
25
|
-
import { clearCookie, getCookie } from "../utils"
|
|
26
|
-
import { ssoSaveUserNoOp } from "../middleware/passport/sso/sso"
|
|
27
|
-
|
|
28
|
-
const refresh = require("passport-oauth2-refresh")
|
|
29
|
-
export {
|
|
30
|
-
auditLog,
|
|
31
|
-
authError,
|
|
32
|
-
internalApi,
|
|
33
|
-
ssoCallbackUrl,
|
|
34
|
-
adminOnly,
|
|
35
|
-
builderOnly,
|
|
36
|
-
builderOrAdmin,
|
|
37
|
-
joiValidator,
|
|
38
|
-
google,
|
|
39
|
-
oidc,
|
|
40
|
-
} from "../middleware"
|
|
41
|
-
export const buildAuthMiddleware = authenticated
|
|
42
|
-
export const buildTenancyMiddleware = tenancy
|
|
43
|
-
export const buildCsrfMiddleware = csrf
|
|
44
|
-
export const passport = _passport
|
|
45
|
-
export const jwt = require("jsonwebtoken")
|
|
46
|
-
|
|
47
|
-
// Strategies
|
|
48
|
-
_passport.use(new LocalStrategy(local.options, local.authenticate))
|
|
49
|
-
|
|
50
|
-
async function refreshOIDCAccessToken(
|
|
51
|
-
chosenConfig: OIDCInnerConfig,
|
|
52
|
-
refreshToken: string
|
|
53
|
-
): Promise<RefreshResponse> {
|
|
54
|
-
const callbackUrl = await oidc.getCallbackUrl()
|
|
55
|
-
let enrichedConfig: any
|
|
56
|
-
let strategy: any
|
|
57
|
-
|
|
58
|
-
try {
|
|
59
|
-
enrichedConfig = await oidc.fetchStrategyConfig(chosenConfig, callbackUrl)
|
|
60
|
-
if (!enrichedConfig) {
|
|
61
|
-
throw new Error("OIDC Config contents invalid")
|
|
62
|
-
}
|
|
63
|
-
strategy = await oidc.strategyFactory(enrichedConfig, ssoSaveUserNoOp)
|
|
64
|
-
} catch (err) {
|
|
65
|
-
console.error(err)
|
|
66
|
-
throw new Error("Could not refresh OAuth Token")
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
refresh.use(strategy, {
|
|
70
|
-
setRefreshOAuth2() {
|
|
71
|
-
return strategy._getOAuth2Client(enrichedConfig)
|
|
72
|
-
},
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
return new Promise(resolve => {
|
|
76
|
-
refresh.requestNewAccessToken(
|
|
77
|
-
ConfigType.OIDC,
|
|
78
|
-
refreshToken,
|
|
79
|
-
(err: any, accessToken: string, refreshToken: any, params: any) => {
|
|
80
|
-
resolve({ err, accessToken, refreshToken, params })
|
|
81
|
-
}
|
|
82
|
-
)
|
|
83
|
-
})
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async function refreshGoogleAccessToken(
|
|
87
|
-
config: GoogleInnerConfig,
|
|
88
|
-
refreshToken: any
|
|
89
|
-
): Promise<RefreshResponse> {
|
|
90
|
-
let callbackUrl = await google.getCallbackUrl(config)
|
|
91
|
-
|
|
92
|
-
let strategy
|
|
93
|
-
try {
|
|
94
|
-
strategy = await google.strategyFactory(
|
|
95
|
-
config,
|
|
96
|
-
callbackUrl,
|
|
97
|
-
ssoSaveUserNoOp
|
|
98
|
-
)
|
|
99
|
-
} catch (err: any) {
|
|
100
|
-
console.error(err)
|
|
101
|
-
throw new Error(
|
|
102
|
-
`Error constructing OIDC refresh strategy: message=${err.message}`
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
refresh.use(strategy)
|
|
107
|
-
|
|
108
|
-
return new Promise(resolve => {
|
|
109
|
-
refresh.requestNewAccessToken(
|
|
110
|
-
ConfigType.GOOGLE,
|
|
111
|
-
refreshToken,
|
|
112
|
-
(err: any, accessToken: string, refreshToken: string, params: any) => {
|
|
113
|
-
resolve({ err, accessToken, refreshToken, params })
|
|
114
|
-
}
|
|
115
|
-
)
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
interface RefreshResponse {
|
|
120
|
-
err?: {
|
|
121
|
-
data?: string
|
|
122
|
-
}
|
|
123
|
-
accessToken?: string
|
|
124
|
-
refreshToken?: string
|
|
125
|
-
params?: any
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export async function refreshOAuthToken(
|
|
129
|
-
refreshToken: string,
|
|
130
|
-
providerType: SSOProviderType,
|
|
131
|
-
configId?: string
|
|
132
|
-
): Promise<RefreshResponse> {
|
|
133
|
-
switch (providerType) {
|
|
134
|
-
case SSOProviderType.OIDC:
|
|
135
|
-
if (!configId) {
|
|
136
|
-
return { err: { data: "OIDC config id not provided" } }
|
|
137
|
-
}
|
|
138
|
-
const oidcConfig = await configs.getOIDCConfigById(configId)
|
|
139
|
-
if (!oidcConfig) {
|
|
140
|
-
return { err: { data: "OIDC configuration not found" } }
|
|
141
|
-
}
|
|
142
|
-
return refreshOIDCAccessToken(oidcConfig, refreshToken)
|
|
143
|
-
case SSOProviderType.GOOGLE:
|
|
144
|
-
let googleConfig = await configs.getGoogleConfig()
|
|
145
|
-
if (!googleConfig) {
|
|
146
|
-
return { err: { data: "Google configuration not found" } }
|
|
147
|
-
}
|
|
148
|
-
return refreshGoogleAccessToken(googleConfig, refreshToken)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// TODO: Refactor to use user save function instead to prevent the need for
|
|
153
|
-
// manually saving and invalidating on callback
|
|
154
|
-
export async function updateUserOAuth(userId: string, oAuthConfig: any) {
|
|
155
|
-
const details = {
|
|
156
|
-
accessToken: oAuthConfig.accessToken,
|
|
157
|
-
refreshToken: oAuthConfig.refreshToken,
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
const db = getGlobalDB()
|
|
162
|
-
const dbUser = await db.get<any>(userId)
|
|
163
|
-
|
|
164
|
-
//Do not overwrite the refresh token if a valid one is not provided.
|
|
165
|
-
if (typeof details.refreshToken !== "string") {
|
|
166
|
-
delete details.refreshToken
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
dbUser.oauth2 = {
|
|
170
|
-
...dbUser.oauth2,
|
|
171
|
-
...details,
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
await db.put(dbUser)
|
|
175
|
-
|
|
176
|
-
await invalidateUser(userId)
|
|
177
|
-
} catch (e) {
|
|
178
|
-
console.error("Could not update OAuth details for current user", e)
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Logs a user out from budibase. Re-used across account portal and builder.
|
|
184
|
-
*/
|
|
185
|
-
export async function platformLogout(opts: PlatformLogoutOpts) {
|
|
186
|
-
const ctx = opts.ctx
|
|
187
|
-
const userId = opts.userId
|
|
188
|
-
const keepActiveSession = opts.keepActiveSession
|
|
189
|
-
|
|
190
|
-
if (!ctx) throw new Error("Koa context must be supplied to logout.")
|
|
191
|
-
|
|
192
|
-
const currentSession = getCookie(ctx, Cookie.Auth)
|
|
193
|
-
let sessions = await getSessionsForUser(userId)
|
|
194
|
-
|
|
195
|
-
if (keepActiveSession) {
|
|
196
|
-
sessions = sessions.filter(
|
|
197
|
-
session => session.sessionId !== currentSession.sessionId
|
|
198
|
-
)
|
|
199
|
-
} else {
|
|
200
|
-
// clear cookies
|
|
201
|
-
clearCookie(ctx, Cookie.Auth)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const sessionIds = sessions.map(({ sessionId }) => sessionId)
|
|
205
|
-
await invalidateSessions(userId, { sessionIds, reason: "logout" })
|
|
206
|
-
await events.auth.logout(ctx.user?.email)
|
|
207
|
-
await userCache.invalidateUser(userId)
|
|
208
|
-
}
|
package/src/auth/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./auth"
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { structures } from "../../../tests"
|
|
2
|
-
import { testEnv } from "../../../tests/extra"
|
|
3
|
-
import * as auth from "../auth"
|
|
4
|
-
import * as events from "../../events"
|
|
5
|
-
|
|
6
|
-
describe("platformLogout", () => {
|
|
7
|
-
it("should call platform logout", async () => {
|
|
8
|
-
await testEnv.withTenant(async () => {
|
|
9
|
-
const ctx = structures.koa.newContext()
|
|
10
|
-
await auth.platformLogout({ ctx, userId: "test" })
|
|
11
|
-
expect(events.auth.logout).toBeCalledTimes(1)
|
|
12
|
-
})
|
|
13
|
-
})
|
|
14
|
-
})
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import dns from "dns"
|
|
2
|
-
import net from "net"
|
|
3
|
-
import env from "../environment"
|
|
4
|
-
import { promisify } from "util"
|
|
5
|
-
|
|
6
|
-
let blackListArray: string[] | undefined
|
|
7
|
-
const performLookup = promisify(dns.lookup)
|
|
8
|
-
|
|
9
|
-
async function lookup(address: string): Promise<string[]> {
|
|
10
|
-
if (!net.isIP(address)) {
|
|
11
|
-
// need this for URL parsing simply
|
|
12
|
-
if (!address.startsWith("http")) {
|
|
13
|
-
address = `https://${address}`
|
|
14
|
-
}
|
|
15
|
-
address = new URL(address).hostname
|
|
16
|
-
}
|
|
17
|
-
const addresses = await performLookup(address, {
|
|
18
|
-
all: true,
|
|
19
|
-
})
|
|
20
|
-
return addresses.map(addr => addr.address)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export async function refreshBlacklist() {
|
|
24
|
-
const blacklist = env.BLACKLIST_IPS
|
|
25
|
-
const list = blacklist?.split(",") || []
|
|
26
|
-
let final: string[] = []
|
|
27
|
-
for (let addr of list) {
|
|
28
|
-
const trimmed = addr.trim()
|
|
29
|
-
if (!net.isIP(trimmed)) {
|
|
30
|
-
const addresses = await lookup(trimmed)
|
|
31
|
-
final = final.concat(addresses)
|
|
32
|
-
} else {
|
|
33
|
-
final.push(trimmed)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
blackListArray = final
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function isBlacklisted(address: string): Promise<boolean> {
|
|
40
|
-
if (!blackListArray) {
|
|
41
|
-
await refreshBlacklist()
|
|
42
|
-
}
|
|
43
|
-
if (blackListArray?.length === 0) {
|
|
44
|
-
return false
|
|
45
|
-
}
|
|
46
|
-
// no need for DNS
|
|
47
|
-
let ips: string[]
|
|
48
|
-
if (!net.isIP(address)) {
|
|
49
|
-
ips = await lookup(address)
|
|
50
|
-
} else {
|
|
51
|
-
ips = [address]
|
|
52
|
-
}
|
|
53
|
-
return !!blackListArray?.find(addr => ips.includes(addr))
|
|
54
|
-
}
|
package/src/blacklist/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./blacklist"
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { refreshBlacklist, isBlacklisted } from ".."
|
|
2
|
-
import env from "../../environment"
|
|
3
|
-
|
|
4
|
-
describe("blacklist", () => {
|
|
5
|
-
beforeAll(async () => {
|
|
6
|
-
env._set(
|
|
7
|
-
"BLACKLIST_IPS",
|
|
8
|
-
"www.google.com,192.168.1.1, 1.1.1.1,2.2.2.2/something"
|
|
9
|
-
)
|
|
10
|
-
await refreshBlacklist()
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
it("should blacklist 192.168.1.1", async () => {
|
|
14
|
-
expect(await isBlacklisted("192.168.1.1")).toBe(true)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it("should allow 192.168.1.2", async () => {
|
|
18
|
-
expect(await isBlacklisted("192.168.1.2")).toBe(false)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it("should blacklist www.google.com", async () => {
|
|
22
|
-
expect(await isBlacklisted("www.google.com")).toBe(true)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it("should handle a complex domain", async () => {
|
|
26
|
-
expect(
|
|
27
|
-
await isBlacklisted("https://www.google.com/derp/?something=1")
|
|
28
|
-
).toBe(true)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it("should allow www.microsoft.com", async () => {
|
|
32
|
-
expect(await isBlacklisted("www.microsoft.com")).toBe(false)
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it("should blacklist an IP that needed trimming", async () => {
|
|
36
|
-
expect(await isBlacklisted("1.1.1.1")).toBe(true)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it("should blacklist 1.1.1.1/something", async () => {
|
|
40
|
-
expect(await isBlacklisted("1.1.1.1/something")).toBe(true)
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
it("should blacklist 2.2.2.2", async () => {
|
|
44
|
-
expect(await isBlacklisted("2.2.2.2")).toBe(true)
|
|
45
|
-
})
|
|
46
|
-
})
|
package/src/cache/appMetadata.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { getAppClient } from "../redis/init"
|
|
2
|
-
import { doWithDB, DocumentType } from "../db"
|
|
3
|
-
import { Database, App } from "@budibase/types"
|
|
4
|
-
|
|
5
|
-
export enum AppState {
|
|
6
|
-
INVALID = "invalid",
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export interface DeletedApp {
|
|
10
|
-
state: AppState
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const EXPIRY_SECONDS = 3600
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The default populate app metadata function
|
|
17
|
-
*/
|
|
18
|
-
async function populateFromDB(appId: string) {
|
|
19
|
-
return doWithDB(
|
|
20
|
-
appId,
|
|
21
|
-
(db: Database) => {
|
|
22
|
-
return db.get(DocumentType.APP_METADATA)
|
|
23
|
-
},
|
|
24
|
-
{ skip_setup: true }
|
|
25
|
-
)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function isInvalid(metadata?: { state: string }) {
|
|
29
|
-
return !metadata || metadata.state === AppState.INVALID
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Get the requested app metadata by id.
|
|
34
|
-
* Use redis cache to first read the app metadata.
|
|
35
|
-
* If not present fallback to loading the app metadata directly and re-caching.
|
|
36
|
-
* @param {string} appId the id of the app to get metadata from.
|
|
37
|
-
* @returns {object} the app metadata.
|
|
38
|
-
*/
|
|
39
|
-
export async function getAppMetadata(appId: string): Promise<App | DeletedApp> {
|
|
40
|
-
const client = await getAppClient()
|
|
41
|
-
// try cache
|
|
42
|
-
let metadata = await client.get(appId)
|
|
43
|
-
if (!metadata) {
|
|
44
|
-
let expiry: number | undefined = EXPIRY_SECONDS
|
|
45
|
-
try {
|
|
46
|
-
metadata = await populateFromDB(appId)
|
|
47
|
-
} catch (err: any) {
|
|
48
|
-
// app DB left around, but no metadata, it is invalid
|
|
49
|
-
if (err && err.status === 404) {
|
|
50
|
-
metadata = { state: AppState.INVALID }
|
|
51
|
-
// don't expire the reference to an invalid app, it'll only be
|
|
52
|
-
// updated if a metadata doc actually gets stored (app is remade/reverted)
|
|
53
|
-
expiry = undefined
|
|
54
|
-
} else {
|
|
55
|
-
throw err
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// needed for cypress/some scenarios where the caching happens
|
|
59
|
-
// so quickly the requests can get slightly out of sync
|
|
60
|
-
// might store its invalid just before it stores its valid
|
|
61
|
-
if (isInvalid(metadata)) {
|
|
62
|
-
const temp = await client.get(appId)
|
|
63
|
-
if (temp) {
|
|
64
|
-
metadata = temp
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
await client.store(appId, metadata, expiry)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return metadata
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Invalidate/reset the cached metadata when a change occurs in the db.
|
|
75
|
-
* @param appId {string} the cache key to bust/update.
|
|
76
|
-
* @param newMetadata {object|undefined} optional - can simply provide the new metadata to update with.
|
|
77
|
-
* @return {Promise<void>} will respond with success when cache is updated.
|
|
78
|
-
*/
|
|
79
|
-
export async function invalidateAppMetadata(appId: string, newMetadata?: any) {
|
|
80
|
-
if (!appId) {
|
|
81
|
-
throw "Cannot invalidate if no app ID provided."
|
|
82
|
-
}
|
|
83
|
-
const client = await getAppClient()
|
|
84
|
-
await client.delete(appId)
|
|
85
|
-
if (newMetadata) {
|
|
86
|
-
await client.store(appId, newMetadata, EXPIRY_SECONDS)
|
|
87
|
-
}
|
|
88
|
-
}
|
package/src/cache/base/index.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { getTenantId } from "../../context"
|
|
2
|
-
import * as redis from "../../redis/init"
|
|
3
|
-
import { Client } from "../../redis"
|
|
4
|
-
|
|
5
|
-
function generateTenantKey(key: string) {
|
|
6
|
-
const tenantId = getTenantId()
|
|
7
|
-
return `${key}:${tenantId}`
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default class BaseCache {
|
|
11
|
-
client: Client | undefined
|
|
12
|
-
|
|
13
|
-
constructor(client: Client | undefined = undefined) {
|
|
14
|
-
this.client = client
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async getClient() {
|
|
18
|
-
return !this.client ? await redis.getCacheClient() : this.client
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async keys(pattern: string) {
|
|
22
|
-
const client = await this.getClient()
|
|
23
|
-
return client.keys(pattern)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Read only from the cache.
|
|
28
|
-
*/
|
|
29
|
-
async get(key: string, opts = { useTenancy: true }) {
|
|
30
|
-
key = opts.useTenancy ? generateTenantKey(key) : key
|
|
31
|
-
const client = await this.getClient()
|
|
32
|
-
return client.get(key)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Write to the cache.
|
|
37
|
-
*/
|
|
38
|
-
async store(
|
|
39
|
-
key: string,
|
|
40
|
-
value: any,
|
|
41
|
-
ttl: number | null = null,
|
|
42
|
-
opts = { useTenancy: true }
|
|
43
|
-
) {
|
|
44
|
-
key = opts.useTenancy ? generateTenantKey(key) : key
|
|
45
|
-
const client = await this.getClient()
|
|
46
|
-
await client.store(key, value, ttl)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Remove from cache.
|
|
51
|
-
*/
|
|
52
|
-
async delete(key: string, opts = { useTenancy: true }) {
|
|
53
|
-
key = opts.useTenancy ? generateTenantKey(key) : key
|
|
54
|
-
const client = await this.getClient()
|
|
55
|
-
return client.delete(key)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Read from the cache. Write to the cache if not exists.
|
|
60
|
-
*/
|
|
61
|
-
async withCache(
|
|
62
|
-
key: string,
|
|
63
|
-
ttl: number,
|
|
64
|
-
fetchFn: any,
|
|
65
|
-
opts = { useTenancy: true }
|
|
66
|
-
) {
|
|
67
|
-
const cachedValue = await this.get(key, opts)
|
|
68
|
-
if (cachedValue) {
|
|
69
|
-
return cachedValue
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
const fetchedValue = await fetchFn()
|
|
74
|
-
|
|
75
|
-
await this.store(key, fetchedValue, ttl, opts)
|
|
76
|
-
return fetchedValue
|
|
77
|
-
} catch (err) {
|
|
78
|
-
console.error("Error fetching before cache - ", err)
|
|
79
|
-
throw err
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
async bustCache(key: string, opts = { client: null }) {
|
|
84
|
-
const client = await this.getClient()
|
|
85
|
-
try {
|
|
86
|
-
await client.delete(generateTenantKey(key))
|
|
87
|
-
} catch (err) {
|
|
88
|
-
console.error("Error busting cache - ", err)
|
|
89
|
-
throw err
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
package/src/cache/generic.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const BaseCache = require("./base")
|
|
2
|
-
|
|
3
|
-
const GENERIC = new BaseCache.default()
|
|
4
|
-
|
|
5
|
-
export enum CacheKey {
|
|
6
|
-
CHECKLIST = "checklist",
|
|
7
|
-
INSTALLATION = "installation",
|
|
8
|
-
ANALYTICS_ENABLED = "analyticsEnabled",
|
|
9
|
-
UNIQUE_TENANT_ID = "uniqueTenantId",
|
|
10
|
-
EVENTS = "events",
|
|
11
|
-
BACKFILL_METADATA = "backfillMetadata",
|
|
12
|
-
EVENTS_RATE_LIMIT = "eventsRateLimit",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export enum TTL {
|
|
16
|
-
ONE_MINUTE = 600,
|
|
17
|
-
ONE_HOUR = 3600,
|
|
18
|
-
ONE_DAY = 86400,
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function performExport(funcName: string) {
|
|
22
|
-
return (...args: any) => GENERIC[funcName](...args)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const keys = performExport("keys")
|
|
26
|
-
export const get = performExport("get")
|
|
27
|
-
export const store = performExport("store")
|
|
28
|
-
export const destroy = performExport("delete")
|
|
29
|
-
export const withCache = performExport("withCache")
|
|
30
|
-
export const bustCache = performExport("bustCache")
|