@budibase/worker 2.1.40-alpha.5 → 2.1.41
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/package.json +24 -14
- package/{src/tests/jestSetup.ts → scripts/jestSetup.js} +3 -12
- package/scripts/localdomain.js +7 -33
- package/src/api/controllers/global/auth.ts +43 -51
- package/src/api/controllers/global/{configs.ts → configs.js} +114 -119
- package/src/api/controllers/global/{email.ts → email.js} +5 -6
- package/src/api/controllers/global/roles.js +68 -0
- package/src/api/controllers/global/self.ts +2 -2
- package/src/api/controllers/global/users.ts +2 -4
- package/src/api/controllers/global/{workspaces.ts → workspaces.js} +18 -15
- package/src/api/controllers/system/{environment.ts → environment.js} +2 -3
- package/src/api/controllers/system/restore.ts +1 -1
- package/src/api/controllers/system/{status.ts → status.js} +3 -4
- package/src/api/controllers/system/tenants.ts +51 -8
- package/src/api/index.ts +8 -31
- package/src/api/routes/global/{auth.ts → auth.js} +48 -31
- package/src/api/routes/global/{configs.ts → configs.js} +23 -22
- package/src/api/routes/global/{email.ts → email.js} +10 -9
- package/src/api/routes/global/license.ts +1 -1
- package/src/api/routes/global/roles.js +12 -0
- package/src/api/routes/global/self.ts +2 -2
- package/src/api/routes/global/templates.ts +4 -4
- package/src/api/routes/global/tests/auth.spec.ts +64 -134
- package/src/api/routes/global/tests/configs.spec.ts +35 -34
- package/src/api/routes/global/tests/email.spec.ts +3 -4
- package/src/api/routes/global/tests/realEmail.spec.ts +3 -2
- package/src/api/routes/global/tests/self.spec.ts +4 -3
- package/src/api/routes/global/tests/users.spec.ts +59 -51
- package/src/api/routes/global/{users.ts → users.js} +32 -26
- package/src/api/routes/global/{workspaces.ts → workspaces.js} +10 -9
- package/src/api/routes/index.ts +1 -2
- package/src/api/routes/system/accounts.ts +1 -1
- package/src/api/routes/system/environment.js +8 -0
- package/src/api/routes/system/migrations.ts +1 -1
- package/src/api/routes/system/restore.ts +1 -1
- package/src/api/routes/system/status.js +8 -0
- package/src/api/routes/system/tenants.js +12 -0
- package/src/api/routes/system/tests/accounts.spec.ts +6 -5
- package/src/api/routes/validation/users.ts +3 -3
- package/src/constants/{index.ts → index.js} +64 -57
- package/src/constants/templates/{index.ts → index.js} +19 -23
- package/src/db/index.js +11 -0
- package/src/environment.ts +7 -9
- package/src/index.ts +16 -15
- package/src/middleware/{cloudRestricted.ts → cloudRestricted.js} +4 -5
- package/src/tests/TestConfiguration.ts +50 -99
- package/src/tests/api/accounts.ts +8 -5
- package/src/tests/api/auth.ts +6 -3
- package/src/tests/api/configs.ts +8 -15
- package/src/tests/api/email.ts +6 -3
- package/src/tests/api/index.ts +0 -15
- package/src/tests/api/self.ts +6 -11
- package/src/tests/api/users.ts +8 -40
- package/src/tests/controllers.js +7 -0
- package/src/tests/index.ts +1 -5
- package/src/tests/structures/accounts.ts +24 -0
- package/src/tests/structures/{configs.ts → configs.js} +11 -11
- package/src/tests/structures/index.ts +3 -5
- package/src/tests/structures/users.ts +0 -1
- package/src/utilities/appService.js +33 -0
- package/src/utilities/{email.ts → email.js} +45 -78
- package/src/utilities/fileSystem.js +5 -0
- package/src/utilities/{index.ts → index.js} +1 -1
- package/src/utilities/{redis.ts → redis.js} +24 -29
- package/src/utilities/templates.js +49 -0
- package/src/utilities/users.js +17 -0
- package/tsconfig.build.json +3 -2
- package/tsconfig.json +1 -3
- package/__mocks__/aws-sdk.ts +0 -15
- package/__mocks__/oauth.ts +0 -57
- package/coverage/clover.xml +0 -2153
- package/coverage/coverage-final.json +0 -78
- 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 -925
- package/coverage/lcov-report/src/api/controllers/global/configs.ts.html +0 -1405
- package/coverage/lcov-report/src/api/controllers/global/email.ts.html +0 -196
- package/coverage/lcov-report/src/api/controllers/global/index.html +0 -236
- 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 -796
- 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 -583
- 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/index.html +0 -236
- 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 -409
- 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 -196
- 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 -613
- 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 -373
- 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 -577
- 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 -1903
- package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +0 -1051
- 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/index.html +0 -296
- package/coverage/lcov-report/src/tests/api/index.ts.html +0 -205
- 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/self.ts.html +0 -163
- package/coverage/lcov-report/src/tests/api/status.ts.html +0 -121
- package/coverage/lcov-report/src/tests/api/tenants.ts.html +0 -130
- package/coverage/lcov-report/src/tests/api/users.ts.html +0 -511
- 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 -139
- package/coverage/lcov-report/src/tests/mocks/email.js.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 -181
- 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 -3958
- package/jest.config.ts +0 -29
- package/src/api/controllers/global/roles.ts +0 -66
- package/src/api/routes/global/roles.ts +0 -16
- package/src/api/routes/global/tests/license.spec.ts +0 -31
- package/src/api/routes/global/tests/roles.spec.ts +0 -27
- package/src/api/routes/global/tests/templates.spec.ts +0 -35
- package/src/api/routes/global/tests/workspaces.spec.ts +0 -29
- package/src/api/routes/system/environment.ts +0 -8
- package/src/api/routes/system/status.ts +0 -8
- package/src/api/routes/system/tenants.ts +0 -13
- package/src/api/routes/system/tests/environment.spec.ts +0 -29
- package/src/api/routes/system/tests/migrations.spec.ts +0 -63
- package/src/api/routes/system/tests/restore.spec.ts +0 -36
- package/src/api/routes/system/tests/status.spec.ts +0 -48
- package/src/api/routes/system/tests/tenants.spec.ts +0 -61
- package/src/db/index.ts +0 -10
- package/src/middleware/tests/tenancy.spec.ts +0 -73
- package/src/tests/api/base.ts +0 -16
- package/src/tests/api/environment.ts +0 -15
- package/src/tests/api/migrations.ts +0 -22
- package/src/tests/api/restore.ts +0 -14
- package/src/tests/api/status.ts +0 -12
- package/src/tests/api/tenants.ts +0 -15
- package/src/tests/controllers.ts +0 -5
- package/src/utilities/appService.ts +0 -32
- package/src/utilities/fileSystem.ts +0 -5
- package/src/utilities/templates.ts +0 -49
- package/src/utilities/users.ts +0 -16
|
@@ -6,12 +6,14 @@ import {
|
|
|
6
6
|
mocks,
|
|
7
7
|
structures,
|
|
8
8
|
TENANT_1,
|
|
9
|
+
API,
|
|
9
10
|
} from "../../../../tests"
|
|
10
11
|
const sendMailMock = mocks.email.mock()
|
|
11
12
|
import { events, tenancy } from "@budibase/backend-core"
|
|
12
13
|
|
|
13
14
|
describe("/api/global/users", () => {
|
|
14
15
|
const config = new TestConfiguration()
|
|
16
|
+
const api = new API(config)
|
|
15
17
|
|
|
16
18
|
beforeAll(async () => {
|
|
17
19
|
await config.beforeAll()
|
|
@@ -28,10 +30,7 @@ describe("/api/global/users", () => {
|
|
|
28
30
|
describe("invite", () => {
|
|
29
31
|
it("should be able to generate an invitation", async () => {
|
|
30
32
|
const email = structures.users.newEmail()
|
|
31
|
-
const { code, res } = await
|
|
32
|
-
sendMailMock,
|
|
33
|
-
email
|
|
34
|
-
)
|
|
33
|
+
const { code, res } = await api.users.sendUserInvite(sendMailMock, email)
|
|
35
34
|
|
|
36
35
|
expect(res.body).toEqual({ message: "Invitation has been sent." })
|
|
37
36
|
expect(sendMailMock).toHaveBeenCalled()
|
|
@@ -40,7 +39,7 @@ describe("/api/global/users", () => {
|
|
|
40
39
|
})
|
|
41
40
|
|
|
42
41
|
it("should not be able to generate an invitation for existing user", async () => {
|
|
43
|
-
const { code, res } = await
|
|
42
|
+
const { code, res } = await api.users.sendUserInvite(
|
|
44
43
|
sendMailMock,
|
|
45
44
|
config.defaultUser!.email,
|
|
46
45
|
400
|
|
@@ -54,12 +53,9 @@ describe("/api/global/users", () => {
|
|
|
54
53
|
|
|
55
54
|
it("should be able to create new user from invite", async () => {
|
|
56
55
|
const email = structures.users.newEmail()
|
|
57
|
-
const { code } = await
|
|
58
|
-
sendMailMock,
|
|
59
|
-
email
|
|
60
|
-
)
|
|
56
|
+
const { code } = await api.users.sendUserInvite(sendMailMock, email)
|
|
61
57
|
|
|
62
|
-
const res = await
|
|
58
|
+
const res = await api.users.acceptInvite(code)
|
|
63
59
|
|
|
64
60
|
expect(res.body._id).toBeDefined()
|
|
65
61
|
const user = await config.getUser(email)
|
|
@@ -78,7 +74,7 @@ describe("/api/global/users", () => {
|
|
|
78
74
|
})
|
|
79
75
|
const request = [newUserInvite(), newUserInvite()]
|
|
80
76
|
|
|
81
|
-
const res = await
|
|
77
|
+
const res = await api.users.sendMultiUserInvite(request)
|
|
82
78
|
|
|
83
79
|
const body = res.body as InviteUsersResponse
|
|
84
80
|
expect(body.successful.length).toBe(2)
|
|
@@ -90,7 +86,7 @@ describe("/api/global/users", () => {
|
|
|
90
86
|
it("should not be able to generate an invitation for existing user", async () => {
|
|
91
87
|
const request = [{ email: config.defaultUser!.email, userInfo: {} }]
|
|
92
88
|
|
|
93
|
-
const res = await
|
|
89
|
+
const res = await api.users.sendMultiUserInvite(request)
|
|
94
90
|
|
|
95
91
|
const body = res.body as InviteUsersResponse
|
|
96
92
|
expect(body.successful.length).toBe(0)
|
|
@@ -106,7 +102,7 @@ describe("/api/global/users", () => {
|
|
|
106
102
|
const user = await config.createUser()
|
|
107
103
|
jest.clearAllMocks()
|
|
108
104
|
|
|
109
|
-
const response = await
|
|
105
|
+
const response = await api.users.bulkCreateUsers([user])
|
|
110
106
|
|
|
111
107
|
expect(response.created?.successful.length).toBe(0)
|
|
112
108
|
expect(response.created?.unsuccessful.length).toBe(1)
|
|
@@ -119,7 +115,7 @@ describe("/api/global/users", () => {
|
|
|
119
115
|
jest.resetAllMocks()
|
|
120
116
|
|
|
121
117
|
await tenancy.doInTenant(TENANT_1, async () => {
|
|
122
|
-
const response = await
|
|
118
|
+
const response = await api.users.bulkCreateUsers([user])
|
|
123
119
|
|
|
124
120
|
expect(response.created?.successful.length).toBe(0)
|
|
125
121
|
expect(response.created?.unsuccessful.length).toBe(1)
|
|
@@ -130,11 +126,11 @@ describe("/api/global/users", () => {
|
|
|
130
126
|
|
|
131
127
|
it("should ignore accounts using the same email", async () => {
|
|
132
128
|
const account = structures.accounts.account()
|
|
133
|
-
const resp = await
|
|
129
|
+
const resp = await api.accounts.saveMetadata(account)
|
|
134
130
|
const user = structures.users.user({ email: resp.email })
|
|
135
131
|
jest.clearAllMocks()
|
|
136
132
|
|
|
137
|
-
const response = await
|
|
133
|
+
const response = await api.users.bulkCreateUsers([user])
|
|
138
134
|
|
|
139
135
|
expect(response.created?.successful.length).toBe(0)
|
|
140
136
|
expect(response.created?.unsuccessful.length).toBe(1)
|
|
@@ -147,11 +143,7 @@ describe("/api/global/users", () => {
|
|
|
147
143
|
const admin = structures.users.adminUser()
|
|
148
144
|
const user = structures.users.user()
|
|
149
145
|
|
|
150
|
-
const response = await
|
|
151
|
-
builder,
|
|
152
|
-
admin,
|
|
153
|
-
user,
|
|
154
|
-
])
|
|
146
|
+
const response = await api.users.bulkCreateUsers([builder, admin, user])
|
|
155
147
|
|
|
156
148
|
expect(response.created?.successful.length).toBe(3)
|
|
157
149
|
expect(response.created?.successful[0].email).toBe(builder.email)
|
|
@@ -168,7 +160,7 @@ describe("/api/global/users", () => {
|
|
|
168
160
|
it("should be able to create a basic user", async () => {
|
|
169
161
|
const user = structures.users.user()
|
|
170
162
|
|
|
171
|
-
await
|
|
163
|
+
await api.users.saveUser(user)
|
|
172
164
|
|
|
173
165
|
expect(events.user.created).toBeCalledTimes(1)
|
|
174
166
|
expect(events.user.updated).not.toBeCalled()
|
|
@@ -179,7 +171,7 @@ describe("/api/global/users", () => {
|
|
|
179
171
|
it("should be able to create an admin user", async () => {
|
|
180
172
|
const user = structures.users.adminUser()
|
|
181
173
|
|
|
182
|
-
await
|
|
174
|
+
await api.users.saveUser(user)
|
|
183
175
|
|
|
184
176
|
expect(events.user.created).toBeCalledTimes(1)
|
|
185
177
|
expect(events.user.updated).not.toBeCalled()
|
|
@@ -190,7 +182,7 @@ describe("/api/global/users", () => {
|
|
|
190
182
|
it("should be able to create a builder user", async () => {
|
|
191
183
|
const user = structures.users.builderUser()
|
|
192
184
|
|
|
193
|
-
await
|
|
185
|
+
await api.users.saveUser(user)
|
|
194
186
|
|
|
195
187
|
expect(events.user.created).toBeCalledTimes(1)
|
|
196
188
|
expect(events.user.updated).not.toBeCalled()
|
|
@@ -205,7 +197,7 @@ describe("/api/global/users", () => {
|
|
|
205
197
|
app_456: "role2",
|
|
206
198
|
}
|
|
207
199
|
|
|
208
|
-
await
|
|
200
|
+
await api.users.saveUser(user)
|
|
209
201
|
|
|
210
202
|
const savedUser = await config.getUser(user.email)
|
|
211
203
|
expect(events.user.created).toBeCalledTimes(1)
|
|
@@ -221,7 +213,7 @@ describe("/api/global/users", () => {
|
|
|
221
213
|
delete user._id
|
|
222
214
|
delete user._rev
|
|
223
215
|
|
|
224
|
-
const response = await
|
|
216
|
+
const response = await api.users.saveUser(user, 400)
|
|
225
217
|
|
|
226
218
|
expect(response.body.message).toBe(`Unavailable`)
|
|
227
219
|
expect(events.user.created).toBeCalledTimes(0)
|
|
@@ -233,7 +225,7 @@ describe("/api/global/users", () => {
|
|
|
233
225
|
|
|
234
226
|
await tenancy.doInTenant(TENANT_1, async () => {
|
|
235
227
|
delete user._id
|
|
236
|
-
const response = await
|
|
228
|
+
const response = await api.users.saveUser(user, 400)
|
|
237
229
|
|
|
238
230
|
expect(response.body.message).toBe(`Unavailable`)
|
|
239
231
|
expect(events.user.created).toBeCalledTimes(0)
|
|
@@ -245,7 +237,7 @@ describe("/api/global/users", () => {
|
|
|
245
237
|
const account = structures.accounts.cloudAccount()
|
|
246
238
|
mocks.accounts.getAccount.mockReturnValueOnce(account)
|
|
247
239
|
|
|
248
|
-
const response = await
|
|
240
|
+
const response = await api.users.saveUser(user, 400)
|
|
249
241
|
|
|
250
242
|
expect(response.body.message).toBe(`Unavailable`)
|
|
251
243
|
expect(events.user.created).toBeCalledTimes(0)
|
|
@@ -253,23 +245,31 @@ describe("/api/global/users", () => {
|
|
|
253
245
|
|
|
254
246
|
it("should not be able to create a user with the same email and different casing", async () => {
|
|
255
247
|
const user = structures.users.user()
|
|
256
|
-
await
|
|
248
|
+
await api.users.saveUser(user)
|
|
257
249
|
|
|
258
250
|
user.email = user.email.toUpperCase()
|
|
259
|
-
await
|
|
251
|
+
await api.users.saveUser(user, 400)
|
|
260
252
|
|
|
261
253
|
expect(events.user.created).toBeCalledTimes(1)
|
|
262
254
|
})
|
|
263
255
|
|
|
264
256
|
it("should not be able to bulk create a user with the same email and different casing", async () => {
|
|
265
257
|
const user = structures.users.user()
|
|
266
|
-
await
|
|
258
|
+
await api.users.saveUser(user)
|
|
267
259
|
|
|
268
260
|
user.email = user.email.toUpperCase()
|
|
269
|
-
await
|
|
261
|
+
await api.users.bulkCreateUsers([user])
|
|
270
262
|
|
|
271
263
|
expect(events.user.created).toBeCalledTimes(1)
|
|
272
264
|
})
|
|
265
|
+
|
|
266
|
+
it("should not allow a non-admin user to create a new user", async () => {
|
|
267
|
+
const nonAdmin = await config.createUser(structures.users.builderUser())
|
|
268
|
+
await config.createSession(nonAdmin)
|
|
269
|
+
|
|
270
|
+
const newUser = structures.users.user()
|
|
271
|
+
await api.users.saveUser(newUser, 403, config.authHeaders(nonAdmin))
|
|
272
|
+
})
|
|
273
273
|
})
|
|
274
274
|
|
|
275
275
|
describe("update", () => {
|
|
@@ -277,7 +277,7 @@ describe("/api/global/users", () => {
|
|
|
277
277
|
const user = await config.createUser()
|
|
278
278
|
jest.clearAllMocks()
|
|
279
279
|
|
|
280
|
-
await
|
|
280
|
+
await api.users.saveUser(user)
|
|
281
281
|
|
|
282
282
|
expect(events.user.created).not.toBeCalled()
|
|
283
283
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
@@ -292,7 +292,7 @@ describe("/api/global/users", () => {
|
|
|
292
292
|
|
|
293
293
|
user.forceResetPassword = true
|
|
294
294
|
user.password = "tempPassword"
|
|
295
|
-
await
|
|
295
|
+
await api.users.saveUser(user)
|
|
296
296
|
|
|
297
297
|
expect(events.user.created).not.toBeCalled()
|
|
298
298
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
@@ -305,7 +305,7 @@ describe("/api/global/users", () => {
|
|
|
305
305
|
const user = await config.createUser()
|
|
306
306
|
jest.clearAllMocks()
|
|
307
307
|
|
|
308
|
-
await
|
|
308
|
+
await api.users.saveUser(structures.users.adminUser(user))
|
|
309
309
|
|
|
310
310
|
expect(events.user.created).not.toBeCalled()
|
|
311
311
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
@@ -317,7 +317,7 @@ describe("/api/global/users", () => {
|
|
|
317
317
|
const user = await config.createUser()
|
|
318
318
|
jest.clearAllMocks()
|
|
319
319
|
|
|
320
|
-
await
|
|
320
|
+
await api.users.saveUser(structures.users.builderUser(user))
|
|
321
321
|
|
|
322
322
|
expect(events.user.created).not.toBeCalled()
|
|
323
323
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
@@ -331,7 +331,7 @@ describe("/api/global/users", () => {
|
|
|
331
331
|
user.admin!.global = false
|
|
332
332
|
user.builder!.global = false
|
|
333
333
|
|
|
334
|
-
await
|
|
334
|
+
await api.users.saveUser(user)
|
|
335
335
|
|
|
336
336
|
expect(events.user.created).not.toBeCalled()
|
|
337
337
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
@@ -344,7 +344,7 @@ describe("/api/global/users", () => {
|
|
|
344
344
|
jest.clearAllMocks()
|
|
345
345
|
user.builder!.global = false
|
|
346
346
|
|
|
347
|
-
await
|
|
347
|
+
await api.users.saveUser(user)
|
|
348
348
|
|
|
349
349
|
expect(events.user.created).not.toBeCalled()
|
|
350
350
|
expect(events.user.updated).toBeCalledTimes(1)
|
|
@@ -360,7 +360,7 @@ describe("/api/global/users", () => {
|
|
|
360
360
|
app_456: "role2",
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
-
await
|
|
363
|
+
await api.users.saveUser(user)
|
|
364
364
|
|
|
365
365
|
const savedUser = await config.getUser(user.email)
|
|
366
366
|
expect(events.user.created).not.toBeCalled()
|
|
@@ -380,7 +380,7 @@ describe("/api/global/users", () => {
|
|
|
380
380
|
jest.clearAllMocks()
|
|
381
381
|
user.roles = {}
|
|
382
382
|
|
|
383
|
-
await
|
|
383
|
+
await api.users.saveUser(user)
|
|
384
384
|
|
|
385
385
|
const savedUser = await config.getUser(user.email)
|
|
386
386
|
expect(events.user.created).not.toBeCalled()
|
|
@@ -403,7 +403,7 @@ describe("/api/global/users", () => {
|
|
|
403
403
|
app_456: "role2-edit",
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
-
await
|
|
406
|
+
await api.users.saveUser(user)
|
|
407
407
|
|
|
408
408
|
const savedUser = await config.getUser(user.email)
|
|
409
409
|
expect(events.user.created).not.toBeCalled()
|
|
@@ -419,20 +419,28 @@ describe("/api/global/users", () => {
|
|
|
419
419
|
const user = await config.createUser(structures.users.user({ email }))
|
|
420
420
|
user.email = "new@test.com"
|
|
421
421
|
|
|
422
|
-
const response = await
|
|
422
|
+
const response = await api.users.saveUser(user, 400)
|
|
423
423
|
|
|
424
424
|
const dbUser = await config.getUser(email)
|
|
425
425
|
user.email = email
|
|
426
426
|
expect(user).toStrictEqual(dbUser)
|
|
427
427
|
expect(response.body.message).toBe("Email address cannot be changed")
|
|
428
428
|
})
|
|
429
|
+
|
|
430
|
+
it("should allow a non-admin user to update an existing user", async () => {
|
|
431
|
+
const existingUser = await config.createUser(structures.users.user())
|
|
432
|
+
const nonAdmin = await config.createUser(structures.users.builderUser())
|
|
433
|
+
await config.createSession(nonAdmin)
|
|
434
|
+
|
|
435
|
+
await api.users.saveUser(existingUser, 200, config.authHeaders(nonAdmin))
|
|
436
|
+
})
|
|
429
437
|
})
|
|
430
438
|
|
|
431
439
|
describe("bulk (delete)", () => {
|
|
432
440
|
it("should not be able to bulk delete current user", async () => {
|
|
433
441
|
const user = await config.defaultUser!
|
|
434
442
|
|
|
435
|
-
const response = await
|
|
443
|
+
const response = await api.users.bulkDeleteUsers([user._id!], 400)
|
|
436
444
|
|
|
437
445
|
expect(response.message).toBe("Unable to delete self.")
|
|
438
446
|
expect(events.user.deleted).not.toBeCalled()
|
|
@@ -444,7 +452,7 @@ describe("/api/global/users", () => {
|
|
|
444
452
|
account.budibaseUserId = user._id!
|
|
445
453
|
mocks.accounts.getAccountByTenantId.mockReturnValue(account)
|
|
446
454
|
|
|
447
|
-
const response = await
|
|
455
|
+
const response = await api.users.bulkDeleteUsers([user._id!])
|
|
448
456
|
|
|
449
457
|
expect(response.deleted?.successful.length).toBe(0)
|
|
450
458
|
expect(response.deleted?.unsuccessful.length).toBe(1)
|
|
@@ -462,7 +470,7 @@ describe("/api/global/users", () => {
|
|
|
462
470
|
const builder = structures.users.builderUser()
|
|
463
471
|
const admin = structures.users.adminUser()
|
|
464
472
|
const user = structures.users.user()
|
|
465
|
-
const createdUsers = await
|
|
473
|
+
const createdUsers = await api.users.bulkCreateUsers([
|
|
466
474
|
builder,
|
|
467
475
|
admin,
|
|
468
476
|
user,
|
|
@@ -471,7 +479,7 @@ describe("/api/global/users", () => {
|
|
|
471
479
|
const toDelete = createdUsers.created?.successful.map(
|
|
472
480
|
u => u._id!
|
|
473
481
|
) as string[]
|
|
474
|
-
const response = await
|
|
482
|
+
const response = await api.users.bulkDeleteUsers(toDelete)
|
|
475
483
|
|
|
476
484
|
expect(response.deleted?.successful.length).toBe(3)
|
|
477
485
|
expect(response.deleted?.unsuccessful.length).toBe(0)
|
|
@@ -486,7 +494,7 @@ describe("/api/global/users", () => {
|
|
|
486
494
|
const user = await config.createUser()
|
|
487
495
|
jest.clearAllMocks()
|
|
488
496
|
|
|
489
|
-
await
|
|
497
|
+
await api.users.deleteUser(user._id!)
|
|
490
498
|
|
|
491
499
|
expect(events.user.deleted).toBeCalledTimes(1)
|
|
492
500
|
expect(events.user.permissionBuilderRemoved).not.toBeCalled()
|
|
@@ -497,7 +505,7 @@ describe("/api/global/users", () => {
|
|
|
497
505
|
const user = await config.createUser(structures.users.adminUser())
|
|
498
506
|
jest.clearAllMocks()
|
|
499
507
|
|
|
500
|
-
await
|
|
508
|
+
await api.users.deleteUser(user._id!)
|
|
501
509
|
|
|
502
510
|
expect(events.user.deleted).toBeCalledTimes(1)
|
|
503
511
|
expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
|
|
@@ -508,7 +516,7 @@ describe("/api/global/users", () => {
|
|
|
508
516
|
const user = await config.createUser(structures.users.builderUser())
|
|
509
517
|
jest.clearAllMocks()
|
|
510
518
|
|
|
511
|
-
await
|
|
519
|
+
await api.users.deleteUser(user._id!)
|
|
512
520
|
|
|
513
521
|
expect(events.user.deleted).toBeCalledTimes(1)
|
|
514
522
|
expect(events.user.permissionBuilderRemoved).toBeCalledTimes(1)
|
|
@@ -520,7 +528,7 @@ describe("/api/global/users", () => {
|
|
|
520
528
|
const account = structures.accounts.cloudAccount()
|
|
521
529
|
mocks.accounts.getAccount.mockReturnValueOnce(account)
|
|
522
530
|
|
|
523
|
-
const response = await
|
|
531
|
+
const response = await api.users.deleteUser(user._id!, 400)
|
|
524
532
|
|
|
525
533
|
expect(response.body.message).toBe("Account holder cannot be deleted")
|
|
526
534
|
})
|
|
@@ -531,7 +539,7 @@ describe("/api/global/users", () => {
|
|
|
531
539
|
account.email = user.email
|
|
532
540
|
mocks.accounts.getAccount.mockReturnValueOnce(account)
|
|
533
541
|
|
|
534
|
-
const response = await
|
|
542
|
+
const response = await api.users.deleteUser(user._id!, 400)
|
|
535
543
|
|
|
536
544
|
expect(response.body.message).toBe("Unable to delete self.")
|
|
537
545
|
})
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
const Router = require("@koa/router")
|
|
2
|
+
const controller = require("../../controllers/global/users")
|
|
3
|
+
const { joiValidator } = require("@budibase/backend-core/auth")
|
|
4
|
+
const { adminOnly } = require("@budibase/backend-core/auth")
|
|
5
|
+
const Joi = require("joi")
|
|
6
|
+
const cloudRestricted = require("../../../middleware/cloudRestricted")
|
|
7
|
+
const { users } = require("../validation")
|
|
8
|
+
const selfController = require("../../controllers/global/self")
|
|
9
|
+
const { builderOrAdmin } = require("@budibase/backend-core/auth")
|
|
8
10
|
|
|
9
|
-
const router
|
|
11
|
+
const router = new Router()
|
|
10
12
|
|
|
11
13
|
function buildAdminInitValidation() {
|
|
12
|
-
return
|
|
14
|
+
return joiValidator.body(
|
|
13
15
|
Joi.object({
|
|
14
16
|
email: Joi.string().required(),
|
|
15
17
|
password: Joi.string(),
|
|
@@ -22,7 +24,7 @@ function buildAdminInitValidation() {
|
|
|
22
24
|
|
|
23
25
|
function buildInviteValidation() {
|
|
24
26
|
// prettier-ignore
|
|
25
|
-
return
|
|
27
|
+
return joiValidator.body(Joi.object({
|
|
26
28
|
email: Joi.string().required(),
|
|
27
29
|
userInfo: Joi.object().optional(),
|
|
28
30
|
}).required())
|
|
@@ -30,7 +32,7 @@ function buildInviteValidation() {
|
|
|
30
32
|
|
|
31
33
|
function buildInviteMultipleValidation() {
|
|
32
34
|
// prettier-ignore
|
|
33
|
-
return
|
|
35
|
+
return joiValidator.body(Joi.array().required().items(
|
|
34
36
|
Joi.object({
|
|
35
37
|
email: Joi.string(),
|
|
36
38
|
userInfo: Joi.object().optional(),
|
|
@@ -38,9 +40,17 @@ function buildInviteMultipleValidation() {
|
|
|
38
40
|
))
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
const createUserAdminOnly = (ctx, next) => {
|
|
44
|
+
if (!ctx.request.body._id) {
|
|
45
|
+
return adminOnly(ctx, next)
|
|
46
|
+
} else {
|
|
47
|
+
return builderOrAdmin(ctx, next)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
41
51
|
function buildInviteAcceptValidation() {
|
|
42
52
|
// prettier-ignore
|
|
43
|
-
return
|
|
53
|
+
return joiValidator.body(Joi.object({
|
|
44
54
|
inviteCode: Joi.string().required(),
|
|
45
55
|
password: Joi.string().required(),
|
|
46
56
|
}).required().unknown(true))
|
|
@@ -49,35 +59,31 @@ function buildInviteAcceptValidation() {
|
|
|
49
59
|
router
|
|
50
60
|
.post(
|
|
51
61
|
"/api/global/users",
|
|
52
|
-
|
|
62
|
+
createUserAdminOnly,
|
|
53
63
|
users.buildUserSaveValidation(),
|
|
54
64
|
controller.save
|
|
55
65
|
)
|
|
56
66
|
.post(
|
|
57
67
|
"/api/global/users/bulk",
|
|
58
|
-
|
|
68
|
+
adminOnly,
|
|
59
69
|
users.buildUserBulkUserValidation(),
|
|
60
70
|
controller.bulkUpdate
|
|
61
71
|
)
|
|
62
72
|
|
|
63
|
-
.get("/api/global/users",
|
|
64
|
-
.post("/api/global/users/search",
|
|
65
|
-
.delete("/api/global/users/:id",
|
|
66
|
-
.get(
|
|
67
|
-
"/api/global/users/count/:appId",
|
|
68
|
-
auth.builderOrAdmin,
|
|
69
|
-
controller.countByApp
|
|
70
|
-
)
|
|
73
|
+
.get("/api/global/users", builderOrAdmin, controller.fetch)
|
|
74
|
+
.post("/api/global/users/search", builderOrAdmin, controller.search)
|
|
75
|
+
.delete("/api/global/users/:id", adminOnly, controller.destroy)
|
|
76
|
+
.get("/api/global/users/count/:appId", builderOrAdmin, controller.countByApp)
|
|
71
77
|
.get("/api/global/roles/:appId")
|
|
72
78
|
.post(
|
|
73
79
|
"/api/global/users/invite",
|
|
74
|
-
|
|
80
|
+
adminOnly,
|
|
75
81
|
buildInviteValidation(),
|
|
76
82
|
controller.invite
|
|
77
83
|
)
|
|
78
84
|
.post(
|
|
79
85
|
"/api/global/users/multi/invite",
|
|
80
|
-
|
|
86
|
+
adminOnly,
|
|
81
87
|
buildInviteMultipleValidation(),
|
|
82
88
|
controller.inviteMultiple
|
|
83
89
|
)
|
|
@@ -96,7 +102,7 @@ router
|
|
|
96
102
|
)
|
|
97
103
|
.get("/api/global/users/tenant/:id", controller.tenantUserLookup)
|
|
98
104
|
// global endpoint but needs to come at end (blocks other endpoints otherwise)
|
|
99
|
-
.get("/api/global/users/:id",
|
|
105
|
+
.get("/api/global/users/:id", builderOrAdmin, controller.find)
|
|
100
106
|
// DEPRECATED - use new versions with self API
|
|
101
107
|
.get("/api/global/users/self", selfController.getSelf)
|
|
102
108
|
.post(
|
|
@@ -105,4 +111,4 @@ router
|
|
|
105
111
|
selfController.updateSelf
|
|
106
112
|
)
|
|
107
113
|
|
|
108
|
-
|
|
114
|
+
module.exports = router
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
const Router = require("@koa/router")
|
|
2
|
+
const controller = require("../../controllers/global/workspaces")
|
|
3
|
+
const { joiValidator } = require("@budibase/backend-core/auth")
|
|
4
|
+
const { adminOnly } = require("@budibase/backend-core/auth")
|
|
5
|
+
const Joi = require("joi")
|
|
5
6
|
|
|
6
|
-
const router
|
|
7
|
+
const router = new Router()
|
|
7
8
|
|
|
8
9
|
function buildWorkspaceSaveValidation() {
|
|
9
10
|
// prettier-ignore
|
|
10
|
-
return
|
|
11
|
+
return joiValidator.body(Joi.object({
|
|
11
12
|
_id: Joi.string().optional(),
|
|
12
13
|
_rev: Joi.string().optional(),
|
|
13
14
|
name: Joi.string().required(),
|
|
@@ -26,12 +27,12 @@ function buildWorkspaceSaveValidation() {
|
|
|
26
27
|
router
|
|
27
28
|
.post(
|
|
28
29
|
"/api/global/workspaces",
|
|
29
|
-
|
|
30
|
+
adminOnly,
|
|
30
31
|
buildWorkspaceSaveValidation(),
|
|
31
32
|
controller.save
|
|
32
33
|
)
|
|
33
|
-
.delete("/api/global/workspaces/:id",
|
|
34
|
+
.delete("/api/global/workspaces/:id", adminOnly, controller.destroy)
|
|
34
35
|
.get("/api/global/workspaces", controller.fetch)
|
|
35
36
|
.get("/api/global/workspaces/:id", controller.find)
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
module.exports = router
|
package/src/api/routes/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Router from "@koa/router"
|
|
2
1
|
import { api } from "@budibase/pro"
|
|
3
2
|
import userRoutes from "./global/users"
|
|
4
3
|
import configRoutes from "./global/configs"
|
|
@@ -17,7 +16,7 @@ import accountRoutes from "./system/accounts"
|
|
|
17
16
|
import restoreRoutes from "./system/restore"
|
|
18
17
|
|
|
19
18
|
let userGroupRoutes = api.groups
|
|
20
|
-
export const routes
|
|
19
|
+
export const routes = [
|
|
21
20
|
configRoutes,
|
|
22
21
|
userRoutes,
|
|
23
22
|
workspaceRoutes,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const Router = require("@koa/router")
|
|
2
|
+
const controller = require("../../controllers/system/tenants")
|
|
3
|
+
const { adminOnly } = require("@budibase/backend-core/auth")
|
|
4
|
+
|
|
5
|
+
const router = new Router()
|
|
6
|
+
|
|
7
|
+
router
|
|
8
|
+
.get("/api/system/tenants/:tenantId/exists", controller.exists)
|
|
9
|
+
.get("/api/system/tenants", adminOnly, controller.fetch)
|
|
10
|
+
.delete("/api/system/tenants/:tenantId", adminOnly, controller.delete)
|
|
11
|
+
|
|
12
|
+
module.exports = router
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import sdk from "../../../../sdk"
|
|
2
|
-
import { TestConfiguration, structures } from "../../../../tests"
|
|
2
|
+
import { TestConfiguration, structures, API } from "../../../../tests"
|
|
3
3
|
import { v4 as uuid } from "uuid"
|
|
4
4
|
|
|
5
5
|
describe("accounts", () => {
|
|
6
6
|
const config = new TestConfiguration()
|
|
7
|
+
const api = new API(config)
|
|
7
8
|
|
|
8
9
|
beforeAll(async () => {
|
|
9
10
|
await config.beforeAll()
|
|
@@ -22,7 +23,7 @@ describe("accounts", () => {
|
|
|
22
23
|
it("saves account metadata", async () => {
|
|
23
24
|
let account = structures.accounts.account()
|
|
24
25
|
|
|
25
|
-
const response = await
|
|
26
|
+
const response = await api.accounts.saveMetadata(account)
|
|
26
27
|
|
|
27
28
|
const id = sdk.accounts.formatAccountMetadataId(account.accountId)
|
|
28
29
|
const metadata = await sdk.accounts.getMetadata(id)
|
|
@@ -33,9 +34,9 @@ describe("accounts", () => {
|
|
|
33
34
|
describe("destroyMetadata", () => {
|
|
34
35
|
it("destroys account metadata", async () => {
|
|
35
36
|
const account = structures.accounts.account()
|
|
36
|
-
await
|
|
37
|
+
await api.accounts.saveMetadata(account)
|
|
37
38
|
|
|
38
|
-
await
|
|
39
|
+
await api.accounts.destroyMetadata(account.accountId)
|
|
39
40
|
|
|
40
41
|
const deleted = await sdk.accounts.getMetadata(account.accountId)
|
|
41
42
|
expect(deleted).toBe(undefined)
|
|
@@ -44,7 +45,7 @@ describe("accounts", () => {
|
|
|
44
45
|
it("destroys account metadata that does not exist", async () => {
|
|
45
46
|
const id = uuid()
|
|
46
47
|
|
|
47
|
-
const response = await
|
|
48
|
+
const response = await api.accounts.destroyMetadata(id)
|
|
48
49
|
|
|
49
50
|
expect(response.status).toBe(204)
|
|
50
51
|
})
|