@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.
- package/package.json +7 -6
- package/scripts/jestSetup.js +6 -0
- package/src/api/controllers/global/auth.ts +14 -1
- package/src/api/controllers/global/users.ts +26 -55
- package/src/api/controllers/system/accounts.ts +21 -0
- package/src/api/{index.js → index.ts} +12 -16
- package/src/api/routes/global/configs.js +1 -0
- package/src/api/routes/{tests/auth.spec.js → global/tests/auth.spec.ts} +32 -56
- package/src/api/routes/{tests/configs.spec.js → global/tests/configs.spec.ts} +76 -47
- package/src/api/routes/{tests/email.spec.js → global/tests/email.spec.ts} +7 -15
- package/src/api/routes/{tests/realEmail.spec.js → global/tests/realEmail.spec.ts} +20 -21
- package/src/api/routes/{tests/self.spec.js → global/tests/self.spec.ts} +10 -18
- package/src/api/routes/global/tests/users.spec.ts +512 -0
- package/src/api/routes/index.js +2 -0
- package/src/api/routes/system/accounts.ts +19 -0
- package/src/api/routes/system/tests/accounts.spec.ts +57 -0
- package/src/{environment.js → environment.ts} +10 -9
- package/src/index.ts +6 -4
- package/src/sdk/accounts/accounts.ts +53 -0
- package/src/sdk/accounts/index.ts +1 -0
- package/src/sdk/index.ts +1 -0
- package/src/sdk/users/users.ts +271 -77
- package/src/tests/TestConfiguration.ts +273 -0
- package/src/tests/api/accounts.ts +28 -0
- package/src/tests/api/auth.ts +48 -0
- package/src/tests/api/configs.ts +40 -0
- package/src/tests/api/email.ts +24 -0
- package/src/tests/api/index.ts +25 -0
- package/src/tests/api/self.ts +21 -0
- package/src/tests/api/users.ts +111 -0
- package/src/tests/index.ts +14 -0
- package/src/tests/mocks/index.ts +7 -0
- package/src/tests/structures/accounts.ts +24 -0
- package/src/tests/structures/index.ts +20 -0
- package/src/tests/structures/users.ts +12 -4
- package/src/utilities/redis.js +1 -0
- package/scripts/load/users.js +0 -97
- package/src/api/routes/tests/users.spec.js +0 -390
- package/src/tests/TestConfiguration.js +0 -231
- package/src/tests/index.js +0 -12
- package/src/tests/mocks/index.js +0 -5
- package/src/tests/structures/index.js +0 -14
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import "./mocks"
|
|
2
|
+
import dbConfig from "../db"
|
|
3
|
+
dbConfig.init()
|
|
4
|
+
import env from "../environment"
|
|
5
|
+
import controllers from "./controllers"
|
|
6
|
+
const supertest = require("supertest")
|
|
7
|
+
import { Configs } from "../constants"
|
|
8
|
+
import {
|
|
9
|
+
users,
|
|
10
|
+
tenancy,
|
|
11
|
+
Cookies,
|
|
12
|
+
Headers,
|
|
13
|
+
sessions,
|
|
14
|
+
auth,
|
|
15
|
+
} from "@budibase/backend-core"
|
|
16
|
+
import { TENANT_ID, TENANT_1, CSRF_TOKEN } from "./structures"
|
|
17
|
+
import structures from "./structures"
|
|
18
|
+
import { CreateUserResponse, User, AuthToken } from "@budibase/types"
|
|
19
|
+
|
|
20
|
+
enum Mode {
|
|
21
|
+
ACCOUNT = "account",
|
|
22
|
+
SELF = "self",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
class TestConfiguration {
|
|
26
|
+
server: any
|
|
27
|
+
request: any
|
|
28
|
+
defaultUser?: User
|
|
29
|
+
tenant1User?: User
|
|
30
|
+
|
|
31
|
+
constructor(
|
|
32
|
+
opts: { openServer: boolean; mode: Mode } = {
|
|
33
|
+
openServer: true,
|
|
34
|
+
mode: Mode.ACCOUNT,
|
|
35
|
+
}
|
|
36
|
+
) {
|
|
37
|
+
if (opts.mode === Mode.ACCOUNT) {
|
|
38
|
+
this.modeAccount()
|
|
39
|
+
} else if (opts.mode === Mode.SELF) {
|
|
40
|
+
this.modeSelf()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (opts.openServer) {
|
|
44
|
+
env.PORT = "0" // random port
|
|
45
|
+
this.server = require("../index")
|
|
46
|
+
// we need the request for logging in, involves cookies, hard to fake
|
|
47
|
+
this.request = supertest(this.server)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getRequest() {
|
|
52
|
+
return this.request
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// MODES
|
|
56
|
+
|
|
57
|
+
modeAccount = () => {
|
|
58
|
+
env.SELF_HOSTED = false
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
env.MULTI_TENANCY = true
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
env.DISABLE_ACCOUNT_PORTAL = false
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
modeSelf = () => {
|
|
66
|
+
env.SELF_HOSTED = true
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
env.MULTI_TENANCY = false
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
env.DISABLE_ACCOUNT_PORTAL = true
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// UTILS
|
|
74
|
+
|
|
75
|
+
async _req(config: any, params: any, controlFunc: any) {
|
|
76
|
+
const request: any = {}
|
|
77
|
+
// fake cookies, we don't need them
|
|
78
|
+
request.cookies = { set: () => {}, get: () => {} }
|
|
79
|
+
request.config = { jwtSecret: env.JWT_SECRET }
|
|
80
|
+
request.user = { tenantId: this.getTenantId() }
|
|
81
|
+
request.query = {}
|
|
82
|
+
request.request = {
|
|
83
|
+
body: config,
|
|
84
|
+
}
|
|
85
|
+
request.throw = (status: any, err: any) => {
|
|
86
|
+
throw { status, message: err }
|
|
87
|
+
}
|
|
88
|
+
if (params) {
|
|
89
|
+
request.params = params
|
|
90
|
+
}
|
|
91
|
+
await tenancy.doInTenant(this.getTenantId(), () => {
|
|
92
|
+
return controlFunc(request)
|
|
93
|
+
})
|
|
94
|
+
return request.body
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// SETUP / TEARDOWN
|
|
98
|
+
|
|
99
|
+
async beforeAll() {
|
|
100
|
+
await this.createDefaultUser()
|
|
101
|
+
await this.createSession(this.defaultUser!)
|
|
102
|
+
|
|
103
|
+
await tenancy.doInTenant(TENANT_1, async () => {
|
|
104
|
+
await this.createTenant1User()
|
|
105
|
+
await this.createSession(this.tenant1User!)
|
|
106
|
+
})
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async afterAll() {
|
|
110
|
+
if (this.server) {
|
|
111
|
+
await this.server.close()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// TENANCY
|
|
116
|
+
|
|
117
|
+
getTenantId() {
|
|
118
|
+
try {
|
|
119
|
+
return tenancy.getTenantId()
|
|
120
|
+
} catch (e: any) {
|
|
121
|
+
return TENANT_ID
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// USER / AUTH
|
|
126
|
+
|
|
127
|
+
async createDefaultUser() {
|
|
128
|
+
const user = structures.users.adminUser({
|
|
129
|
+
email: "test@test.com",
|
|
130
|
+
password: "test",
|
|
131
|
+
})
|
|
132
|
+
this.defaultUser = await this.createUser(user)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async createTenant1User() {
|
|
136
|
+
const user = structures.users.adminUser({
|
|
137
|
+
email: "tenant1@test.com",
|
|
138
|
+
password: "test",
|
|
139
|
+
})
|
|
140
|
+
this.tenant1User = await this.createUser(user)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async createSession(user: User) {
|
|
144
|
+
await sessions.createASession(user._id!, {
|
|
145
|
+
sessionId: "sessionid",
|
|
146
|
+
tenantId: user.tenantId,
|
|
147
|
+
csrfToken: CSRF_TOKEN,
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
cookieHeader(cookies: any) {
|
|
152
|
+
return {
|
|
153
|
+
Cookie: [cookies],
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
authHeaders(user: User) {
|
|
158
|
+
const authToken: AuthToken = {
|
|
159
|
+
userId: user._id!,
|
|
160
|
+
sessionId: "sessionid",
|
|
161
|
+
tenantId: user.tenantId,
|
|
162
|
+
}
|
|
163
|
+
const authCookie = auth.jwt.sign(authToken, env.JWT_SECRET)
|
|
164
|
+
return {
|
|
165
|
+
Accept: "application/json",
|
|
166
|
+
...this.cookieHeader([`${Cookies.Auth}=${authCookie}`]),
|
|
167
|
+
[Headers.CSRF_TOKEN]: CSRF_TOKEN,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
defaultHeaders() {
|
|
172
|
+
const tenantId = this.getTenantId()
|
|
173
|
+
if (tenantId === TENANT_ID) {
|
|
174
|
+
return this.authHeaders(this.defaultUser!)
|
|
175
|
+
} else if (tenantId === TENANT_1) {
|
|
176
|
+
return this.authHeaders(this.tenant1User!)
|
|
177
|
+
} else {
|
|
178
|
+
throw new Error("could not determine auth headers to use")
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async getUser(email: string): Promise<User> {
|
|
183
|
+
return tenancy.doInTenant(this.getTenantId(), () => {
|
|
184
|
+
return users.getGlobalUserByEmail(email)
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async createUser(user?: User) {
|
|
189
|
+
if (!user) {
|
|
190
|
+
user = structures.users.user()
|
|
191
|
+
}
|
|
192
|
+
const response = await this._req(user, null, controllers.users.save)
|
|
193
|
+
const body = response as CreateUserResponse
|
|
194
|
+
return this.getUser(body.email)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// CONFIGS
|
|
198
|
+
|
|
199
|
+
async deleteConfig(type: any) {
|
|
200
|
+
try {
|
|
201
|
+
const cfg = await this._req(
|
|
202
|
+
null,
|
|
203
|
+
{
|
|
204
|
+
type,
|
|
205
|
+
},
|
|
206
|
+
controllers.config.find
|
|
207
|
+
)
|
|
208
|
+
if (cfg) {
|
|
209
|
+
await this._req(
|
|
210
|
+
null,
|
|
211
|
+
{
|
|
212
|
+
id: cfg._id,
|
|
213
|
+
rev: cfg._rev,
|
|
214
|
+
},
|
|
215
|
+
controllers.config.destroy
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
} catch (err) {
|
|
219
|
+
// don't need to handle error
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// CONFIGS - SETTINGS
|
|
224
|
+
|
|
225
|
+
async saveSettingsConfig() {
|
|
226
|
+
await this.deleteConfig(Configs.SETTINGS)
|
|
227
|
+
await this._req(
|
|
228
|
+
structures.configs.settings(),
|
|
229
|
+
null,
|
|
230
|
+
controllers.config.save
|
|
231
|
+
)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// CONFIGS - GOOGLE
|
|
235
|
+
|
|
236
|
+
async saveGoogleConfig() {
|
|
237
|
+
await this.deleteConfig(Configs.GOOGLE)
|
|
238
|
+
await this._req(structures.configs.google(), null, controllers.config.save)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// CONFIGS - OIDC
|
|
242
|
+
|
|
243
|
+
getOIDConfigCookie(configId: string) {
|
|
244
|
+
const token = auth.jwt.sign(configId, env.JWT_SECRET)
|
|
245
|
+
return this.cookieHeader([[`${Cookies.OIDC_CONFIG}=${token}`]])
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async saveOIDCConfig() {
|
|
249
|
+
await this.deleteConfig(Configs.OIDC)
|
|
250
|
+
const config = structures.configs.oidc()
|
|
251
|
+
|
|
252
|
+
await this._req(config, null, controllers.config.save)
|
|
253
|
+
return config
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// CONFIGS - SMTP
|
|
257
|
+
|
|
258
|
+
async saveSmtpConfig() {
|
|
259
|
+
await this.deleteConfig(Configs.SMTP)
|
|
260
|
+
await this._req(structures.configs.smtp(), null, controllers.config.save)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
async saveEtherealSmtpConfig() {
|
|
264
|
+
await this.deleteConfig(Configs.SMTP)
|
|
265
|
+
await this._req(
|
|
266
|
+
structures.configs.smtpEthereal(),
|
|
267
|
+
null,
|
|
268
|
+
controllers.config.save
|
|
269
|
+
)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export = TestConfiguration
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Account, AccountMetadata } from "@budibase/types"
|
|
2
|
+
import TestConfiguration from "../TestConfiguration"
|
|
3
|
+
|
|
4
|
+
export class AccountAPI {
|
|
5
|
+
config: TestConfiguration
|
|
6
|
+
request: any
|
|
7
|
+
|
|
8
|
+
constructor(config: TestConfiguration) {
|
|
9
|
+
this.config = config
|
|
10
|
+
this.request = config.request
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
saveMetadata = async (account: Account) => {
|
|
14
|
+
const res = await this.request
|
|
15
|
+
.put(`/api/system/accounts/${account.accountId}/metadata`)
|
|
16
|
+
.send(account)
|
|
17
|
+
.set(this.config.defaultHeaders())
|
|
18
|
+
.expect("Content-Type", /json/)
|
|
19
|
+
.expect(200)
|
|
20
|
+
return res.body as AccountMetadata
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
destroyMetadata = (accountId: string) => {
|
|
24
|
+
return this.request
|
|
25
|
+
.del(`/api/system/accounts/${accountId}/metadata`)
|
|
26
|
+
.set(this.config.defaultHeaders())
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import TestConfiguration from "../TestConfiguration"
|
|
2
|
+
|
|
3
|
+
export class AuthAPI {
|
|
4
|
+
config: TestConfiguration
|
|
5
|
+
request: any
|
|
6
|
+
|
|
7
|
+
constructor(config: TestConfiguration) {
|
|
8
|
+
this.config = config
|
|
9
|
+
this.request = config.request
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
updatePassword = (code: string) => {
|
|
13
|
+
return this.request
|
|
14
|
+
.post(`/api/global/auth/${this.config.getTenantId()}/reset/update`)
|
|
15
|
+
.send({
|
|
16
|
+
password: "newpassword",
|
|
17
|
+
resetCode: code,
|
|
18
|
+
})
|
|
19
|
+
.expect("Content-Type", /json/)
|
|
20
|
+
.expect(200)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
logout = () => {
|
|
24
|
+
return this.request
|
|
25
|
+
.post("/api/global/auth/logout")
|
|
26
|
+
.set(this.config.defaultHeaders())
|
|
27
|
+
.expect(200)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
requestPasswordReset = async (sendMailMock: any) => {
|
|
31
|
+
await this.config.saveSmtpConfig()
|
|
32
|
+
await this.config.saveSettingsConfig()
|
|
33
|
+
await this.config.createUser()
|
|
34
|
+
const res = await this.request
|
|
35
|
+
.post(`/api/global/auth/${this.config.getTenantId()}/reset`)
|
|
36
|
+
.send({
|
|
37
|
+
email: "test@test.com",
|
|
38
|
+
})
|
|
39
|
+
.expect("Content-Type", /json/)
|
|
40
|
+
.expect(200)
|
|
41
|
+
const emailCall = sendMailMock.mock.calls[0][0]
|
|
42
|
+
const parts = emailCall.html.split(
|
|
43
|
+
`http://localhost:10000/builder/auth/reset?code=`
|
|
44
|
+
)
|
|
45
|
+
const code = parts[1].split('"')[0].split("&")[0]
|
|
46
|
+
return { code, res }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import TestConfiguration from "../TestConfiguration"
|
|
2
|
+
|
|
3
|
+
export class ConfigAPI {
|
|
4
|
+
config: TestConfiguration
|
|
5
|
+
request: any
|
|
6
|
+
|
|
7
|
+
constructor(config: TestConfiguration) {
|
|
8
|
+
this.config = config
|
|
9
|
+
this.request = config.request
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
getConfigChecklist = () => {
|
|
13
|
+
return this.request
|
|
14
|
+
.get(`/api/global/configs/checklist`)
|
|
15
|
+
.set(this.config.defaultHeaders())
|
|
16
|
+
.expect("Content-Type", /json/)
|
|
17
|
+
.expect(200)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
saveConfig = (data: any) => {
|
|
21
|
+
return this.request
|
|
22
|
+
.post(`/api/global/configs`)
|
|
23
|
+
.send(data)
|
|
24
|
+
.set(this.config.defaultHeaders())
|
|
25
|
+
.expect("Content-Type", /json/)
|
|
26
|
+
.expect(200)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
OIDCCallback = (configId: string) => {
|
|
30
|
+
return this.request
|
|
31
|
+
.get(`/api/global/auth/${this.config.getTenantId()}/oidc/callback`)
|
|
32
|
+
.set(this.config.getOIDConfigCookie(configId))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getOIDCConfig = (configId: string) => {
|
|
36
|
+
return this.request.get(
|
|
37
|
+
`/api/global/auth/${this.config.getTenantId()}/oidc/configs/${configId}`
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import TestConfiguration from "../TestConfiguration"
|
|
2
|
+
|
|
3
|
+
export class EmailAPI {
|
|
4
|
+
config: TestConfiguration
|
|
5
|
+
request: any
|
|
6
|
+
|
|
7
|
+
constructor(config: TestConfiguration) {
|
|
8
|
+
this.config = config
|
|
9
|
+
this.request = config.request
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
sendEmail = (purpose: string) => {
|
|
13
|
+
return this.request
|
|
14
|
+
.post(`/api/global/email/send`)
|
|
15
|
+
.send({
|
|
16
|
+
email: "test@test.com",
|
|
17
|
+
purpose,
|
|
18
|
+
tenantId: this.config.getTenantId(),
|
|
19
|
+
})
|
|
20
|
+
.set(this.config.defaultHeaders())
|
|
21
|
+
.expect("Content-Type", /json/)
|
|
22
|
+
.expect(200)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import TestConfiguration from "../TestConfiguration"
|
|
2
|
+
import { AccountAPI } from "./accounts"
|
|
3
|
+
import { AuthAPI } from "./auth"
|
|
4
|
+
import { ConfigAPI } from "./configs"
|
|
5
|
+
import { EmailAPI } from "./email"
|
|
6
|
+
import { SelfAPI } from "./self"
|
|
7
|
+
import { UserAPI } from "./users"
|
|
8
|
+
|
|
9
|
+
export default class API {
|
|
10
|
+
accounts: AccountAPI
|
|
11
|
+
auth: AuthAPI
|
|
12
|
+
configs: ConfigAPI
|
|
13
|
+
emails: EmailAPI
|
|
14
|
+
self: SelfAPI
|
|
15
|
+
users: UserAPI
|
|
16
|
+
|
|
17
|
+
constructor(config: TestConfiguration) {
|
|
18
|
+
this.accounts = new AccountAPI(config)
|
|
19
|
+
this.auth = new AuthAPI(config)
|
|
20
|
+
this.configs = new ConfigAPI(config)
|
|
21
|
+
this.emails = new EmailAPI(config)
|
|
22
|
+
this.self = new SelfAPI(config)
|
|
23
|
+
this.users = new UserAPI(config)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import TestConfiguration from "../TestConfiguration"
|
|
2
|
+
import { User } from "@budibase/types"
|
|
3
|
+
|
|
4
|
+
export class SelfAPI {
|
|
5
|
+
config: TestConfiguration
|
|
6
|
+
request: any
|
|
7
|
+
|
|
8
|
+
constructor(config: TestConfiguration) {
|
|
9
|
+
this.config = config
|
|
10
|
+
this.request = config.request
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
updateSelf = (user: User) => {
|
|
14
|
+
return this.request
|
|
15
|
+
.post(`/api/global/self`)
|
|
16
|
+
.send(user)
|
|
17
|
+
.set(this.config.authHeaders(user))
|
|
18
|
+
.expect("Content-Type", /json/)
|
|
19
|
+
.expect(200)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BulkCreateUsersRequest,
|
|
3
|
+
BulkCreateUsersResponse,
|
|
4
|
+
BulkDeleteUsersRequest,
|
|
5
|
+
CreateUserResponse,
|
|
6
|
+
InviteUsersRequest,
|
|
7
|
+
User,
|
|
8
|
+
UserDetails,
|
|
9
|
+
} from "@budibase/types"
|
|
10
|
+
import TestConfiguration from "../TestConfiguration"
|
|
11
|
+
|
|
12
|
+
export class UserAPI {
|
|
13
|
+
config: TestConfiguration
|
|
14
|
+
request: any
|
|
15
|
+
|
|
16
|
+
constructor(config: TestConfiguration) {
|
|
17
|
+
this.config = config
|
|
18
|
+
this.request = config.request
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// INVITE
|
|
22
|
+
|
|
23
|
+
sendUserInvite = async (sendMailMock: any, email: string, status = 200) => {
|
|
24
|
+
await this.config.saveSmtpConfig()
|
|
25
|
+
await this.config.saveSettingsConfig()
|
|
26
|
+
const res = await this.request
|
|
27
|
+
.post(`/api/global/users/invite`)
|
|
28
|
+
.send({
|
|
29
|
+
email,
|
|
30
|
+
})
|
|
31
|
+
.set(this.config.defaultHeaders())
|
|
32
|
+
.expect("Content-Type", /json/)
|
|
33
|
+
.expect(status)
|
|
34
|
+
|
|
35
|
+
if (status !== 200) {
|
|
36
|
+
return { code: undefined, res }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const emailCall = sendMailMock.mock.calls[0][0]
|
|
40
|
+
// after this URL there should be a code
|
|
41
|
+
const parts = emailCall.html.split(
|
|
42
|
+
"http://localhost:10000/builder/invite?code="
|
|
43
|
+
)
|
|
44
|
+
const code = parts[1].split('"')[0].split("&")[0]
|
|
45
|
+
return { code, res }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
acceptInvite = (code: string) => {
|
|
49
|
+
return this.request
|
|
50
|
+
.post(`/api/global/users/invite/accept`)
|
|
51
|
+
.send({
|
|
52
|
+
password: "newpassword",
|
|
53
|
+
inviteCode: code,
|
|
54
|
+
})
|
|
55
|
+
.expect("Content-Type", /json/)
|
|
56
|
+
.expect(200)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
sendMultiUserInvite = async (request: InviteUsersRequest, status = 200) => {
|
|
60
|
+
await this.config.saveSmtpConfig()
|
|
61
|
+
await this.config.saveSettingsConfig()
|
|
62
|
+
return this.request
|
|
63
|
+
.post(`/api/global/users/multi/invite`)
|
|
64
|
+
.send(request)
|
|
65
|
+
.set(this.config.defaultHeaders())
|
|
66
|
+
.expect("Content-Type", /json/)
|
|
67
|
+
.expect(status)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// BULK
|
|
71
|
+
|
|
72
|
+
bulkCreateUsers = async (users: User[], groups: any[] = []) => {
|
|
73
|
+
const body: BulkCreateUsersRequest = { users, groups }
|
|
74
|
+
const res = await this.request
|
|
75
|
+
.post(`/api/global/users/bulkCreate`)
|
|
76
|
+
.send(body)
|
|
77
|
+
.set(this.config.defaultHeaders())
|
|
78
|
+
.expect("Content-Type", /json/)
|
|
79
|
+
.expect(200)
|
|
80
|
+
|
|
81
|
+
return res.body as BulkCreateUsersResponse
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
bulkDeleteUsers = (body: BulkDeleteUsersRequest, status?: number) => {
|
|
85
|
+
return this.request
|
|
86
|
+
.post(`/api/global/users/bulkDelete`)
|
|
87
|
+
.send(body)
|
|
88
|
+
.set(this.config.defaultHeaders())
|
|
89
|
+
.expect("Content-Type", /json/)
|
|
90
|
+
.expect(status ? status : 200)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// USER
|
|
94
|
+
|
|
95
|
+
saveUser = (user: User, status?: number) => {
|
|
96
|
+
return this.request
|
|
97
|
+
.post(`/api/global/users`)
|
|
98
|
+
.send(user)
|
|
99
|
+
.set(this.config.defaultHeaders())
|
|
100
|
+
.expect("Content-Type", /json/)
|
|
101
|
+
.expect(status ? status : 200)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
deleteUser = (userId: string, status?: number) => {
|
|
105
|
+
return this.request
|
|
106
|
+
.delete(`/api/global/users/${userId}`)
|
|
107
|
+
.set(this.config.defaultHeaders())
|
|
108
|
+
.expect("Content-Type", /json/)
|
|
109
|
+
.expect(status ? status : 200)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import TestConfiguration from "./TestConfiguration"
|
|
2
|
+
import structures from "./structures"
|
|
3
|
+
import mocks from "./mocks"
|
|
4
|
+
import API from "./api"
|
|
5
|
+
|
|
6
|
+
const pkg = {
|
|
7
|
+
structures,
|
|
8
|
+
TENANT_1: structures.TENANT_1,
|
|
9
|
+
mocks,
|
|
10
|
+
TestConfiguration,
|
|
11
|
+
API,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export = pkg
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Account, AuthType, Hosting, CloudAccount } from "@budibase/types"
|
|
2
|
+
import { v4 as uuid } from "uuid"
|
|
3
|
+
import { utils } from "@budibase/backend-core"
|
|
4
|
+
|
|
5
|
+
export const account = (): Account => {
|
|
6
|
+
return {
|
|
7
|
+
email: `${uuid()}@test.com`,
|
|
8
|
+
tenantId: utils.newid(),
|
|
9
|
+
hosting: Hosting.SELF,
|
|
10
|
+
authType: AuthType.SSO,
|
|
11
|
+
accountId: uuid(),
|
|
12
|
+
createdAt: Date.now(),
|
|
13
|
+
verified: true,
|
|
14
|
+
verificationSent: true,
|
|
15
|
+
tier: "FREE",
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const cloudAccount = (): CloudAccount => {
|
|
20
|
+
return {
|
|
21
|
+
...account(),
|
|
22
|
+
budibaseUserId: uuid(),
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import configs from "./configs"
|
|
2
|
+
import * as users from "./users"
|
|
3
|
+
import * as groups from "./groups"
|
|
4
|
+
import * as accounts from "./accounts"
|
|
5
|
+
|
|
6
|
+
const TENANT_ID = "default"
|
|
7
|
+
const TENANT_1 = "tenant1"
|
|
8
|
+
const CSRF_TOKEN = "e3727778-7af0-4226-b5eb-f43cbe60a306"
|
|
9
|
+
|
|
10
|
+
const pkg = {
|
|
11
|
+
configs,
|
|
12
|
+
users,
|
|
13
|
+
accounts,
|
|
14
|
+
TENANT_ID,
|
|
15
|
+
TENANT_1,
|
|
16
|
+
CSRF_TOKEN,
|
|
17
|
+
groups,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export = pkg
|
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
export const email = "test@test.com"
|
|
2
|
+
import { AdminUser, BuilderUser, User } from "@budibase/types"
|
|
3
|
+
import { v4 as uuid } from "uuid"
|
|
2
4
|
|
|
3
|
-
export const
|
|
5
|
+
export const newEmail = () => {
|
|
6
|
+
return `${uuid()}@test.com`
|
|
7
|
+
}
|
|
8
|
+
export const user = (userProps?: any): User => {
|
|
4
9
|
return {
|
|
5
|
-
email:
|
|
10
|
+
email: newEmail(),
|
|
6
11
|
password: "test",
|
|
7
12
|
roles: {},
|
|
8
13
|
...userProps,
|
|
9
14
|
}
|
|
10
15
|
}
|
|
11
16
|
|
|
12
|
-
export const adminUser = (userProps
|
|
17
|
+
export const adminUser = (userProps?: any): AdminUser => {
|
|
13
18
|
return {
|
|
14
19
|
...user(userProps),
|
|
15
20
|
admin: {
|
|
16
21
|
global: true,
|
|
17
22
|
},
|
|
23
|
+
builder: {
|
|
24
|
+
global: true,
|
|
25
|
+
},
|
|
18
26
|
}
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
export const builderUser = (userProps
|
|
29
|
+
export const builderUser = (userProps?: any): BuilderUser => {
|
|
22
30
|
return {
|
|
23
31
|
...user(userProps),
|
|
24
32
|
builder: {
|