@budibase/worker 1.2.58-alpha.6 → 1.2.58

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 (42) hide show
  1. package/package.json +6 -7
  2. package/scripts/jestSetup.js +0 -6
  3. package/scripts/load/users.js +97 -0
  4. package/src/api/controllers/global/auth.ts +1 -14
  5. package/src/api/controllers/global/users.ts +55 -26
  6. package/src/api/{index.ts → index.js} +16 -12
  7. package/src/api/routes/global/configs.js +0 -1
  8. package/src/api/routes/index.js +0 -2
  9. package/src/api/routes/{global/tests/auth.spec.ts → tests/auth.spec.js} +56 -32
  10. package/src/api/routes/{global/tests/configs.spec.ts → tests/configs.spec.js} +47 -76
  11. package/src/api/routes/{global/tests/email.spec.ts → tests/email.spec.js} +15 -7
  12. package/src/api/routes/{global/tests/realEmail.spec.ts → tests/realEmail.spec.js} +21 -20
  13. package/src/api/routes/{global/tests/self.spec.ts → tests/self.spec.js} +18 -10
  14. package/src/api/routes/tests/users.spec.js +390 -0
  15. package/src/{environment.ts → environment.js} +9 -10
  16. package/src/index.ts +4 -6
  17. package/src/sdk/index.ts +0 -1
  18. package/src/sdk/users/users.ts +77 -271
  19. package/src/tests/TestConfiguration.js +231 -0
  20. package/src/tests/index.js +12 -0
  21. package/src/tests/mocks/index.js +5 -0
  22. package/src/tests/structures/index.js +14 -0
  23. package/src/tests/structures/users.ts +4 -12
  24. package/src/utilities/redis.js +0 -1
  25. package/src/api/controllers/system/accounts.ts +0 -21
  26. package/src/api/routes/global/tests/users.spec.ts +0 -512
  27. package/src/api/routes/system/accounts.ts +0 -19
  28. package/src/api/routes/system/tests/accounts.spec.ts +0 -57
  29. package/src/sdk/accounts/accounts.ts +0 -53
  30. package/src/sdk/accounts/index.ts +0 -1
  31. package/src/tests/TestConfiguration.ts +0 -273
  32. package/src/tests/api/accounts.ts +0 -28
  33. package/src/tests/api/auth.ts +0 -48
  34. package/src/tests/api/configs.ts +0 -40
  35. package/src/tests/api/email.ts +0 -24
  36. package/src/tests/api/index.ts +0 -25
  37. package/src/tests/api/self.ts +0 -21
  38. package/src/tests/api/users.ts +0 -111
  39. package/src/tests/index.ts +0 -14
  40. package/src/tests/mocks/index.ts +0 -7
  41. package/src/tests/structures/accounts.ts +0 -24
  42. package/src/tests/structures/index.ts +0 -20
@@ -0,0 +1,390 @@
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")
5
+ describe("/api/global/users", () => {
6
+
7
+ beforeAll(async () => {
8
+ await config.beforeAll()
9
+ })
10
+
11
+ afterAll(async () => {
12
+ await config.afterAll()
13
+ })
14
+
15
+ const sendUserInvite = async () => {
16
+ await config.saveSmtpConfig()
17
+ await config.saveSettingsConfig()
18
+ const res = await request
19
+ .post(`/api/global/users/invite`)
20
+ .send({
21
+ email: "invite@test.com",
22
+ })
23
+ .set(config.defaultHeaders())
24
+ .expect("Content-Type", /json/)
25
+ .expect(200)
26
+
27
+ const emailCall = sendMailMock.mock.calls[0][0]
28
+ // after this URL there should be a code
29
+ const parts = emailCall.html.split("http://localhost:10000/builder/invite?code=")
30
+ const code = parts[1].split("\"")[0].split("&")[0]
31
+ return { code, res }
32
+ }
33
+
34
+ it("should be able to generate an invitation", async () => {
35
+ const { code, res } = await sendUserInvite()
36
+
37
+ expect(res.body).toEqual({ message: "Invitation has been sent." })
38
+ expect(sendMailMock).toHaveBeenCalled()
39
+ expect(code).toBeDefined()
40
+ expect(events.user.invited).toBeCalledTimes(1)
41
+ })
42
+
43
+ it("should be able to create new user from invite", async () => {
44
+ const { code } = await sendUserInvite()
45
+
46
+ const res = await request
47
+ .post(`/api/global/users/invite/accept`)
48
+ .send({
49
+ password: "newpassword",
50
+ inviteCode: code,
51
+ })
52
+ .expect("Content-Type", /json/)
53
+ .expect(200)
54
+ expect(res.body._id).toBeDefined()
55
+ const user = await config.getUser("invite@test.com")
56
+ expect(user).toBeDefined()
57
+ expect(user._id).toEqual(res.body._id)
58
+ expect(events.user.inviteAccepted).toBeCalledTimes(1)
59
+ expect(events.user.inviteAccepted).toBeCalledWith(user)
60
+ })
61
+
62
+ const createUser = async (user) => {
63
+ const existing = await config.getUser(user.email)
64
+ if (existing) {
65
+ await deleteUser(existing._id)
66
+ }
67
+ return saveUser(user)
68
+ }
69
+
70
+ const updateUser = async (user) => {
71
+ const existing = await config.getUser(user.email)
72
+ user._id = existing._id
73
+ return saveUser(user)
74
+ }
75
+
76
+ const saveUser = async (user) => {
77
+ const res = await request
78
+ .post(`/api/global/users`)
79
+ .send(user)
80
+ .set(config.defaultHeaders())
81
+ .expect("Content-Type", /json/)
82
+ .expect(200)
83
+ return res.body
84
+ }
85
+
86
+
87
+ const bulkCreateUsers = async (users) => {
88
+ const res = await request
89
+ .post(`/api/global/users/bulkCreate`)
90
+ .send(users)
91
+ .set(config.defaultHeaders())
92
+ .expect("Content-Type", /json/)
93
+ .expect(200)
94
+ return res.body
95
+ }
96
+
97
+ const bulkDeleteUsers = async (users) => {
98
+ const res = await request
99
+ .post(`/api/global/users/bulkDelete`)
100
+ .send(users)
101
+ .set(config.defaultHeaders())
102
+ .expect("Content-Type", /json/)
103
+ .expect(200)
104
+ return res.body
105
+ }
106
+
107
+
108
+
109
+ const deleteUser = async (email) => {
110
+ const user = await config.getUser(email)
111
+ if (user) {
112
+ await request
113
+ .delete(`/api/global/users/${user._id}`)
114
+ .set(config.defaultHeaders())
115
+ .expect("Content-Type", /json/)
116
+ .expect(200)
117
+ }
118
+ }
119
+
120
+ describe("create", () => {
121
+ it("should be able to create a basic user", async () => {
122
+ jest.clearAllMocks()
123
+ const user = structures.users.user({ email: "basic@test.com" })
124
+ await createUser(user)
125
+
126
+ expect(events.user.created).toBeCalledTimes(1)
127
+ expect(events.user.updated).not.toBeCalled()
128
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
129
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
130
+ })
131
+
132
+ it("should be able to bulkCreate users with different permissions", async () => {
133
+ jest.clearAllMocks()
134
+ const builder = structures.users.builderUser({ email: "bulkbasic@test.com" })
135
+ const admin = structures.users.adminUser({ email: "bulkadmin@test.com" })
136
+ const user = structures.users.user({ email: "bulkuser@test.com" })
137
+
138
+ let toCreate = { users: [builder, admin, user], groups: [] }
139
+ await bulkCreateUsers(toCreate)
140
+
141
+ expect(events.user.created).toBeCalledTimes(3)
142
+ expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
143
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(1)
144
+ })
145
+
146
+
147
+ it("should be able to create an admin user", async () => {
148
+ jest.clearAllMocks()
149
+ const user = structures.users.adminUser({ email: "admin@test.com" })
150
+ await createUser(user)
151
+
152
+ expect(events.user.created).toBeCalledTimes(1)
153
+ expect(events.user.updated).not.toBeCalled()
154
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
155
+ expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
156
+ })
157
+
158
+ it("should be able to create a builder user", async () => {
159
+ jest.clearAllMocks()
160
+ const user = structures.users.builderUser({ email: "builder@test.com" })
161
+ await createUser(user)
162
+
163
+ expect(events.user.created).toBeCalledTimes(1)
164
+ expect(events.user.updated).not.toBeCalled()
165
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(1)
166
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
167
+ })
168
+
169
+ it("should be able to assign app roles", async () => {
170
+ jest.clearAllMocks()
171
+ const user = structures.users.user({ email: "assign-roles@test.com" })
172
+ user.roles = {
173
+ "app_123": "role1",
174
+ "app_456": "role2",
175
+ }
176
+
177
+ await createUser(user)
178
+ const savedUser = await config.getUser(user.email)
179
+
180
+ expect(events.user.created).toBeCalledTimes(1)
181
+ expect(events.user.updated).not.toBeCalled()
182
+ expect(events.role.assigned).toBeCalledTimes(2)
183
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role1")
184
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role2")
185
+ })
186
+ })
187
+
188
+ describe("update", () => {
189
+ it("should be able to update a basic user", async () => {
190
+ let user = structures.users.user({ email: "basic-update@test.com" })
191
+ await createUser(user)
192
+ jest.clearAllMocks()
193
+
194
+ await updateUser(user)
195
+
196
+ expect(events.user.created).not.toBeCalled()
197
+ expect(events.user.updated).toBeCalledTimes(1)
198
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
199
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
200
+ expect(events.user.passwordForceReset).not.toBeCalled()
201
+ })
202
+
203
+ it("should be able to force reset password", async () => {
204
+ let user = structures.users.user({ email: "basic-password-update@test.com" })
205
+ await createUser(user)
206
+ jest.clearAllMocks()
207
+
208
+ user.forceResetPassword = true
209
+ user.password = "tempPassword"
210
+ await updateUser(user)
211
+
212
+ expect(events.user.created).not.toBeCalled()
213
+ expect(events.user.updated).toBeCalledTimes(1)
214
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
215
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
216
+ expect(events.user.passwordForceReset).toBeCalledTimes(1)
217
+ })
218
+
219
+ it("should be able to update a basic user to an admin user", async () => {
220
+ let user = structures.users.user({ email: "basic-update-admin@test.com" })
221
+ await createUser(user)
222
+ jest.clearAllMocks()
223
+
224
+ await updateUser(structures.users.adminUser(user))
225
+
226
+ expect(events.user.created).not.toBeCalled()
227
+ expect(events.user.updated).toBeCalledTimes(1)
228
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
229
+ expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
230
+ })
231
+
232
+ it("should be able to update a basic user to a builder user", async () => {
233
+ let user = structures.users.user({ email: "basic-update-builder@test.com" })
234
+ await createUser(user)
235
+ jest.clearAllMocks()
236
+
237
+ await updateUser(structures.users.builderUser(user))
238
+
239
+ expect(events.user.created).not.toBeCalled()
240
+ expect(events.user.updated).toBeCalledTimes(1)
241
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(1)
242
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
243
+ })
244
+
245
+ it("should be able to update an admin user to a basic user", async () => {
246
+ let user = structures.users.adminUser({ email: "admin-update-basic@test.com" })
247
+ await createUser(user)
248
+ jest.clearAllMocks()
249
+
250
+ user.admin.global = false
251
+ await updateUser(user)
252
+
253
+ expect(events.user.created).not.toBeCalled()
254
+ expect(events.user.updated).toBeCalledTimes(1)
255
+ expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
256
+ expect(events.user.permissionBuilderRemoved).not.toBeCalled()
257
+ })
258
+
259
+ it("should be able to update an builder user to a basic user", async () => {
260
+ let user = structures.users.builderUser({ email: "builder-update-basic@test.com" })
261
+ await createUser(user)
262
+ jest.clearAllMocks()
263
+
264
+ user.builder.global = false
265
+ await updateUser(user)
266
+
267
+ expect(events.user.created).not.toBeCalled()
268
+ expect(events.user.updated).toBeCalledTimes(1)
269
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
270
+ expect(events.user.permissionAdminRemoved).not.toBeCalled()
271
+ })
272
+
273
+ it("should be able to assign app roles", async () => {
274
+ const user = structures.users.user({ email: "assign-roles-update@test.com" })
275
+ await createUser(user)
276
+ jest.clearAllMocks()
277
+
278
+ user.roles = {
279
+ "app_123": "role1",
280
+ "app_456": "role2",
281
+ }
282
+ await updateUser(user)
283
+ const savedUser = await config.getUser(user.email)
284
+
285
+ expect(events.user.created).not.toBeCalled()
286
+ expect(events.user.updated).toBeCalledTimes(1)
287
+ expect(events.role.assigned).toBeCalledTimes(2)
288
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role1")
289
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role2")
290
+ })
291
+
292
+ it("should be able to unassign app roles", async () => {
293
+ const user = structures.users.user({ email: "unassign-roles@test.com" })
294
+ user.roles = {
295
+ "app_123": "role1",
296
+ "app_456": "role2",
297
+ }
298
+ await createUser(user)
299
+ jest.clearAllMocks()
300
+
301
+ user.roles = {}
302
+ await updateUser(user)
303
+ const savedUser = await config.getUser(user.email)
304
+
305
+ expect(events.user.created).not.toBeCalled()
306
+ expect(events.user.updated).toBeCalledTimes(1)
307
+ expect(events.role.unassigned).toBeCalledTimes(2)
308
+ expect(events.role.unassigned).toBeCalledWith(savedUser, "role1")
309
+ expect(events.role.unassigned).toBeCalledWith(savedUser, "role2")
310
+ })
311
+
312
+ it("should be able to update existing app roles", async () => {
313
+ const user = structures.users.user({ email: "update-roles@test.com" })
314
+ user.roles = {
315
+ "app_123": "role1",
316
+ "app_456": "role2",
317
+ }
318
+ await createUser(user)
319
+ jest.clearAllMocks()
320
+
321
+ user.roles = {
322
+ "app_123": "role1",
323
+ "app_456": "role2-edit",
324
+ }
325
+ await updateUser(user)
326
+ const savedUser = await config.getUser(user.email)
327
+
328
+ expect(events.user.created).not.toBeCalled()
329
+ expect(events.user.updated).toBeCalledTimes(1)
330
+ expect(events.role.unassigned).toBeCalledTimes(1)
331
+ expect(events.role.unassigned).toBeCalledWith(savedUser, "role2")
332
+ expect(events.role.assigned).toBeCalledTimes(1)
333
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role2-edit")
334
+ })
335
+ })
336
+
337
+ describe("destroy", () => {
338
+ it("should be able to destroy a basic user", async () => {
339
+ let user = structures.users.user({ email: "destroy@test.com" })
340
+ await createUser(user)
341
+ jest.clearAllMocks()
342
+
343
+ await deleteUser(user.email)
344
+
345
+ expect(events.user.deleted).toBeCalledTimes(1)
346
+ expect(events.user.permissionBuilderRemoved).not.toBeCalled()
347
+ expect(events.user.permissionAdminRemoved).not.toBeCalled()
348
+ })
349
+
350
+ it("should be able to destroy an admin user", async () => {
351
+ let user = structures.users.adminUser({ email: "destroy-admin@test.com" })
352
+ await createUser(user)
353
+ jest.clearAllMocks()
354
+
355
+ await deleteUser(user.email)
356
+
357
+ expect(events.user.deleted).toBeCalledTimes(1)
358
+ expect(events.user.permissionBuilderRemoved).not.toBeCalled()
359
+ expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
360
+ })
361
+
362
+ it("should be able to destroy a builder user", async () => {
363
+ let user = structures.users.builderUser({ email: "destroy-admin@test.com" })
364
+ await createUser(user)
365
+ jest.clearAllMocks()
366
+
367
+ await deleteUser(user.email)
368
+
369
+ expect(events.user.deleted).toBeCalledTimes(1)
370
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
371
+ expect(events.user.permissionAdminRemoved).not.toBeCalled()
372
+ })
373
+
374
+ it("should be able to bulk delete users with different permissions", async () => {
375
+ jest.clearAllMocks()
376
+ const builder = structures.users.builderUser({ email: "basic@test.com" })
377
+ const admin = structures.users.adminUser({ email: "admin@test.com" })
378
+ const user = structures.users.user({ email: "user@test.com" })
379
+
380
+ let toCreate = { users: [builder, admin, user], groups: [] }
381
+ let createdUsers = await bulkCreateUsers(toCreate)
382
+ await bulkDeleteUsers({ userIds: [createdUsers[0]._id, createdUsers[1]._id, createdUsers[2]._id] })
383
+ expect(events.user.deleted).toBeCalledTimes(3)
384
+ expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
385
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
386
+
387
+ })
388
+
389
+ })
390
+ })
@@ -20,13 +20,13 @@ if (!LOADED && isDev() && !isTest()) {
20
20
  LOADED = true
21
21
  }
22
22
 
23
- function parseIntSafe(number: any) {
23
+ function parseIntSafe(number) {
24
24
  if (number) {
25
25
  return parseInt(number)
26
26
  }
27
27
  }
28
28
 
29
- const env = {
29
+ module.exports = {
30
30
  // auth
31
31
  MINIO_ACCESS_KEY: process.env.MINIO_ACCESS_KEY,
32
32
  MINIO_SECRET_KEY: process.env.MINIO_SECRET_KEY,
@@ -47,7 +47,7 @@ const env = {
47
47
  CLUSTER_PORT: process.env.CLUSTER_PORT,
48
48
  // flags
49
49
  NODE_ENV: process.env.NODE_ENV,
50
- SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED || ""),
50
+ SELF_HOSTED: !!parseInt(process.env.SELF_HOSTED),
51
51
  LOG_LEVEL: process.env.LOG_LEVEL,
52
52
  MULTI_TENANCY: process.env.MULTI_TENANCY,
53
53
  DISABLE_ACCOUNT_PORTAL: process.env.DISABLE_ACCOUNT_PORTAL,
@@ -62,7 +62,7 @@ const env = {
62
62
  // other
63
63
  CHECKLIST_CACHE_TTL: parseIntSafe(process.env.CHECKLIST_CACHE_TTL) || 3600,
64
64
  SESSION_UPDATE_PERIOD: process.env.SESSION_UPDATE_PERIOD,
65
- _set(key: any, value: any) {
65
+ _set(key, value) {
66
66
  process.env[key] = value
67
67
  module.exports[key] = value
68
68
  },
@@ -74,17 +74,16 @@ const env = {
74
74
  }
75
75
 
76
76
  // if some var haven't been set, define them
77
- if (!env.APPS_URL) {
78
- env.APPS_URL = isDev() ? "http://localhost:4001" : "http://app-service:4002"
77
+ if (!module.exports.APPS_URL) {
78
+ module.exports.APPS_URL = isDev()
79
+ ? "http://localhost:4001"
80
+ : "http://app-service:4002"
79
81
  }
80
82
 
81
83
  // clean up any environment variable edge cases
82
84
  for (let [key, value] of Object.entries(module.exports)) {
83
85
  // handle the edge case of "0" to disable an environment variable
84
86
  if (value === "0") {
85
- // @ts-ignore
86
- env[key] = 0
87
+ module.exports[key] = 0
87
88
  }
88
89
  }
89
-
90
- export = env
package/src/index.ts CHANGED
@@ -71,7 +71,9 @@ server.on("close", async () => {
71
71
  return
72
72
  }
73
73
  shuttingDown = true
74
- console.log("Server Closed")
74
+ if (!env.isTest()) {
75
+ console.log("Server Closed")
76
+ }
75
77
  await redis.shutdown()
76
78
  await events.shutdown()
77
79
  if (!env.isTest()) {
@@ -84,7 +86,7 @@ const shutdown = () => {
84
86
  server.destroy()
85
87
  }
86
88
 
87
- export = server.listen(parseInt(env.PORT || 4002), async () => {
89
+ module.exports = server.listen(parseInt(env.PORT || 4002), async () => {
88
90
  console.log(`Worker running on ${JSON.stringify(server.address())}`)
89
91
  await redis.init()
90
92
  })
@@ -98,7 +100,3 @@ process.on("uncaughtException", err => {
98
100
  process.on("SIGTERM", () => {
99
101
  shutdown()
100
102
  })
101
-
102
- process.on("SIGINT", () => {
103
- shutdown()
104
- })
package/src/sdk/index.ts CHANGED
@@ -1,2 +1 @@
1
1
  export * as users from "./users"
2
- export * as accounts from "./accounts"