@budibase/worker 2.1.32-alpha.8 → 2.1.33

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 (182) hide show
  1. package/package.json +23 -13
  2. package/{src/tests/jestSetup.ts → scripts/jestSetup.js} +3 -12
  3. package/scripts/localdomain.js +7 -33
  4. package/src/api/controllers/global/auth.ts +31 -35
  5. package/src/api/controllers/global/configs.js +17 -17
  6. package/src/api/controllers/global/self.ts +2 -2
  7. package/src/api/controllers/global/users.ts +1 -3
  8. package/src/api/controllers/system/{environment.ts → environment.js} +2 -3
  9. package/src/api/controllers/system/{status.ts → status.js} +3 -4
  10. package/src/api/controllers/system/tenants.ts +51 -8
  11. package/src/api/index.ts +6 -29
  12. package/src/api/routes/global/auth.js +39 -22
  13. package/src/api/routes/global/configs.js +9 -9
  14. package/src/api/routes/global/templates.ts +2 -2
  15. package/src/api/routes/global/tests/auth.spec.ts +64 -134
  16. package/src/api/routes/global/tests/configs.spec.ts +35 -34
  17. package/src/api/routes/global/tests/email.spec.ts +3 -4
  18. package/src/api/routes/global/tests/realEmail.spec.ts +3 -2
  19. package/src/api/routes/global/tests/self.spec.ts +4 -3
  20. package/src/api/routes/global/tests/users.spec.ts +43 -51
  21. package/src/api/routes/system/environment.js +8 -0
  22. package/src/api/routes/system/status.js +8 -0
  23. package/src/api/routes/system/tenants.js +12 -0
  24. package/src/api/routes/system/tests/accounts.spec.ts +6 -5
  25. package/src/constants/{index.ts → index.js} +64 -57
  26. package/src/constants/templates/index.js +2 -2
  27. package/src/db/index.js +11 -0
  28. package/src/index.ts +1 -1
  29. package/src/middleware/cloudRestricted.js +2 -2
  30. package/src/tests/TestConfiguration.ts +49 -98
  31. package/src/tests/api/accounts.ts +8 -5
  32. package/src/tests/api/auth.ts +6 -3
  33. package/src/tests/api/configs.ts +8 -15
  34. package/src/tests/api/email.ts +6 -3
  35. package/src/tests/api/index.ts +0 -15
  36. package/src/tests/api/self.ts +6 -11
  37. package/src/tests/api/users.ts +6 -38
  38. package/src/tests/index.ts +1 -5
  39. package/src/tests/structures/accounts.ts +24 -0
  40. package/src/tests/structures/configs.js +6 -6
  41. package/src/tests/structures/index.ts +2 -4
  42. package/src/tests/structures/users.ts +0 -1
  43. package/src/utilities/appService.js +3 -3
  44. package/src/utilities/{email.ts → email.js} +45 -78
  45. package/src/utilities/{redis.ts → redis.js} +24 -29
  46. package/src/utilities/templates.js +49 -0
  47. package/tsconfig.build.json +2 -2
  48. package/tsconfig.json +1 -3
  49. package/__mocks__/aws-sdk.ts +0 -15
  50. package/__mocks__/oauth.ts +0 -57
  51. package/coverage/clover.xml +0 -2160
  52. package/coverage/coverage-final.json +0 -78
  53. package/coverage/lcov-report/base.css +0 -224
  54. package/coverage/lcov-report/block-navigation.js +0 -87
  55. package/coverage/lcov-report/favicon.png +0 -0
  56. package/coverage/lcov-report/index.html +0 -431
  57. package/coverage/lcov-report/prettify.css +0 -1
  58. package/coverage/lcov-report/prettify.js +0 -2
  59. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  60. package/coverage/lcov-report/sorter.js +0 -196
  61. package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +0 -913
  62. package/coverage/lcov-report/src/api/controllers/global/configs.js.html +0 -1390
  63. package/coverage/lcov-report/src/api/controllers/global/email.js.html +0 -193
  64. package/coverage/lcov-report/src/api/controllers/global/index.html +0 -236
  65. package/coverage/lcov-report/src/api/controllers/global/license.ts.html +0 -187
  66. package/coverage/lcov-report/src/api/controllers/global/roles.js.html +0 -289
  67. package/coverage/lcov-report/src/api/controllers/global/self.ts.html +0 -577
  68. package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +0 -316
  69. package/coverage/lcov-report/src/api/controllers/global/users.ts.html +0 -796
  70. package/coverage/lcov-report/src/api/controllers/global/workspaces.js.html +0 -253
  71. package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +0 -148
  72. package/coverage/lcov-report/src/api/controllers/system/environment.ts.html +0 -124
  73. package/coverage/lcov-report/src/api/controllers/system/index.html +0 -191
  74. package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +0 -124
  75. package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +0 -124
  76. package/coverage/lcov-report/src/api/controllers/system/status.ts.html +0 -133
  77. package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +0 -154
  78. package/coverage/lcov-report/src/api/index.html +0 -116
  79. package/coverage/lcov-report/src/api/index.ts.html +0 -583
  80. package/coverage/lcov-report/src/api/routes/global/auth.js.html +0 -349
  81. package/coverage/lcov-report/src/api/routes/global/configs.js.html +0 -460
  82. package/coverage/lcov-report/src/api/routes/global/email.js.html +0 -196
  83. package/coverage/lcov-report/src/api/routes/global/index.html +0 -236
  84. package/coverage/lcov-report/src/api/routes/global/license.ts.html +0 -124
  85. package/coverage/lcov-report/src/api/routes/global/roles.js.html +0 -121
  86. package/coverage/lcov-report/src/api/routes/global/self.ts.html +0 -139
  87. package/coverage/lcov-report/src/api/routes/global/templates.ts.html +0 -196
  88. package/coverage/lcov-report/src/api/routes/global/users.js.html +0 -403
  89. package/coverage/lcov-report/src/api/routes/global/workspaces.js.html +0 -199
  90. package/coverage/lcov-report/src/api/routes/index.html +0 -116
  91. package/coverage/lcov-report/src/api/routes/index.ts.html +0 -193
  92. package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +0 -142
  93. package/coverage/lcov-report/src/api/routes/system/environment.ts.html +0 -109
  94. package/coverage/lcov-report/src/api/routes/system/index.html +0 -191
  95. package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +0 -142
  96. package/coverage/lcov-report/src/api/routes/system/restore.ts.html +0 -109
  97. package/coverage/lcov-report/src/api/routes/system/status.ts.html +0 -109
  98. package/coverage/lcov-report/src/api/routes/system/tenants.ts.html +0 -124
  99. package/coverage/lcov-report/src/api/routes/validation/index.html +0 -131
  100. package/coverage/lcov-report/src/api/routes/validation/index.ts.html +0 -88
  101. package/coverage/lcov-report/src/api/routes/validation/users.ts.html +0 -235
  102. package/coverage/lcov-report/src/constants/index.html +0 -116
  103. package/coverage/lcov-report/src/constants/index.ts.html +0 -613
  104. package/coverage/lcov-report/src/constants/templates/index.html +0 -116
  105. package/coverage/lcov-report/src/constants/templates/index.js.html +0 -304
  106. package/coverage/lcov-report/src/db/index.html +0 -116
  107. package/coverage/lcov-report/src/db/index.ts.html +0 -115
  108. package/coverage/lcov-report/src/environment.ts.html +0 -364
  109. package/coverage/lcov-report/src/index.html +0 -131
  110. package/coverage/lcov-report/src/index.ts.html +0 -397
  111. package/coverage/lcov-report/src/middleware/cloudRestricted.js.html +0 -136
  112. package/coverage/lcov-report/src/middleware/index.html +0 -116
  113. package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +0 -145
  114. package/coverage/lcov-report/src/migrations/functions/index.html +0 -116
  115. package/coverage/lcov-report/src/migrations/index.html +0 -116
  116. package/coverage/lcov-report/src/migrations/index.ts.html +0 -271
  117. package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +0 -262
  118. package/coverage/lcov-report/src/sdk/accounts/index.html +0 -131
  119. package/coverage/lcov-report/src/sdk/accounts/index.ts.html +0 -88
  120. package/coverage/lcov-report/src/sdk/index.html +0 -116
  121. package/coverage/lcov-report/src/sdk/index.ts.html +0 -106
  122. package/coverage/lcov-report/src/sdk/users/events.ts.html +0 -577
  123. package/coverage/lcov-report/src/sdk/users/index.html +0 -146
  124. package/coverage/lcov-report/src/sdk/users/index.ts.html +0 -88
  125. package/coverage/lcov-report/src/sdk/users/users.ts.html +0 -1903
  126. package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +0 -1051
  127. package/coverage/lcov-report/src/tests/api/accounts.ts.html +0 -160
  128. package/coverage/lcov-report/src/tests/api/auth.ts.html +0 -220
  129. package/coverage/lcov-report/src/tests/api/base.ts.html +0 -133
  130. package/coverage/lcov-report/src/tests/api/configs.ts.html +0 -226
  131. package/coverage/lcov-report/src/tests/api/email.ts.html +0 -148
  132. package/coverage/lcov-report/src/tests/api/environment.ts.html +0 -130
  133. package/coverage/lcov-report/src/tests/api/index.html +0 -296
  134. package/coverage/lcov-report/src/tests/api/index.ts.html +0 -205
  135. package/coverage/lcov-report/src/tests/api/migrations.ts.html +0 -151
  136. package/coverage/lcov-report/src/tests/api/restore.ts.html +0 -127
  137. package/coverage/lcov-report/src/tests/api/self.ts.html +0 -163
  138. package/coverage/lcov-report/src/tests/api/status.ts.html +0 -121
  139. package/coverage/lcov-report/src/tests/api/tenants.ts.html +0 -130
  140. package/coverage/lcov-report/src/tests/api/users.ts.html +0 -511
  141. package/coverage/lcov-report/src/tests/controllers.js.html +0 -106
  142. package/coverage/lcov-report/src/tests/index.html +0 -146
  143. package/coverage/lcov-report/src/tests/index.ts.html +0 -139
  144. package/coverage/lcov-report/src/tests/mocks/email.js.html +0 -115
  145. package/coverage/lcov-report/src/tests/mocks/index.html +0 -131
  146. package/coverage/lcov-report/src/tests/mocks/index.ts.html +0 -106
  147. package/coverage/lcov-report/src/tests/structures/configs.js.html +0 -313
  148. package/coverage/lcov-report/src/tests/structures/groups.ts.html +0 -118
  149. package/coverage/lcov-report/src/tests/structures/index.html +0 -161
  150. package/coverage/lcov-report/src/tests/structures/index.ts.html +0 -151
  151. package/coverage/lcov-report/src/tests/structures/users.ts.html +0 -196
  152. package/coverage/lcov-report/src/utilities/appService.js.html +0 -184
  153. package/coverage/lcov-report/src/utilities/email.ts.html +0 -850
  154. package/coverage/lcov-report/src/utilities/fileSystem.js.html +0 -100
  155. package/coverage/lcov-report/src/utilities/index.html +0 -206
  156. package/coverage/lcov-report/src/utilities/index.js.html +0 -112
  157. package/coverage/lcov-report/src/utilities/redis.ts.html +0 -424
  158. package/coverage/lcov-report/src/utilities/templates.ts.html +0 -232
  159. package/coverage/lcov-report/src/utilities/users.js.html +0 -136
  160. package/coverage/lcov.info +0 -3986
  161. package/jest.config.ts +0 -29
  162. package/src/api/routes/global/tests/license.spec.ts +0 -31
  163. package/src/api/routes/global/tests/roles.spec.ts +0 -27
  164. package/src/api/routes/global/tests/templates.spec.ts +0 -35
  165. package/src/api/routes/global/tests/workspaces.spec.ts +0 -29
  166. package/src/api/routes/system/environment.ts +0 -8
  167. package/src/api/routes/system/status.ts +0 -8
  168. package/src/api/routes/system/tenants.ts +0 -13
  169. package/src/api/routes/system/tests/environment.spec.ts +0 -29
  170. package/src/api/routes/system/tests/migrations.spec.ts +0 -63
  171. package/src/api/routes/system/tests/restore.spec.ts +0 -36
  172. package/src/api/routes/system/tests/status.spec.ts +0 -48
  173. package/src/api/routes/system/tests/tenants.spec.ts +0 -61
  174. package/src/db/index.ts +0 -10
  175. package/src/middleware/tests/tenancy.spec.ts +0 -73
  176. package/src/tests/api/base.ts +0 -16
  177. package/src/tests/api/environment.ts +0 -15
  178. package/src/tests/api/migrations.ts +0 -22
  179. package/src/tests/api/restore.ts +0 -14
  180. package/src/tests/api/status.ts +0 -12
  181. package/src/tests/api/tenants.ts +0 -15
  182. package/src/utilities/templates.ts +0 -49
@@ -2,6 +2,7 @@ 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")
5
6
 
6
7
  const router = new Router()
7
8
 
@@ -28,61 +29,77 @@ function buildResetUpdateValidation() {
28
29
  }).required().unknown(false))
29
30
  }
30
31
 
32
+ function updateTenant(ctx, next) {
33
+ if (ctx.params) {
34
+ updateTenantId(ctx.params.tenantId)
35
+ }
36
+ return next()
37
+ }
38
+
31
39
  router
32
- // PASSWORD
33
40
  .post(
34
41
  "/api/global/auth/:tenantId/login",
35
42
  buildAuthValidation(),
43
+ updateTenant,
36
44
  authController.authenticate
37
45
  )
38
- .post("/api/global/auth/logout", authController.logout)
39
46
  .post(
40
47
  "/api/global/auth/:tenantId/reset",
41
48
  buildResetValidation(),
49
+ updateTenant,
42
50
  authController.reset
43
51
  )
44
52
  .post(
45
53
  "/api/global/auth/:tenantId/reset/update",
46
54
  buildResetUpdateValidation(),
55
+ updateTenant,
47
56
  authController.resetUpdate
48
57
  )
49
- // INIT
58
+ .post("/api/global/auth/logout", authController.logout)
50
59
  .post("/api/global/auth/init", authController.setInitInfo)
51
60
  .get("/api/global/auth/init", authController.getInitInfo)
52
-
53
- // DATASOURCE - MULTI TENANT
61
+ .get(
62
+ "/api/global/auth/:tenantId/google",
63
+ updateTenant,
64
+ authController.googlePreAuth
65
+ )
54
66
  .get(
55
67
  "/api/global/auth/:tenantId/datasource/:provider",
68
+ updateTenant,
56
69
  authController.datasourcePreAuth
57
70
  )
71
+ // single tenancy endpoint
72
+ .get("/api/global/auth/google/callback", authController.googleAuth)
58
73
  .get(
59
- "/api/global/auth/:tenantId/datasource/:provider/callback",
74
+ "/api/global/auth/datasource/:provider/callback",
60
75
  authController.datasourceAuth
61
76
  )
62
-
63
- // DATASOURCE - SINGLE TENANT - DEPRECATED
77
+ // multi-tenancy endpoint
64
78
  .get(
65
- "/api/global/auth/datasource/:provider/callback",
79
+ "/api/global/auth/:tenantId/google/callback",
80
+ updateTenant,
81
+ authController.googleAuth
82
+ )
83
+ .get(
84
+ "/api/global/auth/:tenantId/datasource/:provider/callback",
85
+ updateTenant,
66
86
  authController.datasourceAuth
67
87
  )
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
78
88
  .get(
79
89
  "/api/global/auth/:tenantId/oidc/configs/:configId",
90
+ updateTenant,
80
91
  authController.oidcPreAuth
81
92
  )
82
- .get("/api/global/auth/:tenantId/oidc/callback", authController.oidcAuth)
83
-
84
- // OIDC - SINGLE TENANT - DEPRECATED
93
+ // single tenancy endpoint
85
94
  .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)
86
103
  .get("/api/admin/auth/oidc/callback", authController.oidcAuth)
87
104
 
88
105
  module.exports = router
@@ -3,7 +3,7 @@ const controller = require("../../controllers/global/configs")
3
3
  const { joiValidator } = require("@budibase/backend-core/auth")
4
4
  const { adminOnly } = require("@budibase/backend-core/auth")
5
5
  const Joi = require("joi")
6
- const { Config } = require("@budibase/backend-core/constants")
6
+ const { Configs } = require("../../../constants")
7
7
 
8
8
  const router = new Router()
9
9
 
@@ -65,17 +65,17 @@ function buildConfigSaveValidation() {
65
65
  _id: Joi.string().optional(),
66
66
  _rev: Joi.string().optional(),
67
67
  workspace: Joi.string().optional(),
68
- type: Joi.string().valid(...Object.values(Config)).required(),
68
+ type: Joi.string().valid(...Object.values(Configs)).required(),
69
69
  createdAt: Joi.string().optional(),
70
70
  updatedAt: Joi.string().optional(),
71
71
  config: Joi.alternatives()
72
72
  .conditional("type", {
73
73
  switch: [
74
- { is: Config.SMTP, then: smtpValidation() },
75
- { is: Config.SETTINGS, then: settingValidation() },
76
- { is: Config.ACCOUNT, then: Joi.object().unknown(true) },
77
- { is: Config.GOOGLE, then: googleValidation() },
78
- { is: Config.OIDC, then: oidcValidation() }
74
+ { is: Configs.SMTP, then: smtpValidation() },
75
+ { is: Configs.SETTINGS, then: settingValidation() },
76
+ { is: Configs.ACCOUNT, then: Joi.object().unknown(true) },
77
+ { is: Configs.GOOGLE, then: googleValidation() },
78
+ { is: Configs.OIDC, then: oidcValidation() }
79
79
  ],
80
80
  }),
81
81
  }).required().unknown(true),
@@ -85,7 +85,7 @@ function buildConfigSaveValidation() {
85
85
  function buildUploadValidation() {
86
86
  // prettier-ignore
87
87
  return joiValidator.params(Joi.object({
88
- type: Joi.string().valid(...Object.values(Config)).required(),
88
+ type: Joi.string().valid(...Object.values(Configs)).required(),
89
89
  name: Joi.string().required(),
90
90
  }).required().unknown(true))
91
91
  }
@@ -93,7 +93,7 @@ function buildUploadValidation() {
93
93
  function buildConfigGetValidation() {
94
94
  // prettier-ignore
95
95
  return joiValidator.params(Joi.object({
96
- type: Joi.string().valid(...Object.values(Config)).required()
96
+ type: Joi.string().valid(...Object.values(Configs)).required()
97
97
  }).required().unknown(true))
98
98
  }
99
99
 
@@ -1,6 +1,6 @@
1
1
  import Router from "@koa/router"
2
2
  import * as controller from "../../controllers/global/templates"
3
- import { TemplatePurpose, TemplateType } from "../../../constants"
3
+ import { TemplatePurpose, TemplateTypes } from "../../../constants"
4
4
  import { auth as authCore } from "@budibase/backend-core"
5
5
  import Joi from "joi"
6
6
  const { adminOnly, joiValidator } = authCore
@@ -16,7 +16,7 @@ function buildTemplateSaveValidation() {
16
16
  name: Joi.string().allow(null, ""),
17
17
  contents: Joi.string().required(),
18
18
  purpose: Joi.string().required().valid(...Object.values(TemplatePurpose)),
19
- type: Joi.string().required().valid(...Object.values(TemplateType)),
19
+ type: Joi.string().required().valid(...Object.values(TemplateTypes)),
20
20
  }).required().unknown(true).optional())
21
21
  }
22
22
 
@@ -1,16 +1,11 @@
1
1
  jest.mock("nodemailer")
2
- import { TestConfiguration, mocks } from "../../../../tests"
2
+ import { TestConfiguration, mocks, API } 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
-
12
6
  describe("/api/global/auth", () => {
13
7
  const config = new TestConfiguration()
8
+ const api = new API(config)
14
9
 
15
10
  beforeAll(async () => {
16
11
  await config.beforeAll()
@@ -24,155 +19,90 @@ describe("/api/global/auth", () => {
24
19
  jest.clearAllMocks()
25
20
  })
26
21
 
27
- describe("password", () => {
28
- describe("POST /api/global/auth/:tenantId/login", () => {
29
- it("should login", () => {})
30
- })
31
-
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)
36
-
37
- // TODO: Verify sessions deleted
38
- })
39
- })
40
-
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)
22
+ it("should logout", async () => {
23
+ await api.auth.logout()
24
+ expect(events.auth.logout).toBeCalledTimes(1)
25
+ })
68
26
 
69
- expect(res.body).toEqual({ message: "password reset successfully." })
70
- expect(events.user.passwordReset).toBeCalledTimes(1)
71
- expect(events.user.passwordReset).toBeCalledWith(user)
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")
72
30
 
73
- // TODO: Login using new password
74
- })
31
+ expect(res.body).toEqual({
32
+ message: "Please check your email for a reset link.",
75
33
  })
76
- })
34
+ expect(sendMailMock).toHaveBeenCalled()
77
35
 
78
- describe("init", () => {
79
- describe("POST /api/global/auth/init", () => {})
80
-
81
- describe("GET /api/global/auth/init", () => {})
36
+ expect(code).toBeDefined()
37
+ expect(events.user.passwordResetRequested).toBeCalledTimes(1)
38
+ expect(events.user.passwordResetRequested).toBeCalledWith(user)
82
39
  })
83
40
 
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", () => {})
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
90
45
 
91
- // SINGLE TENANT
46
+ const res = await api.auth.updatePassword(code)
92
47
 
93
- describe("GET /api/global/auth/datasource/:provider/callback", () => {})
48
+ expect(res.body).toEqual({ message: "password reset successfully." })
49
+ expect(events.user.passwordReset).toBeCalledTimes(1)
50
+ expect(events.user.passwordReset).toBeCalledWith(user)
94
51
  })
95
52
 
96
- describe("google", () => {
97
- // MULTI TENANT
98
-
99
- describe("GET /api/global/auth/:tenantId/google", () => {})
100
-
101
- describe("GET /api/global/auth/:tenantId/google/callback", () => {})
53
+ describe("oidc", () => {
54
+ const auth = require("@budibase/backend-core/auth")
102
55
 
103
- // SINGLE TENANT
56
+ const passportSpy = jest.spyOn(auth.passport, "authenticate")
57
+ let oidcConf
58
+ let chosenConfig: any
59
+ let configId: string
104
60
 
105
- describe("GET /api/global/auth/google/callback", () => {})
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
106
66
 
107
- describe("GET /api/admin/auth/google/callback", () => {})
108
- })
67
+ strategyFactory.mockReturnValue(mockStrategyReturn)
68
+ auth.oidc.strategyFactory = strategyFactory
109
69
 
110
- describe("oidc", () => {
111
70
  beforeEach(async () => {
112
- jest.clearAllMocks()
113
- mockGetWellKnownConfig()
114
-
115
- // see: __mocks__/oauth
116
- // for associated mocking inside passport
71
+ oidcConf = await config.saveOIDCConfig()
72
+ chosenConfig = oidcConf.config.configs[0]
73
+ configId = chosenConfig.uuid
74
+ mockStrategyConfig.mockReturnValue(chosenConfig)
117
75
  })
118
76
 
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)
151
- })
77
+ afterEach(() => {
78
+ expect(strategyFactory).toBeCalledWith(chosenConfig, expect.any(Function))
152
79
  })
153
80
 
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)
81
+ describe("oidc configs", () => {
82
+ it("should load strategy and delegate to passport", async () => {
83
+ await api.configs.getOIDCConfig(configId)
160
84
 
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)
85
+ expect(passportSpy).toBeCalledWith(mockStrategyReturn, {
86
+ scope: ["profile", "email", "offline_access"],
87
+ })
88
+ expect(passportSpy.mock.calls.length).toBe(1)
167
89
  })
168
90
  })
169
91
 
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", () => {})
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)
105
+ })
106
+ })
177
107
  })
178
108
  })
@@ -1,11 +1,12 @@
1
1
  // mock the email system
2
2
  jest.mock("nodemailer")
3
- import { TestConfiguration, structures, mocks } from "../../../../tests"
3
+ import { TestConfiguration, structures, mocks, API } from "../../../../tests"
4
4
  mocks.email.mock()
5
- import { Config, events } from "@budibase/backend-core"
5
+ import { Configs, events } from "@budibase/backend-core"
6
6
 
7
7
  describe("configs", () => {
8
8
  const config = new TestConfiguration()
9
+ const api = new API(config)
9
10
 
10
11
  beforeAll(async () => {
11
12
  await config.beforeAll()
@@ -27,7 +28,7 @@ describe("configs", () => {
27
28
  _rev,
28
29
  }
29
30
 
30
- const res = await config.api.configs.saveConfig(data)
31
+ const res = await api.configs.saveConfig(data)
31
32
 
32
33
  return {
33
34
  ...data,
@@ -49,20 +50,20 @@ describe("configs", () => {
49
50
  it("should create activated google config", async () => {
50
51
  await saveGoogleConfig()
51
52
  expect(events.auth.SSOCreated).toBeCalledTimes(1)
52
- expect(events.auth.SSOCreated).toBeCalledWith(Config.GOOGLE)
53
+ expect(events.auth.SSOCreated).toBeCalledWith(Configs.GOOGLE)
53
54
  expect(events.auth.SSODeactivated).not.toBeCalled()
54
55
  expect(events.auth.SSOActivated).toBeCalledTimes(1)
55
- expect(events.auth.SSOActivated).toBeCalledWith(Config.GOOGLE)
56
- await config.deleteConfig(Config.GOOGLE)
56
+ expect(events.auth.SSOActivated).toBeCalledWith(Configs.GOOGLE)
57
+ await config.deleteConfig(Configs.GOOGLE)
57
58
  })
58
59
 
59
60
  it("should create deactivated google config", async () => {
60
61
  await saveGoogleConfig({ activated: false })
61
62
  expect(events.auth.SSOCreated).toBeCalledTimes(1)
62
- expect(events.auth.SSOCreated).toBeCalledWith(Config.GOOGLE)
63
+ expect(events.auth.SSOCreated).toBeCalledWith(Configs.GOOGLE)
63
64
  expect(events.auth.SSOActivated).not.toBeCalled()
64
65
  expect(events.auth.SSODeactivated).not.toBeCalled()
65
- await config.deleteConfig(Config.GOOGLE)
66
+ await config.deleteConfig(Configs.GOOGLE)
66
67
  })
67
68
  })
68
69
 
@@ -76,11 +77,11 @@ describe("configs", () => {
76
77
  googleConf._rev
77
78
  )
78
79
  expect(events.auth.SSOUpdated).toBeCalledTimes(1)
79
- expect(events.auth.SSOUpdated).toBeCalledWith(Config.GOOGLE)
80
+ expect(events.auth.SSOUpdated).toBeCalledWith(Configs.GOOGLE)
80
81
  expect(events.auth.SSOActivated).not.toBeCalled()
81
82
  expect(events.auth.SSODeactivated).toBeCalledTimes(1)
82
- expect(events.auth.SSODeactivated).toBeCalledWith(Config.GOOGLE)
83
- await config.deleteConfig(Config.GOOGLE)
83
+ expect(events.auth.SSODeactivated).toBeCalledWith(Configs.GOOGLE)
84
+ await config.deleteConfig(Configs.GOOGLE)
84
85
  })
85
86
 
86
87
  it("should update google config to activated", async () => {
@@ -92,11 +93,11 @@ describe("configs", () => {
92
93
  googleConf._rev
93
94
  )
94
95
  expect(events.auth.SSOUpdated).toBeCalledTimes(1)
95
- expect(events.auth.SSOUpdated).toBeCalledWith(Config.GOOGLE)
96
+ expect(events.auth.SSOUpdated).toBeCalledWith(Configs.GOOGLE)
96
97
  expect(events.auth.SSODeactivated).not.toBeCalled()
97
98
  expect(events.auth.SSOActivated).toBeCalledTimes(1)
98
- expect(events.auth.SSOActivated).toBeCalledWith(Config.GOOGLE)
99
- await config.deleteConfig(Config.GOOGLE)
99
+ expect(events.auth.SSOActivated).toBeCalledWith(Configs.GOOGLE)
100
+ await config.deleteConfig(Configs.GOOGLE)
100
101
  })
101
102
  })
102
103
  })
@@ -115,20 +116,20 @@ describe("configs", () => {
115
116
  it("should create activated OIDC config", async () => {
116
117
  await saveOIDCConfig()
117
118
  expect(events.auth.SSOCreated).toBeCalledTimes(1)
118
- expect(events.auth.SSOCreated).toBeCalledWith(Config.OIDC)
119
+ expect(events.auth.SSOCreated).toBeCalledWith(Configs.OIDC)
119
120
  expect(events.auth.SSODeactivated).not.toBeCalled()
120
121
  expect(events.auth.SSOActivated).toBeCalledTimes(1)
121
- expect(events.auth.SSOActivated).toBeCalledWith(Config.OIDC)
122
- await config.deleteConfig(Config.OIDC)
122
+ expect(events.auth.SSOActivated).toBeCalledWith(Configs.OIDC)
123
+ await config.deleteConfig(Configs.OIDC)
123
124
  })
124
125
 
125
126
  it("should create deactivated OIDC config", async () => {
126
127
  await saveOIDCConfig({ activated: false })
127
128
  expect(events.auth.SSOCreated).toBeCalledTimes(1)
128
- expect(events.auth.SSOCreated).toBeCalledWith(Config.OIDC)
129
+ expect(events.auth.SSOCreated).toBeCalledWith(Configs.OIDC)
129
130
  expect(events.auth.SSOActivated).not.toBeCalled()
130
131
  expect(events.auth.SSODeactivated).not.toBeCalled()
131
- await config.deleteConfig(Config.OIDC)
132
+ await config.deleteConfig(Configs.OIDC)
132
133
  })
133
134
  })
134
135
 
@@ -142,11 +143,11 @@ describe("configs", () => {
142
143
  oidcConf._rev
143
144
  )
144
145
  expect(events.auth.SSOUpdated).toBeCalledTimes(1)
145
- expect(events.auth.SSOUpdated).toBeCalledWith(Config.OIDC)
146
+ expect(events.auth.SSOUpdated).toBeCalledWith(Configs.OIDC)
146
147
  expect(events.auth.SSOActivated).not.toBeCalled()
147
148
  expect(events.auth.SSODeactivated).toBeCalledTimes(1)
148
- expect(events.auth.SSODeactivated).toBeCalledWith(Config.OIDC)
149
- await config.deleteConfig(Config.OIDC)
149
+ expect(events.auth.SSODeactivated).toBeCalledWith(Configs.OIDC)
150
+ await config.deleteConfig(Configs.OIDC)
150
151
  })
151
152
 
152
153
  it("should update OIDC config to activated", async () => {
@@ -158,11 +159,11 @@ describe("configs", () => {
158
159
  oidcConf._rev
159
160
  )
160
161
  expect(events.auth.SSOUpdated).toBeCalledTimes(1)
161
- expect(events.auth.SSOUpdated).toBeCalledWith(Config.OIDC)
162
+ expect(events.auth.SSOUpdated).toBeCalledWith(Configs.OIDC)
162
163
  expect(events.auth.SSODeactivated).not.toBeCalled()
163
164
  expect(events.auth.SSOActivated).toBeCalledTimes(1)
164
- expect(events.auth.SSOActivated).toBeCalledWith(Config.OIDC)
165
- await config.deleteConfig(Config.OIDC)
165
+ expect(events.auth.SSOActivated).toBeCalledWith(Configs.OIDC)
166
+ await config.deleteConfig(Configs.OIDC)
166
167
  })
167
168
  })
168
169
  })
@@ -179,11 +180,11 @@ describe("configs", () => {
179
180
 
180
181
  describe("create", () => {
181
182
  it("should create SMTP config", async () => {
182
- await config.deleteConfig(Config.SMTP)
183
+ await config.deleteConfig(Configs.SMTP)
183
184
  await saveSMTPConfig()
184
185
  expect(events.email.SMTPUpdated).not.toBeCalled()
185
186
  expect(events.email.SMTPCreated).toBeCalledTimes(1)
186
- await config.deleteConfig(Config.SMTP)
187
+ await config.deleteConfig(Configs.SMTP)
187
188
  })
188
189
  })
189
190
 
@@ -194,7 +195,7 @@ describe("configs", () => {
194
195
  await saveSMTPConfig(smtpConf.config, smtpConf._id, smtpConf._rev)
195
196
  expect(events.email.SMTPCreated).not.toBeCalled()
196
197
  expect(events.email.SMTPUpdated).toBeCalledTimes(1)
197
- await config.deleteConfig(Config.SMTP)
198
+ await config.deleteConfig(Configs.SMTP)
198
199
  })
199
200
  })
200
201
  })
@@ -211,7 +212,7 @@ describe("configs", () => {
211
212
 
212
213
  describe("create", () => {
213
214
  it("should create settings config with default settings", async () => {
214
- await config.deleteConfig(Config.SETTINGS)
215
+ await config.deleteConfig(Configs.SETTINGS)
215
216
 
216
217
  await saveSettingsConfig()
217
218
 
@@ -222,7 +223,7 @@ describe("configs", () => {
222
223
 
223
224
  it("should create settings config with non-default settings", async () => {
224
225
  config.modeSelf()
225
- await config.deleteConfig(Config.SETTINGS)
226
+ await config.deleteConfig(Configs.SETTINGS)
226
227
  const conf = {
227
228
  company: "acme",
228
229
  logoUrl: "http://example.com",
@@ -234,14 +235,14 @@ describe("configs", () => {
234
235
  expect(events.org.nameUpdated).toBeCalledTimes(1)
235
236
  expect(events.org.logoUpdated).toBeCalledTimes(1)
236
237
  expect(events.org.platformURLUpdated).toBeCalledTimes(1)
237
- config.modeCloud()
238
+ config.modeAccount()
238
239
  })
239
240
  })
240
241
 
241
242
  describe("update", () => {
242
243
  it("should update settings config", async () => {
243
244
  config.modeSelf()
244
- await config.deleteConfig(Config.SETTINGS)
245
+ await config.deleteConfig(Configs.SETTINGS)
245
246
  const settingsConfig = await saveSettingsConfig()
246
247
  settingsConfig.config.company = "acme"
247
248
  settingsConfig.config.logoUrl = "http://example.com"
@@ -256,7 +257,7 @@ describe("configs", () => {
256
257
  expect(events.org.nameUpdated).toBeCalledTimes(1)
257
258
  expect(events.org.logoUpdated).toBeCalledTimes(1)
258
259
  expect(events.org.platformURLUpdated).toBeCalledTimes(1)
259
- config.modeCloud()
260
+ config.modeAccount()
260
261
  })
261
262
  })
262
263
  })
@@ -265,7 +266,7 @@ describe("configs", () => {
265
266
  it("should return the correct checklist status based on the state of the budibase installation", async () => {
266
267
  await config.saveSmtpConfig()
267
268
 
268
- const res = await config.api.configs.getConfigChecklist()
269
+ const res = await api.configs.getConfigChecklist()
269
270
  const checklist = res.body
270
271
 
271
272
  expect(checklist.apps.checked).toBeFalsy()
@@ -1,10 +1,11 @@
1
1
  jest.mock("nodemailer")
2
- import { TestConfiguration, mocks } from "../../../../tests"
2
+ import { TestConfiguration, mocks, API } from "../../../../tests"
3
3
  const sendMailMock = mocks.email.mock()
4
4
  import { EmailTemplatePurpose } from "../../../../constants"
5
5
 
6
6
  describe("/api/global/email", () => {
7
7
  const config = new TestConfiguration()
8
+ const api = new API(config)
8
9
 
9
10
  beforeAll(async () => {
10
11
  await config.beforeAll()
@@ -19,9 +20,7 @@ describe("/api/global/email", () => {
19
20
  await config.saveSmtpConfig()
20
21
  await config.saveSettingsConfig()
21
22
 
22
- const res = await config.api.emails.sendEmail(
23
- EmailTemplatePurpose.INVITATION
24
- )
23
+ const res = await api.emails.sendEmail(EmailTemplatePurpose.INVITATION)
25
24
 
26
25
  expect(res.body.message).toBeDefined()
27
26
  expect(sendMailMock).toHaveBeenCalled()
@@ -1,4 +1,4 @@
1
- import { TestConfiguration } from "../../../../tests"
1
+ import { TestConfiguration, API } from "../../../../tests"
2
2
  import { EmailTemplatePurpose } from "../../../../constants"
3
3
  const nodemailer = require("nodemailer")
4
4
  const fetch = require("node-fetch")
@@ -8,6 +8,7 @@ jest.setTimeout(30000)
8
8
 
9
9
  describe("/api/global/email", () => {
10
10
  const config = new TestConfiguration()
11
+ const api = new API(config)
11
12
 
12
13
  beforeAll(async () => {
13
14
  await config.beforeAll()
@@ -34,7 +35,7 @@ describe("/api/global/email", () => {
34
35
  await Promise.race([config.saveEtherealSmtpConfig(), timeout()])
35
36
  await Promise.race([config.saveSettingsConfig(), timeout()])
36
37
 
37
- const res = await config.api.emails.sendEmail(purpose).timeout(20000)
38
+ const res = await api.emails.sendEmail(purpose).timeout(20000)
38
39
  // ethereal hiccup, can't test right now
39
40
  if (res.status >= 300) {
40
41
  return