@budibase/worker 2.1.22-alpha.4 → 2.1.22-alpha.6

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 (156) hide show
  1. package/__mocks__/oauth.ts +57 -0
  2. package/coverage/clover.xml +1093 -1033
  3. package/coverage/coverage-final.json +77 -72
  4. package/coverage/lcov-report/index.html +83 -83
  5. package/coverage/lcov-report/src/api/controllers/global/auth.ts.html +70 -70
  6. package/coverage/lcov-report/src/api/controllers/global/configs.js.html +35 -35
  7. package/coverage/lcov-report/src/api/controllers/global/email.js.html +4 -4
  8. package/coverage/lcov-report/src/api/controllers/global/index.html +38 -38
  9. package/coverage/lcov-report/src/api/controllers/global/license.ts.html +7 -7
  10. package/coverage/lcov-report/src/api/controllers/global/roles.js.html +10 -10
  11. package/coverage/lcov-report/src/api/controllers/global/self.ts.html +58 -58
  12. package/coverage/lcov-report/src/api/controllers/global/templates.ts.html +11 -11
  13. package/coverage/lcov-report/src/api/controllers/global/users.ts.html +75 -69
  14. package/coverage/lcov-report/src/api/controllers/global/workspaces.js.html +7 -7
  15. package/coverage/lcov-report/src/api/controllers/system/accounts.ts.html +4 -4
  16. package/coverage/lcov-report/src/api/controllers/system/{environment.js.html → environment.ts.html} +21 -18
  17. package/coverage/lcov-report/src/api/controllers/system/index.html +63 -63
  18. package/coverage/lcov-report/src/api/controllers/system/migrations.ts.html +23 -23
  19. package/coverage/lcov-report/src/api/controllers/system/restore.ts.html +22 -22
  20. package/coverage/lcov-report/src/api/controllers/system/{status.js.html → status.ts.html} +29 -26
  21. package/coverage/lcov-report/src/api/controllers/system/tenants.ts.html +34 -163
  22. package/coverage/lcov-report/src/api/index.html +11 -11
  23. package/coverage/lcov-report/src/api/index.ts.html +113 -44
  24. package/coverage/lcov-report/src/api/routes/global/auth.js.html +38 -89
  25. package/coverage/lcov-report/src/api/routes/global/configs.js.html +17 -17
  26. package/coverage/lcov-report/src/api/routes/global/email.js.html +11 -11
  27. package/coverage/lcov-report/src/api/routes/global/index.html +11 -11
  28. package/coverage/lcov-report/src/api/routes/global/license.ts.html +6 -6
  29. package/coverage/lcov-report/src/api/routes/global/roles.js.html +7 -7
  30. package/coverage/lcov-report/src/api/routes/global/self.ts.html +8 -8
  31. package/coverage/lcov-report/src/api/routes/global/templates.ts.html +11 -11
  32. package/coverage/lcov-report/src/api/routes/global/users.js.html +17 -17
  33. package/coverage/lcov-report/src/api/routes/global/workspaces.js.html +10 -10
  34. package/coverage/lcov-report/src/api/routes/index.html +1 -1
  35. package/coverage/lcov-report/src/api/routes/index.ts.html +19 -19
  36. package/coverage/lcov-report/src/api/routes/system/accounts.ts.html +7 -7
  37. package/coverage/lcov-report/src/api/routes/system/{environment.js.html → environment.ts.html} +11 -11
  38. package/coverage/lcov-report/src/api/routes/system/index.html +4 -4
  39. package/coverage/lcov-report/src/api/routes/system/migrations.ts.html +7 -7
  40. package/coverage/lcov-report/src/api/routes/system/restore.ts.html +6 -6
  41. package/coverage/lcov-report/src/api/routes/system/{status.js.html → status.ts.html} +11 -11
  42. package/coverage/lcov-report/src/api/routes/system/{tenants.js.html → tenants.ts.html} +20 -17
  43. package/coverage/lcov-report/src/api/routes/validation/index.html +1 -1
  44. package/coverage/lcov-report/src/api/routes/validation/index.ts.html +2 -2
  45. package/coverage/lcov-report/src/api/routes/validation/users.ts.html +13 -13
  46. package/coverage/lcov-report/src/constants/index.html +1 -1
  47. package/coverage/lcov-report/src/constants/index.js.html +18 -18
  48. package/coverage/lcov-report/src/constants/templates/index.html +1 -1
  49. package/coverage/lcov-report/src/constants/templates/index.js.html +10 -10
  50. package/coverage/lcov-report/src/db/index.html +1 -1
  51. package/coverage/lcov-report/src/db/index.ts.html +8 -8
  52. package/coverage/lcov-report/src/environment.ts.html +15 -15
  53. package/coverage/lcov-report/src/index.html +1 -1
  54. package/coverage/lcov-report/src/index.ts.html +40 -40
  55. package/coverage/lcov-report/src/middleware/cloudRestricted.js.html +22 -22
  56. package/coverage/lcov-report/src/middleware/index.html +21 -21
  57. package/coverage/lcov-report/src/migrations/functions/globalInfoSyncUsers.ts.html +3 -3
  58. package/coverage/lcov-report/src/migrations/functions/index.html +1 -1
  59. package/coverage/lcov-report/src/migrations/index.html +1 -1
  60. package/coverage/lcov-report/src/migrations/index.ts.html +17 -17
  61. package/coverage/lcov-report/src/sdk/accounts/accounts.ts.html +6 -6
  62. package/coverage/lcov-report/src/sdk/accounts/index.html +1 -1
  63. package/coverage/lcov-report/src/sdk/accounts/index.ts.html +2 -2
  64. package/coverage/lcov-report/src/sdk/index.html +1 -1
  65. package/coverage/lcov-report/src/sdk/index.ts.html +4 -4
  66. package/coverage/lcov-report/src/sdk/users/events.ts.html +43 -43
  67. package/coverage/lcov-report/src/sdk/users/index.html +19 -19
  68. package/coverage/lcov-report/src/sdk/users/index.ts.html +2 -2
  69. package/coverage/lcov-report/src/sdk/users/users.ts.html +99 -99
  70. package/coverage/lcov-report/src/tests/TestConfiguration.ts.html +261 -123
  71. package/coverage/lcov-report/src/tests/api/accounts.ts.html +12 -21
  72. package/coverage/lcov-report/src/tests/api/auth.ts.html +11 -20
  73. package/coverage/lcov-report/src/tests/api/base.ts.html +133 -0
  74. package/coverage/lcov-report/src/tests/api/configs.ts.html +44 -23
  75. package/coverage/lcov-report/src/tests/api/email.ts.html +9 -18
  76. package/coverage/lcov-report/src/tests/api/environment.ts.html +130 -0
  77. package/coverage/lcov-report/src/tests/api/index.html +106 -16
  78. package/coverage/lcov-report/src/tests/api/index.ts.html +62 -17
  79. package/coverage/lcov-report/src/tests/{structures/accounts.ts.html → api/migrations.ts.html} +31 -37
  80. package/coverage/lcov-report/src/tests/api/restore.ts.html +127 -0
  81. package/coverage/lcov-report/src/tests/api/self.ts.html +31 -16
  82. package/coverage/lcov-report/src/tests/api/status.ts.html +121 -0
  83. package/coverage/lcov-report/src/tests/api/tenants.ts.html +130 -0
  84. package/coverage/lcov-report/src/tests/api/users.ts.html +121 -25
  85. package/coverage/lcov-report/src/tests/controllers.js.html +2 -2
  86. package/coverage/lcov-report/src/tests/index.html +20 -20
  87. package/coverage/lcov-report/src/tests/index.ts.html +21 -9
  88. package/coverage/lcov-report/src/tests/mocks/email.js.html +2 -2
  89. package/coverage/lcov-report/src/tests/mocks/index.html +1 -1
  90. package/coverage/lcov-report/src/tests/mocks/index.ts.html +4 -4
  91. package/coverage/lcov-report/src/tests/structures/configs.js.html +8 -8
  92. package/coverage/lcov-report/src/tests/structures/groups.ts.html +2 -2
  93. package/coverage/lcov-report/src/tests/structures/index.html +9 -24
  94. package/coverage/lcov-report/src/tests/structures/index.ts.html +21 -15
  95. package/coverage/lcov-report/src/tests/structures/users.ts.html +13 -10
  96. package/coverage/lcov-report/src/utilities/appService.js.html +11 -11
  97. package/coverage/lcov-report/src/utilities/email.js.html +16 -16
  98. package/coverage/lcov-report/src/utilities/fileSystem.js.html +4 -4
  99. package/coverage/lcov-report/src/utilities/index.html +1 -1
  100. package/coverage/lcov-report/src/utilities/index.js.html +2 -2
  101. package/coverage/lcov-report/src/utilities/redis.js.html +13 -13
  102. package/coverage/lcov-report/src/utilities/templates.js.html +7 -7
  103. package/coverage/lcov-report/src/utilities/users.js.html +8 -8
  104. package/coverage/lcov.info +1685 -1511
  105. package/package.json +8 -6
  106. package/scripts/localdomain.js +33 -7
  107. package/src/api/controllers/global/auth.ts +1 -1
  108. package/src/api/controllers/global/users.ts +3 -1
  109. package/src/api/controllers/system/{environment.js → environment.ts} +3 -2
  110. package/src/api/controllers/system/{status.js → status.ts} +4 -3
  111. package/src/api/controllers/system/tenants.ts +8 -51
  112. package/src/api/index.ts +29 -6
  113. package/src/api/routes/global/auth.js +22 -39
  114. package/src/api/routes/global/tests/auth.spec.ts +134 -64
  115. package/src/api/routes/global/tests/configs.spec.ts +5 -6
  116. package/src/api/routes/global/tests/email.spec.ts +4 -3
  117. package/src/api/routes/global/tests/license.spec.ts +31 -0
  118. package/src/api/routes/global/tests/realEmail.spec.ts +2 -3
  119. package/src/api/routes/global/tests/roles.spec.ts +27 -0
  120. package/src/api/routes/global/tests/self.spec.ts +3 -4
  121. package/src/api/routes/global/tests/templates.spec.ts +35 -0
  122. package/src/api/routes/global/tests/users.spec.ts +51 -43
  123. package/src/api/routes/global/tests/workspaces.spec.ts +29 -0
  124. package/src/api/routes/system/environment.ts +8 -0
  125. package/src/api/routes/system/status.ts +8 -0
  126. package/src/api/routes/system/tenants.ts +13 -0
  127. package/src/api/routes/system/tests/accounts.spec.ts +5 -6
  128. package/src/api/routes/system/tests/environment.spec.ts +29 -0
  129. package/src/api/routes/system/tests/migrations.spec.ts +63 -0
  130. package/src/api/routes/system/tests/restore.spec.ts +36 -0
  131. package/src/api/routes/system/tests/status.spec.ts +48 -0
  132. package/src/api/routes/system/tests/tenants.spec.ts +61 -0
  133. package/src/middleware/tests/tenancy.spec.ts +73 -0
  134. package/src/tests/TestConfiguration.ts +88 -42
  135. package/src/tests/api/accounts.ts +5 -8
  136. package/src/tests/api/auth.ts +3 -6
  137. package/src/tests/api/base.ts +16 -0
  138. package/src/tests/api/configs.ts +15 -8
  139. package/src/tests/api/email.ts +3 -6
  140. package/src/tests/api/environment.ts +15 -0
  141. package/src/tests/api/index.ts +15 -0
  142. package/src/tests/api/migrations.ts +22 -0
  143. package/src/tests/api/restore.ts +14 -0
  144. package/src/tests/api/self.ts +11 -6
  145. package/src/tests/api/status.ts +12 -0
  146. package/src/tests/api/tenants.ts +15 -0
  147. package/src/tests/api/users.ts +38 -6
  148. package/src/tests/index.ts +4 -0
  149. package/src/tests/jestSetup.ts +7 -1
  150. package/src/tests/structures/index.ts +4 -2
  151. package/src/tests/structures/users.ts +1 -0
  152. package/__mocks__/node-fetch.ts +0 -1
  153. package/src/api/routes/system/environment.js +0 -8
  154. package/src/api/routes/system/status.js +0 -8
  155. package/src/api/routes/system/tenants.js +0 -12
  156. package/src/tests/structures/accounts.ts +0 -24
@@ -1,10 +1,9 @@
1
1
  import sdk from "../../../../sdk"
2
- import { TestConfiguration, structures, API } from "../../../../tests"
2
+ import { TestConfiguration, structures } 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)
8
7
 
9
8
  beforeAll(async () => {
10
9
  await config.beforeAll()
@@ -23,7 +22,7 @@ describe("accounts", () => {
23
22
  it("saves account metadata", async () => {
24
23
  let account = structures.accounts.account()
25
24
 
26
- const response = await api.accounts.saveMetadata(account)
25
+ const response = await config.api.accounts.saveMetadata(account)
27
26
 
28
27
  const id = sdk.accounts.formatAccountMetadataId(account.accountId)
29
28
  const metadata = await sdk.accounts.getMetadata(id)
@@ -34,9 +33,9 @@ describe("accounts", () => {
34
33
  describe("destroyMetadata", () => {
35
34
  it("destroys account metadata", async () => {
36
35
  const account = structures.accounts.account()
37
- await api.accounts.saveMetadata(account)
36
+ await config.api.accounts.saveMetadata(account)
38
37
 
39
- await api.accounts.destroyMetadata(account.accountId)
38
+ await config.api.accounts.destroyMetadata(account.accountId)
40
39
 
41
40
  const deleted = await sdk.accounts.getMetadata(account.accountId)
42
41
  expect(deleted).toBe(undefined)
@@ -45,7 +44,7 @@ describe("accounts", () => {
45
44
  it("destroys account metadata that does not exist", async () => {
46
45
  const id = uuid()
47
46
 
48
- const response = await api.accounts.destroyMetadata(id)
47
+ const response = await config.api.accounts.destroyMetadata(id)
49
48
 
50
49
  expect(response.status).toBe(204)
51
50
  })
@@ -0,0 +1,29 @@
1
+ import { TestConfiguration } from "../../../../tests"
2
+
3
+ describe("/api/system/environment", () => {
4
+ const config = new TestConfiguration()
5
+
6
+ beforeAll(async () => {
7
+ await config.beforeAll()
8
+ })
9
+
10
+ afterAll(async () => {
11
+ await config.afterAll()
12
+ })
13
+
14
+ afterEach(() => {
15
+ jest.clearAllMocks()
16
+ })
17
+
18
+ describe("GET /api/system/environment", () => {
19
+ it("returns the expected environment", async () => {
20
+ const env = await config.api.environment.getEnvironment()
21
+ expect(env.body).toEqual({
22
+ cloud: true,
23
+ disableAccountPortal: false,
24
+ isDev: false,
25
+ multiTenancy: true,
26
+ })
27
+ })
28
+ })
29
+ })
@@ -0,0 +1,63 @@
1
+ const migrateFn = jest.fn()
2
+
3
+ import { TestConfiguration } from "../../../../tests"
4
+
5
+ jest.mock("../../../../migrations", () => {
6
+ return {
7
+ ...jest.requireActual("../../../../migrations"),
8
+ migrate: migrateFn,
9
+ }
10
+ })
11
+
12
+ describe("/api/system/migrations", () => {
13
+ const config = new TestConfiguration()
14
+
15
+ beforeAll(async () => {
16
+ await config.beforeAll()
17
+ })
18
+
19
+ afterAll(async () => {
20
+ await config.afterAll()
21
+ })
22
+
23
+ afterEach(() => {
24
+ jest.clearAllMocks()
25
+ })
26
+
27
+ describe("POST /api/system/migrations/run", () => {
28
+ it("fails with no internal api key", async () => {
29
+ const res = await config.api.migrations.runMigrations({
30
+ headers: {},
31
+ status: 403,
32
+ })
33
+ expect(res.text).toBe("Unauthorized - no public worker access")
34
+ expect(migrateFn).toBeCalledTimes(0)
35
+ })
36
+
37
+ it("runs migrations", async () => {
38
+ const res = await config.api.migrations.runMigrations()
39
+ expect(res.text).toBe("OK")
40
+ expect(migrateFn).toBeCalledTimes(1)
41
+ })
42
+ })
43
+
44
+ describe("DELETE /api/system/migrations/definitions", () => {
45
+ it("fails with no internal api key", async () => {
46
+ const res = await config.api.migrations.getMigrationDefinitions({
47
+ headers: {},
48
+ status: 403,
49
+ })
50
+ expect(res.text).toBe("Unauthorized - no public worker access")
51
+ })
52
+
53
+ it("returns definitions", async () => {
54
+ const res = await config.api.migrations.getMigrationDefinitions()
55
+ expect(res.body).toEqual([
56
+ {
57
+ name: "global_info_sync_users",
58
+ type: "global",
59
+ },
60
+ ])
61
+ })
62
+ })
63
+ })
@@ -0,0 +1,36 @@
1
+ import { TestConfiguration } from "../../../../tests"
2
+
3
+ describe("/api/system/restore", () => {
4
+ const config = new TestConfiguration()
5
+
6
+ beforeAll(async () => {
7
+ await config.beforeAll()
8
+ })
9
+
10
+ afterAll(async () => {
11
+ await config.afterAll()
12
+ })
13
+
14
+ afterEach(() => {
15
+ jest.clearAllMocks()
16
+ })
17
+
18
+ describe("POST /api/global/restore", () => {
19
+ it("doesn't allow restore in cloud", async () => {
20
+ const res = await config.api.restore.restored({ status: 405 })
21
+ expect(res.body).toEqual({
22
+ message: "This operation is not allowed in cloud.",
23
+ status: 405,
24
+ })
25
+ })
26
+
27
+ it("restores in self host", async () => {
28
+ config.modeSelf()
29
+ const res = await config.api.restore.restored()
30
+ expect(res.body).toEqual({
31
+ message: "System prepared after restore.",
32
+ })
33
+ config.modeCloud()
34
+ })
35
+ })
36
+ })
@@ -0,0 +1,48 @@
1
+ import { TestConfiguration } from "../../../../tests"
2
+ import { accounts } from "@budibase/backend-core"
3
+ import { mocks } from "@budibase/backend-core/tests"
4
+
5
+ describe("/api/system/status", () => {
6
+ const config = new TestConfiguration()
7
+
8
+ beforeAll(async () => {
9
+ await config.beforeAll()
10
+ })
11
+
12
+ afterAll(async () => {
13
+ await config.afterAll()
14
+ })
15
+
16
+ afterEach(() => {
17
+ jest.clearAllMocks()
18
+ })
19
+
20
+ describe("GET /api/system/status", () => {
21
+ it("returns status in self host", async () => {
22
+ config.modeSelf()
23
+ const res = await config.api.status.getStatus()
24
+ expect(res.body).toEqual({
25
+ health: {
26
+ passing: true,
27
+ },
28
+ })
29
+ expect(accounts.getStatus).toBeCalledTimes(0)
30
+ config.modeCloud()
31
+ })
32
+
33
+ it("returns status in cloud", async () => {
34
+ const value = {
35
+ health: {
36
+ passing: false,
37
+ },
38
+ }
39
+
40
+ mocks.accounts.getStatus.mockReturnValueOnce(value)
41
+
42
+ const res = await config.api.status.getStatus()
43
+
44
+ expect(accounts.getStatus).toBeCalledTimes(1)
45
+ expect(res.body).toEqual(value)
46
+ })
47
+ })
48
+ })
@@ -0,0 +1,61 @@
1
+ import { TestConfiguration } from "../../../../tests"
2
+ import { tenancy } from "@budibase/backend-core"
3
+
4
+ describe("/api/global/tenants", () => {
5
+ const config = new TestConfiguration()
6
+
7
+ beforeAll(async () => {
8
+ await config.beforeAll()
9
+ })
10
+
11
+ afterAll(async () => {
12
+ await config.afterAll()
13
+ })
14
+
15
+ afterEach(() => {
16
+ jest.clearAllMocks()
17
+ })
18
+
19
+ describe("DELETE /api/system/tenants/:tenantId", () => {
20
+ it("allows deleting the current tenant", async () => {
21
+ const user = await config.createTenant()
22
+
23
+ await config.api.tenants.delete(user.tenantId, {
24
+ headers: config.authHeaders(user),
25
+ })
26
+ })
27
+
28
+ it("rejects deleting another tenant", async () => {
29
+ const user1 = await config.createTenant()
30
+ // create a second user in another tenant
31
+ const user2 = await config.createTenant()
32
+
33
+ const status = 403
34
+ const res = await config.api.tenants.delete(user1.tenantId, {
35
+ status,
36
+ headers: config.authHeaders(user2),
37
+ })
38
+
39
+ expect(res.body).toEqual({
40
+ message: "Tenant ID does not match current user",
41
+ status,
42
+ })
43
+ })
44
+
45
+ it("rejects non-admin", async () => {
46
+ const user1 = await config.createTenant()
47
+ // create an internal non-admin user
48
+ const user2 = await tenancy.doInTenant(user1.tenantId, () => {
49
+ return config.createUser()
50
+ })
51
+ await config.createSession(user2)
52
+
53
+ const res = await config.api.tenants.delete(user1.tenantId, {
54
+ status: 403,
55
+ headers: config.authHeaders(user2),
56
+ })
57
+
58
+ expect(res.body).toEqual(config.adminOnlyResponse())
59
+ })
60
+ })
61
+ })
@@ -0,0 +1,73 @@
1
+ import { TestConfiguration, structures } from "../../tests"
2
+ import { constants } from "@budibase/backend-core"
3
+
4
+ describe("tenancy middleware", () => {
5
+ const config = new TestConfiguration()
6
+
7
+ beforeAll(async () => {
8
+ await config.beforeAll()
9
+ })
10
+
11
+ afterAll(async () => {
12
+ await config.afterAll()
13
+ })
14
+
15
+ afterEach(() => {
16
+ jest.clearAllMocks()
17
+ })
18
+
19
+ it("should get tenant id from user", async () => {
20
+ const user = await config.createTenant()
21
+ await config.createSession(user)
22
+ const res = await config.api.self.getSelf(user)
23
+ expect(res.headers[constants.Headers.TENANT_ID]).toBe(user.tenantId)
24
+ })
25
+
26
+ it("should get tenant id from header", async () => {
27
+ const tenantId = structures.uuid()
28
+ const headers = {
29
+ [constants.Headers.TENANT_ID]: tenantId,
30
+ }
31
+ const res = await config.request
32
+ .get(`/api/global/configs/checklist`)
33
+ .set(headers)
34
+ expect(res.headers[constants.Headers.TENANT_ID]).toBe(tenantId)
35
+ })
36
+
37
+ it("should get tenant id from query param", async () => {
38
+ const tenantId = structures.uuid()
39
+ const res = await config.request.get(
40
+ `/api/global/configs/checklist?tenantId=${tenantId}`
41
+ )
42
+ expect(res.headers[constants.Headers.TENANT_ID]).toBe(tenantId)
43
+ })
44
+
45
+ it("should get tenant id from subdomain", async () => {
46
+ const tenantId = structures.uuid()
47
+ const headers = {
48
+ host: `${tenantId}.localhost:10000`,
49
+ }
50
+ const res = await config.request
51
+ .get(`/api/global/configs/checklist`)
52
+ .set(headers)
53
+ expect(res.headers[constants.Headers.TENANT_ID]).toBe(tenantId)
54
+ })
55
+
56
+ it("should get tenant id from path variable", async () => {
57
+ const user = await config.createTenant()
58
+ const res = await config.request
59
+ .post(`/api/global/auth/${user.tenantId}/login`)
60
+ .send({
61
+ username: user.email,
62
+ password: user.password,
63
+ })
64
+ expect(res.headers[constants.Headers.TENANT_ID]).toBe(user.tenantId)
65
+ })
66
+
67
+ it("should throw when no tenant id is found", async () => {
68
+ const res = await config.request.get(`/api/global/configs/checklist`)
69
+ expect(res.status).toBe(403)
70
+ expect(res.text).toBe("Tenant id not set")
71
+ expect(res.headers[constants.Headers.TENANT_ID]).toBe(undefined)
72
+ })
73
+ })
@@ -12,30 +12,33 @@ import {
12
12
  Headers,
13
13
  sessions,
14
14
  auth,
15
+ constants,
16
+ env as coreEnv,
15
17
  } from "@budibase/backend-core"
16
- import { TENANT_ID, TENANT_1, CSRF_TOKEN } from "./structures"
17
- import structures from "./structures"
18
+ import structures, { TENANT_ID, TENANT_1, CSRF_TOKEN } from "./structures"
18
19
  import { CreateUserResponse, User, AuthToken } from "@budibase/types"
20
+ import API from "./api"
19
21
 
20
22
  enum Mode {
21
- ACCOUNT = "account",
23
+ CLOUD = "cloud",
22
24
  SELF = "self",
23
25
  }
24
26
 
25
27
  class TestConfiguration {
26
28
  server: any
27
29
  request: any
30
+ api: API
28
31
  defaultUser?: User
29
32
  tenant1User?: User
30
33
 
31
34
  constructor(
32
35
  opts: { openServer: boolean; mode: Mode } = {
33
36
  openServer: true,
34
- mode: Mode.ACCOUNT,
37
+ mode: Mode.CLOUD,
35
38
  }
36
39
  ) {
37
- if (opts.mode === Mode.ACCOUNT) {
38
- this.modeAccount()
40
+ if (opts.mode === Mode.CLOUD) {
41
+ this.modeCloud()
39
42
  } else if (opts.mode === Mode.SELF) {
40
43
  this.modeSelf()
41
44
  }
@@ -46,6 +49,8 @@ class TestConfiguration {
46
49
  // we need the request for logging in, involves cookies, hard to fake
47
50
  this.request = supertest(this.server)
48
51
  }
52
+
53
+ this.api = new API(this)
49
54
  }
50
55
 
51
56
  getRequest() {
@@ -54,20 +59,24 @@ class TestConfiguration {
54
59
 
55
60
  // MODES
56
61
 
57
- modeAccount = () => {
58
- env.SELF_HOSTED = false
59
- // @ts-ignore
60
- env.MULTI_TENANCY = true
61
- // @ts-ignore
62
- env.DISABLE_ACCOUNT_PORTAL = false
62
+ setMultiTenancy = (value: boolean) => {
63
+ env._set("MULTI_TENANCY", value)
64
+ coreEnv._set("MULTI_TENANCY", value)
65
+ }
66
+
67
+ setSelfHosted = (value: boolean) => {
68
+ env._set("SELF_HOSTED", value)
69
+ coreEnv._set("SELF_HOSTED", value)
70
+ }
71
+
72
+ modeCloud = () => {
73
+ this.setSelfHosted(false)
74
+ this.setMultiTenancy(true)
63
75
  }
64
76
 
65
77
  modeSelf = () => {
66
- env.SELF_HOSTED = true
67
- // @ts-ignore
68
- env.MULTI_TENANCY = false
69
- // @ts-ignore
70
- env.DISABLE_ACCOUNT_PORTAL = true
78
+ this.setSelfHosted(true)
79
+ this.setMultiTenancy(false)
71
80
  }
72
81
 
73
82
  // UTILS
@@ -114,6 +123,25 @@ class TestConfiguration {
114
123
 
115
124
  // TENANCY
116
125
 
126
+ createTenant = async (): Promise<User> => {
127
+ // create user / new tenant
128
+ const res = await this.api.users.createAdminUser()
129
+
130
+ // return the created user
131
+ const userRes = await this.api.users.getUser(res.userId, {
132
+ headers: {
133
+ ...this.internalAPIHeaders(),
134
+ [constants.Headers.TENANT_ID]: res.tenantId,
135
+ },
136
+ })
137
+
138
+ // create a session for the new user
139
+ const user = userRes.body
140
+ await this.createSession(user)
141
+
142
+ return user
143
+ }
144
+
117
145
  getTenantId() {
118
146
  try {
119
147
  return tenancy.getTenantId()
@@ -122,35 +150,32 @@ class TestConfiguration {
122
150
  }
123
151
  }
124
152
 
125
- // USER / AUTH
153
+ // AUTH
126
154
 
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",
155
+ async _createSession({
156
+ userId,
157
+ tenantId,
158
+ }: {
159
+ userId: string
160
+ tenantId: string
161
+ }) {
162
+ await sessions.createASession(userId!, {
163
+ sessionId: "sessionid",
164
+ tenantId: tenantId,
165
+ csrfToken: CSRF_TOKEN,
139
166
  })
140
- this.tenant1User = await this.createUser(user)
141
167
  }
142
168
 
143
169
  async createSession(user: User) {
144
- await sessions.createASession(user._id!, {
145
- sessionId: "sessionid",
146
- tenantId: user.tenantId,
147
- csrfToken: CSRF_TOKEN,
148
- })
170
+ return this._createSession({ userId: user._id!, tenantId: user.tenantId })
149
171
  }
150
172
 
151
173
  cookieHeader(cookies: any) {
174
+ if (!Array.isArray(cookies)) {
175
+ cookies = [cookies]
176
+ }
152
177
  return {
153
- Cookie: [cookies],
178
+ Cookie: cookies,
154
179
  }
155
180
  }
156
181
 
@@ -179,6 +204,32 @@ class TestConfiguration {
179
204
  }
180
205
  }
181
206
 
207
+ internalAPIHeaders() {
208
+ return { [constants.Headers.API_KEY]: env.INTERNAL_API_KEY }
209
+ }
210
+
211
+ adminOnlyResponse = () => {
212
+ return { message: "Admin user only endpoint.", status: 403 }
213
+ }
214
+
215
+ // USERS
216
+
217
+ async createDefaultUser() {
218
+ const user = structures.users.adminUser({
219
+ email: "test@test.com",
220
+ password: "test",
221
+ })
222
+ this.defaultUser = await this.createUser(user)
223
+ }
224
+
225
+ async createTenant1User() {
226
+ const user = structures.users.adminUser({
227
+ email: "tenant1@test.com",
228
+ password: "test",
229
+ })
230
+ this.tenant1User = await this.createUser(user)
231
+ }
232
+
182
233
  async getUser(email: string): Promise<User> {
183
234
  return tenancy.doInTenant(this.getTenantId(), () => {
184
235
  return users.getGlobalUserByEmail(email)
@@ -240,11 +291,6 @@ class TestConfiguration {
240
291
 
241
292
  // CONFIGS - OIDC
242
293
 
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
294
  async saveOIDCConfig() {
249
295
  await this.deleteConfig(Configs.OIDC)
250
296
  const config = structures.configs.oidc()
@@ -1,20 +1,17 @@
1
1
  import { Account, AccountMetadata } from "@budibase/types"
2
2
  import TestConfiguration from "../TestConfiguration"
3
+ import { TestAPI } from "./base"
3
4
 
4
- export class AccountAPI {
5
- config: TestConfiguration
6
- request: any
7
-
5
+ export class AccountAPI extends TestAPI {
8
6
  constructor(config: TestConfiguration) {
9
- this.config = config
10
- this.request = config.request
7
+ super(config)
11
8
  }
12
9
 
13
10
  saveMetadata = async (account: Account) => {
14
11
  const res = await this.request
15
12
  .put(`/api/system/accounts/${account.accountId}/metadata`)
16
13
  .send(account)
17
- .set(this.config.defaultHeaders())
14
+ .set(this.config.internalAPIHeaders())
18
15
  .expect("Content-Type", /json/)
19
16
  .expect(200)
20
17
  return res.body as AccountMetadata
@@ -23,6 +20,6 @@ export class AccountAPI {
23
20
  destroyMetadata = (accountId: string) => {
24
21
  return this.request
25
22
  .del(`/api/system/accounts/${accountId}/metadata`)
26
- .set(this.config.defaultHeaders())
23
+ .set(this.config.internalAPIHeaders())
27
24
  }
28
25
  }
@@ -1,12 +1,9 @@
1
1
  import TestConfiguration from "../TestConfiguration"
2
+ import { TestAPI } from "./base"
2
3
 
3
- export class AuthAPI {
4
- config: TestConfiguration
5
- request: any
6
-
4
+ export class AuthAPI extends TestAPI {
7
5
  constructor(config: TestConfiguration) {
8
- this.config = config
9
- this.request = config.request
6
+ super(config)
10
7
  }
11
8
 
12
9
  updatePassword = (code: string) => {
@@ -0,0 +1,16 @@
1
+ import TestConfiguration from "../TestConfiguration"
2
+
3
+ export interface TestAPIOpts {
4
+ headers?: any
5
+ status?: number
6
+ }
7
+
8
+ export abstract class TestAPI {
9
+ config: TestConfiguration
10
+ request: any
11
+
12
+ protected constructor(config: TestConfiguration) {
13
+ this.config = config
14
+ this.request = config.request
15
+ }
16
+ }
@@ -1,12 +1,9 @@
1
1
  import TestConfiguration from "../TestConfiguration"
2
+ import { TestAPI } from "./base"
2
3
 
3
- export class ConfigAPI {
4
- config: TestConfiguration
5
- request: any
6
-
4
+ export class ConfigAPI extends TestAPI {
7
5
  constructor(config: TestConfiguration) {
8
- this.config = config
9
- this.request = config.request
6
+ super(config)
10
7
  }
11
8
 
12
9
  getConfigChecklist = () => {
@@ -26,10 +23,20 @@ export class ConfigAPI {
26
23
  .expect(200)
27
24
  }
28
25
 
29
- OIDCCallback = (configId: string) => {
26
+ OIDCCallback = (configId: string, preAuthRes: any) => {
27
+ const cookie = this.config.cookieHeader(preAuthRes.get("set-cookie"))
28
+ const setKoaSession = cookie.Cookie.find((c: string) =>
29
+ c.includes("koa:sess")
30
+ )
31
+ const koaSession = setKoaSession.split("=")[1] + "=="
32
+ const sessionContent = JSON.parse(
33
+ Buffer.from(koaSession, "base64").toString("utf-8")
34
+ )
35
+ const handle = sessionContent["openidconnect:localhost"].state.handle
30
36
  return this.request
31
37
  .get(`/api/global/auth/${this.config.getTenantId()}/oidc/callback`)
32
- .set(this.config.getOIDConfigCookie(configId))
38
+ .query({ code: "test", state: handle })
39
+ .set(cookie)
33
40
  }
34
41
 
35
42
  getOIDCConfig = (configId: string) => {
@@ -1,12 +1,9 @@
1
1
  import TestConfiguration from "../TestConfiguration"
2
+ import { TestAPI } from "./base"
2
3
 
3
- export class EmailAPI {
4
- config: TestConfiguration
5
- request: any
6
-
4
+ export class EmailAPI extends TestAPI {
7
5
  constructor(config: TestConfiguration) {
8
- this.config = config
9
- this.request = config.request
6
+ super(config)
10
7
  }
11
8
 
12
9
  sendEmail = (purpose: string) => {