@budibase/server 2.5.6-alpha.9 → 2.5.7

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/builder/assets/index.7f9a008b.css +6 -0
  2. package/builder/assets/index.f02eef32.js +1817 -0
  3. package/builder/index.html +2 -2
  4. package/dist/api/controllers/automation.js +7 -13
  5. package/dist/api/controllers/plugin/index.js +37 -6
  6. package/dist/api/controllers/table/utils.js +1 -2
  7. package/dist/api/controllers/user.js +83 -1
  8. package/dist/api/routes/index.js +0 -2
  9. package/dist/api/routes/user.js +1 -0
  10. package/dist/app.js +13 -4
  11. package/dist/automations/actions.js +6 -32
  12. package/dist/automations/index.js +2 -3
  13. package/dist/automations/steps/bash.js +6 -6
  14. package/dist/automations/steps/createRow.js +11 -11
  15. package/dist/automations/steps/delay.js +3 -3
  16. package/dist/automations/steps/deleteRow.js +8 -8
  17. package/dist/automations/steps/discord.js +8 -8
  18. package/dist/automations/steps/executeQuery.js +9 -9
  19. package/dist/automations/steps/executeScript.js +6 -6
  20. package/dist/automations/steps/filter.js +6 -6
  21. package/dist/automations/steps/integromat.js +10 -10
  22. package/dist/automations/steps/loop.js +9 -9
  23. package/dist/automations/steps/outgoingWebhook.js +10 -10
  24. package/dist/automations/steps/queryRows.js +14 -14
  25. package/dist/automations/steps/sendSmtpEmail.js +9 -9
  26. package/dist/automations/steps/serverLog.js +4 -4
  27. package/dist/automations/steps/slack.js +6 -6
  28. package/dist/automations/steps/updateRow.js +11 -11
  29. package/dist/automations/steps/zapier.js +9 -9
  30. package/dist/automations/triggerInfo/app.js +5 -5
  31. package/dist/automations/triggerInfo/cron.js +4 -4
  32. package/dist/automations/triggerInfo/rowDeleted.js +5 -5
  33. package/dist/automations/triggerInfo/rowSaved.js +7 -7
  34. package/dist/automations/triggerInfo/rowUpdated.js +7 -7
  35. package/dist/automations/triggerInfo/webhook.js +6 -6
  36. package/dist/elasticApm.js +14 -0
  37. package/dist/environment.js +1 -0
  38. package/dist/events/index.js +0 -3
  39. package/dist/integrations/index.js +3 -3
  40. package/dist/integrations/microsoftSqlServer.js +2 -5
  41. package/dist/integrations/mysql.js +3 -5
  42. package/dist/integrations/postgres.js +5 -7
  43. package/dist/integrations/redis.js +0 -7
  44. package/dist/integrations/rest.js +0 -4
  45. package/dist/migrations/functions/usageQuotas/syncApps.js +1 -1
  46. package/dist/migrations/functions/usageQuotas/syncRows.js +2 -1
  47. package/dist/package.json +15 -15
  48. package/dist/sdk/app/applications/sync.js +23 -117
  49. package/dist/sdk/index.js +0 -2
  50. package/dist/sdk/users/utils.js +4 -21
  51. package/dist/startup.js +28 -31
  52. package/dist/threads/automation.js +5 -16
  53. package/dist/tsconfig.build.tsbuildinfo +1 -1
  54. package/dist/utilities/fileSystem/plugin.js +23 -33
  55. package/dist/utilities/global.js +12 -17
  56. package/dist/watch.js +2 -2
  57. package/dist/websocket.js +22 -0
  58. package/jest.config.ts +3 -3
  59. package/nodemon.json +3 -7
  60. package/package.json +16 -16
  61. package/scripts/dev/manage.js +0 -2
  62. package/scripts/integrations/mssql/data/entrypoint.sh +0 -1
  63. package/scripts/integrations/mssql/data/setup.sql +17 -17
  64. package/scripts/integrations/mysql/init.sql +1 -1
  65. package/scripts/integrations/postgres/init.sql +0 -1
  66. package/scripts/likeCypress.ts +35 -0
  67. package/src/api/controllers/automation.ts +6 -12
  68. package/src/api/controllers/plugin/index.ts +45 -8
  69. package/src/api/controllers/row/internal.ts +10 -9
  70. package/src/api/controllers/row/utils.ts +2 -2
  71. package/src/api/controllers/table/utils.ts +1 -2
  72. package/src/api/controllers/user.ts +96 -10
  73. package/src/api/routes/index.ts +0 -2
  74. package/src/api/routes/tests/automation.spec.js +4 -7
  75. package/src/api/routes/tests/user.spec.js +37 -48
  76. package/src/api/routes/user.ts +5 -0
  77. package/src/app.ts +15 -4
  78. package/src/automations/actions.ts +24 -56
  79. package/src/automations/index.ts +1 -1
  80. package/src/automations/steps/bash.ts +7 -10
  81. package/src/automations/steps/createRow.ts +12 -15
  82. package/src/automations/steps/delay.ts +4 -6
  83. package/src/automations/steps/deleteRow.ts +9 -12
  84. package/src/automations/steps/discord.ts +8 -10
  85. package/src/automations/steps/executeQuery.ts +10 -13
  86. package/src/automations/steps/executeScript.ts +7 -10
  87. package/src/automations/steps/filter.ts +6 -8
  88. package/src/automations/steps/integromat.ts +10 -12
  89. package/src/automations/steps/loop.ts +10 -16
  90. package/src/automations/steps/outgoingWebhook.ts +11 -14
  91. package/src/automations/steps/queryRows.ts +15 -18
  92. package/src/automations/steps/sendSmtpEmail.ts +9 -11
  93. package/src/automations/steps/serverLog.ts +4 -6
  94. package/src/automations/steps/slack.ts +6 -8
  95. package/src/automations/steps/updateRow.ts +12 -15
  96. package/src/automations/steps/zapier.ts +9 -11
  97. package/src/automations/tests/utilities/index.ts +2 -2
  98. package/src/automations/triggerInfo/app.ts +5 -8
  99. package/src/automations/triggerInfo/cron.ts +4 -7
  100. package/src/automations/triggerInfo/rowDeleted.ts +5 -8
  101. package/src/automations/triggerInfo/rowSaved.ts +7 -10
  102. package/src/automations/triggerInfo/rowUpdated.ts +7 -10
  103. package/src/automations/triggerInfo/webhook.ts +6 -9
  104. package/src/elasticApm.ts +10 -0
  105. package/src/environment.ts +1 -0
  106. package/src/events/index.ts +0 -1
  107. package/src/integrations/index.ts +3 -3
  108. package/src/integrations/microsoftSqlServer.ts +2 -5
  109. package/src/integrations/mysql.ts +3 -5
  110. package/src/integrations/postgres.ts +5 -7
  111. package/src/integrations/redis.ts +0 -8
  112. package/src/integrations/rest.ts +0 -3
  113. package/src/migrations/functions/usageQuotas/syncApps.ts +1 -1
  114. package/src/migrations/functions/usageQuotas/syncRows.ts +3 -2
  115. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +2 -2
  116. package/src/sdk/app/applications/sync.ts +22 -129
  117. package/src/sdk/index.ts +0 -2
  118. package/src/sdk/users/tests/utils.spec.ts +32 -1
  119. package/src/sdk/users/utils.ts +5 -23
  120. package/src/startup.ts +34 -36
  121. package/src/tests/jestEnv.ts +1 -0
  122. package/src/tests/jestSetup.ts +1 -0
  123. package/src/tests/logging.ts +34 -0
  124. package/src/tests/utilities/TestConfiguration.ts +0 -28
  125. package/src/tests/utilities/structures.ts +17 -25
  126. package/src/threads/automation.ts +6 -18
  127. package/src/utilities/fileSystem/plugin.ts +4 -13
  128. package/src/utilities/global.ts +16 -21
  129. package/src/watch.ts +2 -2
  130. package/src/websocket.ts +26 -0
  131. package/tsconfig.json +7 -1
  132. package/builder/assets/index.5c1a6913.js +0 -1776
  133. package/builder/assets/index.c0265b74.css +0 -6
  134. package/dist/api/controllers/ops.js +0 -40
  135. package/dist/api/routes/ops.js +0 -52
  136. package/dist/events/docUpdates/index.js +0 -17
  137. package/dist/events/docUpdates/processors.js +0 -18
  138. package/dist/events/docUpdates/syncUsers.js +0 -49
  139. package/dist/sdk/plugins/index.js +0 -27
  140. package/dist/sdk/plugins/plugins.js +0 -53
  141. package/dist/websockets/client.js +0 -14
  142. package/dist/websockets/grid.js +0 -60
  143. package/dist/websockets/index.js +0 -17
  144. package/dist/websockets/websocket.js +0 -78
  145. package/src/api/controllers/ops.ts +0 -32
  146. package/src/api/routes/ops.ts +0 -30
  147. package/src/events/docUpdates/index.ts +0 -1
  148. package/src/events/docUpdates/processors.ts +0 -14
  149. package/src/events/docUpdates/syncUsers.ts +0 -35
  150. package/src/sdk/app/applications/tests/sync.spec.ts +0 -137
  151. package/src/sdk/plugins/index.ts +0 -5
  152. package/src/sdk/plugins/plugins.ts +0 -41
  153. package/src/websockets/client.ts +0 -11
  154. package/src/websockets/grid.ts +0 -55
  155. package/src/websockets/index.ts +0 -14
  156. package/src/websockets/websocket.ts +0 -83
@@ -6,7 +6,6 @@ interface RedisConfig {
6
6
  port: number
7
7
  username: string
8
8
  password?: string
9
- db?: number
10
9
  }
11
10
 
12
11
  const SCHEMA: Integration = {
@@ -33,12 +32,6 @@ const SCHEMA: Integration = {
33
32
  type: "password",
34
33
  required: false,
35
34
  },
36
- db: {
37
- type: "number",
38
- required: false,
39
- display: "DB",
40
- default: 0,
41
- },
42
35
  },
43
36
  query: {
44
37
  create: {
@@ -95,7 +88,6 @@ class RedisIntegration {
95
88
  port: this.config.port,
96
89
  username: this.config.username,
97
90
  password: this.config.password,
98
- db: this.config.db,
99
91
  })
100
92
  }
101
93
 
@@ -151,9 +151,6 @@ class RestIntegration implements IntegrationBase {
151
151
  data = data[keys[0]]
152
152
  }
153
153
  raw = rawXml
154
- } else if (contentType.includes("application/pdf")) {
155
- data = await response.arrayBuffer() // Save PDF as ArrayBuffer
156
- raw = Buffer.from(data)
157
154
  } else {
158
155
  data = await response.text()
159
156
  raw = data
@@ -9,6 +9,6 @@ export const run = async () => {
9
9
 
10
10
  // sync app count
11
11
  const tenantId = tenancy.getTenantId()
12
- console.log(`Syncing app count: ${appCount}`)
12
+ console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`)
13
13
  await quotas.setUsage(appCount, StaticQuotaName.APPS, QuotaUsageType.STATIC)
14
14
  }
@@ -1,4 +1,4 @@
1
- import { db as dbCore } from "@budibase/backend-core"
1
+ import { tenancy, db as dbCore } from "@budibase/backend-core"
2
2
  import { getUniqueRows } from "../../../utilities/usageQuota/rows"
3
3
  import { quotas } from "@budibase/pro"
4
4
  import { StaticQuotaName, QuotaUsageType, App } from "@budibase/types"
@@ -18,7 +18,8 @@ export const run = async () => {
18
18
  })
19
19
 
20
20
  // sync row count
21
- console.log(`Syncing row count: ${rowCount}`)
21
+ const tenantId = tenancy.getTenantId()
22
+ console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`)
22
23
  await quotas.setUsagePerApp(
23
24
  counts,
24
25
  StaticQuotaName.ROWS,
@@ -24,7 +24,7 @@ describe("syncRows", () => {
24
24
 
25
25
  // app 1
26
26
  const app1 = config.app
27
- await context.doInAppContext(app1!.appId, async () => {
27
+ await context.doInAppContext(app1.appId, async () => {
28
28
  await config.createTable()
29
29
  await config.createRow()
30
30
  })
@@ -43,7 +43,7 @@ describe("syncRows", () => {
43
43
  usageDoc = await quotas.getQuotaUsage()
44
44
  expect(usageDoc.usageQuota.rows).toEqual(3)
45
45
  expect(
46
- usageDoc.apps?.[dbCore.getProdAppID(app1!.appId)].usageQuota.rows
46
+ usageDoc.apps?.[dbCore.getProdAppID(app1.appId)].usageQuota.rows
47
47
  ).toEqual(1)
48
48
  expect(
49
49
  usageDoc.apps?.[dbCore.getProdAppID(app2.appId)].usageQuota.rows
@@ -1,117 +1,6 @@
1
1
  import env from "../../../environment"
2
- import {
3
- db as dbCore,
4
- context,
5
- docUpdates,
6
- constants,
7
- logging,
8
- roles,
9
- } from "@budibase/backend-core"
10
- import { User, ContextUser, UserGroup } from "@budibase/types"
11
- import { sdk as proSdk } from "@budibase/pro"
2
+ import { db as dbCore, context } from "@budibase/backend-core"
12
3
  import sdk from "../../"
13
- import { getGlobalUsers, processUser } from "../../../utilities/global"
14
- import { generateUserMetadataID, InternalTables } from "../../../db/utils"
15
-
16
- type DeletedUser = { _id: string; deleted: boolean }
17
-
18
- async function syncUsersToApp(
19
- appId: string,
20
- users: (User | DeletedUser)[],
21
- groups: UserGroup[]
22
- ) {
23
- if (!(await dbCore.dbExists(appId))) {
24
- return
25
- }
26
- await context.doInAppContext(appId, async () => {
27
- const db = context.getAppDB()
28
- for (let user of users) {
29
- let ctxUser = user as ContextUser
30
- let deletedUser = false
31
- const metadataId = generateUserMetadataID(user._id!)
32
- if ((user as DeletedUser).deleted) {
33
- deletedUser = true
34
- }
35
-
36
- // make sure role is correct
37
- if (!deletedUser) {
38
- ctxUser = await processUser(ctxUser, { appId, groups })
39
- }
40
- let roleId = ctxUser.roleId
41
- if (roleId === roles.BUILTIN_ROLE_IDS.PUBLIC) {
42
- roleId = undefined
43
- }
44
-
45
- let metadata
46
- try {
47
- metadata = await db.get(metadataId)
48
- } catch (err: any) {
49
- if (err.status !== 404) {
50
- throw err
51
- }
52
- // no metadata and user is to be deleted, can skip
53
- // no role - user isn't in app anyway
54
- if (!roleId) {
55
- continue
56
- } else if (!deletedUser) {
57
- // doesn't exist yet, creating it
58
- metadata = {
59
- tableId: InternalTables.USER_METADATA,
60
- }
61
- }
62
- }
63
-
64
- // the user doesn't exist, or doesn't have a role anymore
65
- // get rid of their metadata
66
- if (deletedUser || !roleId) {
67
- await db.remove(metadata)
68
- continue
69
- }
70
-
71
- // assign the roleId for the metadata doc
72
- if (roleId) {
73
- metadata.roleId = roleId
74
- }
75
-
76
- let combined = sdk.users.combineMetadataAndUser(ctxUser, metadata)
77
- // if no combined returned, there are no updates to make
78
- if (combined) {
79
- await db.put(combined)
80
- }
81
- }
82
- })
83
- }
84
-
85
- export async function syncUsersToAllApps(userIds: string[]) {
86
- // list of users, if one has been deleted it will be undefined in array
87
- const users = (await getGlobalUsers(userIds, {
88
- noProcessing: true,
89
- })) as User[]
90
- const groups = await proSdk.groups.fetch()
91
- const finalUsers: (User | DeletedUser)[] = []
92
- for (let userId of userIds) {
93
- const user = users.find(user => user._id === userId)
94
- if (!user) {
95
- finalUsers.push({ _id: userId, deleted: true })
96
- } else {
97
- finalUsers.push(user)
98
- }
99
- }
100
- const devAppIds = await dbCore.getDevAppIDs()
101
- let promises = []
102
- for (let devAppId of devAppIds) {
103
- const prodAppId = dbCore.getProdAppID(devAppId)
104
- for (let appId of [prodAppId, devAppId]) {
105
- promises.push(syncUsersToApp(appId, finalUsers, groups))
106
- }
107
- }
108
- const resp = await Promise.allSettled(promises)
109
- const failed = resp.filter(promise => promise.status === "rejected")
110
- if (failed.length > 0) {
111
- const reasons = failed.map(fail => (fail as PromiseRejectedResult).reason)
112
- logging.logAlert("Failed to sync users to apps", reasons)
113
- }
114
- }
115
4
 
116
5
  export async function syncApp(
117
6
  appId: string,
@@ -134,28 +23,32 @@ export async function syncApp(
134
23
  // specific case, want to make sure setup is skipped
135
24
  const prodDb = context.getProdAppDB({ skip_setup: true })
136
25
  const exists = await prodDb.exists()
26
+ if (!exists) {
27
+ // the database doesn't exist. Don't replicate
28
+ return {
29
+ message: "App sync not required, app not deployed.",
30
+ }
31
+ }
137
32
 
33
+ const replication = new dbCore.Replication({
34
+ source: prodAppId,
35
+ target: appId,
36
+ })
138
37
  let error
139
- if (exists) {
140
- const replication = new dbCore.Replication({
141
- source: prodAppId,
142
- target: appId,
143
- })
144
- try {
145
- const replOpts = replication.appReplicateOpts()
146
- if (opts?.automationOnly) {
147
- replOpts.filter = (doc: any) =>
148
- doc._id.startsWith(dbCore.DocumentType.AUTOMATION)
149
- }
150
- await replication.replicate(replOpts)
151
- } catch (err) {
152
- error = err
153
- } finally {
154
- await replication.close()
38
+ try {
39
+ const replOpts = replication.appReplicateOpts()
40
+ if (opts?.automationOnly) {
41
+ replOpts.filter = (doc: any) =>
42
+ doc._id.startsWith(dbCore.DocumentType.AUTOMATION)
155
43
  }
44
+ await replication.replicate(replOpts)
45
+ } catch (err) {
46
+ error = err
47
+ } finally {
48
+ await replication.close()
156
49
  }
157
50
 
158
- // sync the users - kept for safe keeping
51
+ // sync the users
159
52
  await sdk.users.syncGlobalUsers()
160
53
 
161
54
  if (error) {
package/src/sdk/index.ts CHANGED
@@ -6,7 +6,6 @@ import { default as datasources } from "./app/datasources"
6
6
  import { default as queries } from "./app/queries"
7
7
  import { default as rows } from "./app/rows"
8
8
  import { default as users } from "./users"
9
- import { default as plugins } from "./plugins"
10
9
 
11
10
  const sdk = {
12
11
  backups,
@@ -17,7 +16,6 @@ const sdk = {
17
16
  users,
18
17
  datasources,
19
18
  queries,
20
- plugins,
21
19
  }
22
20
 
23
21
  // default export for TS
@@ -121,7 +121,38 @@ describe("syncGlobalUsers", () => {
121
121
  await syncGlobalUsers()
122
122
 
123
123
  const metadata = await rawUserMetadata()
124
- expect(metadata).toHaveLength(0)
124
+ expect(metadata).toHaveLength(1)
125
+ })
126
+ })
127
+ })
128
+
129
+ it("app users are removed when app is removed from user group", async () => {
130
+ await config.doInTenant(async () => {
131
+ const group = await proSdk.groups.save(structures.userGroups.userGroup())
132
+ const user1 = await config.createUser({ admin: false, builder: false })
133
+ const user2 = await config.createUser({ admin: false, builder: false })
134
+ await proSdk.groups.updateGroupApps(group.id, {
135
+ appsToAdd: [
136
+ { appId: config.prodAppId!, roleId: roles.BUILTIN_ROLE_IDS.BASIC },
137
+ ],
138
+ })
139
+ await proSdk.groups.addUsers(group.id, [user1._id, user2._id])
140
+
141
+ await config.doInContext(config.appId, async () => {
142
+ await syncGlobalUsers()
143
+ expect(await rawUserMetadata()).toHaveLength(3)
144
+
145
+ await proSdk.groups.removeUsers(group.id, [user1._id])
146
+ await syncGlobalUsers()
147
+
148
+ const metadata = await rawUserMetadata()
149
+ expect(metadata).toHaveLength(2)
150
+
151
+ expect(metadata).not.toContainEqual(
152
+ expect.objectContaining({
153
+ _id: db.generateUserMetadataID(user1._id),
154
+ })
155
+ )
125
156
  })
126
157
  })
127
158
  })
@@ -1,13 +1,12 @@
1
1
  import { getGlobalUsers } from "../../utilities/global"
2
2
  import { context, roles as rolesCore } from "@budibase/backend-core"
3
3
  import {
4
- getGlobalIDFromUserMetadataID,
5
4
  generateUserMetadataID,
6
5
  getUserMetadataParams,
7
6
  InternalTables,
8
7
  } from "../../db/utils"
9
8
  import { isEqual } from "lodash"
10
- import { ContextUser, UserMetadata, User } from "@budibase/types"
9
+ import { ContextUser, UserMetadata } from "@budibase/types"
11
10
 
12
11
  export function combineMetadataAndUser(
13
12
  user: ContextUser,
@@ -38,10 +37,6 @@ export function combineMetadataAndUser(
38
37
  if (found) {
39
38
  newDoc._rev = found._rev
40
39
  }
41
- // clear fields that shouldn't be in metadata
42
- delete newDoc.password
43
- delete newDoc.forceResetPassword
44
- delete newDoc.roles
45
40
  if (found == null || !isEqual(newDoc, found)) {
46
41
  return {
47
42
  ...found,
@@ -65,9 +60,10 @@ export async function rawUserMetadata() {
65
60
  export async function syncGlobalUsers() {
66
61
  // sync user metadata
67
62
  const db = context.getAppDB()
68
- const resp = await Promise.all([getGlobalUsers(), rawUserMetadata()])
69
- const users = resp[0] as User[]
70
- const metadata = resp[1] as UserMetadata[]
63
+ const [users, metadata] = await Promise.all([
64
+ getGlobalUsers(),
65
+ rawUserMetadata(),
66
+ ])
71
67
  const toWrite = []
72
68
  for (let user of users) {
73
69
  const combined = combineMetadataAndUser(user, metadata)
@@ -75,19 +71,5 @@ export async function syncGlobalUsers() {
75
71
  toWrite.push(combined)
76
72
  }
77
73
  }
78
- let foundEmails: string[] = []
79
- for (let data of metadata) {
80
- if (!data._id) {
81
- continue
82
- }
83
- const alreadyExisting = data.email && foundEmails.indexOf(data.email) !== -1
84
- const globalId = getGlobalIDFromUserMetadataID(data._id)
85
- if (!users.find(user => user._id === globalId) || alreadyExisting) {
86
- toWrite.push({ ...data, _deleted: true })
87
- }
88
- if (data.email) {
89
- foundEmails.push(data.email)
90
- }
91
- }
92
74
  await db.bulkDocs(toWrite)
93
75
  }
package/src/startup.ts CHANGED
@@ -10,16 +10,19 @@ import fs from "fs"
10
10
  import { watch } from "./watch"
11
11
  import * as automations from "./automations"
12
12
  import * as fileSystem from "./utilities/fileSystem"
13
- import { default as eventEmitter, init as eventInit } from "./events"
13
+ import eventEmitter from "./events"
14
14
  import * as migrations from "./migrations"
15
15
  import * as bullboard from "./automations/bullboard"
16
16
  import * as pro from "@budibase/pro"
17
17
  import * as api from "./api"
18
18
  import sdk from "./sdk"
19
+ const pino = require("koa-pino-logger")
19
20
 
20
21
  let STARTUP_RAN = false
21
22
 
22
23
  async function initRoutes(app: any) {
24
+ app.use(pino(logging.pinoSettings()))
25
+
23
26
  if (!env.isTest()) {
24
27
  const plugin = await bullboard.init()
25
28
  app.use(plugin)
@@ -45,10 +48,8 @@ async function initPro() {
45
48
  }
46
49
 
47
50
  function shutdown(server?: any) {
48
- if (server) {
49
- server.close()
50
- server.destroy()
51
- }
51
+ server.close()
52
+ server.destroy()
52
53
  }
53
54
 
54
55
  export async function startup(app?: any, server?: any) {
@@ -63,7 +64,6 @@ export async function startup(app?: any, server?: any) {
63
64
  eventEmitter.emitPort(env.PORT)
64
65
  fileSystem.init()
65
66
  await redis.init()
66
- eventInit()
67
67
 
68
68
  // run migrations on startup if not done via http
69
69
  // not recommended in a clustered environment
@@ -72,39 +72,11 @@ export async function startup(app?: any, server?: any) {
72
72
  await migrations.migrate()
73
73
  } catch (e) {
74
74
  logging.logAlert("Error performing migrations. Exiting.", e)
75
- shutdown(server)
75
+ shutdown()
76
76
  }
77
77
  }
78
78
 
79
- // monitor plugin directory if required
80
- if (
81
- env.SELF_HOSTED &&
82
- !env.MULTI_TENANCY &&
83
- env.PLUGINS_DIR &&
84
- fs.existsSync(env.PLUGINS_DIR)
85
- ) {
86
- watch()
87
- }
88
-
89
- // check for version updates
90
- await installation.checkInstallVersion()
91
-
92
- // get the references to the queue promises, don't await as
93
- // they will never end, unless the processing stops
94
- let queuePromises = []
95
- // configure events to use the pro audit log write
96
- // can't integrate directly into backend-core due to cyclic issues
97
- queuePromises.push(events.processors.init(pro.sdk.auditLogs.write))
98
- queuePromises.push(automations.init())
99
- queuePromises.push(initPro())
100
- if (app) {
101
- // bring routes online as final step once everything ready
102
- await initRoutes(app)
103
- }
104
-
105
79
  // check and create admin user if required
106
- // this must be run after the api has been initialised due to
107
- // the app user sync
108
80
  if (
109
81
  env.SELF_HOSTED &&
110
82
  !env.MULTI_TENANCY &&
@@ -131,8 +103,34 @@ export async function startup(app?: any, server?: any) {
131
103
  )
132
104
  } catch (e) {
133
105
  logging.logAlert("Error creating initial admin user. Exiting.", e)
134
- shutdown(server)
106
+ shutdown()
135
107
  }
136
108
  }
137
109
  }
110
+
111
+ // monitor plugin directory if required
112
+ if (
113
+ env.SELF_HOSTED &&
114
+ !env.MULTI_TENANCY &&
115
+ env.PLUGINS_DIR &&
116
+ fs.existsSync(env.PLUGINS_DIR)
117
+ ) {
118
+ watch()
119
+ }
120
+
121
+ // check for version updates
122
+ await installation.checkInstallVersion()
123
+
124
+ // get the references to the queue promises, don't await as
125
+ // they will never end, unless the processing stops
126
+ let queuePromises = []
127
+ // configure events to use the pro audit log write
128
+ // can't integrate directly into backend-core due to cyclic issues
129
+ queuePromises.push(events.processors.init(pro.sdk.auditLogs.write))
130
+ queuePromises.push(automations.init())
131
+ queuePromises.push(initPro())
132
+ if (app) {
133
+ // bring routes online as final step once everything ready
134
+ await initRoutes(app)
135
+ }
138
136
  }
@@ -6,6 +6,7 @@ process.env.MULTI_TENANCY = "1"
6
6
  // @ts-ignore
7
7
  process.env.BUDIBASE_DIR = tmpdir("budibase-unittests")
8
8
  process.env.LOG_LEVEL = process.env.LOG_LEVEL || "error"
9
+ process.env.ENABLE_4XX_HTTP_LOGGING = "0"
9
10
  process.env.MOCK_REDIS = "1"
10
11
  process.env.PLATFORM_URL = "http://localhost:10000"
11
12
  process.env.REDIS_PASSWORD = "budibase"
@@ -1,3 +1,4 @@
1
+ import "./logging"
1
2
  import env from "../environment"
2
3
  import { env as coreEnv, timers } from "@budibase/backend-core"
3
4
  import { testContainerUtils } from "@budibase/backend-core/tests"
@@ -0,0 +1,34 @@
1
+ export enum LogLevel {
2
+ TRACE = "trace",
3
+ DEBUG = "debug",
4
+ INFO = "info",
5
+ WARN = "warn",
6
+ ERROR = "error",
7
+ }
8
+
9
+ const LOG_INDEX: { [key in LogLevel]: number } = {
10
+ [LogLevel.TRACE]: 1,
11
+ [LogLevel.DEBUG]: 2,
12
+ [LogLevel.INFO]: 3,
13
+ [LogLevel.WARN]: 4,
14
+ [LogLevel.ERROR]: 5,
15
+ }
16
+
17
+ const setIndex = LOG_INDEX[process.env.LOG_LEVEL as LogLevel]
18
+
19
+ if (setIndex > LOG_INDEX.trace) {
20
+ global.console.trace = jest.fn()
21
+ }
22
+
23
+ if (setIndex > LOG_INDEX.debug) {
24
+ global.console.debug = jest.fn()
25
+ }
26
+
27
+ if (setIndex > LOG_INDEX.info) {
28
+ global.console.info = jest.fn()
29
+ global.console.log = jest.fn()
30
+ }
31
+
32
+ if (setIndex > LOG_INDEX.warn) {
33
+ global.console.warn = jest.fn()
34
+ }
@@ -49,7 +49,6 @@ import {
49
49
  SearchFilters,
50
50
  UserRoles,
51
51
  } from "@budibase/types"
52
- import { BUILTIN_ROLE_IDS } from "@budibase/backend-core/src/security/roles"
53
52
 
54
53
  type DefaultUserValues = {
55
54
  globalUserId: string
@@ -307,33 +306,6 @@ class TestConfiguration {
307
306
  }
308
307
  }
309
308
 
310
- async createGroup(roleId: string = BUILTIN_ROLE_IDS.BASIC) {
311
- return context.doInTenant(this.tenantId!, async () => {
312
- const baseGroup = structures.userGroups.userGroup()
313
- baseGroup.roles = {
314
- [this.prodAppId]: roleId,
315
- }
316
- const { id, rev } = await pro.sdk.groups.save(baseGroup)
317
- return {
318
- _id: id,
319
- _rev: rev,
320
- ...baseGroup,
321
- }
322
- })
323
- }
324
-
325
- async addUserToGroup(groupId: string, userId: string) {
326
- return context.doInTenant(this.tenantId!, async () => {
327
- await pro.sdk.groups.addUsers(groupId, [userId])
328
- })
329
- }
330
-
331
- async removeUserFromGroup(groupId: string, userId: string) {
332
- return context.doInTenant(this.tenantId!, async () => {
333
- await pro.sdk.groups.removeUsers(groupId, [userId])
334
- })
335
- }
336
-
337
309
  async login({ roleId, userId, builder, prodApp = false }: any = {}) {
338
310
  const appId = prodApp ? this.prodAppId : this.appId
339
311
  return context.doInAppContext(appId, async () => {
@@ -1,22 +1,18 @@
1
- import { permissions, roles, utils } from "@budibase/backend-core"
1
+ import { permissions, roles } from "@budibase/backend-core"
2
2
  import { createHomeScreen } from "../../constants/screens"
3
3
  import { EMPTY_LAYOUT } from "../../constants/layouts"
4
4
  import { cloneDeep } from "lodash/fp"
5
- import {
6
- BUILTIN_ACTION_DEFINITIONS,
7
- TRIGGER_DEFINITIONS,
8
- } from "../../automations"
5
+ import { ACTION_DEFINITIONS, TRIGGER_DEFINITIONS } from "../../automations"
9
6
  import {
10
7
  Automation,
11
8
  AutomationActionStepId,
12
- AutomationStep,
13
- AutomationStepType,
14
- AutomationTrigger,
15
9
  AutomationTriggerStepId,
16
10
  Datasource,
17
11
  SourceName,
18
12
  } from "@budibase/types"
19
13
 
14
+ const { v4: uuidv4 } = require("uuid")
15
+
20
16
  export function basicTable() {
21
17
  return {
22
18
  name: "TestTable",
@@ -75,19 +71,19 @@ export function view(tableId: string) {
75
71
  }
76
72
 
77
73
  export function automationStep(
78
- actionDefinition = BUILTIN_ACTION_DEFINITIONS.CREATE_ROW
79
- ): AutomationStep {
74
+ actionDefinition = ACTION_DEFINITIONS.CREATE_ROW
75
+ ) {
80
76
  return {
81
- id: utils.newid(),
77
+ id: uuidv4(),
82
78
  ...actionDefinition,
83
79
  }
84
80
  }
85
81
 
86
82
  export function automationTrigger(
87
83
  triggerDefinition = TRIGGER_DEFINITIONS.ROW_SAVED
88
- ): AutomationTrigger {
84
+ ) {
89
85
  return {
90
- id: utils.newid(),
86
+ id: uuidv4(),
91
87
  ...triggerDefinition,
92
88
  }
93
89
  }
@@ -110,7 +106,7 @@ export function newAutomation({ steps, trigger }: any = {}) {
110
106
  return automation
111
107
  }
112
108
 
113
- export function basicAutomation(appId?: string): Automation {
109
+ export function basicAutomation(appId?: string) {
114
110
  return {
115
111
  name: "My Automation",
116
112
  screenId: "kasdkfldsafkl",
@@ -123,22 +119,18 @@ export function basicAutomation(appId?: string): Automation {
123
119
  tagline: "test",
124
120
  icon: "test",
125
121
  description: "test",
126
- type: AutomationStepType.TRIGGER,
122
+ type: "trigger",
127
123
  id: "test",
128
124
  inputs: {},
129
125
  schema: {
130
- inputs: {
131
- properties: {},
132
- },
133
- outputs: {
134
- properties: {},
135
- },
126
+ inputs: {},
127
+ outputs: {},
136
128
  },
137
129
  },
138
130
  steps: [],
139
131
  },
140
132
  type: "automation",
141
- appId: appId!,
133
+ appId,
142
134
  }
143
135
  }
144
136
 
@@ -162,7 +154,7 @@ export function loopAutomation(tableId: string, loopOpts?: any): Automation {
162
154
  inputs: {
163
155
  tableId,
164
156
  },
165
- schema: BUILTIN_ACTION_DEFINITIONS.QUERY_ROWS.schema,
157
+ schema: ACTION_DEFINITIONS.QUERY_ROWS.schema,
166
158
  },
167
159
  {
168
160
  id: "c",
@@ -171,7 +163,7 @@ export function loopAutomation(tableId: string, loopOpts?: any): Automation {
171
163
  internal: true,
172
164
  inputs: loopOpts,
173
165
  blockToLoop: "d",
174
- schema: BUILTIN_ACTION_DEFINITIONS.LOOP.schema,
166
+ schema: ACTION_DEFINITIONS.LOOP.schema,
175
167
  },
176
168
  {
177
169
  id: "d",
@@ -181,7 +173,7 @@ export function loopAutomation(tableId: string, loopOpts?: any): Automation {
181
173
  inputs: {
182
174
  text: "log statement",
183
175
  },
184
- schema: BUILTIN_ACTION_DEFINITIONS.SERVER_LOG.schema,
176
+ schema: ACTION_DEFINITIONS.SERVER_LOG.schema,
185
177
  },
186
178
  ],
187
179
  trigger: {