@budibase/worker 1.0.200-alpha.3 → 1.0.200

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 (40) hide show
  1. package/Dockerfile +0 -3
  2. package/nodemon.json +1 -1
  3. package/package.json +46 -56
  4. package/scripts/dev/manage.js +0 -2
  5. package/scripts/jestSetup.js +0 -9
  6. package/scripts/load/users.js +4 -4
  7. package/src/api/controllers/global/auth.ts +14 -21
  8. package/src/api/controllers/global/configs.js +2 -126
  9. package/src/api/controllers/global/roles.js +3 -3
  10. package/src/api/controllers/global/self.js +3 -12
  11. package/src/api/controllers/global/users.ts +88 -48
  12. package/src/api/routes/global/self.js +2 -2
  13. package/src/api/routes/global/users.js +3 -3
  14. package/src/api/routes/tests/auth.spec.js +16 -38
  15. package/src/api/routes/tests/configs.spec.js +7 -223
  16. package/src/api/routes/tests/email.spec.js +7 -8
  17. package/src/api/routes/tests/realEmail.spec.js +5 -5
  18. package/src/api/routes/tests/users.spec.js +13 -299
  19. package/src/{tests → api/routes/tests/utilities}/TestConfiguration.js +111 -68
  20. package/src/api/routes/tests/utilities/controllers.js +7 -0
  21. package/src/api/routes/tests/utilities/index.js +41 -0
  22. package/src/api/routes/tests/utilities/structures.js +2 -0
  23. package/src/api/utilities/index.js +33 -0
  24. package/src/api/{routes/validation/users.ts → utilities/validation.js} +4 -4
  25. package/src/index.ts +0 -2
  26. package/tsconfig.json +15 -21
  27. package/src/api/routes/tests/self.spec.js +0 -58
  28. package/src/api/routes/validation/index.ts +0 -1
  29. package/src/sdk/index.ts +0 -1
  30. package/src/sdk/users/events.ts +0 -161
  31. package/src/sdk/users/index.ts +0 -1
  32. package/src/sdk/users/users.ts +0 -201
  33. package/src/tests/controllers.js +0 -7
  34. package/src/tests/index.js +0 -12
  35. package/src/tests/mocks/email.js +0 -10
  36. package/src/tests/mocks/index.js +0 -5
  37. package/src/tests/structures/configs.js +0 -76
  38. package/src/tests/structures/index.js +0 -12
  39. package/src/tests/structures/users.ts +0 -28
  40. package/tsconfig.build.json +0 -25
@@ -1,22 +1,35 @@
1
+ const {
2
+ getGlobalUserParams,
3
+ StaticDatabases,
4
+ } = require("@budibase/backend-core/db")
5
+ const { getGlobalUserByEmail } = require("@budibase/backend-core/utils")
6
+ const { user: userCache } = require("@budibase/backend-core/cache")
7
+ const { invalidateSessions } = require("@budibase/backend-core/sessions")
8
+ const accounts = require("@budibase/backend-core/accounts")
9
+ const {
10
+ getGlobalDB,
11
+ doWithGlobalDB,
12
+ getTenantId,
13
+ getTenantUser,
14
+ doesTenantExist,
15
+ doInTenant,
16
+ } = require("@budibase/backend-core/tenancy")
17
+ const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
18
+ const { errors } = require("@budibase/backend-core")
19
+ const { CacheKeys, bustCache } = require("@budibase/backend-core/cache")
20
+ import env from "../../../environment"
21
+ import { syncUserInApps } from "../../../utilities/appService"
22
+ import { quotas, users } from "@budibase/pro"
23
+ import { allUsers, getUser } from "../../utilities"
1
24
  import { EmailTemplatePurpose } from "../../../constants"
2
25
  import { checkInviteCode } from "../../../utilities/redis"
3
26
  import { sendEmail } from "../../../utilities/email"
4
- import { users } from "../../../sdk"
5
- import env from "../../../environment"
6
- import { User, CloudAccount } from "@budibase/types"
7
- import {
8
- events,
9
- errors,
10
- accounts,
11
- db as dbUtils,
12
- users as usersCore,
13
- tenancy,
14
- cache,
15
- } from "@budibase/backend-core"
16
27
 
17
28
  export const save = async (ctx: any) => {
18
29
  try {
19
- const user = await users.save(ctx.request.body)
30
+ const user: any = await users.save(ctx.request.body, getTenantId())
31
+ // let server know to sync user
32
+ await syncUserInApps(user._id)
20
33
  ctx.body = user
21
34
  } catch (err: any) {
22
35
  ctx.throw(err.status || 400, err)
@@ -29,22 +42,38 @@ const parseBooleanParam = (param: any) => {
29
42
 
30
43
  export const adminUser = async (ctx: any) => {
31
44
  const { email, password, tenantId } = ctx.request.body
32
- await tenancy.doInTenant(tenantId, async () => {
45
+ await doInTenant(tenantId, async () => {
33
46
  // account portal sends a pre-hashed password - honour param to prevent double hashing
34
47
  const hashPassword = parseBooleanParam(ctx.request.query.hashPassword)
35
48
  // account portal sends no password for SSO users
36
49
  const requirePassword = parseBooleanParam(ctx.request.query.requirePassword)
37
50
 
38
- if (await tenancy.doesTenantExist(tenantId)) {
51
+ if (await doesTenantExist(tenantId)) {
39
52
  ctx.throw(403, "Organisation already exists.")
40
53
  }
41
54
 
42
- const response = await tenancy.doWithGlobalDB(tenantId, async (db: any) => {
43
- return db.allDocs(
44
- dbUtils.getGlobalUserParams(null, {
55
+ const response = await doWithGlobalDB(tenantId, async (db: any) => {
56
+ const response = await db.allDocs(
57
+ getGlobalUserParams(null, {
45
58
  include_docs: true,
46
59
  })
47
60
  )
61
+ // write usage quotas for cloud
62
+ if (!env.SELF_HOSTED) {
63
+ // could be a scenario where it exists, make sure its clean
64
+ try {
65
+ const usageQuota = await db.get(
66
+ StaticDatabases.GLOBAL.docs.usageQuota
67
+ )
68
+ if (usageQuota) {
69
+ await db.remove(usageQuota._id, usageQuota._rev)
70
+ }
71
+ } catch (err) {
72
+ // don't worry about errors
73
+ }
74
+ await db.put(quotas.generateNewQuotaUsage())
75
+ }
76
+ return response
48
77
  })
49
78
 
50
79
  if (response.rows.some((row: any) => row.doc.admin)) {
@@ -54,7 +83,7 @@ export const adminUser = async (ctx: any) => {
54
83
  )
55
84
  }
56
85
 
57
- const user: User = {
86
+ const user = {
58
87
  email: email,
59
88
  password: password,
60
89
  createdAt: Date.now(),
@@ -68,19 +97,13 @@ export const adminUser = async (ctx: any) => {
68
97
  tenantId,
69
98
  }
70
99
  try {
71
- const finalUser = await users.save(user, {
100
+ const finalUser = await users.save(
101
+ user,
102
+ tenantId,
72
103
  hashPassword,
73
- requirePassword,
74
- })
75
- await cache.bustCache(cache.CacheKeys.CHECKLIST)
76
-
77
- // events
78
- let account: CloudAccount | undefined
79
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
80
- account = await accounts.getAccountByTenantId(tenantId)
81
- }
82
- await events.identification.identifyTenantGroup(tenantId, account)
83
-
104
+ requirePassword
105
+ )
106
+ await bustCache(CacheKeys.CHECKLIST)
84
107
  ctx.body = finalUser
85
108
  } catch (err: any) {
86
109
  ctx.throw(err.status || 400, err)
@@ -89,16 +112,37 @@ export const adminUser = async (ctx: any) => {
89
112
  }
90
113
 
91
114
  export const destroy = async (ctx: any) => {
92
- const id = ctx.params.id
93
- await users.destroy(id, ctx.user)
115
+ const db = getGlobalDB()
116
+ const dbUser = await db.get(ctx.params.id)
117
+
118
+ if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
119
+ // root account holder can't be deleted from inside budibase
120
+ const email = dbUser.email
121
+ const account = await accounts.getAccount(email)
122
+ if (account) {
123
+ if (email === ctx.user.email) {
124
+ ctx.throw(400, 'Please visit "Account" to delete this user')
125
+ } else {
126
+ ctx.throw(400, "Account holder cannot be deleted")
127
+ }
128
+ }
129
+ }
130
+
131
+ await removeUserFromInfoDB(dbUser)
132
+ await db.remove(dbUser._id, dbUser._rev)
133
+ await quotas.removeUser(dbUser)
134
+ await userCache.invalidateUser(dbUser._id)
135
+ await invalidateSessions(dbUser._id)
136
+ // let server know to sync user
137
+ await syncUserInApps(dbUser._id)
94
138
  ctx.body = {
95
- message: `User ${id} deleted.`,
139
+ message: `User ${ctx.params.id} deleted.`,
96
140
  }
97
141
  }
98
142
 
99
143
  // called internally by app server user fetch
100
144
  export const fetch = async (ctx: any) => {
101
- const all = await users.allUsers()
145
+ const all = await allUsers()
102
146
  // user hashed password shouldn't ever be returned
103
147
  for (let user of all) {
104
148
  if (user) {
@@ -110,12 +154,12 @@ export const fetch = async (ctx: any) => {
110
154
 
111
155
  // called internally by app server user find
112
156
  export const find = async (ctx: any) => {
113
- ctx.body = await users.getUser(ctx.params.id)
157
+ ctx.body = await getUser(ctx.params.id)
114
158
  }
115
159
 
116
160
  export const tenantUserLookup = async (ctx: any) => {
117
161
  const id = ctx.params.id
118
- const user = await tenancy.getTenantUser(id)
162
+ const user = await getTenantUser(id)
119
163
  if (user) {
120
164
  ctx.body = user
121
165
  } else {
@@ -125,14 +169,14 @@ export const tenantUserLookup = async (ctx: any) => {
125
169
 
126
170
  export const invite = async (ctx: any) => {
127
171
  let { email, userInfo } = ctx.request.body
128
- const existing = await usersCore.getGlobalUserByEmail(email)
172
+ const existing = await getGlobalUserByEmail(email)
129
173
  if (existing) {
130
174
  ctx.throw(400, "Email address already in use.")
131
175
  }
132
176
  if (!userInfo) {
133
177
  userInfo = {}
134
178
  }
135
- userInfo.tenantId = tenancy.getTenantId()
179
+ userInfo.tenantId = getTenantId()
136
180
  const opts: any = {
137
181
  subject: "{{ company }} platform invitation",
138
182
  info: userInfo,
@@ -141,7 +185,6 @@ export const invite = async (ctx: any) => {
141
185
  ctx.body = {
142
186
  message: "Invitation has been sent.",
143
187
  }
144
- await events.user.invited()
145
188
  }
146
189
 
147
190
  export const inviteAccept = async (ctx: any) => {
@@ -149,19 +192,16 @@ export const inviteAccept = async (ctx: any) => {
149
192
  try {
150
193
  // info is an extension of the user object that was stored by global
151
194
  const { email, info }: any = await checkInviteCode(inviteCode)
152
- ctx.body = await tenancy.doInTenant(info.tenantId, async () => {
153
- const saved = await users.save({
195
+ ctx.body = await users.save(
196
+ {
154
197
  firstName,
155
198
  lastName,
156
199
  password,
157
200
  email,
158
201
  ...info,
159
- })
160
- const db = tenancy.getGlobalDB()
161
- const user = await db.get(saved._id)
162
- await events.user.inviteAccepted(user)
163
- return saved
164
- })
202
+ },
203
+ info.tenantId
204
+ )
165
205
  } catch (err: any) {
166
206
  if (err.code === errors.codes.USAGE_LIMIT_EXCEEDED) {
167
207
  // explicitly re-throw limit exceeded errors
@@ -1,7 +1,7 @@
1
1
  const Router = require("@koa/router")
2
2
  const controller = require("../../controllers/global/self")
3
3
  const builderOnly = require("../../../middleware/builderOnly")
4
- const { users } = require("../validation")
4
+ const { buildUserSaveValidation } = require("../../utilities/validation")
5
5
 
6
6
  const router = Router()
7
7
 
@@ -11,7 +11,7 @@ router
11
11
  .get("/api/global/self", controller.getSelf)
12
12
  .post(
13
13
  "/api/global/self",
14
- users.buildUserSaveValidation(true),
14
+ buildUserSaveValidation(true),
15
15
  controller.updateSelf
16
16
  )
17
17
 
@@ -4,7 +4,7 @@ const joiValidator = require("../../../middleware/joi-validator")
4
4
  const adminOnly = require("../../../middleware/adminOnly")
5
5
  const Joi = require("joi")
6
6
  const cloudRestricted = require("../../../middleware/cloudRestricted")
7
- const { users } = require("../validation")
7
+ const { buildUserSaveValidation } = require("../../utilities/validation")
8
8
  const selfController = require("../../controllers/global/self")
9
9
  const builderOrAdmin = require("../../../middleware/builderOrAdmin")
10
10
 
@@ -42,7 +42,7 @@ router
42
42
  .post(
43
43
  "/api/global/users",
44
44
  adminOnly,
45
- users.buildUserSaveValidation(),
45
+ buildUserSaveValidation(),
46
46
  controller.save
47
47
  )
48
48
  .get("/api/global/users", builderOrAdmin, controller.fetch)
@@ -73,7 +73,7 @@ router
73
73
  .get("/api/global/users/self", selfController.getSelf)
74
74
  .post(
75
75
  "/api/global/users/self",
76
- users.buildUserSaveValidation(true),
76
+ buildUserSaveValidation(true),
77
77
  selfController.updateSelf
78
78
  )
79
79
 
@@ -1,25 +1,26 @@
1
1
  jest.mock("nodemailer")
2
- const { config, request, mocks, structures } = require("../../../tests")
3
- const sendMailMock = mocks.email.mock()
4
- const { events } = require("@budibase/backend-core")
2
+ const setup = require("./utilities")
3
+ const sendMailMock = setup.emailMock()
5
4
 
6
- const TENANT_ID = structures.TENANT_ID
5
+ const TENANT_ID = "default"
7
6
 
8
7
  describe("/api/global/auth", () => {
8
+ let request = setup.getRequest()
9
+ let config = setup.getConfig()
10
+ let code
9
11
 
10
12
  beforeAll(async () => {
11
- await config.beforeAll()
13
+ await config.init()
12
14
  })
13
15
 
14
- afterAll(async () => {
15
- await config.afterAll()
16
- })
16
+ afterAll(setup.afterAll)
17
17
 
18
18
  afterEach(() => {
19
19
  jest.clearAllMocks()
20
20
  })
21
21
 
22
- const requestPasswordReset = async () => {
22
+ it("should be able to generate password reset email", async () => {
23
+ // initially configure settings
23
24
  await config.saveSmtpConfig()
24
25
  await config.saveSettingsConfig()
25
26
  await config.createUser()
@@ -30,37 +31,16 @@ describe("/api/global/auth", () => {
30
31
  })
31
32
  .expect("Content-Type", /json/)
32
33
  .expect(200)
33
- const emailCall = sendMailMock.mock.calls[0][0]
34
- const parts = emailCall.html.split(`http://localhost:10000/builder/auth/reset?code=`)
35
- const code = parts[1].split("\"")[0].split("&")[0]
36
- return { code, res }
37
- }
38
-
39
- it("should logout", async () => {
40
- await request
41
- .post("/api/global/auth/logout")
42
- .set(config.defaultHeaders())
43
- .expect(200)
44
- expect(events.auth.logout).toBeCalledTimes(1)
45
- })
46
-
47
- it("should be able to generate password reset email", async () => {
48
- const { res, code } = await requestPasswordReset()
49
- const user = await config.getUser("test@test.com")
50
-
51
34
  expect(res.body).toEqual({ message: "Please check your email for a reset link." })
52
35
  expect(sendMailMock).toHaveBeenCalled()
53
-
36
+ const emailCall = sendMailMock.mock.calls[0][0]
37
+ // after this URL there should be a code
38
+ const parts = emailCall.html.split(`http://localhost:10000/builder/auth/reset?code=`)
39
+ code = parts[1].split("\"")[0].split("&")[0]
54
40
  expect(code).toBeDefined()
55
- expect(events.user.passwordResetRequested).toBeCalledTimes(1)
56
- expect(events.user.passwordResetRequested).toBeCalledWith(user)
57
41
  })
58
42
 
59
43
  it("should allow resetting user password with code", async () => {
60
- const { code } = await requestPasswordReset()
61
- const user = await config.getUser("test@test.com")
62
- delete user.password
63
-
64
44
  const res = await request
65
45
  .post(`/api/global/auth/${TENANT_ID}/reset/update`)
66
46
  .send({
@@ -70,16 +50,14 @@ describe("/api/global/auth", () => {
70
50
  .expect("Content-Type", /json/)
71
51
  .expect(200)
72
52
  expect(res.body).toEqual({ message: "password reset successfully." })
73
- expect(events.user.passwordReset).toBeCalledTimes(1)
74
- expect(events.user.passwordReset).toBeCalledWith(user)
75
53
  })
76
54
 
77
55
  describe("oidc", () => {
78
56
  const auth = require("@budibase/backend-core/auth")
79
57
 
80
58
  // mock the oidc strategy implementation and return value
81
- let strategyFactory = jest.fn()
82
- let mockStrategyReturn = jest.fn()
59
+ strategyFactory = jest.fn()
60
+ mockStrategyReturn = jest.fn()
83
61
  strategyFactory.mockReturnValue(mockStrategyReturn)
84
62
  auth.oidc.strategyFactory = strategyFactory
85
63
 
@@ -1,233 +1,17 @@
1
1
  // mock the email system
2
2
  jest.mock("nodemailer")
3
- const { config, structures, mocks, request } = require("../../../tests")
4
- mocks.email.mock()
5
- const { Configs } = require("@budibase/backend-core/constants")
6
- const { events } = require("@budibase/backend-core")
3
+ const setup = require("./utilities")
4
+ setup.emailMock()
7
5
 
8
- describe("configs", () => {
6
+ describe("/api/global/configs/checklist", () => {
7
+ let request = setup.getRequest()
8
+ let config = setup.getConfig()
9
9
 
10
10
  beforeAll(async () => {
11
- await config.beforeAll()
11
+ await config.init()
12
12
  })
13
13
 
14
- beforeEach(() => {
15
- jest.clearAllMocks()
16
- })
17
-
18
- afterAll(async () => {
19
- await config.afterAll()
20
- })
21
-
22
- describe("post /api/global/configs", () => {
23
-
24
- const saveConfig = async (conf, _id, _rev) => {
25
- const data = {
26
- ...conf,
27
- _id,
28
- _rev
29
- }
30
-
31
- const res = await request
32
- .post(`/api/global/configs`)
33
- .send(data)
34
- .set(config.defaultHeaders())
35
- .expect("Content-Type", /json/)
36
- .expect(200)
37
-
38
- return {
39
- ...data,
40
- ...res.body
41
- }
42
- }
43
-
44
- describe("google", () => {
45
- const saveGoogleConfig = async (conf, _id, _rev) => {
46
- const googleConfig = structures.configs.google(conf)
47
- return saveConfig(googleConfig, _id, _rev)
48
- }
49
-
50
- describe("create", () => {
51
- it ("should create activated google config", async () => {
52
- await saveGoogleConfig()
53
- expect(events.auth.SSOCreated).toBeCalledTimes(1)
54
- expect(events.auth.SSOCreated).toBeCalledWith(Configs.GOOGLE)
55
- expect(events.auth.SSODeactivated).not.toBeCalled()
56
- expect(events.auth.SSOActivated).toBeCalledTimes(1)
57
- expect(events.auth.SSOActivated).toBeCalledWith(Configs.GOOGLE)
58
- await config.deleteConfig(Configs.GOOGLE)
59
- })
60
-
61
- it ("should create deactivated google config", async () => {
62
- await saveGoogleConfig({ activated: false })
63
- expect(events.auth.SSOCreated).toBeCalledTimes(1)
64
- expect(events.auth.SSOCreated).toBeCalledWith(Configs.GOOGLE)
65
- expect(events.auth.SSOActivated).not.toBeCalled()
66
- expect(events.auth.SSODeactivated).not.toBeCalled()
67
- await config.deleteConfig(Configs.GOOGLE)
68
- })
69
- })
70
-
71
- describe("update", () => {
72
- it ("should update google config to deactivated", async () => {
73
- const googleConf = await saveGoogleConfig()
74
- jest.clearAllMocks()
75
- await saveGoogleConfig({ ...googleConf.config, activated: false }, googleConf._id, googleConf._rev)
76
- expect(events.auth.SSOUpdated).toBeCalledTimes(1)
77
- expect(events.auth.SSOUpdated).toBeCalledWith(Configs.GOOGLE)
78
- expect(events.auth.SSOActivated).not.toBeCalled()
79
- expect(events.auth.SSODeactivated).toBeCalledTimes(1)
80
- expect(events.auth.SSODeactivated).toBeCalledWith(Configs.GOOGLE)
81
- await config.deleteConfig(Configs.GOOGLE)
82
- })
83
-
84
- it ("should update google config to activated", async () => {
85
- const googleConf = await saveGoogleConfig({ activated: false })
86
- jest.clearAllMocks()
87
- await saveGoogleConfig({ ...googleConf.config, activated: true}, googleConf._id, googleConf._rev)
88
- expect(events.auth.SSOUpdated).toBeCalledTimes(1)
89
- expect(events.auth.SSOUpdated).toBeCalledWith(Configs.GOOGLE)
90
- expect(events.auth.SSODeactivated).not.toBeCalled()
91
- expect(events.auth.SSOActivated).toBeCalledTimes(1)
92
- expect(events.auth.SSOActivated).toBeCalledWith(Configs.GOOGLE)
93
- await config.deleteConfig(Configs.GOOGLE)
94
- })
95
- })
96
- })
97
-
98
- describe("oidc", () => {
99
- const saveOIDCConfig = async (conf, _id, _rev) => {
100
- const oidcConfig = structures.configs.oidc(conf)
101
- return saveConfig(oidcConfig, _id, _rev)
102
- }
103
-
104
- describe("create", () => {
105
- it ("should create activated OIDC config", async () => {
106
- await saveOIDCConfig()
107
- expect(events.auth.SSOCreated).toBeCalledTimes(1)
108
- expect(events.auth.SSOCreated).toBeCalledWith(Configs.OIDC)
109
- expect(events.auth.SSODeactivated).not.toBeCalled()
110
- expect(events.auth.SSOActivated).toBeCalledTimes(1)
111
- expect(events.auth.SSOActivated).toBeCalledWith(Configs.OIDC)
112
- await config.deleteConfig(Configs.OIDC)
113
- })
114
-
115
- it ("should create deactivated OIDC config", async () => {
116
- await saveOIDCConfig({ activated: false })
117
- expect(events.auth.SSOCreated).toBeCalledTimes(1)
118
- expect(events.auth.SSOCreated).toBeCalledWith(Configs.OIDC)
119
- expect(events.auth.SSOActivated).not.toBeCalled()
120
- expect(events.auth.SSODeactivated).not.toBeCalled()
121
- await config.deleteConfig(Configs.OIDC)
122
- })
123
- })
124
-
125
- describe("update", () => {
126
- it ("should update OIDC config to deactivated", async () => {
127
- const oidcConf = await saveOIDCConfig()
128
- jest.clearAllMocks()
129
- await saveOIDCConfig({ ...oidcConf.config.configs[0], activated: false }, oidcConf._id, oidcConf._rev)
130
- expect(events.auth.SSOUpdated).toBeCalledTimes(1)
131
- expect(events.auth.SSOUpdated).toBeCalledWith(Configs.OIDC)
132
- expect(events.auth.SSOActivated).not.toBeCalled()
133
- expect(events.auth.SSODeactivated).toBeCalledTimes(1)
134
- expect(events.auth.SSODeactivated).toBeCalledWith(Configs.OIDC)
135
- await config.deleteConfig(Configs.OIDC)
136
- })
137
-
138
- it ("should update OIDC config to activated", async () => {
139
- const oidcConf = await saveOIDCConfig({ activated: false })
140
- jest.clearAllMocks()
141
- await saveOIDCConfig({ ...oidcConf.config.configs[0], activated: true}, oidcConf._id, oidcConf._rev)
142
- expect(events.auth.SSOUpdated).toBeCalledTimes(1)
143
- expect(events.auth.SSOUpdated).toBeCalledWith(Configs.OIDC)
144
- expect(events.auth.SSODeactivated).not.toBeCalled()
145
- expect(events.auth.SSOActivated).toBeCalledTimes(1)
146
- expect(events.auth.SSOActivated).toBeCalledWith(Configs.OIDC)
147
- await config.deleteConfig(Configs.OIDC)
148
- })
149
- })
150
-
151
- })
152
-
153
- describe("smtp", () => {
154
- const saveSMTPConfig = async (conf, _id, _rev) => {
155
- const smtpConfig = structures.configs.smtp(conf)
156
- return saveConfig(smtpConfig, _id, _rev)
157
- }
158
-
159
- describe("create", () => {
160
- it ("should create SMTP config", async () => {
161
- await config.deleteConfig(Configs.SMTP)
162
- await saveSMTPConfig()
163
- expect(events.email.SMTPUpdated).not.toBeCalled()
164
- expect(events.email.SMTPCreated).toBeCalledTimes(1)
165
- await config.deleteConfig(Configs.SMTP)
166
- })
167
- })
168
-
169
- describe("update", () => {
170
- it ("should update SMTP config", async () => {
171
- const smtpConf = await saveSMTPConfig()
172
- jest.clearAllMocks()
173
- await saveSMTPConfig(smtpConf.config, smtpConf._id, smtpConf._rev)
174
- expect(events.email.SMTPCreated).not.toBeCalled()
175
- expect(events.email.SMTPUpdated).toBeCalledTimes(1)
176
- await config.deleteConfig(Configs.SMTP)
177
- })
178
- })
179
- })
180
-
181
- describe("settings", () => {
182
- const saveSettingsConfig = async (conf, _id, _rev) => {
183
- const settingsConfig = structures.configs.settings(conf)
184
- return saveConfig(settingsConfig, _id, _rev)
185
- }
186
-
187
- describe("create", () => {
188
- it ("should create settings config with default settings", async () => {
189
- await config.deleteConfig(Configs.SETTINGS)
190
-
191
- await saveSettingsConfig()
192
-
193
- expect(events.org.nameUpdated).not.toBeCalled()
194
- expect(events.org.logoUpdated).not.toBeCalled()
195
- expect(events.org.platformURLUpdated).not.toBeCalled()
196
- })
197
-
198
- it ("should create settings config with non-default settings", async () => {
199
- await config.deleteConfig(Configs.SETTINGS)
200
- const conf = {
201
- company: "acme",
202
- logoUrl: "http://example.com",
203
- platformUrl: "http://example.com"
204
- }
205
-
206
- await saveSettingsConfig(conf)
207
-
208
- expect(events.org.nameUpdated).toBeCalledTimes(1)
209
- expect(events.org.logoUpdated).toBeCalledTimes(1)
210
- expect(events.org.platformURLUpdated).toBeCalledTimes(1)
211
- })
212
- })
213
-
214
- describe("update", () => {
215
- it ("should update settings config", async () => {
216
- await config.deleteConfig(Configs.SETTINGS)
217
- const settingsConfig = await saveSettingsConfig()
218
- settingsConfig.config.company = "acme"
219
- settingsConfig.config.logoUrl = "http://example.com"
220
- settingsConfig.config.platformUrl = "http://example.com"
221
-
222
- await saveSettingsConfig(settingsConfig.config, settingsConfig._id, settingsConfig._rev)
223
-
224
- expect(events.org.nameUpdated).toBeCalledTimes(1)
225
- expect(events.org.logoUpdated).toBeCalledTimes(1)
226
- expect(events.org.platformURLUpdated).toBeCalledTimes(1)
227
- })
228
- })
229
- })
230
- })
14
+ afterAll(setup.afterAll)
231
15
 
232
16
  it("should return the correct checklist status based on the state of the budibase installation", async () => {
233
17
  await config.saveSmtpConfig()
@@ -1,20 +1,19 @@
1
1
  jest.mock("nodemailer")
2
- const { config, mocks, structures, request } = require("../../../tests")
3
- const sendMailMock = mocks.email.mock()
2
+ const setup = require("./utilities")
3
+ const sendMailMock = setup.emailMock()
4
4
 
5
5
  const { EmailTemplatePurpose } = require("../../../constants")
6
-
7
- const TENANT_ID = structures.TENANT_ID
6
+ const { TENANT_ID } = require("./utilities/structures")
8
7
 
9
8
  describe("/api/global/email", () => {
9
+ let request = setup.getRequest()
10
+ let config = setup.getConfig()
10
11
 
11
12
  beforeAll(async () => {
12
- await config.beforeAll()
13
+ await config.init()
13
14
  })
14
15
 
15
- afterAll(async () => {
16
- await config.afterAll()
17
- })
16
+ afterAll(setup.afterAll)
18
17
 
19
18
  it("should be able to send an email (with mocking)", async () => {
20
19
  // initially configure settings
@@ -1,4 +1,4 @@
1
- const { config, request } = require("../../../tests")
1
+ const setup = require("./utilities")
2
2
  const { EmailTemplatePurpose } = require("../../../constants")
3
3
  const nodemailer = require("nodemailer")
4
4
  const fetch = require("node-fetch")
@@ -7,14 +7,14 @@ const fetch = require("node-fetch")
7
7
  jest.setTimeout(30000)
8
8
 
9
9
  describe("/api/global/email", () => {
10
+ let request = setup.getRequest()
11
+ let config = setup.getConfig()
10
12
 
11
13
  beforeAll(async () => {
12
- await config.beforeAll()
14
+ await config.init()
13
15
  })
14
16
 
15
- afterAll(async () => {
16
- await config.afterAll()
17
- })
17
+ afterAll(setup.afterAll)
18
18
 
19
19
  async function sendRealEmail(purpose) {
20
20
  let response, text