@budibase/worker 1.2.58 → 1.3.1

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 +7 -6
  2. package/scripts/jestSetup.js +6 -0
  3. package/src/api/controllers/global/auth.ts +14 -1
  4. package/src/api/controllers/global/users.ts +26 -55
  5. package/src/api/controllers/system/accounts.ts +21 -0
  6. package/src/api/{index.js → index.ts} +12 -16
  7. package/src/api/routes/global/configs.js +1 -0
  8. package/src/api/routes/{tests/auth.spec.js → global/tests/auth.spec.ts} +32 -56
  9. package/src/api/routes/{tests/configs.spec.js → global/tests/configs.spec.ts} +76 -47
  10. package/src/api/routes/{tests/email.spec.js → global/tests/email.spec.ts} +7 -15
  11. package/src/api/routes/{tests/realEmail.spec.js → global/tests/realEmail.spec.ts} +20 -21
  12. package/src/api/routes/{tests/self.spec.js → global/tests/self.spec.ts} +10 -18
  13. package/src/api/routes/global/tests/users.spec.ts +512 -0
  14. package/src/api/routes/index.js +2 -0
  15. package/src/api/routes/system/accounts.ts +19 -0
  16. package/src/api/routes/system/tests/accounts.spec.ts +57 -0
  17. package/src/{environment.js → environment.ts} +10 -9
  18. package/src/index.ts +6 -4
  19. package/src/sdk/accounts/accounts.ts +53 -0
  20. package/src/sdk/accounts/index.ts +1 -0
  21. package/src/sdk/index.ts +1 -0
  22. package/src/sdk/users/users.ts +271 -77
  23. package/src/tests/TestConfiguration.ts +273 -0
  24. package/src/tests/api/accounts.ts +28 -0
  25. package/src/tests/api/auth.ts +48 -0
  26. package/src/tests/api/configs.ts +40 -0
  27. package/src/tests/api/email.ts +24 -0
  28. package/src/tests/api/index.ts +25 -0
  29. package/src/tests/api/self.ts +21 -0
  30. package/src/tests/api/users.ts +111 -0
  31. package/src/tests/index.ts +14 -0
  32. package/src/tests/mocks/index.ts +7 -0
  33. package/src/tests/structures/accounts.ts +24 -0
  34. package/src/tests/structures/index.ts +20 -0
  35. package/src/tests/structures/users.ts +12 -4
  36. package/src/utilities/redis.js +1 -0
  37. package/scripts/load/users.js +0 -97
  38. package/src/api/routes/tests/users.spec.js +0 -390
  39. package/src/tests/TestConfiguration.js +0 -231
  40. package/src/tests/index.js +0 -12
  41. package/src/tests/mocks/index.js +0 -5
  42. package/src/tests/structures/index.js +0 -14
@@ -0,0 +1,512 @@
1
+ import { InviteUsersResponse } from "@budibase/types"
2
+
3
+ jest.mock("nodemailer")
4
+ import {
5
+ TestConfiguration,
6
+ mocks,
7
+ structures,
8
+ TENANT_1,
9
+ API,
10
+ } from "../../../../tests"
11
+ const sendMailMock = mocks.email.mock()
12
+ import { events, tenancy } from "@budibase/backend-core"
13
+
14
+ describe("/api/global/users", () => {
15
+ const config = new TestConfiguration()
16
+ const api = new API(config)
17
+
18
+ beforeAll(async () => {
19
+ await config.beforeAll()
20
+ })
21
+
22
+ afterAll(async () => {
23
+ await config.afterAll()
24
+ })
25
+
26
+ beforeEach(() => {
27
+ jest.clearAllMocks()
28
+ })
29
+
30
+ describe("invite", () => {
31
+ it("should be able to generate an invitation", async () => {
32
+ const email = structures.users.newEmail()
33
+ const { code, res } = await api.users.sendUserInvite(sendMailMock, email)
34
+
35
+ expect(res.body).toEqual({ message: "Invitation has been sent." })
36
+ expect(sendMailMock).toHaveBeenCalled()
37
+ expect(code).toBeDefined()
38
+ expect(events.user.invited).toBeCalledTimes(1)
39
+ })
40
+
41
+ it("should not be able to generate an invitation for existing user", async () => {
42
+ const { code, res } = await api.users.sendUserInvite(
43
+ sendMailMock,
44
+ config.defaultUser!.email,
45
+ 400
46
+ )
47
+
48
+ expect(res.body.message).toBe("Unavailable")
49
+ expect(sendMailMock).toHaveBeenCalledTimes(0)
50
+ expect(code).toBeUndefined()
51
+ expect(events.user.invited).toBeCalledTimes(0)
52
+ })
53
+
54
+ it("should be able to create new user from invite", async () => {
55
+ const email = structures.users.newEmail()
56
+ const { code } = await api.users.sendUserInvite(sendMailMock, email)
57
+
58
+ const res = await api.users.acceptInvite(code)
59
+
60
+ expect(res.body._id).toBeDefined()
61
+ const user = await config.getUser(email)
62
+ expect(user).toBeDefined()
63
+ expect(user._id).toEqual(res.body._id)
64
+ expect(events.user.inviteAccepted).toBeCalledTimes(1)
65
+ expect(events.user.inviteAccepted).toBeCalledWith(user)
66
+ })
67
+ })
68
+
69
+ describe("inviteMultiple", () => {
70
+ it("should be able to generate an invitation", async () => {
71
+ const newUserInvite = () => ({
72
+ email: structures.users.newEmail(),
73
+ userInfo: {},
74
+ })
75
+ const request = [newUserInvite(), newUserInvite()]
76
+
77
+ const res = await api.users.sendMultiUserInvite(request)
78
+
79
+ const body = res.body as InviteUsersResponse
80
+ expect(body.successful.length).toBe(2)
81
+ expect(body.unsuccessful.length).toBe(0)
82
+ expect(sendMailMock).toHaveBeenCalledTimes(2)
83
+ expect(events.user.invited).toBeCalledTimes(2)
84
+ })
85
+
86
+ it("should not be able to generate an invitation for existing user", async () => {
87
+ const request = [{ email: config.defaultUser!.email, userInfo: {} }]
88
+
89
+ const res = await api.users.sendMultiUserInvite(request)
90
+
91
+ const body = res.body as InviteUsersResponse
92
+ expect(body.successful.length).toBe(0)
93
+ expect(body.unsuccessful.length).toBe(1)
94
+ expect(body.unsuccessful[0].reason).toBe("Unavailable")
95
+ expect(sendMailMock).toHaveBeenCalledTimes(0)
96
+ expect(events.user.invited).toBeCalledTimes(0)
97
+ })
98
+ })
99
+
100
+ describe("bulkCreate", () => {
101
+ it("should ignore users existing in the same tenant", async () => {
102
+ const user = await config.createUser()
103
+ jest.clearAllMocks()
104
+
105
+ const response = await api.users.bulkCreateUsers([user])
106
+
107
+ expect(response.successful.length).toBe(0)
108
+ expect(response.unsuccessful.length).toBe(1)
109
+ expect(response.unsuccessful[0].email).toBe(user.email)
110
+ expect(events.user.created).toBeCalledTimes(0)
111
+ })
112
+
113
+ it("should ignore users existing in other tenants", async () => {
114
+ const user = await config.createUser()
115
+ jest.resetAllMocks()
116
+
117
+ await tenancy.doInTenant(TENANT_1, async () => {
118
+ const response = await api.users.bulkCreateUsers([user])
119
+
120
+ expect(response.successful.length).toBe(0)
121
+ expect(response.unsuccessful.length).toBe(1)
122
+ expect(response.unsuccessful[0].email).toBe(user.email)
123
+ expect(events.user.created).toBeCalledTimes(0)
124
+ })
125
+ })
126
+
127
+ it("should ignore accounts using the same email", async () => {
128
+ const account = structures.accounts.account()
129
+ const resp = await api.accounts.saveMetadata(account)
130
+ const user = structures.users.user({ email: resp.email })
131
+ jest.clearAllMocks()
132
+
133
+ const response = await api.users.bulkCreateUsers([user])
134
+
135
+ expect(response.successful.length).toBe(0)
136
+ expect(response.unsuccessful.length).toBe(1)
137
+ expect(response.unsuccessful[0].email).toBe(user.email)
138
+ expect(events.user.created).toBeCalledTimes(0)
139
+ })
140
+
141
+ it("should be able to bulkCreate users", async () => {
142
+ const builder = structures.users.builderUser()
143
+ const admin = structures.users.adminUser()
144
+ const user = structures.users.user()
145
+
146
+ const response = await api.users.bulkCreateUsers([builder, admin, user])
147
+
148
+ expect(response.successful.length).toBe(3)
149
+ expect(response.successful[0].email).toBe(builder.email)
150
+ expect(response.successful[1].email).toBe(admin.email)
151
+ expect(response.successful[2].email).toBe(user.email)
152
+ expect(response.unsuccessful.length).toBe(0)
153
+ expect(events.user.created).toBeCalledTimes(3)
154
+ expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
155
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(2)
156
+ })
157
+ })
158
+
159
+ describe("create", () => {
160
+ it("should be able to create a basic user", async () => {
161
+ const user = structures.users.user()
162
+
163
+ await api.users.saveUser(user)
164
+
165
+ expect(events.user.created).toBeCalledTimes(1)
166
+ expect(events.user.updated).not.toBeCalled()
167
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
168
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
169
+ })
170
+
171
+ it("should be able to create an admin user", async () => {
172
+ const user = structures.users.adminUser()
173
+
174
+ await api.users.saveUser(user)
175
+
176
+ expect(events.user.created).toBeCalledTimes(1)
177
+ expect(events.user.updated).not.toBeCalled()
178
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(1)
179
+ expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
180
+ })
181
+
182
+ it("should be able to create a builder user", async () => {
183
+ const user = structures.users.builderUser()
184
+
185
+ await api.users.saveUser(user)
186
+
187
+ expect(events.user.created).toBeCalledTimes(1)
188
+ expect(events.user.updated).not.toBeCalled()
189
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(1)
190
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
191
+ })
192
+
193
+ it("should be able to assign app roles", async () => {
194
+ const user = structures.users.user()
195
+ user.roles = {
196
+ app_123: "role1",
197
+ app_456: "role2",
198
+ }
199
+
200
+ await api.users.saveUser(user)
201
+
202
+ const savedUser = await config.getUser(user.email)
203
+ expect(events.user.created).toBeCalledTimes(1)
204
+ expect(events.user.updated).not.toBeCalled()
205
+ expect(events.role.assigned).toBeCalledTimes(2)
206
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role1")
207
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role2")
208
+ })
209
+
210
+ it("should not be able to create user that exists in same tenant", async () => {
211
+ const user = await config.createUser()
212
+ jest.clearAllMocks()
213
+ delete user._id
214
+ delete user._rev
215
+
216
+ const response = await api.users.saveUser(user, 400)
217
+
218
+ expect(response.body.message).toBe(`Unavailable`)
219
+ expect(events.user.created).toBeCalledTimes(0)
220
+ })
221
+
222
+ it("should not be able to create user that exists in other tenant", async () => {
223
+ const user = await config.createUser()
224
+ jest.resetAllMocks()
225
+
226
+ await tenancy.doInTenant(TENANT_1, async () => {
227
+ delete user._id
228
+ const response = await api.users.saveUser(user, 400)
229
+
230
+ expect(response.body.message).toBe(`Unavailable`)
231
+ expect(events.user.created).toBeCalledTimes(0)
232
+ })
233
+ })
234
+
235
+ it("should not be able to create user with the same email as an account", async () => {
236
+ const user = structures.users.user()
237
+ const account = structures.accounts.cloudAccount()
238
+ mocks.accounts.getAccount.mockReturnValueOnce(account)
239
+
240
+ const response = await api.users.saveUser(user, 400)
241
+
242
+ expect(response.body.message).toBe(`Unavailable`)
243
+ expect(events.user.created).toBeCalledTimes(0)
244
+ })
245
+ })
246
+
247
+ describe("update", () => {
248
+ it("should be able to update a basic user", async () => {
249
+ const user = await config.createUser()
250
+ jest.clearAllMocks()
251
+
252
+ await api.users.saveUser(user)
253
+
254
+ expect(events.user.created).not.toBeCalled()
255
+ expect(events.user.updated).toBeCalledTimes(1)
256
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
257
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
258
+ expect(events.user.passwordForceReset).not.toBeCalled()
259
+ })
260
+
261
+ it("should be able to force reset password", async () => {
262
+ const user = await config.createUser()
263
+ jest.clearAllMocks()
264
+
265
+ user.forceResetPassword = true
266
+ user.password = "tempPassword"
267
+ await api.users.saveUser(user)
268
+
269
+ expect(events.user.created).not.toBeCalled()
270
+ expect(events.user.updated).toBeCalledTimes(1)
271
+ expect(events.user.permissionBuilderAssigned).not.toBeCalled()
272
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
273
+ expect(events.user.passwordForceReset).toBeCalledTimes(1)
274
+ })
275
+
276
+ it("should be able to update a basic user to an admin user", async () => {
277
+ const user = await config.createUser()
278
+ jest.clearAllMocks()
279
+
280
+ await api.users.saveUser(structures.users.adminUser(user))
281
+
282
+ expect(events.user.created).not.toBeCalled()
283
+ expect(events.user.updated).toBeCalledTimes(1)
284
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(1)
285
+ expect(events.user.permissionAdminAssigned).toBeCalledTimes(1)
286
+ })
287
+
288
+ it("should be able to update a basic user to a builder user", async () => {
289
+ const user = await config.createUser()
290
+ jest.clearAllMocks()
291
+
292
+ await api.users.saveUser(structures.users.builderUser(user))
293
+
294
+ expect(events.user.created).not.toBeCalled()
295
+ expect(events.user.updated).toBeCalledTimes(1)
296
+ expect(events.user.permissionBuilderAssigned).toBeCalledTimes(1)
297
+ expect(events.user.permissionAdminAssigned).not.toBeCalled()
298
+ })
299
+
300
+ it("should be able to update an admin user to a basic user", async () => {
301
+ const user = await config.createUser(structures.users.adminUser())
302
+ jest.clearAllMocks()
303
+ user.admin!.global = false
304
+ user.builder!.global = false
305
+
306
+ await api.users.saveUser(user)
307
+
308
+ expect(events.user.created).not.toBeCalled()
309
+ expect(events.user.updated).toBeCalledTimes(1)
310
+ expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
311
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
312
+ })
313
+
314
+ it("should be able to update an builder user to a basic user", async () => {
315
+ const user = await config.createUser(structures.users.builderUser())
316
+ jest.clearAllMocks()
317
+ user.builder!.global = false
318
+
319
+ await api.users.saveUser(user)
320
+
321
+ expect(events.user.created).not.toBeCalled()
322
+ expect(events.user.updated).toBeCalledTimes(1)
323
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
324
+ expect(events.user.permissionAdminRemoved).not.toBeCalled()
325
+ })
326
+
327
+ it("should be able to assign app roles", async () => {
328
+ const user = await config.createUser()
329
+ jest.clearAllMocks()
330
+ user.roles = {
331
+ app_123: "role1",
332
+ app_456: "role2",
333
+ }
334
+
335
+ await api.users.saveUser(user)
336
+
337
+ const savedUser = await config.getUser(user.email)
338
+ expect(events.user.created).not.toBeCalled()
339
+ expect(events.user.updated).toBeCalledTimes(1)
340
+ expect(events.role.assigned).toBeCalledTimes(2)
341
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role1")
342
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role2")
343
+ })
344
+
345
+ it("should be able to unassign app roles", async () => {
346
+ let user = structures.users.user()
347
+ user.roles = {
348
+ app_123: "role1",
349
+ app_456: "role2",
350
+ }
351
+ user = await config.createUser(user)
352
+ jest.clearAllMocks()
353
+ user.roles = {}
354
+
355
+ await api.users.saveUser(user)
356
+
357
+ const savedUser = await config.getUser(user.email)
358
+ expect(events.user.created).not.toBeCalled()
359
+ expect(events.user.updated).toBeCalledTimes(1)
360
+ expect(events.role.unassigned).toBeCalledTimes(2)
361
+ expect(events.role.unassigned).toBeCalledWith(savedUser, "role1")
362
+ expect(events.role.unassigned).toBeCalledWith(savedUser, "role2")
363
+ })
364
+
365
+ it("should be able to update existing app roles", async () => {
366
+ let user = structures.users.user()
367
+ user.roles = {
368
+ app_123: "role1",
369
+ app_456: "role2",
370
+ }
371
+ user = await config.createUser(user)
372
+ jest.clearAllMocks()
373
+ user.roles = {
374
+ app_123: "role1",
375
+ app_456: "role2-edit",
376
+ }
377
+
378
+ await api.users.saveUser(user)
379
+
380
+ const savedUser = await config.getUser(user.email)
381
+ expect(events.user.created).not.toBeCalled()
382
+ expect(events.user.updated).toBeCalledTimes(1)
383
+ expect(events.role.unassigned).toBeCalledTimes(1)
384
+ expect(events.role.unassigned).toBeCalledWith(savedUser, "role2")
385
+ expect(events.role.assigned).toBeCalledTimes(1)
386
+ expect(events.role.assigned).toBeCalledWith(savedUser, "role2-edit")
387
+ })
388
+
389
+ it("should not be able to update email address", async () => {
390
+ const email = "email@test.com"
391
+ const user = await config.createUser(structures.users.user({ email }))
392
+ user.email = "new@test.com"
393
+
394
+ const response = await api.users.saveUser(user, 400)
395
+
396
+ const dbUser = await config.getUser(email)
397
+ user.email = email
398
+ expect(user).toStrictEqual(dbUser)
399
+ expect(response.body.message).toBe("Email address cannot be changed")
400
+ })
401
+ })
402
+
403
+ describe("bulkDelete", () => {
404
+ it("should not be able to bulkDelete current user", async () => {
405
+ const user = await config.defaultUser!
406
+ const request = { userIds: [user._id!] }
407
+
408
+ const response = await api.users.bulkDeleteUsers(request, 400)
409
+
410
+ expect(response.body.message).toBe("Unable to delete self.")
411
+ expect(events.user.deleted).not.toBeCalled()
412
+ })
413
+
414
+ it("should not be able to bulkDelete account owner", async () => {
415
+ const user = await config.createUser()
416
+ const account = structures.accounts.cloudAccount()
417
+ account.budibaseUserId = user._id!
418
+ mocks.accounts.getAccountByTenantId.mockReturnValue(account)
419
+
420
+ const request = { userIds: [user._id!] }
421
+
422
+ const response = await api.users.bulkDeleteUsers(request)
423
+
424
+ expect(response.body.successful.length).toBe(0)
425
+ expect(response.body.unsuccessful.length).toBe(1)
426
+ expect(response.body.unsuccessful[0].reason).toBe(
427
+ "Account holder cannot be deleted"
428
+ )
429
+ expect(response.body.unsuccessful[0]._id).toBe(user._id)
430
+ expect(events.user.deleted).not.toBeCalled()
431
+ })
432
+
433
+ it("should be able to bulk delete users", async () => {
434
+ const account = structures.accounts.cloudAccount()
435
+ mocks.accounts.getAccountByTenantId.mockReturnValue(account)
436
+
437
+ const builder = structures.users.builderUser()
438
+ const admin = structures.users.adminUser()
439
+ const user = structures.users.user()
440
+ const createdUsers = await api.users.bulkCreateUsers([
441
+ builder,
442
+ admin,
443
+ user,
444
+ ])
445
+ const request = { userIds: createdUsers.successful.map(u => u._id!) }
446
+
447
+ const response = await api.users.bulkDeleteUsers(request)
448
+
449
+ expect(response.body.successful.length).toBe(3)
450
+ expect(response.body.unsuccessful.length).toBe(0)
451
+ expect(events.user.deleted).toBeCalledTimes(3)
452
+ expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
453
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(2)
454
+ })
455
+ })
456
+
457
+ describe("destroy", () => {
458
+ it("should be able to destroy a basic user", async () => {
459
+ const user = await config.createUser()
460
+ jest.clearAllMocks()
461
+
462
+ await api.users.deleteUser(user._id!)
463
+
464
+ expect(events.user.deleted).toBeCalledTimes(1)
465
+ expect(events.user.permissionBuilderRemoved).not.toBeCalled()
466
+ expect(events.user.permissionAdminRemoved).not.toBeCalled()
467
+ })
468
+
469
+ it("should be able to destroy an admin user", async () => {
470
+ const user = await config.createUser(structures.users.adminUser())
471
+ jest.clearAllMocks()
472
+
473
+ await api.users.deleteUser(user._id!)
474
+
475
+ expect(events.user.deleted).toBeCalledTimes(1)
476
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
477
+ expect(events.user.permissionAdminRemoved).toBeCalledTimes(1)
478
+ })
479
+
480
+ it("should be able to destroy a builder user", async () => {
481
+ const user = await config.createUser(structures.users.builderUser())
482
+ jest.clearAllMocks()
483
+
484
+ await api.users.deleteUser(user._id!)
485
+
486
+ expect(events.user.deleted).toBeCalledTimes(1)
487
+ expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
488
+ expect(events.user.permissionAdminRemoved).not.toBeCalled()
489
+ })
490
+
491
+ it("should not be able to destroy account owner", async () => {
492
+ const user = await config.createUser()
493
+ const account = structures.accounts.cloudAccount()
494
+ mocks.accounts.getAccount.mockReturnValueOnce(account)
495
+
496
+ const response = await api.users.deleteUser(user._id!, 400)
497
+
498
+ expect(response.body.message).toBe("Account holder cannot be deleted")
499
+ })
500
+
501
+ it("should not be able to destroy account owner as account owner", async () => {
502
+ const user = await config.defaultUser!
503
+ const account = structures.accounts.cloudAccount()
504
+ account.email = user.email
505
+ mocks.accounts.getAccount.mockReturnValueOnce(account)
506
+
507
+ const response = await api.users.deleteUser(user._id!, 400)
508
+
509
+ expect(response.body.message).toBe("Unable to delete self.")
510
+ })
511
+ })
512
+ })
@@ -12,6 +12,7 @@ const statusRoutes = require("./system/status")
12
12
  const selfRoutes = require("./global/self")
13
13
  const licenseRoutes = require("./global/license")
14
14
  const migrationRoutes = require("./system/migrations")
15
+ const accountRoutes = require("./system/accounts")
15
16
 
16
17
  let userGroupRoutes = api.groups
17
18
  exports.routes = [
@@ -29,4 +30,5 @@ exports.routes = [
29
30
  licenseRoutes,
30
31
  userGroupRoutes,
31
32
  migrationRoutes,
33
+ accountRoutes,
32
34
  ]
@@ -0,0 +1,19 @@
1
+ import Router from "@koa/router"
2
+ import * as controller from "../../controllers/system/accounts"
3
+ import { middleware } from "@budibase/backend-core"
4
+
5
+ const router = new Router()
6
+
7
+ router
8
+ .put(
9
+ "/api/system/accounts/:accountId/metadata",
10
+ middleware.internalApi,
11
+ controller.save
12
+ )
13
+ .delete(
14
+ "/api/system/accounts/:accountId/metadata",
15
+ middleware.internalApi,
16
+ controller.destroy
17
+ )
18
+
19
+ export = router
@@ -0,0 +1,57 @@
1
+ import { accounts } from "../../../../sdk"
2
+ import { TestConfiguration, structures, API } from "../../../../tests"
3
+ import { v4 as uuid } from "uuid"
4
+
5
+ describe("accounts", () => {
6
+ const config = new TestConfiguration()
7
+ const api = new API(config)
8
+
9
+ beforeAll(async () => {
10
+ await config.beforeAll()
11
+ })
12
+
13
+ afterAll(async () => {
14
+ await config.afterAll()
15
+ })
16
+
17
+ beforeEach(() => {
18
+ jest.clearAllMocks()
19
+ })
20
+
21
+ describe("metadata", () => {
22
+ describe("saveMetadata", () => {
23
+ it("saves account metadata", async () => {
24
+ let account = structures.accounts.account()
25
+
26
+ const response = await api.accounts.saveMetadata(account)
27
+
28
+ const id = accounts.formatAccountMetadataId(account.accountId)
29
+ const metadata = await accounts.getMetadata(id)
30
+ expect(response).toStrictEqual(metadata)
31
+ })
32
+ })
33
+
34
+ describe("destroyMetadata", () => {
35
+ it("destroys account metadata", async () => {
36
+ const account = structures.accounts.account()
37
+ await api.accounts.saveMetadata(account)
38
+
39
+ await api.accounts.destroyMetadata(account.accountId)
40
+
41
+ const deleted = await accounts.getMetadata(account.accountId)
42
+ expect(deleted).toBe(undefined)
43
+ })
44
+
45
+ it("destroys account metadata that does not exist", async () => {
46
+ const id = uuid()
47
+
48
+ const response = await api.accounts.destroyMetadata(id)
49
+
50
+ expect(response.status).toBe(404)
51
+ expect(response.body.message).toBe(
52
+ `id=${accounts.formatAccountMetadataId(id)} does not exist`
53
+ )
54
+ })
55
+ })
56
+ })
57
+ })
@@ -20,13 +20,13 @@ if (!LOADED && isDev() && !isTest()) {
20
20
  LOADED = true
21
21
  }
22
22
 
23
- function parseIntSafe(number) {
23
+ function parseIntSafe(number: any) {
24
24
  if (number) {
25
25
  return parseInt(number)
26
26
  }
27
27
  }
28
28
 
29
- module.exports = {
29
+ const env = {
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 @@ module.exports = {
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 @@ module.exports = {
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, value) {
65
+ _set(key: any, value: any) {
66
66
  process.env[key] = value
67
67
  module.exports[key] = value
68
68
  },
@@ -74,16 +74,17 @@ module.exports = {
74
74
  }
75
75
 
76
76
  // if some var haven't been set, define them
77
- if (!module.exports.APPS_URL) {
78
- module.exports.APPS_URL = isDev()
79
- ? "http://localhost:4001"
80
- : "http://app-service:4002"
77
+ if (!env.APPS_URL) {
78
+ env.APPS_URL = isDev() ? "http://localhost:4001" : "http://app-service:4002"
81
79
  }
82
80
 
83
81
  // clean up any environment variable edge cases
84
82
  for (let [key, value] of Object.entries(module.exports)) {
85
83
  // handle the edge case of "0" to disable an environment variable
86
84
  if (value === "0") {
87
- module.exports[key] = 0
85
+ // @ts-ignore
86
+ env[key] = 0
88
87
  }
89
88
  }
89
+
90
+ export = env
package/src/index.ts CHANGED
@@ -71,9 +71,7 @@ server.on("close", async () => {
71
71
  return
72
72
  }
73
73
  shuttingDown = true
74
- if (!env.isTest()) {
75
- console.log("Server Closed")
76
- }
74
+ console.log("Server Closed")
77
75
  await redis.shutdown()
78
76
  await events.shutdown()
79
77
  if (!env.isTest()) {
@@ -86,7 +84,7 @@ const shutdown = () => {
86
84
  server.destroy()
87
85
  }
88
86
 
89
- module.exports = server.listen(parseInt(env.PORT || 4002), async () => {
87
+ export = server.listen(parseInt(env.PORT || 4002), async () => {
90
88
  console.log(`Worker running on ${JSON.stringify(server.address())}`)
91
89
  await redis.init()
92
90
  })
@@ -100,3 +98,7 @@ process.on("uncaughtException", err => {
100
98
  process.on("SIGTERM", () => {
101
99
  shutdown()
102
100
  })
101
+
102
+ process.on("SIGINT", () => {
103
+ shutdown()
104
+ })