@budibase/worker 2.1.22-alpha.5 → 2.1.22-alpha.6

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 (156) hide show
  1. package/__mocks__/oauth.ts +57 -0
  2. package/coverage/clover.xml +1093 -1033
  3. package/coverage/coverage-final.json +77 -72
  4. package/coverage/lcov-report/index.html +83 -83
  5. package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +70 -70
  6. package/coverage/lcov-report/src/api/controllers/global/configs.js.html +35 -35
  7. package/coverage/lcov-report/src/api/controllers/global/email.js.html +4 -4
  8. package/coverage/lcov-report/src/api/controllers/global/index.html +38 -38
  9. package/coverage/lcov-report/src/api/controllers/global/license.ts.html +7 -7
  10. package/coverage/lcov-report/src/api/controllers/global/roles.js.html +10 -10
  11. package/coverage/lcov-report/src/api/controllers/global/self.ts.html +58 -58
  12. package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +11 -11
  13. package/coverage/lcov-report/src/api/controllers/global/users.ts.html +75 -69
  14. package/coverage/lcov-report/src/api/controllers/global/workspaces.js.html +7 -7
  15. package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +4 -4
  16. package/coverage/lcov-report/src/api/controllers/system/{environment.js.html → environment.ts.html} +21 -18
  17. package/coverage/lcov-report/src/api/controllers/system/index.html +63 -63
  18. package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +23 -23
  19. package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +22 -22
  20. package/coverage/lcov-report/src/api/controllers/system/{status.js.html → status.ts.html} +29 -26
  21. package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +34 -163
  22. package/coverage/lcov-report/src/api/index.html +11 -11
  23. package/coverage/lcov-report/src/api/index.ts.html +113 -44
  24. package/coverage/lcov-report/src/api/routes/global/auth.js.html +38 -89
  25. package/coverage/lcov-report/src/api/routes/global/configs.js.html +17 -17
  26. package/coverage/lcov-report/src/api/routes/global/email.js.html +11 -11
  27. package/coverage/lcov-report/src/api/routes/global/index.html +11 -11
  28. package/coverage/lcov-report/src/api/routes/global/license.ts.html +6 -6
  29. package/coverage/lcov-report/src/api/routes/global/roles.js.html +7 -7
  30. package/coverage/lcov-report/src/api/routes/global/self.ts.html +8 -8
  31. package/coverage/lcov-report/src/api/routes/global/templates.ts.html +11 -11
  32. package/coverage/lcov-report/src/api/routes/global/users.js.html +17 -17
  33. package/coverage/lcov-report/src/api/routes/global/workspaces.js.html +10 -10
  34. package/coverage/lcov-report/src/api/routes/index.html +1 -1
  35. package/coverage/lcov-report/src/api/routes/index.ts.html +19 -19
  36. package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +7 -7
  37. package/coverage/lcov-report/src/api/routes/system/{environment.js.html → environment.ts.html} +11 -11
  38. package/coverage/lcov-report/src/api/routes/system/index.html +4 -4
  39. package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +7 -7
  40. package/coverage/lcov-report/src/api/routes/system/restore.ts.html +6 -6
  41. package/coverage/lcov-report/src/api/routes/system/{status.js.html → status.ts.html} +11 -11
  42. package/coverage/lcov-report/src/api/routes/system/{tenants.js.html → tenants.ts.html} +20 -17
  43. package/coverage/lcov-report/src/api/routes/validation/index.html +1 -1
  44. package/coverage/lcov-report/src/api/routes/validation/index.ts.html +2 -2
  45. package/coverage/lcov-report/src/api/routes/validation/users.ts.html +13 -13
  46. package/coverage/lcov-report/src/constants/index.html +1 -1
  47. package/coverage/lcov-report/src/constants/index.js.html +18 -18
  48. package/coverage/lcov-report/src/constants/templates/index.html +1 -1
  49. package/coverage/lcov-report/src/constants/templates/index.js.html +10 -10
  50. package/coverage/lcov-report/src/db/index.html +1 -1
  51. package/coverage/lcov-report/src/db/index.ts.html +8 -8
  52. package/coverage/lcov-report/src/environment.ts.html +15 -15
  53. package/coverage/lcov-report/src/index.html +1 -1
  54. package/coverage/lcov-report/src/index.ts.html +40 -40
  55. package/coverage/lcov-report/src/middleware/cloudRestricted.js.html +22 -22
  56. package/coverage/lcov-report/src/middleware/index.html +21 -21
  57. package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +3 -3
  58. package/coverage/lcov-report/src/migrations/functions/index.html +1 -1
  59. package/coverage/lcov-report/src/migrations/index.html +1 -1
  60. package/coverage/lcov-report/src/migrations/index.ts.html +17 -17
  61. package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +6 -6
  62. package/coverage/lcov-report/src/sdk/accounts/index.html +1 -1
  63. package/coverage/lcov-report/src/sdk/accounts/index.ts.html +2 -2
  64. package/coverage/lcov-report/src/sdk/index.html +1 -1
  65. package/coverage/lcov-report/src/sdk/index.ts.html +4 -4
  66. package/coverage/lcov-report/src/sdk/users/events.ts.html +43 -43
  67. package/coverage/lcov-report/src/sdk/users/index.html +19 -19
  68. package/coverage/lcov-report/src/sdk/users/index.ts.html +2 -2
  69. package/coverage/lcov-report/src/sdk/users/users.ts.html +99 -99
  70. package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +261 -123
  71. package/coverage/lcov-report/src/tests/api/accounts.ts.html +12 -21
  72. package/coverage/lcov-report/src/tests/api/auth.ts.html +11 -20
  73. package/coverage/lcov-report/src/tests/api/base.ts.html +133 -0
  74. package/coverage/lcov-report/src/tests/api/configs.ts.html +44 -23
  75. package/coverage/lcov-report/src/tests/api/email.ts.html +9 -18
  76. package/coverage/lcov-report/src/tests/api/environment.ts.html +130 -0
  77. package/coverage/lcov-report/src/tests/api/index.html +106 -16
  78. package/coverage/lcov-report/src/tests/api/index.ts.html +62 -17
  79. package/coverage/lcov-report/src/tests/{structures/accounts.ts.html → api/migrations.ts.html} +31 -37
  80. package/coverage/lcov-report/src/tests/api/restore.ts.html +127 -0
  81. package/coverage/lcov-report/src/tests/api/self.ts.html +31 -16
  82. package/coverage/lcov-report/src/tests/api/status.ts.html +121 -0
  83. package/coverage/lcov-report/src/tests/api/tenants.ts.html +130 -0
  84. package/coverage/lcov-report/src/tests/api/users.ts.html +121 -25
  85. package/coverage/lcov-report/src/tests/controllers.js.html +2 -2
  86. package/coverage/lcov-report/src/tests/index.html +20 -20
  87. package/coverage/lcov-report/src/tests/index.ts.html +21 -9
  88. package/coverage/lcov-report/src/tests/mocks/email.js.html +2 -2
  89. package/coverage/lcov-report/src/tests/mocks/index.html +1 -1
  90. package/coverage/lcov-report/src/tests/mocks/index.ts.html +4 -4
  91. package/coverage/lcov-report/src/tests/structures/configs.js.html +8 -8
  92. package/coverage/lcov-report/src/tests/structures/groups.ts.html +2 -2
  93. package/coverage/lcov-report/src/tests/structures/index.html +9 -24
  94. package/coverage/lcov-report/src/tests/structures/index.ts.html +21 -15
  95. package/coverage/lcov-report/src/tests/structures/users.ts.html +13 -10
  96. package/coverage/lcov-report/src/utilities/appService.js.html +11 -11
  97. package/coverage/lcov-report/src/utilities/email.js.html +16 -16
  98. package/coverage/lcov-report/src/utilities/fileSystem.js.html +4 -4
  99. package/coverage/lcov-report/src/utilities/index.html +1 -1
  100. package/coverage/lcov-report/src/utilities/index.js.html +2 -2
  101. package/coverage/lcov-report/src/utilities/redis.js.html +13 -13
  102. package/coverage/lcov-report/src/utilities/templates.js.html +7 -7
  103. package/coverage/lcov-report/src/utilities/users.js.html +8 -8
  104. package/coverage/lcov.info +1685 -1511
  105. package/package.json +8 -6
  106. package/scripts/localdomain.js +33 -7
  107. package/src/api/controllers/global/auth.ts +1 -1
  108. package/src/api/controllers/global/users.ts +3 -1
  109. package/src/api/controllers/system/{environment.js → environment.ts} +3 -2
  110. package/src/api/controllers/system/{status.js → status.ts} +4 -3
  111. package/src/api/controllers/system/tenants.ts +8 -51
  112. package/src/api/index.ts +29 -6
  113. package/src/api/routes/global/auth.js +22 -39
  114. package/src/api/routes/global/tests/auth.spec.ts +134 -64
  115. package/src/api/routes/global/tests/configs.spec.ts +5 -6
  116. package/src/api/routes/global/tests/email.spec.ts +4 -3
  117. package/src/api/routes/global/tests/license.spec.ts +31 -0
  118. package/src/api/routes/global/tests/realEmail.spec.ts +2 -3
  119. package/src/api/routes/global/tests/roles.spec.ts +27 -0
  120. package/src/api/routes/global/tests/self.spec.ts +3 -4
  121. package/src/api/routes/global/tests/templates.spec.ts +35 -0
  122. package/src/api/routes/global/tests/users.spec.ts +51 -43
  123. package/src/api/routes/global/tests/workspaces.spec.ts +29 -0
  124. package/src/api/routes/system/environment.ts +8 -0
  125. package/src/api/routes/system/status.ts +8 -0
  126. package/src/api/routes/system/tenants.ts +13 -0
  127. package/src/api/routes/system/tests/accounts.spec.ts +5 -6
  128. package/src/api/routes/system/tests/environment.spec.ts +29 -0
  129. package/src/api/routes/system/tests/migrations.spec.ts +63 -0
  130. package/src/api/routes/system/tests/restore.spec.ts +36 -0
  131. package/src/api/routes/system/tests/status.spec.ts +48 -0
  132. package/src/api/routes/system/tests/tenants.spec.ts +61 -0
  133. package/src/middleware/tests/tenancy.spec.ts +73 -0
  134. package/src/tests/TestConfiguration.ts +88 -42
  135. package/src/tests/api/accounts.ts +5 -8
  136. package/src/tests/api/auth.ts +3 -6
  137. package/src/tests/api/base.ts +16 -0
  138. package/src/tests/api/configs.ts +15 -8
  139. package/src/tests/api/email.ts +3 -6
  140. package/src/tests/api/environment.ts +15 -0
  141. package/src/tests/api/index.ts +15 -0
  142. package/src/tests/api/migrations.ts +22 -0
  143. package/src/tests/api/restore.ts +14 -0
  144. package/src/tests/api/self.ts +11 -6
  145. package/src/tests/api/status.ts +12 -0
  146. package/src/tests/api/tenants.ts +15 -0
  147. package/src/tests/api/users.ts +38 -6
  148. package/src/tests/index.ts +4 -0
  149. package/src/tests/jestSetup.ts +7 -1
  150. package/src/tests/structures/index.ts +4 -2
  151. package/src/tests/structures/users.ts +1 -0
  152. package/__mocks__/node-fetch.ts +0 -1
  153. package/src/api/routes/system/environment.js +0 -8
  154. package/src/api/routes/system/status.js +0 -8
  155. package/src/api/routes/system/tenants.js +0 -12
  156. package/src/tests/structures/accounts.ts +0 -24
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/worker",
3
3
  "email": "hi@budibase.com",
4
- "version": "2.1.22-alpha.5",
4
+ "version": "2.1.22-alpha.6",
5
5
  "description": "Budibase background service",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -36,10 +36,10 @@
36
36
  "author": "Budibase",
37
37
  "license": "GPL-3.0",
38
38
  "dependencies": {
39
- "@budibase/backend-core": "2.1.22-alpha.5",
40
- "@budibase/pro": "2.1.22-alpha.4",
41
- "@budibase/string-templates": "2.1.22-alpha.5",
42
- "@budibase/types": "2.1.22-alpha.5",
39
+ "@budibase/backend-core": "2.1.22-alpha.6",
40
+ "@budibase/pro": "2.1.22-alpha.5",
41
+ "@budibase/string-templates": "2.1.22-alpha.6",
42
+ "@budibase/types": "2.1.22-alpha.6",
43
43
  "@koa/router": "8.0.8",
44
44
  "@sentry/node": "6.17.7",
45
45
  "@techpass/passport-openidconnect": "0.3.2",
@@ -71,9 +71,11 @@
71
71
  },
72
72
  "devDependencies": {
73
73
  "@types/jest": "26.0.23",
74
+ "@types/jsonwebtoken": "8.5.1",
74
75
  "@types/koa": "2.13.4",
75
76
  "@types/koa__router": "8.0.11",
76
77
  "@types/node": "14.18.20",
78
+ "@types/node-fetch": "2.6.1",
77
79
  "@types/pouchdb": "6.4.0",
78
80
  "@types/uuid": "8.3.4",
79
81
  "@typescript-eslint/parser": "5.12.0",
@@ -92,5 +94,5 @@
92
94
  "typescript": "4.7.3",
93
95
  "update-dotenv": "1.1.1"
94
96
  },
95
- "gitHead": "0367d466c3c566be54d45d040654929966c836ff"
97
+ "gitHead": "395a9a21c27c534fd2b4297f5d0d19a341089993"
96
98
  }
@@ -2,6 +2,36 @@
2
2
  const updateDotEnv = require("update-dotenv")
3
3
 
4
4
  const arg = process.argv.slice(2)[0]
5
+ const isEnable = arg === "enable"
6
+
7
+ let domain = process.argv.slice(2)[1]
8
+ if (!domain) {
9
+ domain = "local.com"
10
+ }
11
+
12
+ const getAccountPortalUrl = () => {
13
+ if (isEnable) {
14
+ return `http://account.${domain}:10001`
15
+ } else {
16
+ return `http://localhost:10001`
17
+ }
18
+ }
19
+
20
+ const getBudibaseUrl = () => {
21
+ if (isEnable) {
22
+ return `http://${domain}:10000`
23
+ } else {
24
+ return `http://localhost:10000`
25
+ }
26
+ }
27
+
28
+ const getCookieDomain = () => {
29
+ if (isEnable) {
30
+ return `.${domain}`
31
+ } else {
32
+ return ""
33
+ }
34
+ }
5
35
 
6
36
  /**
7
37
  * For testing multi tenancy sub domains locally.
@@ -16,11 +46,7 @@ const arg = process.argv.slice(2)[0]
16
46
  * 127.0.0.1 t2.local.com
17
47
  */
18
48
  updateDotEnv({
19
- ACCOUNT_PORTAL_URL:
20
- arg === "enable"
21
- ? "http://account.local.com:10001"
22
- : "http://localhost:10001",
23
- COOKIE_DOMAIN: arg === "enable" ? ".local.com" : "",
24
- PLATFORM_URL:
25
- arg === "enable" ? "http://local.com:10000" : "http://localhost:10000",
49
+ ACCOUNT_PORTAL_URL: getAccountPortalUrl(),
50
+ COOKIE_DOMAIN: getCookieDomain(),
51
+ PLATFORM_URL: getBudibaseUrl(),
26
52
  }).then(() => console.log("Updated worker!"))
@@ -1,4 +1,4 @@
1
- const core = require("@budibase/backend-core")
1
+ import core from "@budibase/backend-core"
2
2
  const { Configs, EmailTemplatePurpose } = require("../../../constants")
3
3
  const { sendEmail, isEmailConfigured } = require("../../../utilities/email")
4
4
  const { setCookie, getCookie, clearCookie, hash, platformLogout } = core.utils
@@ -5,6 +5,7 @@ import {
5
5
  BulkUserRequest,
6
6
  BulkUserResponse,
7
7
  CloudAccount,
8
+ CreateAdminUserRequest,
8
9
  InviteUserRequest,
9
10
  InviteUsersRequest,
10
11
  SearchUsersRequest,
@@ -67,7 +68,8 @@ const parseBooleanParam = (param: any) => {
67
68
  }
68
69
 
69
70
  export const adminUser = async (ctx: any) => {
70
- const { email, password, tenantId } = ctx.request.body
71
+ const { email, password, tenantId } = ctx.request
72
+ .body as CreateAdminUserRequest
71
73
  await tenancy.doInTenant(tenantId, async () => {
72
74
  // account portal sends a pre-hashed password - honour param to prevent double hashing
73
75
  const hashPassword = parseBooleanParam(ctx.request.query.hashPassword)
@@ -1,6 +1,7 @@
1
- const env = require("../../../environment")
1
+ import { BBContext } from "@budibase/types"
2
+ import env from "../../../environment"
2
3
 
3
- exports.fetch = async ctx => {
4
+ export const fetch = async (ctx: BBContext) => {
4
5
  ctx.body = {
5
6
  multiTenancy: !!env.MULTI_TENANCY,
6
7
  cloud: !env.SELF_HOSTED,
@@ -1,7 +1,8 @@
1
- const accounts = require("@budibase/backend-core/accounts")
2
- const env = require("../../../environment")
1
+ import { accounts } from "@budibase/backend-core"
2
+ import env from "../../../environment"
3
+ import { BBContext } from "@budibase/types"
3
4
 
4
- exports.fetch = async ctx => {
5
+ export const fetch = async (ctx: BBContext) => {
5
6
  if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
6
7
  const status = await accounts.getStatus()
7
8
  ctx.body = status
@@ -1,61 +1,18 @@
1
- const { StaticDatabases, doWithDB } = require("@budibase/backend-core/db")
2
- const { getTenantId } = require("@budibase/backend-core/tenancy")
3
- const { deleteTenant } = require("@budibase/backend-core/deprovision")
1
+ import { BBContext } from "@budibase/types"
2
+ import { deprovisioning } from "@budibase/backend-core"
4
3
  import { quotas } from "@budibase/pro"
5
4
 
6
- export const exists = async (ctx: any) => {
7
- const tenantId = ctx.request.params
8
- ctx.body = {
9
- exists: await doWithDB(
10
- StaticDatabases.PLATFORM_INFO.name,
11
- async (db: any) => {
12
- let exists = false
13
- try {
14
- const tenantsDoc = await db.get(
15
- StaticDatabases.PLATFORM_INFO.docs.tenants
16
- )
17
- if (tenantsDoc) {
18
- exists = tenantsDoc.tenantIds.indexOf(tenantId) !== -1
19
- }
20
- } catch (err) {
21
- // if error it doesn't exist
22
- }
23
- return exists
24
- }
25
- ),
26
- }
27
- }
28
-
29
- export const fetch = async (ctx: any) => {
30
- ctx.body = await doWithDB(
31
- StaticDatabases.PLATFORM_INFO.name,
32
- async (db: any) => {
33
- let tenants = []
34
- try {
35
- const tenantsDoc = await db.get(
36
- StaticDatabases.PLATFORM_INFO.docs.tenants
37
- )
38
- if (tenantsDoc) {
39
- tenants = tenantsDoc.tenantIds
40
- }
41
- } catch (err) {
42
- // if error it doesn't exist
43
- }
44
- return tenants
45
- }
46
- )
47
- }
48
-
49
- const _delete = async (ctx: any) => {
50
- const tenantId = getTenantId()
5
+ const _delete = async (ctx: BBContext) => {
6
+ const user = ctx.user!
7
+ const tenantId = ctx.params.tenantId
51
8
 
52
- if (ctx.params.tenantId !== tenantId) {
53
- ctx.throw(403, "Unauthorized")
9
+ if (tenantId !== user.tenantId) {
10
+ ctx.throw(403, "Tenant ID does not match current user")
54
11
  }
55
12
 
56
13
  try {
57
- await deleteTenant(tenantId)
58
14
  await quotas.bustCache()
15
+ await deprovisioning.deleteTenant(tenantId)
59
16
  ctx.status = 204
60
17
  } catch (err) {
61
18
  ctx.log.error(err)
package/src/api/index.ts CHANGED
@@ -7,11 +7,12 @@ import { errors, auth, middleware } from "@budibase/backend-core"
7
7
  import { APIError } from "@budibase/types"
8
8
 
9
9
  const PUBLIC_ENDPOINTS = [
10
- // old deprecated endpoints kept for backwards compat
10
+ // deprecated single tenant sso callback
11
11
  {
12
12
  route: "/api/admin/auth/google/callback",
13
13
  method: "GET",
14
14
  },
15
+ // deprecated single tenant sso callback
15
16
  {
16
17
  route: "/api/admin/auth/oidc/callback",
17
18
  method: "GET",
@@ -44,17 +45,19 @@ const PUBLIC_ENDPOINTS = [
44
45
  method: "POST",
45
46
  },
46
47
  {
47
- route: "api/system/environment",
48
+ route: "/api/system/environment",
48
49
  method: "GET",
49
50
  },
50
51
  {
51
- route: "api/system/status",
52
+ route: "/api/system/status",
52
53
  method: "GET",
53
54
  },
55
+ // TODO: This should be an internal api
54
56
  {
55
57
  route: "/api/global/users/tenant/:id",
56
58
  method: "GET",
57
59
  },
60
+ // TODO: This should be an internal api
58
61
  {
59
62
  route: "/api/system/restored",
60
63
  method: "POST",
@@ -62,17 +65,37 @@ const PUBLIC_ENDPOINTS = [
62
65
  ]
63
66
 
64
67
  const NO_TENANCY_ENDPOINTS = [
65
- ...PUBLIC_ENDPOINTS,
68
+ // system endpoints are not specific to any tenant
66
69
  {
67
70
  route: "/api/system",
68
71
  method: "ALL",
69
72
  },
73
+ // tenant is determined in request body
74
+ // used for creating the tenant
70
75
  {
71
- route: "/api/global/users/self",
76
+ route: "/api/global/users/init",
77
+ method: "POST",
78
+ },
79
+ // deprecated single tenant sso callback
80
+ {
81
+ route: "/api/admin/auth/google/callback",
82
+ method: "GET",
83
+ },
84
+ // deprecated single tenant sso callback
85
+ {
86
+ route: "/api/admin/auth/oidc/callback",
72
87
  method: "GET",
73
88
  },
89
+ // tenant is determined from code in redis
74
90
  {
75
- route: "/api/global/self",
91
+ route: "/api/global/users/invite/accept",
92
+ method: "POST",
93
+ },
94
+ // global user search - no tenancy
95
+ // :id is user id
96
+ // TODO: this should really be `/api/system/users/:id`
97
+ {
98
+ route: "/api/global/users/tenant/:id",
76
99
  method: "GET",
77
100
  },
78
101
  ]
@@ -2,7 +2,6 @@ const Router = require("@koa/router")
2
2
  const authController = require("../../controllers/global/auth")
3
3
  const { joiValidator } = require("@budibase/backend-core/auth")
4
4
  const Joi = require("joi")
5
- const { updateTenantId } = require("@budibase/backend-core/tenancy")
6
5
 
7
6
  const router = new Router()
8
7
 
@@ -29,77 +28,61 @@ function buildResetUpdateValidation() {
29
28
  }).required().unknown(false))
30
29
  }
31
30
 
32
- function updateTenant(ctx, next) {
33
- if (ctx.params) {
34
- updateTenantId(ctx.params.tenantId)
35
- }
36
- return next()
37
- }
38
-
39
31
  router
32
+ // PASSWORD
40
33
  .post(
41
34
  "/api/global/auth/:tenantId/login",
42
35
  buildAuthValidation(),
43
- updateTenant,
44
36
  authController.authenticate
45
37
  )
38
+ .post("/api/global/auth/logout", authController.logout)
46
39
  .post(
47
40
  "/api/global/auth/:tenantId/reset",
48
41
  buildResetValidation(),
49
- updateTenant,
50
42
  authController.reset
51
43
  )
52
44
  .post(
53
45
  "/api/global/auth/:tenantId/reset/update",
54
46
  buildResetUpdateValidation(),
55
- updateTenant,
56
47
  authController.resetUpdate
57
48
  )
58
- .post("/api/global/auth/logout", authController.logout)
49
+ // INIT
59
50
  .post("/api/global/auth/init", authController.setInitInfo)
60
51
  .get("/api/global/auth/init", authController.getInitInfo)
61
- .get(
62
- "/api/global/auth/:tenantId/google",
63
- updateTenant,
64
- authController.googlePreAuth
65
- )
52
+
53
+ // DATASOURCE - MULTI TENANT
66
54
  .get(
67
55
  "/api/global/auth/:tenantId/datasource/:provider",
68
- updateTenant,
69
56
  authController.datasourcePreAuth
70
57
  )
71
- // single tenancy endpoint
72
- .get("/api/global/auth/google/callback", authController.googleAuth)
73
58
  .get(
74
- "/api/global/auth/datasource/:provider/callback",
59
+ "/api/global/auth/:tenantId/datasource/:provider/callback",
75
60
  authController.datasourceAuth
76
61
  )
77
- // multi-tenancy endpoint
78
- .get(
79
- "/api/global/auth/:tenantId/google/callback",
80
- updateTenant,
81
- authController.googleAuth
82
- )
62
+
63
+ // DATASOURCE - SINGLE TENANT - DEPRECATED
83
64
  .get(
84
- "/api/global/auth/:tenantId/datasource/:provider/callback",
85
- updateTenant,
65
+ "/api/global/auth/datasource/:provider/callback",
86
66
  authController.datasourceAuth
87
67
  )
68
+
69
+ // GOOGLE - MULTI TENANT
70
+ .get("/api/global/auth/:tenantId/google", authController.googlePreAuth)
71
+ .get("/api/global/auth/:tenantId/google/callback", authController.googleAuth)
72
+
73
+ // GOOGLE - SINGLE TENANT - DEPRECATED
74
+ .get("/api/global/auth/google/callback", authController.googleAuth)
75
+ .get("/api/admin/auth/google/callback", authController.googleAuth)
76
+
77
+ // OIDC - MULTI TENANT
88
78
  .get(
89
79
  "/api/global/auth/:tenantId/oidc/configs/:configId",
90
- updateTenant,
91
80
  authController.oidcPreAuth
92
81
  )
93
- // single tenancy endpoint
82
+ .get("/api/global/auth/:tenantId/oidc/callback", authController.oidcAuth)
83
+
84
+ // OIDC - SINGLE TENANT - DEPRECATED
94
85
  .get("/api/global/auth/oidc/callback", authController.oidcAuth)
95
- // multi-tenancy endpoint
96
- .get(
97
- "/api/global/auth/:tenantId/oidc/callback",
98
- updateTenant,
99
- authController.oidcAuth
100
- )
101
- // deprecated - used by the default system before tenancy
102
- .get("/api/admin/auth/google/callback", authController.googleAuth)
103
86
  .get("/api/admin/auth/oidc/callback", authController.oidcAuth)
104
87
 
105
88
  module.exports = router
@@ -1,11 +1,16 @@
1
1
  jest.mock("nodemailer")
2
- import { TestConfiguration, mocks, API } from "../../../../tests"
2
+ import { TestConfiguration, mocks } from "../../../../tests"
3
3
  const sendMailMock = mocks.email.mock()
4
4
  import { events } from "@budibase/backend-core"
5
5
 
6
+ const expectSetAuthCookie = (res: any) => {
7
+ expect(
8
+ res.get("Set-Cookie").find((c: string) => c.startsWith("budibase:auth"))
9
+ ).toBeDefined()
10
+ }
11
+
6
12
  describe("/api/global/auth", () => {
7
13
  const config = new TestConfiguration()
8
- const api = new API(config)
9
14
 
10
15
  beforeAll(async () => {
11
16
  await config.beforeAll()
@@ -19,90 +24,155 @@ describe("/api/global/auth", () => {
19
24
  jest.clearAllMocks()
20
25
  })
21
26
 
22
- it("should logout", async () => {
23
- await api.auth.logout()
24
- expect(events.auth.logout).toBeCalledTimes(1)
25
- })
27
+ describe("password", () => {
28
+ describe("POST /api/global/auth/:tenantId/login", () => {
29
+ it("should login", () => {})
30
+ })
26
31
 
27
- it("should be able to generate password reset email", async () => {
28
- const { res, code } = await api.auth.requestPasswordReset(sendMailMock)
29
- const user = await config.getUser("test@test.com")
32
+ describe("POST /api/global/auth/logout", () => {
33
+ it("should logout", async () => {
34
+ await config.api.auth.logout()
35
+ expect(events.auth.logout).toBeCalledTimes(1)
30
36
 
31
- expect(res.body).toEqual({
32
- message: "Please check your email for a reset link.",
37
+ // TODO: Verify sessions deleted
38
+ })
33
39
  })
34
- expect(sendMailMock).toHaveBeenCalled()
35
40
 
36
- expect(code).toBeDefined()
37
- expect(events.user.passwordResetRequested).toBeCalledTimes(1)
38
- expect(events.user.passwordResetRequested).toBeCalledWith(user)
41
+ describe("POST /api/global/auth/:tenantId/reset", () => {
42
+ it("should generate password reset email", async () => {
43
+ const { res, code } = await config.api.auth.requestPasswordReset(
44
+ sendMailMock
45
+ )
46
+ const user = await config.getUser("test@test.com")
47
+
48
+ expect(res.body).toEqual({
49
+ message: "Please check your email for a reset link.",
50
+ })
51
+ expect(sendMailMock).toHaveBeenCalled()
52
+
53
+ expect(code).toBeDefined()
54
+ expect(events.user.passwordResetRequested).toBeCalledTimes(1)
55
+ expect(events.user.passwordResetRequested).toBeCalledWith(user)
56
+ })
57
+ })
58
+
59
+ describe("POST /api/global/auth/:tenantId/reset/update", () => {
60
+ it("should reset password", async () => {
61
+ const { code } = await config.api.auth.requestPasswordReset(
62
+ sendMailMock
63
+ )
64
+ const user = await config.getUser("test@test.com")
65
+ delete user.password
66
+
67
+ const res = await config.api.auth.updatePassword(code)
68
+
69
+ expect(res.body).toEqual({ message: "password reset successfully." })
70
+ expect(events.user.passwordReset).toBeCalledTimes(1)
71
+ expect(events.user.passwordReset).toBeCalledWith(user)
72
+
73
+ // TODO: Login using new password
74
+ })
75
+ })
76
+ })
77
+
78
+ describe("init", () => {
79
+ describe("POST /api/global/auth/init", () => {})
80
+
81
+ describe("GET /api/global/auth/init", () => {})
39
82
  })
40
83
 
41
- it("should allow resetting user password with code", async () => {
42
- const { code } = await api.auth.requestPasswordReset(sendMailMock)
43
- const user = await config.getUser("test@test.com")
44
- delete user.password
84
+ describe("datasource", () => {
85
+ // MULTI TENANT
86
+
87
+ describe("GET /api/global/auth/:tenantId/datasource/:provider", () => {})
88
+
89
+ describe("GET /api/global/auth/:tenantId/datasource/:provider/callback", () => {})
45
90
 
46
- const res = await api.auth.updatePassword(code)
91
+ // SINGLE TENANT
47
92
 
48
- expect(res.body).toEqual({ message: "password reset successfully." })
49
- expect(events.user.passwordReset).toBeCalledTimes(1)
50
- expect(events.user.passwordReset).toBeCalledWith(user)
93
+ describe("GET /api/global/auth/datasource/:provider/callback", () => {})
51
94
  })
52
95
 
53
- describe("oidc", () => {
54
- const auth = require("@budibase/backend-core/auth")
96
+ describe("google", () => {
97
+ // MULTI TENANT
98
+
99
+ describe("GET /api/global/auth/:tenantId/google", () => {})
55
100
 
56
- const passportSpy = jest.spyOn(auth.passport, "authenticate")
57
- let oidcConf
58
- let chosenConfig: any
59
- let configId: string
101
+ describe("GET /api/global/auth/:tenantId/google/callback", () => {})
60
102
 
61
- // mock the oidc strategy implementation and return value
62
- let strategyFactory = jest.fn()
63
- let mockStrategyReturn = jest.fn()
64
- let mockStrategyConfig = jest.fn()
65
- auth.oidc.fetchStrategyConfig = mockStrategyConfig
103
+ // SINGLE TENANT
66
104
 
67
- strategyFactory.mockReturnValue(mockStrategyReturn)
68
- auth.oidc.strategyFactory = strategyFactory
105
+ describe("GET /api/global/auth/google/callback", () => {})
69
106
 
107
+ describe("GET /api/admin/auth/google/callback", () => {})
108
+ })
109
+
110
+ describe("oidc", () => {
70
111
  beforeEach(async () => {
71
- oidcConf = await config.saveOIDCConfig()
72
- chosenConfig = oidcConf.config.configs[0]
73
- configId = chosenConfig.uuid
74
- mockStrategyConfig.mockReturnValue(chosenConfig)
75
- })
112
+ jest.clearAllMocks()
113
+ mockGetWellKnownConfig()
76
114
 
77
- afterEach(() => {
78
- expect(strategyFactory).toBeCalledWith(chosenConfig, expect.any(Function))
115
+ // see: __mocks__/oauth
116
+ // for associated mocking inside passport
79
117
  })
80
118
 
81
- describe("oidc configs", () => {
82
- it("should load strategy and delegate to passport", async () => {
83
- await api.configs.getOIDCConfig(configId)
84
-
85
- expect(passportSpy).toBeCalledWith(mockStrategyReturn, {
86
- scope: ["profile", "email", "offline_access"],
87
- })
88
- expect(passportSpy.mock.calls.length).toBe(1)
119
+ const generateOidcConfig = async () => {
120
+ const oidcConf = await config.saveOIDCConfig()
121
+ const chosenConfig = oidcConf.config.configs[0]
122
+ return chosenConfig.uuid
123
+ }
124
+
125
+ const mockGetWellKnownConfig = () => {
126
+ mocks.fetch.mockReturnValue({
127
+ ok: true,
128
+ json: () => ({
129
+ issuer: "test",
130
+ authorization_endpoint: "http://localhost/auth",
131
+ token_endpoint: "http://localhost/token",
132
+ userinfo_endpoint: "http://localhost/userinfo",
133
+ }),
134
+ })
135
+ }
136
+
137
+ // MULTI TENANT
138
+ describe("GET /api/global/auth/:tenantId/oidc/configs/:configId", () => {
139
+ it("redirects to auth provider", async () => {
140
+ const configId = await generateOidcConfig()
141
+
142
+ const res = await config.api.configs.getOIDCConfig(configId)
143
+
144
+ expect(res.status).toBe(302)
145
+ const location: string = res.get("location")
146
+ expect(
147
+ location.startsWith(
148
+ "http://localhost/auth?response_type=code&client_id=clientId&redirect_uri=http%3A%2F%2Flocalhost%3A10000%2Fapi%2Fglobal%2Fauth%2Fdefault%2Foidc%2Fcallback&scope=openid%20profile%20email%20offline_access"
149
+ )
150
+ ).toBe(true)
89
151
  })
90
152
  })
91
153
 
92
- describe("oidc callback", () => {
93
- it("should load strategy and delegate to passport", async () => {
94
- await api.configs.OIDCCallback(configId)
95
-
96
- expect(passportSpy).toBeCalledWith(
97
- mockStrategyReturn,
98
- {
99
- successRedirect: "/",
100
- failureRedirect: "/error",
101
- },
102
- expect.anything()
103
- )
104
- expect(passportSpy.mock.calls.length).toBe(1)
154
+ describe("GET /api/global/auth/:tenantId/oidc/callback", () => {
155
+ it("logs in", async () => {
156
+ const configId = await generateOidcConfig()
157
+ const preAuthRes = await config.api.configs.getOIDCConfig(configId)
158
+
159
+ const res = await config.api.configs.OIDCCallback(configId, preAuthRes)
160
+
161
+ expect(events.auth.login).toBeCalledWith("oidc")
162
+ expect(events.auth.login).toBeCalledTimes(1)
163
+ expect(res.status).toBe(302)
164
+ const location: string = res.get("location")
165
+ expect(location).toBe("/")
166
+ expectSetAuthCookie(res)
105
167
  })
106
168
  })
169
+
170
+ // SINGLE TENANT
171
+
172
+ describe("GET /api/global/auth/oidc/callback", () => {})
173
+
174
+ describe("GET /api/global/auth/oidc/callback", () => {})
175
+
176
+ describe("GET /api/admin/auth/oidc/callback", () => {})
107
177
  })
108
178
  })