@budibase/worker 2.3.20 → 2.3.21-alpha.0
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.
- package/__mocks__/node-fetch.ts +23 -0
- package/jest-testcontainers-config.js +8 -0
- package/jest.config.ts +14 -18
- package/package.json +12 -8
- package/scripts/dev/manage.js +1 -0
- package/scripts/test.sh +12 -0
- package/src/api/controllers/global/auth.ts +109 -111
- package/src/api/controllers/global/configs.ts +150 -142
- package/src/api/controllers/global/self.ts +28 -44
- package/src/api/controllers/global/users.ts +211 -32
- package/src/api/controllers/system/accounts.ts +7 -5
- package/src/api/controllers/system/tenants.ts +4 -8
- package/src/api/index.ts +4 -20
- package/src/api/routes/global/auth.ts +10 -7
- package/src/api/routes/global/configs.ts +6 -12
- package/src/api/routes/global/tests/auditLogs.spec.ts +111 -0
- package/src/api/routes/global/tests/auth.spec.ts +217 -18
- package/src/api/routes/global/tests/configs.spec.ts +93 -65
- package/src/api/routes/global/tests/realEmail.spec.ts +1 -0
- package/src/api/routes/global/tests/roles.spec.ts +20 -14
- package/src/api/routes/global/tests/self.spec.ts +3 -4
- package/src/api/routes/global/tests/users.spec.ts +29 -28
- package/src/api/routes/global/users.ts +19 -14
- package/src/api/routes/index.ts +3 -0
- package/src/api/routes/system/tenants.ts +1 -1
- package/src/api/routes/system/tests/accounts.spec.ts +4 -4
- package/src/api/routes/system/tests/migrations.spec.ts +2 -2
- package/src/api/routes/system/tests/restore.spec.ts +2 -2
- package/src/api/routes/system/tests/status.spec.ts +5 -5
- package/src/db/index.ts +8 -2
- package/src/ddApm.ts +7 -0
- package/src/elasticApm.ts +10 -0
- package/src/environment.ts +4 -0
- package/src/index.ts +29 -8
- package/src/middleware/tests/tenancy.spec.ts +4 -4
- package/src/migrations/functions/globalInfoSyncUsers.ts +4 -3
- package/src/sdk/accounts/index.ts +2 -1
- package/src/sdk/accounts/{accounts.ts → metadata.ts} +0 -1
- package/src/sdk/auth/auth.ts +86 -0
- package/src/sdk/auth/index.ts +1 -0
- package/src/sdk/tenants/index.ts +1 -0
- package/src/sdk/tenants/tenants.ts +76 -0
- package/src/sdk/users/events.ts +4 -0
- package/src/sdk/users/index.ts +1 -0
- package/src/sdk/users/tests/users.spec.ts +76 -0
- package/src/sdk/users/users.ts +86 -53
- package/src/tests/TestConfiguration.ts +41 -62
- package/src/tests/api/auditLogs.ts +26 -0
- package/src/tests/api/auth.ts +44 -14
- package/src/tests/api/base.ts +2 -1
- package/src/tests/api/configs.ts +9 -1
- package/src/tests/api/email.ts +1 -0
- package/src/tests/api/index.ts +3 -0
- package/src/tests/api/restore.ts +1 -0
- package/src/tests/api/users.ts +2 -2
- package/src/tests/jestEnv.ts +2 -1
- package/src/tests/jestSetup.ts +10 -6
- package/src/tests/logging.ts +34 -0
- package/src/tests/structures/configs.ts +20 -13
- package/src/tests/structures/index.ts +0 -4
- package/src/utilities/email.ts +22 -68
- package/src/utilities/redis.ts +42 -2
- package/src/utilities/templates.ts +4 -9
- package/coverage/clover.xml +0 -2199
- package/coverage/coverage-final.json +0 -84
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -431
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +0 -934
- package/coverage/lcov-report/src/api/controllers/global/configs.ts.html +0 -1348
- package/coverage/lcov-report/src/api/controllers/global/email.ts.html +0 -196
- package/coverage/lcov-report/src/api/controllers/global/events.ts.html +0 -136
- package/coverage/lcov-report/src/api/controllers/global/index.html +0 -251
- package/coverage/lcov-report/src/api/controllers/global/license.ts.html +0 -187
- package/coverage/lcov-report/src/api/controllers/global/roles.ts.html +0 -283
- package/coverage/lcov-report/src/api/controllers/global/self.ts.html +0 -577
- package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +0 -316
- package/coverage/lcov-report/src/api/controllers/global/users.ts.html +0 -838
- package/coverage/lcov-report/src/api/controllers/global/workspaces.ts.html +0 -244
- package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +0 -148
- package/coverage/lcov-report/src/api/controllers/system/environment.ts.html +0 -124
- package/coverage/lcov-report/src/api/controllers/system/index.html +0 -191
- package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +0 -124
- package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +0 -124
- package/coverage/lcov-report/src/api/controllers/system/status.ts.html +0 -133
- package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +0 -154
- package/coverage/lcov-report/src/api/index.html +0 -116
- package/coverage/lcov-report/src/api/index.ts.html +0 -595
- package/coverage/lcov-report/src/api/routes/global/auth.ts.html +0 -349
- package/coverage/lcov-report/src/api/routes/global/configs.ts.html +0 -457
- package/coverage/lcov-report/src/api/routes/global/email.ts.html +0 -193
- package/coverage/lcov-report/src/api/routes/global/events.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/global/index.html +0 -251
- package/coverage/lcov-report/src/api/routes/global/license.ts.html +0 -124
- package/coverage/lcov-report/src/api/routes/global/roles.ts.html +0 -133
- package/coverage/lcov-report/src/api/routes/global/self.ts.html +0 -139
- package/coverage/lcov-report/src/api/routes/global/templates.ts.html +0 -196
- package/coverage/lcov-report/src/api/routes/global/users.ts.html +0 -475
- package/coverage/lcov-report/src/api/routes/global/workspaces.ts.html +0 -196
- package/coverage/lcov-report/src/api/routes/index.html +0 -116
- package/coverage/lcov-report/src/api/routes/index.ts.html +0 -202
- package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +0 -142
- package/coverage/lcov-report/src/api/routes/system/environment.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/system/index.html +0 -191
- package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +0 -142
- package/coverage/lcov-report/src/api/routes/system/restore.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/system/status.ts.html +0 -109
- package/coverage/lcov-report/src/api/routes/system/tenants.ts.html +0 -124
- package/coverage/lcov-report/src/api/routes/validation/index.html +0 -131
- package/coverage/lcov-report/src/api/routes/validation/index.ts.html +0 -88
- package/coverage/lcov-report/src/api/routes/validation/users.ts.html +0 -235
- package/coverage/lcov-report/src/constants/index.html +0 -116
- package/coverage/lcov-report/src/constants/index.ts.html +0 -637
- package/coverage/lcov-report/src/constants/templates/index.html +0 -116
- package/coverage/lcov-report/src/constants/templates/index.ts.html +0 -316
- package/coverage/lcov-report/src/db/index.html +0 -116
- package/coverage/lcov-report/src/db/index.ts.html +0 -115
- package/coverage/lcov-report/src/environment.ts.html +0 -388
- package/coverage/lcov-report/src/index.html +0 -131
- package/coverage/lcov-report/src/index.ts.html +0 -394
- package/coverage/lcov-report/src/middleware/cloudRestricted.ts.html +0 -139
- package/coverage/lcov-report/src/middleware/index.html +0 -116
- package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +0 -145
- package/coverage/lcov-report/src/migrations/functions/index.html +0 -116
- package/coverage/lcov-report/src/migrations/index.html +0 -116
- package/coverage/lcov-report/src/migrations/index.ts.html +0 -271
- package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +0 -262
- package/coverage/lcov-report/src/sdk/accounts/index.html +0 -131
- package/coverage/lcov-report/src/sdk/accounts/index.ts.html +0 -88
- package/coverage/lcov-report/src/sdk/index.html +0 -116
- package/coverage/lcov-report/src/sdk/index.ts.html +0 -106
- package/coverage/lcov-report/src/sdk/users/events.ts.html +0 -601
- package/coverage/lcov-report/src/sdk/users/index.html +0 -146
- package/coverage/lcov-report/src/sdk/users/index.ts.html +0 -88
- package/coverage/lcov-report/src/sdk/users/users.ts.html +0 -1999
- package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +0 -1075
- package/coverage/lcov-report/src/tests/api/accounts.ts.html +0 -160
- package/coverage/lcov-report/src/tests/api/auth.ts.html +0 -220
- package/coverage/lcov-report/src/tests/api/base.ts.html +0 -133
- package/coverage/lcov-report/src/tests/api/configs.ts.html +0 -226
- package/coverage/lcov-report/src/tests/api/email.ts.html +0 -148
- package/coverage/lcov-report/src/tests/api/environment.ts.html +0 -130
- package/coverage/lcov-report/src/tests/api/groups.ts.html +0 -163
- package/coverage/lcov-report/src/tests/api/index.html +0 -356
- package/coverage/lcov-report/src/tests/api/index.ts.html +0 -238
- package/coverage/lcov-report/src/tests/api/license.ts.html +0 -136
- package/coverage/lcov-report/src/tests/api/migrations.ts.html +0 -151
- package/coverage/lcov-report/src/tests/api/restore.ts.html +0 -127
- package/coverage/lcov-report/src/tests/api/roles.ts.html +0 -181
- package/coverage/lcov-report/src/tests/api/self.ts.html +0 -163
- package/coverage/lcov-report/src/tests/api/status.ts.html +0 -121
- package/coverage/lcov-report/src/tests/api/templates.ts.html +0 -175
- package/coverage/lcov-report/src/tests/api/tenants.ts.html +0 -130
- package/coverage/lcov-report/src/tests/api/users.ts.html +0 -514
- package/coverage/lcov-report/src/tests/controllers.ts.html +0 -100
- package/coverage/lcov-report/src/tests/index.html +0 -146
- package/coverage/lcov-report/src/tests/index.ts.html +0 -103
- package/coverage/lcov-report/src/tests/mocks/email.ts.html +0 -115
- package/coverage/lcov-report/src/tests/mocks/index.html +0 -131
- package/coverage/lcov-report/src/tests/mocks/index.ts.html +0 -106
- package/coverage/lcov-report/src/tests/structures/configs.ts.html +0 -313
- package/coverage/lcov-report/src/tests/structures/groups.ts.html +0 -118
- package/coverage/lcov-report/src/tests/structures/index.html +0 -161
- package/coverage/lcov-report/src/tests/structures/index.ts.html +0 -151
- package/coverage/lcov-report/src/tests/structures/users.ts.html +0 -196
- package/coverage/lcov-report/src/utilities/appService.ts.html +0 -208
- package/coverage/lcov-report/src/utilities/email.ts.html +0 -850
- package/coverage/lcov-report/src/utilities/fileSystem.ts.html +0 -100
- package/coverage/lcov-report/src/utilities/index.html +0 -206
- package/coverage/lcov-report/src/utilities/index.ts.html +0 -112
- package/coverage/lcov-report/src/utilities/redis.ts.html +0 -424
- package/coverage/lcov-report/src/utilities/templates.ts.html +0 -232
- package/coverage/lcov-report/src/utilities/users.ts.html +0 -133
- package/coverage/lcov.info +0 -4187
- package/src/tests/structures/users.ts +0 -37
|
@@ -30,7 +30,7 @@ describe("/api/global/self", () => {
|
|
|
30
30
|
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
|
31
31
|
expect(res.body._id).toBe(user._id)
|
|
32
32
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
33
|
-
expect(events.user.updated).toBeCalledWith(
|
|
33
|
+
expect(events.user.updated).toBeCalledWith(dbUser)
|
|
34
34
|
expect(events.user.passwordUpdated).not.toBeCalled()
|
|
35
35
|
})
|
|
36
36
|
|
|
@@ -44,12 +44,11 @@ describe("/api/global/self", () => {
|
|
|
44
44
|
const dbUser = await config.getUser(user.email)
|
|
45
45
|
user._rev = dbUser._rev
|
|
46
46
|
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
|
47
|
-
delete user.password
|
|
48
47
|
expect(res.body._id).toBe(user._id)
|
|
49
48
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
50
|
-
expect(events.user.updated).toBeCalledWith(
|
|
49
|
+
expect(events.user.updated).toBeCalledWith(dbUser)
|
|
51
50
|
expect(events.user.passwordUpdated).toBeCalledTimes(1)
|
|
52
|
-
expect(events.user.passwordUpdated).toBeCalledWith(
|
|
51
|
+
expect(events.user.passwordUpdated).toBeCalledWith(dbUser)
|
|
53
52
|
})
|
|
54
53
|
})
|
|
55
54
|
})
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { InviteUsersResponse, User } from "@budibase/types"
|
|
2
2
|
|
|
3
3
|
jest.mock("nodemailer")
|
|
4
|
-
import {
|
|
5
|
-
TestConfiguration,
|
|
6
|
-
mocks,
|
|
7
|
-
structures,
|
|
8
|
-
TENANT_1,
|
|
9
|
-
} from "../../../../tests"
|
|
4
|
+
import { TestConfiguration, mocks, structures } from "../../../../tests"
|
|
10
5
|
const sendMailMock = mocks.email.mock()
|
|
11
|
-
import { events, tenancy } from "@budibase/backend-core"
|
|
6
|
+
import { events, tenancy, accounts as _accounts } from "@budibase/backend-core"
|
|
7
|
+
|
|
8
|
+
const accounts = jest.mocked(_accounts)
|
|
12
9
|
|
|
13
10
|
describe("/api/global/users", () => {
|
|
14
11
|
const config = new TestConfiguration()
|
|
@@ -25,7 +22,7 @@ describe("/api/global/users", () => {
|
|
|
25
22
|
jest.clearAllMocks()
|
|
26
23
|
})
|
|
27
24
|
|
|
28
|
-
describe("invite", () => {
|
|
25
|
+
describe("POST /api/global/users/invite", () => {
|
|
29
26
|
it("should be able to generate an invitation", async () => {
|
|
30
27
|
const email = structures.users.newEmail()
|
|
31
28
|
const { code, res } = await config.api.users.sendUserInvite(
|
|
@@ -33,7 +30,11 @@ describe("/api/global/users", () => {
|
|
|
33
30
|
email
|
|
34
31
|
)
|
|
35
32
|
|
|
36
|
-
expect(res.body).
|
|
33
|
+
expect(res.body?.message).toBe("Invitation has been sent.")
|
|
34
|
+
expect(res.body?.unsuccessful.length).toBe(0)
|
|
35
|
+
expect(res.body?.successful.length).toBe(1)
|
|
36
|
+
expect(res.body?.successful[0].email).toBe(email)
|
|
37
|
+
|
|
37
38
|
expect(sendMailMock).toHaveBeenCalled()
|
|
38
39
|
expect(code).toBeDefined()
|
|
39
40
|
expect(events.user.invited).toBeCalledTimes(1)
|
|
@@ -42,7 +43,7 @@ describe("/api/global/users", () => {
|
|
|
42
43
|
it("should not be able to generate an invitation for existing user", async () => {
|
|
43
44
|
const { code, res } = await config.api.users.sendUserInvite(
|
|
44
45
|
sendMailMock,
|
|
45
|
-
config.
|
|
46
|
+
config.user!.email,
|
|
46
47
|
400
|
|
47
48
|
)
|
|
48
49
|
|
|
@@ -70,7 +71,7 @@ describe("/api/global/users", () => {
|
|
|
70
71
|
})
|
|
71
72
|
})
|
|
72
73
|
|
|
73
|
-
describe("
|
|
74
|
+
describe("POST /api/global/users/multi/invite", () => {
|
|
74
75
|
it("should be able to generate an invitation", async () => {
|
|
75
76
|
const newUserInvite = () => ({
|
|
76
77
|
email: structures.users.newEmail(),
|
|
@@ -88,7 +89,7 @@ describe("/api/global/users", () => {
|
|
|
88
89
|
})
|
|
89
90
|
|
|
90
91
|
it("should not be able to generate an invitation for existing user", async () => {
|
|
91
|
-
const request = [{ email: config.
|
|
92
|
+
const request = [{ email: config.user!.email, userInfo: {} }]
|
|
92
93
|
|
|
93
94
|
const res = await config.api.users.sendMultiUserInvite(request)
|
|
94
95
|
|
|
@@ -101,7 +102,7 @@ describe("/api/global/users", () => {
|
|
|
101
102
|
})
|
|
102
103
|
})
|
|
103
104
|
|
|
104
|
-
describe("bulk
|
|
105
|
+
describe("POST /api/global/users/bulk", () => {
|
|
105
106
|
it("should ignore users existing in the same tenant", async () => {
|
|
106
107
|
const user = await config.createUser()
|
|
107
108
|
jest.clearAllMocks()
|
|
@@ -118,7 +119,7 @@ describe("/api/global/users", () => {
|
|
|
118
119
|
const user = await config.createUser()
|
|
119
120
|
jest.clearAllMocks()
|
|
120
121
|
|
|
121
|
-
await tenancy.doInTenant(
|
|
122
|
+
await tenancy.doInTenant(config.getTenantId(), async () => {
|
|
122
123
|
const response = await config.api.users.bulkCreateUsers([user])
|
|
123
124
|
|
|
124
125
|
expect(response.created?.successful.length).toBe(0)
|
|
@@ -164,7 +165,7 @@ describe("/api/global/users", () => {
|
|
|
164
165
|
})
|
|
165
166
|
})
|
|
166
167
|
|
|
167
|
-
describe("
|
|
168
|
+
describe("POST /api/global/users", () => {
|
|
168
169
|
it("should be able to create a basic user", async () => {
|
|
169
170
|
const user = structures.users.user()
|
|
170
171
|
|
|
@@ -231,7 +232,7 @@ describe("/api/global/users", () => {
|
|
|
231
232
|
const user = await config.createUser()
|
|
232
233
|
jest.clearAllMocks()
|
|
233
234
|
|
|
234
|
-
await tenancy.doInTenant(
|
|
235
|
+
await tenancy.doInTenant(config.getTenantId(), async () => {
|
|
235
236
|
delete user._id
|
|
236
237
|
const response = await config.api.users.saveUser(user, 400)
|
|
237
238
|
|
|
@@ -243,7 +244,7 @@ describe("/api/global/users", () => {
|
|
|
243
244
|
it("should not be able to create user with the same email as an account", async () => {
|
|
244
245
|
const user = structures.users.user()
|
|
245
246
|
const account = structures.accounts.cloudAccount()
|
|
246
|
-
|
|
247
|
+
accounts.getAccount.mockReturnValueOnce(Promise.resolve(account))
|
|
247
248
|
|
|
248
249
|
const response = await config.api.users.saveUser(user, 400)
|
|
249
250
|
|
|
@@ -284,7 +285,7 @@ describe("/api/global/users", () => {
|
|
|
284
285
|
})
|
|
285
286
|
})
|
|
286
287
|
|
|
287
|
-
describe("update", () => {
|
|
288
|
+
describe("POST /api/global/users (update)", () => {
|
|
288
289
|
it("should be able to update a basic user", async () => {
|
|
289
290
|
const user = await config.createUser()
|
|
290
291
|
jest.clearAllMocks()
|
|
@@ -299,7 +300,7 @@ describe("/api/global/users", () => {
|
|
|
299
300
|
})
|
|
300
301
|
|
|
301
302
|
it("should not allow a user to update their own admin/builder status", async () => {
|
|
302
|
-
const user = (await config.api.users.getUser(config.
|
|
303
|
+
const user = (await config.api.users.getUser(config.user?._id!))
|
|
303
304
|
.body as User
|
|
304
305
|
await config.api.users.saveUser({
|
|
305
306
|
...user,
|
|
@@ -444,7 +445,7 @@ describe("/api/global/users", () => {
|
|
|
444
445
|
})
|
|
445
446
|
|
|
446
447
|
it("should not be able to update email address", async () => {
|
|
447
|
-
const email =
|
|
448
|
+
const email = structures.email()
|
|
448
449
|
const user = await config.createUser(structures.users.user({ email }))
|
|
449
450
|
user.email = "new@test.com"
|
|
450
451
|
|
|
@@ -469,9 +470,9 @@ describe("/api/global/users", () => {
|
|
|
469
470
|
})
|
|
470
471
|
})
|
|
471
472
|
|
|
472
|
-
describe("bulk (delete)", () => {
|
|
473
|
+
describe("POST /api/global/users/bulk (delete)", () => {
|
|
473
474
|
it("should not be able to bulk delete current user", async () => {
|
|
474
|
-
const user = await config.
|
|
475
|
+
const user = await config.user!
|
|
475
476
|
|
|
476
477
|
const response = await config.api.users.bulkDeleteUsers([user._id!], 400)
|
|
477
478
|
|
|
@@ -483,7 +484,7 @@ describe("/api/global/users", () => {
|
|
|
483
484
|
const user = await config.createUser()
|
|
484
485
|
const account = structures.accounts.cloudAccount()
|
|
485
486
|
account.budibaseUserId = user._id!
|
|
486
|
-
|
|
487
|
+
accounts.getAccountByTenantId.mockReturnValue(Promise.resolve(account))
|
|
487
488
|
|
|
488
489
|
const response = await config.api.users.bulkDeleteUsers([user._id!])
|
|
489
490
|
|
|
@@ -498,7 +499,7 @@ describe("/api/global/users", () => {
|
|
|
498
499
|
|
|
499
500
|
it("should be able to bulk delete users", async () => {
|
|
500
501
|
const account = structures.accounts.cloudAccount()
|
|
501
|
-
|
|
502
|
+
accounts.getAccountByTenantId.mockReturnValue(Promise.resolve(account))
|
|
502
503
|
|
|
503
504
|
const builder = structures.users.builderUser()
|
|
504
505
|
const admin = structures.users.adminUser()
|
|
@@ -522,7 +523,7 @@ describe("/api/global/users", () => {
|
|
|
522
523
|
})
|
|
523
524
|
})
|
|
524
525
|
|
|
525
|
-
describe("
|
|
526
|
+
describe("DELETE /api/global/users/:userId", () => {
|
|
526
527
|
it("should be able to destroy a basic user", async () => {
|
|
527
528
|
const user = await config.createUser()
|
|
528
529
|
jest.clearAllMocks()
|
|
@@ -559,7 +560,7 @@ describe("/api/global/users", () => {
|
|
|
559
560
|
it("should not be able to destroy account owner", async () => {
|
|
560
561
|
const user = await config.createUser()
|
|
561
562
|
const account = structures.accounts.cloudAccount()
|
|
562
|
-
|
|
563
|
+
accounts.getAccount.mockReturnValueOnce(Promise.resolve(account))
|
|
563
564
|
|
|
564
565
|
const response = await config.api.users.deleteUser(user._id!, 400)
|
|
565
566
|
|
|
@@ -567,10 +568,10 @@ describe("/api/global/users", () => {
|
|
|
567
568
|
})
|
|
568
569
|
|
|
569
570
|
it("should not be able to destroy account owner as account owner", async () => {
|
|
570
|
-
const user = await config.
|
|
571
|
+
const user = await config.user!
|
|
571
572
|
const account = structures.accounts.cloudAccount()
|
|
572
573
|
account.email = user.email
|
|
573
|
-
|
|
574
|
+
accounts.getAccount.mockReturnValueOnce(Promise.resolve(account))
|
|
574
575
|
|
|
575
576
|
const response = await config.api.users.deleteUser(user._id!, 400)
|
|
576
577
|
|
|
@@ -38,13 +38,6 @@ function buildInviteMultipleValidation() {
|
|
|
38
38
|
))
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function buildInviteLookupValidation() {
|
|
42
|
-
// prettier-ignore
|
|
43
|
-
return auth.joiValidator.params(Joi.object({
|
|
44
|
-
code: Joi.string().required()
|
|
45
|
-
}).unknown(true))
|
|
46
|
-
}
|
|
47
|
-
|
|
48
41
|
const createUserAdminOnly = (ctx: any, next: any) => {
|
|
49
42
|
if (!ctx.request.body._id) {
|
|
50
43
|
return auth.adminOnly(ctx, next)
|
|
@@ -57,8 +50,8 @@ function buildInviteAcceptValidation() {
|
|
|
57
50
|
// prettier-ignore
|
|
58
51
|
return auth.joiValidator.body(Joi.object({
|
|
59
52
|
inviteCode: Joi.string().required(),
|
|
60
|
-
password: Joi.string().
|
|
61
|
-
firstName: Joi.string().
|
|
53
|
+
password: Joi.string().optional(),
|
|
54
|
+
firstName: Joi.string().optional(),
|
|
62
55
|
lastName: Joi.string().optional(),
|
|
63
56
|
}).required().unknown(true))
|
|
64
57
|
}
|
|
@@ -88,22 +81,34 @@ router
|
|
|
88
81
|
.get("/api/global/roles/:appId")
|
|
89
82
|
.post(
|
|
90
83
|
"/api/global/users/invite",
|
|
91
|
-
auth.
|
|
84
|
+
auth.builderOrAdmin,
|
|
92
85
|
buildInviteValidation(),
|
|
93
86
|
controller.invite
|
|
94
87
|
)
|
|
88
|
+
.post(
|
|
89
|
+
"/api/global/users/onboard",
|
|
90
|
+
auth.builderOrAdmin,
|
|
91
|
+
buildInviteMultipleValidation(),
|
|
92
|
+
controller.onboardUsers
|
|
93
|
+
)
|
|
95
94
|
.post(
|
|
96
95
|
"/api/global/users/multi/invite",
|
|
97
|
-
auth.
|
|
96
|
+
auth.builderOrAdmin,
|
|
98
97
|
buildInviteMultipleValidation(),
|
|
99
98
|
controller.inviteMultiple
|
|
100
99
|
)
|
|
101
100
|
|
|
102
101
|
// non-global endpoints
|
|
102
|
+
.get("/api/global/users/invite/:code", controller.checkInvite)
|
|
103
|
+
.post(
|
|
104
|
+
"/api/global/users/invite/update/:code",
|
|
105
|
+
auth.builderOrAdmin,
|
|
106
|
+
controller.updateInvite
|
|
107
|
+
)
|
|
103
108
|
.get(
|
|
104
|
-
"/api/global/users/
|
|
105
|
-
|
|
106
|
-
controller.
|
|
109
|
+
"/api/global/users/invites",
|
|
110
|
+
auth.builderOrAdmin,
|
|
111
|
+
controller.getUserInvites
|
|
107
112
|
)
|
|
108
113
|
.post(
|
|
109
114
|
"/api/global/users/invite/accept",
|
package/src/api/routes/index.ts
CHANGED
|
@@ -18,6 +18,8 @@ import accountRoutes from "./system/accounts"
|
|
|
18
18
|
import restoreRoutes from "./system/restore"
|
|
19
19
|
|
|
20
20
|
let userGroupRoutes = api.groups
|
|
21
|
+
let auditLogRoutes = api.auditLogs
|
|
22
|
+
|
|
21
23
|
export const routes: Router[] = [
|
|
22
24
|
configRoutes,
|
|
23
25
|
userRoutes,
|
|
@@ -32,6 +34,7 @@ export const routes: Router[] = [
|
|
|
32
34
|
selfRoutes,
|
|
33
35
|
licenseRoutes,
|
|
34
36
|
userGroupRoutes,
|
|
37
|
+
auditLogRoutes,
|
|
35
38
|
migrationRoutes,
|
|
36
39
|
accountRoutes,
|
|
37
40
|
restoreRoutes,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as accounts from "../../../../sdk/accounts"
|
|
2
2
|
import { TestConfiguration, structures } from "../../../../tests"
|
|
3
3
|
import { v4 as uuid } from "uuid"
|
|
4
4
|
|
|
@@ -24,8 +24,8 @@ describe("accounts", () => {
|
|
|
24
24
|
|
|
25
25
|
const response = await config.api.accounts.saveMetadata(account)
|
|
26
26
|
|
|
27
|
-
const id =
|
|
28
|
-
const metadata = await
|
|
27
|
+
const id = accounts.metadata.formatAccountMetadataId(account.accountId)
|
|
28
|
+
const metadata = await accounts.metadata.getMetadata(id)
|
|
29
29
|
expect(response).toStrictEqual(metadata)
|
|
30
30
|
})
|
|
31
31
|
})
|
|
@@ -37,7 +37,7 @@ describe("accounts", () => {
|
|
|
37
37
|
|
|
38
38
|
await config.api.accounts.destroyMetadata(account.accountId)
|
|
39
39
|
|
|
40
|
-
const deleted = await
|
|
40
|
+
const deleted = await accounts.metadata.getMetadata(account.accountId)
|
|
41
41
|
expect(deleted).toBe(undefined)
|
|
42
42
|
})
|
|
43
43
|
|
|
@@ -30,7 +30,7 @@ describe("/api/system/migrations", () => {
|
|
|
30
30
|
headers: {},
|
|
31
31
|
status: 403,
|
|
32
32
|
})
|
|
33
|
-
expect(res.
|
|
33
|
+
expect(res.body).toEqual({ message: "Unauthorized", status: 403 })
|
|
34
34
|
expect(migrateFn).toBeCalledTimes(0)
|
|
35
35
|
})
|
|
36
36
|
|
|
@@ -47,7 +47,7 @@ describe("/api/system/migrations", () => {
|
|
|
47
47
|
headers: {},
|
|
48
48
|
status: 403,
|
|
49
49
|
})
|
|
50
|
-
expect(res.
|
|
50
|
+
expect(res.body).toEqual({ message: "Unauthorized", status: 403 })
|
|
51
51
|
})
|
|
52
52
|
|
|
53
53
|
it("returns definitions", async () => {
|
|
@@ -25,12 +25,12 @@ describe("/api/system/restore", () => {
|
|
|
25
25
|
})
|
|
26
26
|
|
|
27
27
|
it("restores in self host", async () => {
|
|
28
|
-
config.
|
|
28
|
+
config.selfHosted()
|
|
29
29
|
const res = await config.api.restore.restored()
|
|
30
30
|
expect(res.body).toEqual({
|
|
31
31
|
message: "System prepared after restore.",
|
|
32
32
|
})
|
|
33
|
-
config.
|
|
33
|
+
config.cloudHosted()
|
|
34
34
|
})
|
|
35
35
|
})
|
|
36
36
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TestConfiguration } from "../../../../tests"
|
|
2
|
-
import { accounts } from "@budibase/backend-core"
|
|
3
|
-
|
|
2
|
+
import { accounts as _accounts } from "@budibase/backend-core"
|
|
3
|
+
const accounts = jest.mocked(_accounts)
|
|
4
4
|
|
|
5
5
|
describe("/api/system/status", () => {
|
|
6
6
|
const config = new TestConfiguration()
|
|
@@ -19,7 +19,7 @@ describe("/api/system/status", () => {
|
|
|
19
19
|
|
|
20
20
|
describe("GET /api/system/status", () => {
|
|
21
21
|
it("returns status in self host", async () => {
|
|
22
|
-
config.
|
|
22
|
+
config.selfHosted()
|
|
23
23
|
const res = await config.api.status.getStatus()
|
|
24
24
|
expect(res.body).toEqual({
|
|
25
25
|
health: {
|
|
@@ -27,7 +27,7 @@ describe("/api/system/status", () => {
|
|
|
27
27
|
},
|
|
28
28
|
})
|
|
29
29
|
expect(accounts.getStatus).toBeCalledTimes(0)
|
|
30
|
-
config.
|
|
30
|
+
config.cloudHosted()
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
it("returns status in cloud", async () => {
|
|
@@ -37,7 +37,7 @@ describe("/api/system/status", () => {
|
|
|
37
37
|
},
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
accounts.getStatus.mockReturnValueOnce(Promise.resolve(value))
|
|
41
41
|
|
|
42
42
|
const res = await config.api.status.getStatus()
|
|
43
43
|
|
package/src/db/index.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import * as core from "@budibase/backend-core"
|
|
2
2
|
import env from "../environment"
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
const dbConfig: any = {
|
|
4
|
+
export function init() {
|
|
5
|
+
const dbConfig: any = {
|
|
6
|
+
replication: true,
|
|
7
|
+
find: true,
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
if (env.isTest() && !env.COUCH_DB_URL) {
|
|
7
11
|
dbConfig.inMemory = true
|
|
12
|
+
dbConfig.allDbs = true
|
|
8
13
|
}
|
|
14
|
+
|
|
9
15
|
core.init({ db: dbConfig })
|
|
10
16
|
}
|
package/src/ddApm.ts
ADDED
package/src/environment.ts
CHANGED
|
@@ -65,6 +65,10 @@ const environment = {
|
|
|
65
65
|
CHECKLIST_CACHE_TTL: parseIntSafe(process.env.CHECKLIST_CACHE_TTL) || 3600,
|
|
66
66
|
SESSION_UPDATE_PERIOD: process.env.SESSION_UPDATE_PERIOD,
|
|
67
67
|
ENCRYPTED_TEST_PUBLIC_API_KEY: process.env.ENCRYPTED_TEST_PUBLIC_API_KEY,
|
|
68
|
+
/**
|
|
69
|
+
* Mock the email service in use - links to ethereal hosted emails are logged instead.
|
|
70
|
+
*/
|
|
71
|
+
ENABLE_EMAIL_TEST_MODE: process.env.ENABLE_EMAIL_TEST_MODE,
|
|
68
72
|
_set(key: any, value: any) {
|
|
69
73
|
process.env[key] = value
|
|
70
74
|
// @ts-ignore
|
package/src/index.ts
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
if (process.env.DD_APM_ENABLED) {
|
|
2
|
+
require("./ddApm")
|
|
3
|
+
}
|
|
3
4
|
|
|
4
|
-
// enable APM if configured
|
|
5
5
|
if (process.env.ELASTIC_APM_ENABLED) {
|
|
6
|
-
|
|
7
|
-
serviceName: process.env.SERVICE,
|
|
8
|
-
environment: process.env.BUDIBASE_ENVIRONMENT,
|
|
9
|
-
})
|
|
6
|
+
require("./elasticApm")
|
|
10
7
|
}
|
|
11
8
|
|
|
9
|
+
// need to load environment first
|
|
10
|
+
import env from "./environment"
|
|
12
11
|
import { Scope } from "@sentry/node"
|
|
13
12
|
import { Event } from "@sentry/types/dist/event"
|
|
14
13
|
import Application from "koa"
|
|
15
14
|
import { bootstrap } from "global-agent"
|
|
16
15
|
import * as db from "./db"
|
|
17
|
-
import {
|
|
16
|
+
import { sdk as proSdk } from "@budibase/pro"
|
|
17
|
+
import {
|
|
18
|
+
auth,
|
|
19
|
+
logging,
|
|
20
|
+
events,
|
|
21
|
+
middleware,
|
|
22
|
+
queue,
|
|
23
|
+
env as coreEnv,
|
|
24
|
+
} from "@budibase/backend-core"
|
|
18
25
|
db.init()
|
|
19
26
|
import Koa from "koa"
|
|
20
27
|
import koaBody from "koa-body"
|
|
@@ -24,8 +31,20 @@ import * as redis from "./utilities/redis"
|
|
|
24
31
|
const Sentry = require("@sentry/node")
|
|
25
32
|
const koaSession = require("koa-session")
|
|
26
33
|
const logger = require("koa-pino-logger")
|
|
34
|
+
const { userAgent } = require("koa-useragent")
|
|
35
|
+
|
|
27
36
|
import destroyable from "server-destroy"
|
|
28
37
|
|
|
38
|
+
// configure events to use the pro audit log write
|
|
39
|
+
// can't integrate directly into backend-core due to cyclic issues
|
|
40
|
+
events.processors.init(proSdk.auditLogs.write)
|
|
41
|
+
|
|
42
|
+
if (coreEnv.ENABLE_SSO_MAINTENANCE_MODE) {
|
|
43
|
+
console.warn(
|
|
44
|
+
"Warning: ENABLE_SSO_MAINTENANCE_MODE is set. It is recommended this flag is disabled if maintenance is not in progress"
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
29
48
|
// this will setup http and https proxies form env variables
|
|
30
49
|
bootstrap()
|
|
31
50
|
|
|
@@ -38,6 +57,7 @@ app.use(koaBody({ multipart: true }))
|
|
|
38
57
|
app.use(koaSession(app))
|
|
39
58
|
app.use(middleware.logging)
|
|
40
59
|
app.use(logger(logging.pinoSettings()))
|
|
60
|
+
app.use(userAgent)
|
|
41
61
|
|
|
42
62
|
// authentication
|
|
43
63
|
app.use(auth.passport.initialize())
|
|
@@ -73,6 +93,7 @@ server.on("close", async () => {
|
|
|
73
93
|
console.log("Server Closed")
|
|
74
94
|
await redis.shutdown()
|
|
75
95
|
await events.shutdown()
|
|
96
|
+
await queue.shutdown()
|
|
76
97
|
if (!env.isTest()) {
|
|
77
98
|
process.exit(errCode)
|
|
78
99
|
}
|
|
@@ -24,7 +24,7 @@ describe("tenancy middleware", () => {
|
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
it("should get tenant id from header", async () => {
|
|
27
|
-
const tenantId = structures.
|
|
27
|
+
const tenantId = structures.tenant.id()
|
|
28
28
|
const headers = {
|
|
29
29
|
[constants.Header.TENANT_ID]: tenantId,
|
|
30
30
|
}
|
|
@@ -35,7 +35,7 @@ describe("tenancy middleware", () => {
|
|
|
35
35
|
})
|
|
36
36
|
|
|
37
37
|
it("should get tenant id from query param", async () => {
|
|
38
|
-
const tenantId = structures.
|
|
38
|
+
const tenantId = structures.tenant.id()
|
|
39
39
|
const res = await config.request.get(
|
|
40
40
|
`/api/global/configs/checklist?tenantId=${tenantId}`
|
|
41
41
|
)
|
|
@@ -43,7 +43,7 @@ describe("tenancy middleware", () => {
|
|
|
43
43
|
})
|
|
44
44
|
|
|
45
45
|
it("should get tenant id from subdomain", async () => {
|
|
46
|
-
const tenantId = structures.
|
|
46
|
+
const tenantId = structures.tenant.id()
|
|
47
47
|
const headers = {
|
|
48
48
|
host: `${tenantId}.localhost:10000`,
|
|
49
49
|
}
|
|
@@ -67,7 +67,7 @@ describe("tenancy middleware", () => {
|
|
|
67
67
|
it("should throw when no tenant id is found", async () => {
|
|
68
68
|
const res = await config.request.get(`/api/global/configs/checklist`)
|
|
69
69
|
expect(res.status).toBe(403)
|
|
70
|
-
expect(res.
|
|
70
|
+
expect(res.body).toEqual({ message: "Tenant id not set", status: 403 })
|
|
71
71
|
expect(res.headers[constants.Header.TENANT_ID]).toBe(undefined)
|
|
72
72
|
})
|
|
73
73
|
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { User } from "@budibase/types"
|
|
2
|
-
import
|
|
2
|
+
import * as usersSdk from "../../sdk/users"
|
|
3
|
+
import { platform } from "@budibase/backend-core"
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Date:
|
|
@@ -9,11 +10,11 @@ import sdk from "../../sdk"
|
|
|
9
10
|
* Re-sync the global-db users to the global-info db users
|
|
10
11
|
*/
|
|
11
12
|
export const run = async (globalDb: any) => {
|
|
12
|
-
const users = (await
|
|
13
|
+
const users = (await usersSdk.allUsers()) as User[]
|
|
13
14
|
const promises = []
|
|
14
15
|
for (let user of users) {
|
|
15
16
|
promises.push(
|
|
16
|
-
|
|
17
|
+
platform.users.addUser(user.tenantId, user._id as string, user.email)
|
|
17
18
|
)
|
|
18
19
|
}
|
|
19
20
|
await Promise.all(promises)
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * as metadata from "./metadata"
|
|
2
|
+
export { accounts as api } from "@budibase/backend-core"
|