@budibase/backend-core 2.9.19 → 2.9.21-alpha.0
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 +266 -324
- package/dist/index.js.map +4 -4
- package/dist/index.js.meta.json +1 -1
- package/dist/package.json +19 -4
- package/dist/plugins.js +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/plugins.js.meta.json +1 -1
- package/dist/src/security/permissions.d.ts +1 -1
- package/dist/tests.js +222 -260
- package/dist/tests.js.map +4 -4
- package/dist/tests.js.meta.json +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/middleware/csrf.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Header } from "../constants"
|
|
2
|
-
import { buildMatcherRegex, matches } from "./matchers"
|
|
3
|
-
import { BBContext, EndpointMatcher } from "@budibase/types"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* GET, HEAD and OPTIONS methods are considered safe operations
|
|
7
|
-
*
|
|
8
|
-
* POST, PUT, PATCH, and DELETE methods, being state changing verbs,
|
|
9
|
-
* should have a CSRF token attached to the request
|
|
10
|
-
*/
|
|
11
|
-
const EXCLUDED_METHODS = ["GET", "HEAD", "OPTIONS"]
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* There are only three content type values that can be used in cross domain requests.
|
|
15
|
-
* If any other value is used, e.g. application/json, the browser will first make a OPTIONS
|
|
16
|
-
* request which will be protected by CORS.
|
|
17
|
-
*/
|
|
18
|
-
const INCLUDED_CONTENT_TYPES = [
|
|
19
|
-
"application/x-www-form-urlencoded",
|
|
20
|
-
"multipart/form-data",
|
|
21
|
-
"text/plain",
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Validate the CSRF token generated aganst the user session.
|
|
26
|
-
* Compare the token with the x-csrf-token header.
|
|
27
|
-
*
|
|
28
|
-
* If the token is not found within the request or the value provided
|
|
29
|
-
* does not match the value within the user session, the request is rejected.
|
|
30
|
-
*
|
|
31
|
-
* CSRF protection provided using the 'Synchronizer Token Pattern'
|
|
32
|
-
* https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#synchronizer-token-pattern
|
|
33
|
-
*
|
|
34
|
-
*/
|
|
35
|
-
export default function (
|
|
36
|
-
opts: { noCsrfPatterns: EndpointMatcher[] } = { noCsrfPatterns: [] }
|
|
37
|
-
) {
|
|
38
|
-
const noCsrfOptions = buildMatcherRegex(opts.noCsrfPatterns)
|
|
39
|
-
return async (ctx: BBContext | any, next: any) => {
|
|
40
|
-
// don't apply for excluded paths
|
|
41
|
-
const found = matches(ctx, noCsrfOptions)
|
|
42
|
-
if (found) {
|
|
43
|
-
return next()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// don't apply for the excluded http methods
|
|
47
|
-
if (EXCLUDED_METHODS.indexOf(ctx.method) !== -1) {
|
|
48
|
-
return next()
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// don't apply when the content type isn't supported
|
|
52
|
-
let contentType = ctx.get("content-type")
|
|
53
|
-
? ctx.get("content-type").toLowerCase()
|
|
54
|
-
: ""
|
|
55
|
-
if (
|
|
56
|
-
!INCLUDED_CONTENT_TYPES.filter(type => contentType.includes(type)).length
|
|
57
|
-
) {
|
|
58
|
-
return next()
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// don't apply csrf when the internal api key has been used
|
|
62
|
-
if (ctx.internal) {
|
|
63
|
-
return next()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// apply csrf when there is a token in the session (new logins)
|
|
67
|
-
// in future there should be a hard requirement that the token is present
|
|
68
|
-
const userToken = ctx.user?.csrfToken
|
|
69
|
-
if (!userToken) {
|
|
70
|
-
return next()
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// reject if no token in request or mismatch
|
|
74
|
-
const requestToken = ctx.get(Header.CSRF_TOKEN)
|
|
75
|
-
if (!requestToken || requestToken !== userToken) {
|
|
76
|
-
ctx.throw(403, "Invalid CSRF token")
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return next()
|
|
80
|
-
}
|
|
81
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { APIError } from "@budibase/types"
|
|
2
|
-
import * as errors from "../errors"
|
|
3
|
-
|
|
4
|
-
export async function errorHandling(ctx: any, next: any) {
|
|
5
|
-
try {
|
|
6
|
-
await next()
|
|
7
|
-
} catch (err: any) {
|
|
8
|
-
const status = err.status || err.statusCode || 500
|
|
9
|
-
ctx.status = status
|
|
10
|
-
|
|
11
|
-
if (status >= 400 && status < 500) {
|
|
12
|
-
console.warn(err)
|
|
13
|
-
} else {
|
|
14
|
-
console.error(err)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const error = errors.getPublicError(err)
|
|
18
|
-
const body: APIError = {
|
|
19
|
-
message: err.message,
|
|
20
|
-
status: status,
|
|
21
|
-
validationErrors: err.validation,
|
|
22
|
-
error,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
ctx.body = body
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default errorHandling
|
package/src/middleware/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export * as local from "./passport/local"
|
|
2
|
-
export * as google from "./passport/sso/google"
|
|
3
|
-
export * as oidc from "./passport/sso/oidc"
|
|
4
|
-
import * as datasourceGoogle from "./passport/datasource/google"
|
|
5
|
-
export const datasource = {
|
|
6
|
-
google: datasourceGoogle,
|
|
7
|
-
}
|
|
8
|
-
export { authError, ssoCallbackUrl } from "./passport/utils"
|
|
9
|
-
export { default as authenticated } from "./authenticated"
|
|
10
|
-
export { default as auditLog } from "./auditLog"
|
|
11
|
-
export { default as tenancy } from "./tenancy"
|
|
12
|
-
export { default as internalApi } from "./internalApi"
|
|
13
|
-
export { default as csrf } from "./csrf"
|
|
14
|
-
export { default as adminOnly } from "./adminOnly"
|
|
15
|
-
export { default as builderOrAdmin } from "./builderOrAdmin"
|
|
16
|
-
export { default as builderOnly } from "./builderOnly"
|
|
17
|
-
export { default as pino } from "../logging/pino/middleware"
|
|
18
|
-
export { default as correlation } from "../logging/correlation/middleware"
|
|
19
|
-
export { default as errorHandling } from "./errorHandling"
|
|
20
|
-
export { default as querystringToBody } from "./querystringToBody"
|
|
21
|
-
export * as joiValidator from "./joi-validator"
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Header } from "../constants"
|
|
2
|
-
import { BBContext } from "@budibase/types"
|
|
3
|
-
import { isValidInternalAPIKey } from "../utils"
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* API Key only endpoint.
|
|
7
|
-
*/
|
|
8
|
-
export default async (ctx: BBContext, next: any) => {
|
|
9
|
-
const apiKey = ctx.request.headers[Header.API_KEY]
|
|
10
|
-
if (!apiKey) {
|
|
11
|
-
ctx.throw(403, "Unauthorized")
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (Array.isArray(apiKey)) {
|
|
15
|
-
ctx.throw(403, "Unauthorized")
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (!isValidInternalAPIKey(apiKey)) {
|
|
19
|
-
ctx.throw(403, "Unauthorized")
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return next()
|
|
23
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import Joi, { ObjectSchema } from "joi"
|
|
2
|
-
import { BBContext } from "@budibase/types"
|
|
3
|
-
|
|
4
|
-
function validate(
|
|
5
|
-
schema: Joi.ObjectSchema | Joi.ArraySchema,
|
|
6
|
-
property: string
|
|
7
|
-
) {
|
|
8
|
-
// Return a Koa middleware function
|
|
9
|
-
return (ctx: BBContext, next: any) => {
|
|
10
|
-
if (!schema) {
|
|
11
|
-
return next()
|
|
12
|
-
}
|
|
13
|
-
let params = null
|
|
14
|
-
// @ts-ignore
|
|
15
|
-
let reqProp = ctx.request?.[property]
|
|
16
|
-
if (ctx[property] != null) {
|
|
17
|
-
params = ctx[property]
|
|
18
|
-
} else if (reqProp != null) {
|
|
19
|
-
params = reqProp
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// not all schemas have the append property e.g. array schemas
|
|
23
|
-
if ((schema as Joi.ObjectSchema).append) {
|
|
24
|
-
schema = (schema as Joi.ObjectSchema).append({
|
|
25
|
-
createdAt: Joi.any().optional(),
|
|
26
|
-
updatedAt: Joi.any().optional(),
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const { error } = schema.validate(params)
|
|
31
|
-
if (error) {
|
|
32
|
-
ctx.throw(400, `Invalid ${property} - ${error.message}`)
|
|
33
|
-
return
|
|
34
|
-
}
|
|
35
|
-
return next()
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function body(schema: Joi.ObjectSchema | Joi.ArraySchema) {
|
|
40
|
-
return validate(schema, "body")
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function params(schema: Joi.ObjectSchema | Joi.ArraySchema) {
|
|
44
|
-
return validate(schema, "params")
|
|
45
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { BBContext, EndpointMatcher, RegexMatcher } from "@budibase/types"
|
|
2
|
-
|
|
3
|
-
const PARAM_REGEX = /\/:(.*?)(\/.*)?$/g
|
|
4
|
-
|
|
5
|
-
export const buildMatcherRegex = (
|
|
6
|
-
patterns: EndpointMatcher[]
|
|
7
|
-
): RegexMatcher[] => {
|
|
8
|
-
if (!patterns) {
|
|
9
|
-
return []
|
|
10
|
-
}
|
|
11
|
-
return patterns.map(pattern => {
|
|
12
|
-
let route = pattern.route
|
|
13
|
-
const method = pattern.method
|
|
14
|
-
const strict = pattern.strict ? pattern.strict : false
|
|
15
|
-
|
|
16
|
-
// if there is a param in the route
|
|
17
|
-
// use a wildcard pattern
|
|
18
|
-
const matches = route.match(PARAM_REGEX)
|
|
19
|
-
if (matches) {
|
|
20
|
-
for (let match of matches) {
|
|
21
|
-
const suffix = match.endsWith("/") ? "/" : ""
|
|
22
|
-
const pattern = "/.*" + suffix
|
|
23
|
-
route = route.replace(match, pattern)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return { regex: new RegExp(route), method, strict, route }
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const matches = (ctx: BBContext, options: RegexMatcher[]) => {
|
|
32
|
-
return options.find(({ regex, method, strict, route }) => {
|
|
33
|
-
let urlMatch
|
|
34
|
-
if (strict) {
|
|
35
|
-
urlMatch = ctx.request.url === route
|
|
36
|
-
} else {
|
|
37
|
-
urlMatch = regex.test(ctx.request.url)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const methodMatch =
|
|
41
|
-
method === "ALL"
|
|
42
|
-
? true
|
|
43
|
-
: ctx.request.method.toLowerCase() === method.toLowerCase()
|
|
44
|
-
|
|
45
|
-
return urlMatch && methodMatch
|
|
46
|
-
})
|
|
47
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import * as google from "../sso/google"
|
|
2
|
-
import { Cookie } from "../../../constants"
|
|
3
|
-
import * as configs from "../../../configs"
|
|
4
|
-
import * as cache from "../../../cache"
|
|
5
|
-
import * as utils from "../../../utils"
|
|
6
|
-
import { UserCtx, SSOProfile } from "@budibase/types"
|
|
7
|
-
import { ssoSaveUserNoOp } from "../sso/sso"
|
|
8
|
-
|
|
9
|
-
const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy
|
|
10
|
-
|
|
11
|
-
type Passport = {
|
|
12
|
-
authenticate: any
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async function fetchGoogleCreds() {
|
|
16
|
-
let config = await configs.getGoogleDatasourceConfig()
|
|
17
|
-
|
|
18
|
-
if (!config) {
|
|
19
|
-
throw new Error("No google configuration found")
|
|
20
|
-
}
|
|
21
|
-
return config
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function preAuth(
|
|
25
|
-
passport: Passport,
|
|
26
|
-
ctx: UserCtx,
|
|
27
|
-
next: Function
|
|
28
|
-
) {
|
|
29
|
-
// get the relevant config
|
|
30
|
-
const googleConfig = await fetchGoogleCreds()
|
|
31
|
-
const platformUrl = await configs.getPlatformUrl({ tenantAware: false })
|
|
32
|
-
|
|
33
|
-
let callbackUrl = `${platformUrl}/api/global/auth/datasource/google/callback`
|
|
34
|
-
const strategy = await google.strategyFactory(
|
|
35
|
-
googleConfig,
|
|
36
|
-
callbackUrl,
|
|
37
|
-
ssoSaveUserNoOp
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
if (!ctx.query.appId) {
|
|
41
|
-
ctx.throw(400, "appId query param not present.")
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return passport.authenticate(strategy, {
|
|
45
|
-
scope: ["profile", "email", "https://www.googleapis.com/auth/spreadsheets"],
|
|
46
|
-
accessType: "offline",
|
|
47
|
-
prompt: "consent",
|
|
48
|
-
})(ctx, next)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export async function postAuth(
|
|
52
|
-
passport: Passport,
|
|
53
|
-
ctx: UserCtx,
|
|
54
|
-
next: Function
|
|
55
|
-
) {
|
|
56
|
-
// get the relevant config
|
|
57
|
-
const config = await fetchGoogleCreds()
|
|
58
|
-
const platformUrl = await configs.getPlatformUrl({ tenantAware: false })
|
|
59
|
-
|
|
60
|
-
let callbackUrl = `${platformUrl}/api/global/auth/datasource/google/callback`
|
|
61
|
-
const authStateCookie = utils.getCookie(ctx, Cookie.DatasourceAuth)
|
|
62
|
-
|
|
63
|
-
return passport.authenticate(
|
|
64
|
-
new GoogleStrategy(
|
|
65
|
-
{
|
|
66
|
-
clientID: config.clientID,
|
|
67
|
-
clientSecret: config.clientSecret,
|
|
68
|
-
callbackURL: callbackUrl,
|
|
69
|
-
},
|
|
70
|
-
(
|
|
71
|
-
accessToken: string,
|
|
72
|
-
refreshToken: string,
|
|
73
|
-
_profile: SSOProfile,
|
|
74
|
-
done: Function
|
|
75
|
-
) => {
|
|
76
|
-
utils.clearCookie(ctx, Cookie.DatasourceAuth)
|
|
77
|
-
done(null, { accessToken, refreshToken })
|
|
78
|
-
}
|
|
79
|
-
),
|
|
80
|
-
{ successRedirect: "/", failureRedirect: "/error" },
|
|
81
|
-
async (err: any, tokens: string[]) => {
|
|
82
|
-
const baseUrl = `/builder/app/${authStateCookie.appId}/data`
|
|
83
|
-
|
|
84
|
-
const id = utils.newid()
|
|
85
|
-
await cache.store(
|
|
86
|
-
`datasource:creation:${authStateCookie.appId}:google:${id}`,
|
|
87
|
-
{
|
|
88
|
-
tokens,
|
|
89
|
-
}
|
|
90
|
-
)
|
|
91
|
-
|
|
92
|
-
ctx.redirect(`${baseUrl}/new?continue_google_setup=${id}`)
|
|
93
|
-
}
|
|
94
|
-
)(ctx, next)
|
|
95
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { UserStatus } from "../../constants"
|
|
2
|
-
import { compare } from "../../utils"
|
|
3
|
-
import * as users from "../../users"
|
|
4
|
-
import { authError } from "./utils"
|
|
5
|
-
import { BBContext } from "@budibase/types"
|
|
6
|
-
|
|
7
|
-
const INVALID_ERR = "Invalid credentials"
|
|
8
|
-
const EXPIRED = "This account has expired. Please reset your password"
|
|
9
|
-
|
|
10
|
-
export const options = {
|
|
11
|
-
passReqToCallback: true,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Passport Local Authentication Middleware.
|
|
16
|
-
* @param {*} ctx the request structure
|
|
17
|
-
* @param {*} email username to login with
|
|
18
|
-
* @param {*} password plain text password to log in with
|
|
19
|
-
* @param {*} done callback from passport to return user information and errors
|
|
20
|
-
* @returns The authenticated user, or errors if they occur
|
|
21
|
-
*/
|
|
22
|
-
export async function authenticate(
|
|
23
|
-
ctx: BBContext,
|
|
24
|
-
email: string,
|
|
25
|
-
password: string,
|
|
26
|
-
done: Function
|
|
27
|
-
) {
|
|
28
|
-
if (!email) return authError(done, "Email Required")
|
|
29
|
-
if (!password) return authError(done, "Password Required")
|
|
30
|
-
|
|
31
|
-
const dbUser = await users.getGlobalUserByEmail(email)
|
|
32
|
-
if (dbUser == null) {
|
|
33
|
-
console.info(`user=${email} could not be found`)
|
|
34
|
-
return authError(done, INVALID_ERR)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (dbUser.status === UserStatus.INACTIVE) {
|
|
38
|
-
console.info(`user=${email} is inactive`, dbUser)
|
|
39
|
-
return authError(done, INVALID_ERR)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (!dbUser.password) {
|
|
43
|
-
console.info(`user=${email} has no password set`, dbUser)
|
|
44
|
-
return authError(done, EXPIRED)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!(await compare(password, dbUser.password))) {
|
|
48
|
-
return authError(done, INVALID_ERR)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// intentionally remove the users password in payload
|
|
52
|
-
delete dbUser.password
|
|
53
|
-
return done(null, dbUser)
|
|
54
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { ssoCallbackUrl } from "../utils"
|
|
2
|
-
import * as sso from "./sso"
|
|
3
|
-
import {
|
|
4
|
-
ConfigType,
|
|
5
|
-
SSOProfile,
|
|
6
|
-
SSOAuthDetails,
|
|
7
|
-
SSOProviderType,
|
|
8
|
-
SaveSSOUserFunction,
|
|
9
|
-
GoogleInnerConfig,
|
|
10
|
-
} from "@budibase/types"
|
|
11
|
-
const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy
|
|
12
|
-
|
|
13
|
-
export function buildVerifyFn(saveUserFn: SaveSSOUserFunction) {
|
|
14
|
-
return (
|
|
15
|
-
accessToken: string,
|
|
16
|
-
refreshToken: string,
|
|
17
|
-
profile: SSOProfile,
|
|
18
|
-
done: Function
|
|
19
|
-
) => {
|
|
20
|
-
const details: SSOAuthDetails = {
|
|
21
|
-
provider: "google",
|
|
22
|
-
providerType: SSOProviderType.GOOGLE,
|
|
23
|
-
userId: profile.id,
|
|
24
|
-
profile: profile,
|
|
25
|
-
email: profile._json.email,
|
|
26
|
-
oauth2: {
|
|
27
|
-
accessToken,
|
|
28
|
-
refreshToken,
|
|
29
|
-
},
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return sso.authenticate(
|
|
33
|
-
details,
|
|
34
|
-
true, // require local accounts to exist
|
|
35
|
-
done,
|
|
36
|
-
saveUserFn
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Create an instance of the google passport strategy. This wrapper fetches the configuration
|
|
43
|
-
* from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport.
|
|
44
|
-
* @returns Dynamically configured Passport Google Strategy
|
|
45
|
-
*/
|
|
46
|
-
export async function strategyFactory(
|
|
47
|
-
config: GoogleInnerConfig,
|
|
48
|
-
callbackUrl: string,
|
|
49
|
-
saveUserFn: SaveSSOUserFunction
|
|
50
|
-
) {
|
|
51
|
-
try {
|
|
52
|
-
const { clientID, clientSecret } = config
|
|
53
|
-
|
|
54
|
-
if (!clientID || !clientSecret) {
|
|
55
|
-
throw new Error(
|
|
56
|
-
"Configuration invalid. Must contain google clientID and clientSecret"
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const verify = buildVerifyFn(saveUserFn)
|
|
61
|
-
return new GoogleStrategy(
|
|
62
|
-
{
|
|
63
|
-
clientID: config.clientID,
|
|
64
|
-
clientSecret: config.clientSecret,
|
|
65
|
-
callbackURL: callbackUrl,
|
|
66
|
-
},
|
|
67
|
-
verify
|
|
68
|
-
)
|
|
69
|
-
} catch (err: any) {
|
|
70
|
-
console.error(err)
|
|
71
|
-
throw new Error(`Error constructing google authentication strategy: ${err}`)
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export async function getCallbackUrl(config: GoogleInnerConfig) {
|
|
76
|
-
return ssoCallbackUrl(ConfigType.GOOGLE, config)
|
|
77
|
-
}
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import fetch from "node-fetch"
|
|
2
|
-
import * as sso from "./sso"
|
|
3
|
-
import { ssoCallbackUrl } from "../utils"
|
|
4
|
-
import { validEmail } from "../../../utils"
|
|
5
|
-
import {
|
|
6
|
-
ConfigType,
|
|
7
|
-
OIDCInnerConfig,
|
|
8
|
-
SSOProfile,
|
|
9
|
-
OIDCStrategyConfiguration,
|
|
10
|
-
SSOAuthDetails,
|
|
11
|
-
SSOProviderType,
|
|
12
|
-
JwtClaims,
|
|
13
|
-
SaveSSOUserFunction,
|
|
14
|
-
} from "@budibase/types"
|
|
15
|
-
|
|
16
|
-
const OIDCStrategy = require("@techpass/passport-openidconnect").Strategy
|
|
17
|
-
|
|
18
|
-
export function buildVerifyFn(saveUserFn: SaveSSOUserFunction) {
|
|
19
|
-
/**
|
|
20
|
-
* @param {*} issuer The identity provider base URL
|
|
21
|
-
* @param {*} sub The user ID
|
|
22
|
-
* @param {*} profile The user profile information. Created by passport from the /userinfo response
|
|
23
|
-
* @param {*} jwtClaims The parsed id_token claims
|
|
24
|
-
* @param {*} accessToken The access_token for contacting the identity provider - may or may not be a JWT
|
|
25
|
-
* @param {*} refreshToken The refresh_token for obtaining a new access_token - usually not a JWT
|
|
26
|
-
* @param {*} idToken The id_token - always a JWT
|
|
27
|
-
* @param {*} params The response body from requesting an access_token
|
|
28
|
-
* @param {*} done The passport callback: err, user, info
|
|
29
|
-
*/
|
|
30
|
-
return async (
|
|
31
|
-
issuer: string,
|
|
32
|
-
sub: string,
|
|
33
|
-
profile: SSOProfile,
|
|
34
|
-
jwtClaims: JwtClaims,
|
|
35
|
-
accessToken: string,
|
|
36
|
-
refreshToken: string,
|
|
37
|
-
idToken: string,
|
|
38
|
-
params: any,
|
|
39
|
-
done: Function
|
|
40
|
-
) => {
|
|
41
|
-
const details: SSOAuthDetails = {
|
|
42
|
-
// store the issuer info to enable sync in future
|
|
43
|
-
provider: issuer,
|
|
44
|
-
providerType: SSOProviderType.OIDC,
|
|
45
|
-
userId: profile.id,
|
|
46
|
-
profile: profile,
|
|
47
|
-
email: getEmail(profile, jwtClaims),
|
|
48
|
-
oauth2: {
|
|
49
|
-
accessToken: accessToken,
|
|
50
|
-
refreshToken: refreshToken,
|
|
51
|
-
},
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return sso.authenticate(
|
|
55
|
-
details,
|
|
56
|
-
false, // don't require local accounts to exist
|
|
57
|
-
done,
|
|
58
|
-
saveUserFn
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* @param {*} profile The structured profile created by passport using the user info endpoint
|
|
65
|
-
* @param {*} jwtClaims The claims returned in the id token
|
|
66
|
-
*/
|
|
67
|
-
function getEmail(profile: SSOProfile, jwtClaims: JwtClaims) {
|
|
68
|
-
// profile not guaranteed to contain email e.g. github connected azure ad account
|
|
69
|
-
if (profile._json.email) {
|
|
70
|
-
return profile._json.email
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// fallback to id token email
|
|
74
|
-
if (jwtClaims.email) {
|
|
75
|
-
return jwtClaims.email
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// fallback to id token preferred username
|
|
79
|
-
const username = jwtClaims.preferred_username
|
|
80
|
-
if (username && validEmail(username)) {
|
|
81
|
-
return username
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
throw new Error(
|
|
85
|
-
`Could not determine user email from profile ${JSON.stringify(
|
|
86
|
-
profile
|
|
87
|
-
)} and claims ${JSON.stringify(jwtClaims)}`
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Create an instance of the oidc passport strategy. This wrapper fetches the configuration
|
|
93
|
-
* from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport.
|
|
94
|
-
* @returns Dynamically configured Passport OIDC Strategy
|
|
95
|
-
*/
|
|
96
|
-
export async function strategyFactory(
|
|
97
|
-
config: OIDCStrategyConfiguration,
|
|
98
|
-
saveUserFn: SaveSSOUserFunction
|
|
99
|
-
) {
|
|
100
|
-
try {
|
|
101
|
-
const verify = buildVerifyFn(saveUserFn)
|
|
102
|
-
const strategy = new OIDCStrategy(config, verify)
|
|
103
|
-
strategy.name = "oidc"
|
|
104
|
-
return strategy
|
|
105
|
-
} catch (err: any) {
|
|
106
|
-
console.error(err)
|
|
107
|
-
throw new Error(`Error constructing OIDC authentication strategy - ${err}`)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export async function fetchStrategyConfig(
|
|
112
|
-
oidcConfig: OIDCInnerConfig,
|
|
113
|
-
callbackUrl?: string
|
|
114
|
-
): Promise<OIDCStrategyConfiguration> {
|
|
115
|
-
try {
|
|
116
|
-
const { clientID, clientSecret, configUrl } = oidcConfig
|
|
117
|
-
|
|
118
|
-
if (!clientID || !clientSecret || !callbackUrl || !configUrl) {
|
|
119
|
-
// check for remote config and all required elements
|
|
120
|
-
throw new Error(
|
|
121
|
-
"Configuration invalid. Must contain clientID, clientSecret, callbackUrl and configUrl"
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const response = await fetch(configUrl)
|
|
126
|
-
|
|
127
|
-
if (!response.ok) {
|
|
128
|
-
throw new Error(
|
|
129
|
-
`Unexpected response when fetching openid-configuration: ${response.statusText}`
|
|
130
|
-
)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const body = await response.json()
|
|
134
|
-
|
|
135
|
-
return {
|
|
136
|
-
issuer: body.issuer,
|
|
137
|
-
authorizationURL: body.authorization_endpoint,
|
|
138
|
-
tokenURL: body.token_endpoint,
|
|
139
|
-
userInfoURL: body.userinfo_endpoint,
|
|
140
|
-
clientID: clientID,
|
|
141
|
-
clientSecret: clientSecret,
|
|
142
|
-
callbackURL: callbackUrl,
|
|
143
|
-
}
|
|
144
|
-
} catch (err) {
|
|
145
|
-
console.error(err)
|
|
146
|
-
throw new Error(
|
|
147
|
-
`Error constructing OIDC authentication configuration - ${err}`
|
|
148
|
-
)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export async function getCallbackUrl() {
|
|
153
|
-
return ssoCallbackUrl(ConfigType.OIDC)
|
|
154
|
-
}
|