@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.
Files changed (250) hide show
  1. package/dist/index.js +266 -324
  2. package/dist/index.js.map +4 -4
  3. package/dist/index.js.meta.json +1 -1
  4. package/dist/package.json +19 -4
  5. package/dist/plugins.js +1 -1
  6. package/dist/plugins.js.map +1 -1
  7. package/dist/plugins.js.meta.json +1 -1
  8. package/dist/src/security/permissions.d.ts +1 -1
  9. package/dist/tests.js +222 -260
  10. package/dist/tests.js.map +4 -4
  11. package/dist/tests.js.meta.json +1 -1
  12. package/package.json +19 -4
  13. package/dist/tsconfig.build.tsbuildinfo +0 -1
  14. package/src/accounts/accounts.ts +0 -82
  15. package/src/accounts/api.ts +0 -59
  16. package/src/accounts/index.ts +0 -1
  17. package/src/auth/auth.ts +0 -208
  18. package/src/auth/index.ts +0 -1
  19. package/src/auth/tests/auth.spec.ts +0 -14
  20. package/src/blacklist/blacklist.ts +0 -54
  21. package/src/blacklist/index.ts +0 -1
  22. package/src/blacklist/tests/blacklist.spec.ts +0 -46
  23. package/src/cache/appMetadata.ts +0 -88
  24. package/src/cache/base/index.ts +0 -92
  25. package/src/cache/generic.ts +0 -30
  26. package/src/cache/index.ts +0 -5
  27. package/src/cache/tests/writethrough.spec.ts +0 -138
  28. package/src/cache/user.ts +0 -69
  29. package/src/cache/writethrough.ts +0 -133
  30. package/src/configs/configs.ts +0 -257
  31. package/src/configs/index.ts +0 -1
  32. package/src/configs/tests/configs.spec.ts +0 -184
  33. package/src/constants/db.ts +0 -63
  34. package/src/constants/index.ts +0 -2
  35. package/src/constants/misc.ts +0 -50
  36. package/src/context/Context.ts +0 -14
  37. package/src/context/identity.ts +0 -58
  38. package/src/context/index.ts +0 -3
  39. package/src/context/mainContext.ts +0 -310
  40. package/src/context/tests/index.spec.ts +0 -147
  41. package/src/context/types.ts +0 -11
  42. package/src/db/Replication.ts +0 -84
  43. package/src/db/constants.ts +0 -10
  44. package/src/db/couch/DatabaseImpl.ts +0 -238
  45. package/src/db/couch/connections.ts +0 -77
  46. package/src/db/couch/index.ts +0 -5
  47. package/src/db/couch/pouchDB.ts +0 -97
  48. package/src/db/couch/pouchDump.ts +0 -0
  49. package/src/db/couch/utils.ts +0 -50
  50. package/src/db/db.ts +0 -39
  51. package/src/db/errors.ts +0 -14
  52. package/src/db/index.ts +0 -12
  53. package/src/db/lucene.ts +0 -732
  54. package/src/db/searchIndexes/index.ts +0 -1
  55. package/src/db/searchIndexes/searchIndexes.ts +0 -62
  56. package/src/db/tests/index.spec.js +0 -25
  57. package/src/db/tests/lucene.spec.ts +0 -298
  58. package/src/db/tests/pouch.spec.js +0 -62
  59. package/src/db/tests/utils.spec.ts +0 -63
  60. package/src/db/utils.ts +0 -207
  61. package/src/db/views.ts +0 -241
  62. package/src/docIds/conversions.ts +0 -59
  63. package/src/docIds/ids.ts +0 -113
  64. package/src/docIds/index.ts +0 -2
  65. package/src/docIds/newid.ts +0 -5
  66. package/src/docIds/params.ts +0 -174
  67. package/src/docUpdates/index.ts +0 -29
  68. package/src/environment.ts +0 -201
  69. package/src/errors/errors.ts +0 -119
  70. package/src/errors/index.ts +0 -1
  71. package/src/events/analytics.ts +0 -6
  72. package/src/events/asyncEvents/index.ts +0 -2
  73. package/src/events/asyncEvents/publisher.ts +0 -12
  74. package/src/events/asyncEvents/queue.ts +0 -22
  75. package/src/events/backfill.ts +0 -183
  76. package/src/events/documentId.ts +0 -56
  77. package/src/events/events.ts +0 -40
  78. package/src/events/identification.ts +0 -310
  79. package/src/events/index.ts +0 -14
  80. package/src/events/processors/AnalyticsProcessor.ts +0 -64
  81. package/src/events/processors/AuditLogsProcessor.ts +0 -93
  82. package/src/events/processors/LoggingProcessor.ts +0 -37
  83. package/src/events/processors/Processors.ts +0 -52
  84. package/src/events/processors/async/DocumentUpdateProcessor.ts +0 -43
  85. package/src/events/processors/index.ts +0 -19
  86. package/src/events/processors/posthog/PosthogProcessor.ts +0 -118
  87. package/src/events/processors/posthog/index.ts +0 -2
  88. package/src/events/processors/posthog/rateLimiting.ts +0 -106
  89. package/src/events/processors/posthog/tests/PosthogProcessor.spec.ts +0 -168
  90. package/src/events/processors/types.ts +0 -1
  91. package/src/events/publishers/account.ts +0 -35
  92. package/src/events/publishers/app.ts +0 -155
  93. package/src/events/publishers/auditLog.ts +0 -26
  94. package/src/events/publishers/auth.ts +0 -73
  95. package/src/events/publishers/automation.ts +0 -110
  96. package/src/events/publishers/backfill.ts +0 -74
  97. package/src/events/publishers/backup.ts +0 -42
  98. package/src/events/publishers/datasource.ts +0 -48
  99. package/src/events/publishers/email.ts +0 -17
  100. package/src/events/publishers/environmentVariable.ts +0 -38
  101. package/src/events/publishers/group.ts +0 -99
  102. package/src/events/publishers/index.ts +0 -24
  103. package/src/events/publishers/installation.ts +0 -38
  104. package/src/events/publishers/layout.ts +0 -26
  105. package/src/events/publishers/license.ts +0 -84
  106. package/src/events/publishers/org.ts +0 -37
  107. package/src/events/publishers/plugin.ts +0 -47
  108. package/src/events/publishers/query.ts +0 -88
  109. package/src/events/publishers/role.ts +0 -62
  110. package/src/events/publishers/rows.ts +0 -29
  111. package/src/events/publishers/screen.ts +0 -36
  112. package/src/events/publishers/serve.ts +0 -43
  113. package/src/events/publishers/table.ts +0 -70
  114. package/src/events/publishers/user.ts +0 -202
  115. package/src/events/publishers/view.ts +0 -107
  116. package/src/featureFlags/index.ts +0 -77
  117. package/src/featureFlags/tests/featureFlags.spec.ts +0 -85
  118. package/src/helpers.ts +0 -9
  119. package/src/index.ts +0 -53
  120. package/src/installation.ts +0 -107
  121. package/src/logging/alerts.ts +0 -26
  122. package/src/logging/correlation/correlation.ts +0 -13
  123. package/src/logging/correlation/index.ts +0 -1
  124. package/src/logging/correlation/middleware.ts +0 -17
  125. package/src/logging/index.ts +0 -4
  126. package/src/logging/pino/logger.ts +0 -232
  127. package/src/logging/pino/middleware.ts +0 -45
  128. package/src/logging/system.ts +0 -81
  129. package/src/logging/tests/system.spec.ts +0 -61
  130. package/src/middleware/adminOnly.ts +0 -9
  131. package/src/middleware/auditLog.ts +0 -6
  132. package/src/middleware/authenticated.ts +0 -193
  133. package/src/middleware/builderOnly.ts +0 -20
  134. package/src/middleware/builderOrAdmin.ts +0 -20
  135. package/src/middleware/csrf.ts +0 -81
  136. package/src/middleware/errorHandling.ts +0 -29
  137. package/src/middleware/index.ts +0 -21
  138. package/src/middleware/internalApi.ts +0 -23
  139. package/src/middleware/joi-validator.ts +0 -45
  140. package/src/middleware/matchers.ts +0 -47
  141. package/src/middleware/passport/datasource/google.ts +0 -95
  142. package/src/middleware/passport/local.ts +0 -54
  143. package/src/middleware/passport/sso/google.ts +0 -77
  144. package/src/middleware/passport/sso/oidc.ts +0 -154
  145. package/src/middleware/passport/sso/sso.ts +0 -165
  146. package/src/middleware/passport/sso/tests/google.spec.ts +0 -67
  147. package/src/middleware/passport/sso/tests/oidc.spec.ts +0 -152
  148. package/src/middleware/passport/sso/tests/sso.spec.ts +0 -197
  149. package/src/middleware/passport/utils.ts +0 -38
  150. package/src/middleware/querystringToBody.ts +0 -28
  151. package/src/middleware/tenancy.ts +0 -36
  152. package/src/middleware/tests/builder.spec.ts +0 -180
  153. package/src/middleware/tests/matchers.spec.ts +0 -134
  154. package/src/migrations/definitions.ts +0 -40
  155. package/src/migrations/index.ts +0 -2
  156. package/src/migrations/migrations.ts +0 -191
  157. package/src/migrations/tests/__snapshots__/migrations.spec.ts.snap +0 -11
  158. package/src/migrations/tests/migrations.spec.ts +0 -64
  159. package/src/objectStore/buckets/app.ts +0 -40
  160. package/src/objectStore/buckets/global.ts +0 -29
  161. package/src/objectStore/buckets/index.ts +0 -3
  162. package/src/objectStore/buckets/plugins.ts +0 -71
  163. package/src/objectStore/buckets/tests/app.spec.ts +0 -171
  164. package/src/objectStore/buckets/tests/global.spec.ts +0 -74
  165. package/src/objectStore/buckets/tests/plugins.spec.ts +0 -111
  166. package/src/objectStore/cloudfront.ts +0 -41
  167. package/src/objectStore/index.ts +0 -3
  168. package/src/objectStore/objectStore.ts +0 -440
  169. package/src/objectStore/utils.ts +0 -27
  170. package/src/platform/index.ts +0 -3
  171. package/src/platform/platformDb.ts +0 -6
  172. package/src/platform/tenants.ts +0 -101
  173. package/src/platform/tests/tenants.spec.ts +0 -26
  174. package/src/platform/users.ts +0 -90
  175. package/src/plugin/index.ts +0 -1
  176. package/src/plugin/tests/validation.spec.ts +0 -83
  177. package/src/plugin/utils.ts +0 -156
  178. package/src/queue/constants.ts +0 -6
  179. package/src/queue/inMemoryQueue.ts +0 -141
  180. package/src/queue/index.ts +0 -2
  181. package/src/queue/listeners.ts +0 -195
  182. package/src/queue/queue.ts +0 -54
  183. package/src/redis/index.ts +0 -6
  184. package/src/redis/init.ts +0 -86
  185. package/src/redis/redis.ts +0 -308
  186. package/src/redis/redlockImpl.ts +0 -139
  187. package/src/redis/utils.ts +0 -117
  188. package/src/security/encryption.ts +0 -179
  189. package/src/security/permissions.ts +0 -159
  190. package/src/security/roles.ts +0 -420
  191. package/src/security/sessions.ts +0 -120
  192. package/src/security/tests/encryption.spec.ts +0 -31
  193. package/src/security/tests/permissions.spec.ts +0 -145
  194. package/src/security/tests/sessions.spec.ts +0 -12
  195. package/src/tenancy/db.ts +0 -6
  196. package/src/tenancy/index.ts +0 -2
  197. package/src/tenancy/tenancy.ts +0 -140
  198. package/src/tenancy/tests/tenancy.spec.ts +0 -184
  199. package/src/timers/index.ts +0 -1
  200. package/src/timers/timers.ts +0 -22
  201. package/src/users/db.ts +0 -460
  202. package/src/users/events.ts +0 -176
  203. package/src/users/index.ts +0 -4
  204. package/src/users/lookup.ts +0 -102
  205. package/src/users/users.ts +0 -276
  206. package/src/users/utils.ts +0 -55
  207. package/src/utils/hashing.ts +0 -14
  208. package/src/utils/index.ts +0 -3
  209. package/src/utils/stringUtils.ts +0 -8
  210. package/src/utils/tests/utils.spec.ts +0 -191
  211. package/src/utils/utils.ts +0 -239
  212. package/tests/core/logging.ts +0 -34
  213. package/tests/core/utilities/index.ts +0 -6
  214. package/tests/core/utilities/jestUtils.ts +0 -30
  215. package/tests/core/utilities/mocks/alerts.ts +0 -3
  216. package/tests/core/utilities/mocks/date.ts +0 -2
  217. package/tests/core/utilities/mocks/events.ts +0 -131
  218. package/tests/core/utilities/mocks/fetch.ts +0 -17
  219. package/tests/core/utilities/mocks/index.ts +0 -10
  220. package/tests/core/utilities/mocks/licenses.ts +0 -107
  221. package/tests/core/utilities/mocks/posthog.ts +0 -7
  222. package/tests/core/utilities/structures/Chance.ts +0 -20
  223. package/tests/core/utilities/structures/accounts.ts +0 -115
  224. package/tests/core/utilities/structures/apps.ts +0 -21
  225. package/tests/core/utilities/structures/common.ts +0 -7
  226. package/tests/core/utilities/structures/db.ts +0 -12
  227. package/tests/core/utilities/structures/documents/index.ts +0 -1
  228. package/tests/core/utilities/structures/documents/platform/index.ts +0 -1
  229. package/tests/core/utilities/structures/documents/platform/installation.ts +0 -12
  230. package/tests/core/utilities/structures/generator.ts +0 -2
  231. package/tests/core/utilities/structures/index.ts +0 -15
  232. package/tests/core/utilities/structures/koa.ts +0 -16
  233. package/tests/core/utilities/structures/licenses.ts +0 -167
  234. package/tests/core/utilities/structures/plugins.ts +0 -19
  235. package/tests/core/utilities/structures/quotas.ts +0 -67
  236. package/tests/core/utilities/structures/scim.ts +0 -80
  237. package/tests/core/utilities/structures/shared.ts +0 -19
  238. package/tests/core/utilities/structures/sso.ts +0 -119
  239. package/tests/core/utilities/structures/tenants.ts +0 -5
  240. package/tests/core/utilities/structures/userGroups.ts +0 -10
  241. package/tests/core/utilities/structures/users.ts +0 -73
  242. package/tests/core/utilities/testContainerUtils.ts +0 -98
  243. package/tests/core/utilities/utils/index.ts +0 -1
  244. package/tests/core/utilities/utils/time.ts +0 -3
  245. package/tests/extra/DBTestConfiguration.ts +0 -36
  246. package/tests/extra/index.ts +0 -2
  247. package/tests/extra/testEnv.ts +0 -95
  248. package/tests/index.ts +0 -1
  249. package/tests/jestEnv.ts +0 -6
  250. package/tests/jestSetup.ts +0 -28
@@ -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
@@ -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
- }