@budibase/worker 1.2.58-alpha.6 → 1.2.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/package.json +6 -7
  2. package/scripts/jestSetup.js +0 -6
  3. package/scripts/load/users.js +97 -0
  4. package/src/api/controllers/global/auth.ts +1 -14
  5. package/src/api/controllers/global/users.ts +55 -26
  6. package/src/api/{index.ts → index.js} +16 -12
  7. package/src/api/routes/global/configs.js +0 -1
  8. package/src/api/routes/index.js +0 -2
  9. package/src/api/routes/{global/tests/auth.spec.ts → tests/auth.spec.js} +56 -32
  10. package/src/api/routes/{global/tests/configs.spec.ts → tests/configs.spec.js} +47 -76
  11. package/src/api/routes/{global/tests/email.spec.ts → tests/email.spec.js} +15 -7
  12. package/src/api/routes/{global/tests/realEmail.spec.ts → tests/realEmail.spec.js} +21 -20
  13. package/src/api/routes/{global/tests/self.spec.ts → tests/self.spec.js} +18 -10
  14. package/src/api/routes/tests/users.spec.js +390 -0
  15. package/src/{environment.ts → environment.js} +9 -10
  16. package/src/index.ts +4 -6
  17. package/src/sdk/index.ts +0 -1
  18. package/src/sdk/users/users.ts +77 -271
  19. package/src/tests/TestConfiguration.js +231 -0
  20. package/src/tests/index.js +12 -0
  21. package/src/tests/mocks/index.js +5 -0
  22. package/src/tests/structures/index.js +14 -0
  23. package/src/tests/structures/users.ts +4 -12
  24. package/src/utilities/redis.js +0 -1
  25. package/src/api/controllers/system/accounts.ts +0 -21
  26. package/src/api/routes/global/tests/users.spec.ts +0 -512
  27. package/src/api/routes/system/accounts.ts +0 -19
  28. package/src/api/routes/system/tests/accounts.spec.ts +0 -57
  29. package/src/sdk/accounts/accounts.ts +0 -53
  30. package/src/sdk/accounts/index.ts +0 -1
  31. package/src/tests/TestConfiguration.ts +0 -273
  32. package/src/tests/api/accounts.ts +0 -28
  33. package/src/tests/api/auth.ts +0 -48
  34. package/src/tests/api/configs.ts +0 -40
  35. package/src/tests/api/email.ts +0 -24
  36. package/src/tests/api/index.ts +0 -25
  37. package/src/tests/api/self.ts +0 -21
  38. package/src/tests/api/users.ts +0 -111
  39. package/src/tests/index.ts +0 -14
  40. package/src/tests/mocks/index.ts +0 -7
  41. package/src/tests/structures/accounts.ts +0 -24
  42. package/src/tests/structures/index.ts +0 -20
@@ -14,28 +14,9 @@ import {
14
14
  HTTPError,
15
15
  accounts,
16
16
  migrations,
17
- StaticDatabases,
18
- ViewName,
19
- events,
20
17
  } from "@budibase/backend-core"
21
- import {
22
- MigrationType,
23
- PlatformUserByEmail,
24
- User,
25
- BulkCreateUsersResponse,
26
- CreateUserResponse,
27
- BulkDeleteUsersResponse,
28
- CloudAccount,
29
- AllDocsResponse,
30
- RowResponse,
31
- BulkDocsResponse,
32
- AccountMetadata,
33
- InviteUsersRequest,
34
- InviteUsersResponse,
35
- } from "@budibase/types"
18
+ import { MigrationType, User } from "@budibase/types"
36
19
  import { groups as groupUtils } from "@budibase/pro"
37
- import { sendEmail } from "../../utilities/email"
38
- import { EmailTemplatePurpose } from "../../constants"
39
20
 
40
21
  const PAGE_LIMIT = 8
41
22
 
@@ -117,6 +98,7 @@ export const getUser = async (userId: string) => {
117
98
  interface SaveUserOpts {
118
99
  hashPassword?: boolean
119
100
  requirePassword?: boolean
101
+ bulkCreate?: boolean
120
102
  }
121
103
 
122
104
  const buildUser = async (
@@ -127,7 +109,7 @@ const buildUser = async (
127
109
  },
128
110
  tenantId: string,
129
111
  dbUser?: any
130
- ): Promise<User> => {
112
+ ) => {
131
113
  let { password, _id } = user
132
114
 
133
115
  let hashedPassword
@@ -161,63 +143,62 @@ const buildUser = async (
161
143
  return user
162
144
  }
163
145
 
164
- const validateUniqueUser = async (email: string, tenantId: string) => {
165
- // check budibase users in other tenants
166
- if (env.MULTI_TENANCY) {
167
- const tenantUser = await tenancy.getTenantUser(email)
168
- if (tenantUser != null && tenantUser.tenantId !== tenantId) {
169
- throw `Unavailable`
170
- }
171
- }
172
-
173
- // check root account users in account portal
174
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
175
- const account = await accounts.getAccount(email)
176
- if (account && account.verified && account.tenantId !== tenantId) {
177
- throw `Unavailable`
178
- }
179
- }
180
- }
181
-
182
146
  export const save = async (
183
- user: User,
147
+ user: any,
184
148
  opts: SaveUserOpts = {
185
149
  hashPassword: true,
186
150
  requirePassword: true,
151
+ bulkCreate: false,
187
152
  }
188
- ): Promise<CreateUserResponse> => {
153
+ ) => {
189
154
  const tenantId = tenancy.getTenantId()
190
155
  const db = tenancy.getGlobalDB()
191
156
  let { email, _id } = user
192
-
193
- let dbUser: User | undefined
194
- if (_id) {
195
- // try to get existing user from db
196
- dbUser = (await db.get(_id)) as User
197
- if (email && dbUser.email !== email) {
198
- throw "Email address cannot be changed"
199
- }
200
- email = dbUser.email
157
+ // make sure another user isn't using the same email
158
+ let dbUser: any
159
+ if (opts.bulkCreate) {
160
+ dbUser = null
201
161
  } else if (email) {
202
- // no id was specified - load from email instead
162
+ // check budibase users inside the tenant
203
163
  dbUser = await usersCore.getGlobalUserByEmail(email)
204
- if (dbUser && dbUser._id !== _id) {
205
- throw `Unavailable`
164
+ if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) {
165
+ throw `Email address ${email} already in use.`
206
166
  }
207
- } else {
208
- throw new Error("_id or email is required")
209
- }
210
167
 
211
- await validateUniqueUser(email, tenantId)
168
+ // check budibase users in other tenants
169
+ if (env.MULTI_TENANCY) {
170
+ const tenantUser = await tenancy.getTenantUser(email)
171
+ if (tenantUser != null && tenantUser.tenantId !== tenantId) {
172
+ throw `Email address ${email} already in use.`
173
+ }
174
+ }
175
+
176
+ // check root account users in account portal
177
+ if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
178
+ const account = await accounts.getAccount(email)
179
+ if (account && account.verified && account.tenantId !== tenantId) {
180
+ throw `Email address ${email} already in use.`
181
+ }
182
+ }
183
+ } else if (_id) {
184
+ dbUser = await db.get(_id)
185
+ }
212
186
 
213
187
  let builtUser = await buildUser(user, opts, tenantId, dbUser)
214
188
 
215
189
  // make sure we set the _id field for a new user
216
190
  if (!_id) {
217
- _id = builtUser._id!
191
+ _id = builtUser._id
218
192
  }
219
193
 
220
194
  try {
195
+ const putOpts = {
196
+ password: builtUser.password,
197
+ ...user,
198
+ }
199
+ if (opts.bulkCreate) {
200
+ return putOpts
201
+ }
221
202
  // save the user to db
222
203
  let response
223
204
  const putUserFn = () => {
@@ -266,87 +247,29 @@ export const addTenant = async (
266
247
  }
267
248
  }
268
249
 
269
- const getExistingTenantUsers = async (emails: string[]): Promise<User[]> => {
270
- return dbUtils.queryGlobalView(ViewName.USER_BY_EMAIL, {
271
- keys: emails,
272
- include_docs: true,
273
- arrayResponse: true,
274
- })
275
- }
276
-
277
- const getExistingPlatformUsers = async (
278
- emails: string[]
279
- ): Promise<PlatformUserByEmail[]> => {
280
- return dbUtils.doWithDB(
281
- StaticDatabases.PLATFORM_INFO.name,
282
- async (infoDb: any) => {
283
- const response: AllDocsResponse<PlatformUserByEmail> =
284
- await infoDb.allDocs({
285
- keys: emails,
286
- include_docs: true,
287
- })
288
- return response.rows
289
- .filter(row => row.doc && (row.error !== "not_found") !== null)
290
- .map((row: any) => row.doc)
291
- }
292
- )
293
- }
294
-
295
- const getExistingAccounts = async (
296
- emails: string[]
297
- ): Promise<AccountMetadata[]> => {
298
- return dbUtils.queryPlatformView(ViewName.ACCOUNT_BY_EMAIL, {
299
- keys: emails,
300
- include_docs: true,
301
- arrayResponse: true,
302
- })
303
- }
304
-
305
- /**
306
- * Apply a system-wide search on emails:
307
- * - in tenant
308
- * - cross tenant
309
- * - accounts
310
- * return an array of emails that match the supplied emails.
311
- */
312
- const searchExistingEmails = async (emails: string[]) => {
313
- let matchedEmails: string[] = []
314
-
315
- const existingTenantUsers = await getExistingTenantUsers(emails)
316
- matchedEmails.push(...existingTenantUsers.map(user => user.email))
317
-
318
- const existingPlatformUsers = await getExistingPlatformUsers(emails)
319
- matchedEmails.push(...existingPlatformUsers.map(user => user._id!))
320
-
321
- const existingAccounts = await getExistingAccounts(emails)
322
- matchedEmails.push(...existingAccounts.map(account => account.email))
323
-
324
- return [...new Set(matchedEmails)]
325
- }
326
-
327
250
  export const bulkCreate = async (
328
251
  newUsersRequested: User[],
329
252
  groups: string[]
330
- ): Promise<BulkCreateUsersResponse> => {
253
+ ) => {
331
254
  const db = tenancy.getGlobalDB()
332
255
  const tenantId = tenancy.getTenantId()
333
256
 
334
257
  let usersToSave: any[] = []
335
258
  let newUsers: any[] = []
336
259
 
337
- const emails = newUsersRequested.map((user: User) => user.email)
338
- const existingEmails = await searchExistingEmails(emails)
339
- const unsuccessful: { email: string; reason: string }[] = []
260
+ const allUsers = await db.allDocs(
261
+ dbUtils.getGlobalUserParams(null, {
262
+ include_docs: true,
263
+ })
264
+ )
265
+ let mapped = allUsers.rows.map((row: any) => row.id)
340
266
 
267
+ const currentUserEmails = mapped.map((x: any) => x.email) || []
341
268
  for (const newUser of newUsersRequested) {
342
269
  if (
343
270
  newUsers.find((x: any) => x.email === newUser.email) ||
344
- existingEmails.includes(newUser.email)
271
+ currentUserEmails.includes(newUser.email)
345
272
  ) {
346
- unsuccessful.push({
347
- email: newUser.email,
348
- reason: `Unavailable`,
349
- })
350
273
  continue
351
274
  }
352
275
  newUser.userGroups = groups
@@ -384,129 +307,62 @@ export const bulkCreate = async (
384
307
  await apps.syncUserInApps(user._id)
385
308
  }
386
309
 
387
- const saved = usersToBulkSave.map(user => {
310
+ return usersToBulkSave.map(user => {
388
311
  return {
389
312
  _id: user._id,
390
313
  email: user.email,
391
314
  }
392
315
  })
393
-
394
- return {
395
- successful: saved,
396
- unsuccessful,
397
- }
398
- }
399
-
400
- /**
401
- * For the given user id's, return the account holder if it is in the ids.
402
- */
403
- const getAccountHolderFromUserIds = async (
404
- userIds: string[]
405
- ): Promise<CloudAccount | undefined> => {
406
- if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
407
- const tenantId = tenancy.getTenantId()
408
- const account = await accounts.getAccountByTenantId(tenantId)
409
- if (!account) {
410
- throw new Error(`Account not found for tenantId=${tenantId}`)
411
- }
412
-
413
- const budibaseUserId = account.budibaseUserId
414
- if (userIds.includes(budibaseUserId)) {
415
- return account
416
- }
417
- }
418
316
  }
419
317
 
420
- export const bulkDelete = async (
421
- userIds: string[]
422
- ): Promise<BulkDeleteUsersResponse> => {
318
+ export const bulkDelete = async (userIds: any) => {
423
319
  const db = tenancy.getGlobalDB()
424
320
 
425
- const response: BulkDeleteUsersResponse = {
426
- successful: [],
427
- unsuccessful: [],
428
- }
429
-
430
- // remove the account holder from the delete request if present
431
- const account = await getAccountHolderFromUserIds(userIds)
432
- if (account) {
433
- userIds = userIds.filter(u => u !== account.budibaseUserId)
434
- // mark user as unsuccessful
435
- response.unsuccessful.push({
436
- _id: account.budibaseUserId,
437
- email: account.email,
438
- reason: "Account holder cannot be deleted",
439
- })
440
- }
441
-
442
321
  let groupsToModify: any = {}
443
322
  let builderCount = 0
444
-
445
323
  // Get users and delete
446
- const allDocsResponse: AllDocsResponse<User> = await db.allDocs({
447
- include_docs: true,
448
- keys: userIds,
449
- })
450
- const usersToDelete: User[] = allDocsResponse.rows.map(
451
- (user: RowResponse<User>) => {
452
- // if we find a user that has an associated group, add it to
453
- // an array so we can easily use allDocs on them later.
454
- // This prevents us having to re-loop over all the users
455
- if (user.doc.userGroups) {
456
- for (let groupId of user.doc.userGroups) {
457
- if (!Object.keys(groupsToModify).includes(groupId)) {
458
- groupsToModify[groupId] = [user.id]
459
- } else {
460
- groupsToModify[groupId] = [...groupsToModify[groupId], user.id]
461
- }
324
+ let usersToDelete = (
325
+ await db.allDocs({
326
+ include_docs: true,
327
+ keys: userIds,
328
+ })
329
+ ).rows.map((user: any) => {
330
+ // if we find a user that has an associated group, add it to
331
+ // an array so we can easily use allDocs on them later.
332
+ // This prevents us having to re-loop over all the users
333
+ if (user.doc.userGroups) {
334
+ for (let groupId of user.doc.userGroups) {
335
+ if (!Object.keys(groupsToModify).includes(groupId)) {
336
+ groupsToModify[groupId] = [user.id]
337
+ } else {
338
+ groupsToModify[groupId] = [...groupsToModify[groupId], user.id]
462
339
  }
463
340
  }
341
+ }
464
342
 
465
- // Also figure out how many builders are being deleted
466
- if (eventHelpers.isAddingBuilder(user.doc, null)) {
467
- builderCount++
468
- }
469
-
470
- return user.doc
343
+ // Also figure out how many builders are being deleted
344
+ if (eventHelpers.isAddingBuilder(user.doc, null)) {
345
+ builderCount++
471
346
  }
472
- )
473
347
 
474
- // Delete from DB
475
- const dbResponse: BulkDocsResponse = await db.bulkDocs(
476
- usersToDelete.map(user => ({
348
+ return user.doc
349
+ })
350
+
351
+ const response = await db.bulkDocs(
352
+ usersToDelete.map((user: any) => ({
477
353
  ...user,
478
354
  _deleted: true,
479
355
  }))
480
356
  )
481
357
 
482
- // Deletion post processing
483
358
  await groupUtils.bulkDeleteGroupUsers(groupsToModify)
359
+
360
+ //Deletion post processing
484
361
  for (let user of usersToDelete) {
485
362
  await bulkDeleteProcessing(user)
486
363
  }
487
- await quotas.removeDevelopers(builderCount)
488
364
 
489
- // Build Response
490
- // index users by id
491
- const userIndex: { [key: string]: User } = {}
492
- usersToDelete.reduce((prev, current) => {
493
- prev[current._id!] = current
494
- return prev
495
- }, userIndex)
496
-
497
- // add the successful and unsuccessful users to response
498
- dbResponse.forEach(item => {
499
- const email = userIndex[item.id].email
500
- if (item.ok) {
501
- response.successful.push({ _id: item.id, email })
502
- } else {
503
- response.unsuccessful.push({
504
- _id: item.id,
505
- email,
506
- reason: "Database error",
507
- })
508
- }
509
- })
365
+ await quotas.removeDevelopers(builderCount)
510
366
 
511
367
  return response
512
368
  }
@@ -555,53 +411,3 @@ const bulkDeleteProcessing = async (dbUser: User) => {
555
411
  // let server know to sync user
556
412
  await apps.syncUserInApps(userId)
557
413
  }
558
-
559
- export const invite = async (
560
- users: InviteUsersRequest
561
- ): Promise<InviteUsersResponse> => {
562
- const response: InviteUsersResponse = {
563
- successful: [],
564
- unsuccessful: [],
565
- }
566
-
567
- const matchedEmails = await searchExistingEmails(users.map(u => u.email))
568
- const newUsers = []
569
-
570
- // separate duplicates from new users
571
- for (let user of users) {
572
- if (matchedEmails.includes(user.email)) {
573
- response.unsuccessful.push({ email: user.email, reason: "Unavailable" })
574
- } else {
575
- newUsers.push(user)
576
- }
577
- }
578
- // overwrite users with new only
579
- users = newUsers
580
-
581
- // send the emails for new users
582
- const tenantId = tenancy.getTenantId()
583
- for (let user of users) {
584
- try {
585
- let userInfo = user.userInfo
586
- if (!userInfo) {
587
- userInfo = {}
588
- }
589
- userInfo.tenantId = tenantId
590
- const opts: any = {
591
- subject: "{{ company }} platform invitation",
592
- info: userInfo,
593
- }
594
- await sendEmail(user.email, EmailTemplatePurpose.INVITATION, opts)
595
- response.successful.push({ email: user.email })
596
- await events.user.invited()
597
- } catch (e) {
598
- console.error(`Failed to send email invitation email=${user.email}`, e)
599
- response.unsuccessful.push({
600
- email: user.email,
601
- reason: "Failed to send email",
602
- })
603
- }
604
- }
605
-
606
- return response
607
- }
@@ -0,0 +1,231 @@
1
+ require("./mocks")
2
+ require("../db").init()
3
+ const env = require("../environment")
4
+ const controllers = require("./controllers")
5
+ const supertest = require("supertest")
6
+ const { jwt } = require("@budibase/backend-core/auth")
7
+ const { Cookies, Headers } = require("@budibase/backend-core/constants")
8
+ const { Configs } = require("../constants")
9
+ const { users } = require("@budibase/backend-core")
10
+ const { createASession } = require("@budibase/backend-core/sessions")
11
+ const { TENANT_ID, CSRF_TOKEN } = require("./structures")
12
+ const structures = require("./structures")
13
+ const { doInTenant } = require("@budibase/backend-core/tenancy")
14
+ const { groups } = require("@budibase/pro")
15
+ class TestConfiguration {
16
+ constructor(openServer = true) {
17
+ if (openServer) {
18
+ env.PORT = "0" // random port
19
+ this.server = require("../index")
20
+ // we need the request for logging in, involves cookies, hard to fake
21
+ this.request = supertest(this.server)
22
+ }
23
+ }
24
+
25
+ getRequest() {
26
+ return this.request
27
+ }
28
+
29
+ // UTILS
30
+
31
+ async _req(config, params, controlFunc) {
32
+ const request = {}
33
+ // fake cookies, we don't need them
34
+ request.cookies = { set: () => {}, get: () => {} }
35
+ request.config = { jwtSecret: env.JWT_SECRET }
36
+ request.appId = this.appId
37
+ request.user = { appId: this.appId, tenantId: TENANT_ID }
38
+ request.query = {}
39
+ request.request = {
40
+ body: config,
41
+ }
42
+ request.throw = (status, err) => {
43
+ throw { status, message: err }
44
+ }
45
+ if (params) {
46
+ request.params = params
47
+ }
48
+ await doInTenant(TENANT_ID, () => {
49
+ return controlFunc(request)
50
+ })
51
+ return request.body
52
+ }
53
+
54
+ // SETUP / TEARDOWN
55
+
56
+ async beforeAll() {
57
+ await this.login()
58
+ }
59
+
60
+ async afterAll() {
61
+ if (this.server) {
62
+ await this.server.close()
63
+ }
64
+ }
65
+
66
+ // USER / AUTH
67
+
68
+ async login() {
69
+ // create a test user
70
+ await this._req(
71
+ {
72
+ email: "test@test.com",
73
+ password: "test",
74
+ _id: "us_uuid1",
75
+ builder: {
76
+ global: true,
77
+ },
78
+ admin: {
79
+ global: true,
80
+ },
81
+ },
82
+ null,
83
+ controllers.users.save
84
+ )
85
+ await createASession("us_uuid1", {
86
+ sessionId: "sessionid",
87
+ tenantId: TENANT_ID,
88
+ csrfToken: CSRF_TOKEN,
89
+ })
90
+ }
91
+
92
+ cookieHeader(cookies) {
93
+ return {
94
+ Cookie: [cookies],
95
+ }
96
+ }
97
+
98
+ defaultHeaders() {
99
+ const user = {
100
+ _id: "us_uuid1",
101
+ userId: "us_uuid1",
102
+ sessionId: "sessionid",
103
+ tenantId: TENANT_ID,
104
+ }
105
+ const authToken = jwt.sign(user, env.JWT_SECRET)
106
+ return {
107
+ Accept: "application/json",
108
+ ...this.cookieHeader([`${Cookies.Auth}=${authToken}`]),
109
+ [Headers.CSRF_TOKEN]: CSRF_TOKEN,
110
+ }
111
+ }
112
+
113
+ async getUser(email) {
114
+ return doInTenant(TENANT_ID, () => {
115
+ return users.getGlobalUserByEmail(email)
116
+ })
117
+ }
118
+
119
+ async getGroup(id) {
120
+ return doInTenant(TENANT_ID, () => {
121
+ return groups.get(id)
122
+ })
123
+ }
124
+
125
+ async saveGroup(group) {
126
+ const res = await this.getRequest()
127
+ .post(`/api/global/groups`)
128
+ .send(group)
129
+ .set(this.defaultHeaders())
130
+ .expect("Content-Type", /json/)
131
+ .expect(200)
132
+ return res.body
133
+ }
134
+
135
+ async createUser(email, password) {
136
+ const user = await this.getUser(structures.users.email)
137
+ if (user) {
138
+ return user
139
+ }
140
+ await this._req(
141
+ structures.users.user({ email, password }),
142
+ null,
143
+ controllers.users.save
144
+ )
145
+ }
146
+
147
+ async saveAdminUser() {
148
+ await this._req(
149
+ structures.users.user({ tenantId: TENANT_ID }),
150
+ null,
151
+ controllers.users.adminUser
152
+ )
153
+ }
154
+
155
+ // CONFIGS
156
+
157
+ async deleteConfig(type) {
158
+ try {
159
+ const cfg = await this._req(
160
+ null,
161
+ {
162
+ type,
163
+ },
164
+ controllers.config.find
165
+ )
166
+ if (cfg) {
167
+ await this._req(
168
+ null,
169
+ {
170
+ id: cfg._id,
171
+ rev: cfg._rev,
172
+ },
173
+ controllers.config.destroy
174
+ )
175
+ }
176
+ } catch (err) {
177
+ // don't need to handle error
178
+ }
179
+ }
180
+
181
+ // CONFIGS - SETTINGS
182
+
183
+ async saveSettingsConfig() {
184
+ await this.deleteConfig(Configs.SETTINGS)
185
+ await this._req(
186
+ structures.configs.settings(),
187
+ null,
188
+ controllers.config.save
189
+ )
190
+ }
191
+
192
+ // CONFIGS - GOOGLE
193
+
194
+ async saveGoogleConfig() {
195
+ await this.deleteConfig(Configs.GOOGLE)
196
+ await this._req(structures.configs.google(), null, controllers.config.save)
197
+ }
198
+
199
+ // CONFIGS - OIDC
200
+
201
+ getOIDConfigCookie(configId) {
202
+ const token = jwt.sign(configId, env.JWT_SECRET)
203
+ return this.cookieHeader([[`${Cookies.OIDC_CONFIG}=${token}`]])
204
+ }
205
+
206
+ async saveOIDCConfig() {
207
+ await this.deleteConfig(Configs.OIDC)
208
+ const config = structures.configs.oidc()
209
+
210
+ await this._req(config, null, controllers.config.save)
211
+ return config
212
+ }
213
+
214
+ // CONFIGS - SMTP
215
+
216
+ async saveSmtpConfig() {
217
+ await this.deleteConfig(Configs.SMTP)
218
+ await this._req(structures.configs.smtp(), null, controllers.config.save)
219
+ }
220
+
221
+ async saveEtherealSmtpConfig() {
222
+ await this.deleteConfig(Configs.SMTP)
223
+ await this._req(
224
+ structures.configs.smtpEthereal(),
225
+ null,
226
+ controllers.config.save
227
+ )
228
+ }
229
+ }
230
+
231
+ module.exports = TestConfiguration
@@ -0,0 +1,12 @@
1
+ const TestConfiguration = require("./TestConfiguration")
2
+ const structures = require("./structures")
3
+ const mocks = require("./mocks")
4
+ const config = new TestConfiguration()
5
+ const request = config.getRequest()
6
+
7
+ module.exports = {
8
+ structures,
9
+ mocks,
10
+ config,
11
+ request,
12
+ }
@@ -0,0 +1,5 @@
1
+ const email = require("./email")
2
+
3
+ module.exports = {
4
+ email,
5
+ }