@budibase/server 2.4.42-alpha.8 → 2.4.43

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 (65) hide show
  1. package/builder/assets/favicon.e7fc7733.png +0 -0
  2. package/builder/assets/{index.89bb7cf4.js → index.8b377b88.js} +384 -385
  3. package/builder/assets/index.b0e3aca6.css +6 -0
  4. package/builder/index.html +7 -7
  5. package/dist/api/controllers/application.js +24 -28
  6. package/dist/api/controllers/row/external.js +0 -15
  7. package/dist/api/controllers/static/index.js +24 -84
  8. package/dist/api/controllers/static/templates/BudibaseApp.svelte +11 -34
  9. package/dist/api/controllers/table/utils.js +4 -2
  10. package/dist/api/routes/public/index.js +0 -8
  11. package/dist/app.js +0 -1
  12. package/dist/integrations/googlesheets.js +0 -4
  13. package/dist/integrations/redis.js +1 -1
  14. package/dist/middleware/currentapp.js +27 -1
  15. package/dist/package.json +12 -13
  16. package/dist/sdk/users/utils.js +6 -11
  17. package/dist/tsconfig.build.tsbuildinfo +1 -1
  18. package/dist/utilities/fileSystem/filesystem.js +0 -4
  19. package/dist/utilities/global.js +7 -17
  20. package/jest.config.ts +1 -1
  21. package/package.json +13 -14
  22. package/scripts/test.sh +5 -3
  23. package/specs/openapi.json +0 -39
  24. package/specs/openapi.yaml +0 -169
  25. package/specs/resources/application.ts +0 -11
  26. package/specs/resources/index.ts +0 -2
  27. package/src/api/controllers/application.ts +21 -20
  28. package/src/api/controllers/row/external.ts +0 -14
  29. package/src/api/controllers/static/index.ts +26 -69
  30. package/src/api/controllers/static/templates/BudibaseApp.svelte +11 -34
  31. package/src/api/controllers/table/utils.ts +12 -20
  32. package/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap +48 -48
  33. package/src/api/routes/public/index.ts +1 -10
  34. package/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap +22 -22
  35. package/src/api/routes/tests/__snapshots__/view.spec.js.snap +5 -5
  36. package/src/api/routes/tests/appSync.spec.ts +1 -1
  37. package/src/api/routes/tests/internalSearch.spec.js +6 -6
  38. package/src/app.ts +1 -2
  39. package/src/automations/automationUtils.ts +1 -1
  40. package/src/automations/tests/automation.spec.js +84 -0
  41. package/src/db/defaultData/datasource_bb_default.ts +1 -1
  42. package/src/definitions/openapi.ts +0 -15
  43. package/src/integrations/googlesheets.ts +0 -4
  44. package/src/integrations/redis.ts +1 -1
  45. package/src/integrations/tests/googlesheets.spec.ts +0 -4
  46. package/src/integrations/tests/redis.spec.ts +5 -9
  47. package/src/middleware/currentapp.ts +32 -3
  48. package/src/middleware/tests/currentapp.spec.js +42 -6
  49. package/src/sdk/users/utils.ts +7 -18
  50. package/src/tests/jestSetup.ts +1 -5
  51. package/src/tests/utilities/TestConfiguration.ts +19 -7
  52. package/src/tests/utilities/structures.ts +1 -13
  53. package/src/utilities/fileSystem/filesystem.ts +0 -4
  54. package/src/utilities/global.ts +9 -21
  55. package/src/utilities/rowProcessor/index.ts +1 -1
  56. package/builder/assets/index.7f9a008b.css +0 -6
  57. package/dist/api/controllers/public/metrics.js +0 -113
  58. package/dist/api/routes/public/metrics.js +0 -30
  59. package/specs/resources/metrics.ts +0 -81
  60. package/src/api/controllers/public/metrics.ts +0 -251
  61. package/src/api/controllers/table/tests/utils.spec.ts +0 -97
  62. package/src/api/routes/public/metrics.ts +0 -28
  63. package/src/api/routes/public/tests/metrics.spec.js +0 -34
  64. package/src/automations/tests/automation.spec.ts +0 -99
  65. package/src/sdk/users/tests/utils.spec.ts +0 -159
@@ -23,7 +23,7 @@ import { LoopStep, LoopStepType, LoopInput } from "../definitions/automations"
23
23
  * @returns {object} The inputs object which has had all the various types supported by this function converted to their
24
24
  * primitive types.
25
25
  */
26
- export function cleanInputValues(inputs: Record<string, any>, schema?: any) {
26
+ export function cleanInputValues(inputs: Record<string, any>, schema: any) {
27
27
  if (schema == null) {
28
28
  return inputs
29
29
  }
@@ -0,0 +1,84 @@
1
+ jest.mock("../../threads/automation")
2
+ jest.mock("../../utilities/redis", () => ({
3
+ init: jest.fn(),
4
+ checkTestFlag: () => {
5
+ return false
6
+ },
7
+ }))
8
+
9
+ jest.spyOn(global.console, "error")
10
+
11
+ require("../../environment")
12
+ const automation = require("../index")
13
+ const thread = require("../../threads/automation")
14
+ const triggers = require("../triggers")
15
+ const { basicAutomation } = require("../../tests/utilities/structures")
16
+ const { wait } = require("../../utilities")
17
+ const { makePartial } = require("../../tests/utilities")
18
+ const { cleanInputValues } = require("../automationUtils")
19
+ const setup = require("./utilities")
20
+
21
+ describe("Run through some parts of the automations system", () => {
22
+ let config = setup.getConfig()
23
+
24
+ beforeAll(async () => {
25
+ await automation.init()
26
+ await config.init()
27
+ })
28
+
29
+ afterAll(setup.afterAll)
30
+
31
+ it("should be able to init in builder", async () => {
32
+ await triggers.externalTrigger(basicAutomation(), { a: 1, appId: config.appId })
33
+ await wait(100)
34
+ expect(thread.execute).toHaveBeenCalled()
35
+ })
36
+
37
+ it("should check coercion", async () => {
38
+ const table = await config.createTable()
39
+ const automation = basicAutomation()
40
+ automation.definition.trigger.inputs.tableId = table._id
41
+ automation.definition.trigger.stepId = "APP"
42
+ automation.definition.trigger.inputs.fields = { a: "number" }
43
+ await triggers.externalTrigger(automation, {
44
+ appId: config.getAppId(),
45
+ fields: {
46
+ a: "1"
47
+ }
48
+ })
49
+ await wait(100)
50
+ expect(thread.execute).toHaveBeenCalledWith(makePartial({
51
+ data: {
52
+ event: {
53
+ fields: {
54
+ a: 1
55
+ }
56
+ }
57
+ }
58
+ }), expect.any(Function))
59
+ })
60
+
61
+ it("should be able to clean inputs with the utilities", () => {
62
+ // can't clean without a schema
63
+ let output = cleanInputValues({a: "1"})
64
+ expect(output.a).toBe("1")
65
+ output = cleanInputValues({a: "1", b: "true", c: "false", d: 1, e: "help"}, {
66
+ properties: {
67
+ a: {
68
+ type: "number",
69
+ },
70
+ b: {
71
+ type: "boolean",
72
+ },
73
+ c: {
74
+ type: "boolean",
75
+ }
76
+ }
77
+ })
78
+ expect(output.a).toBe(1)
79
+ expect(output.b).toBe(true)
80
+ expect(output.c).toBe(false)
81
+ expect(output.d).toBe(1)
82
+ expect(output.e).toBe("help")
83
+ })
84
+ })
@@ -34,7 +34,7 @@ function syncLastIds(table: Table, rowCount: number) {
34
34
  })
35
35
  }
36
36
 
37
- function tableImport(table: Table, data: Row[]) {
37
+ function tableImport(table: Table, data: Row) {
38
38
  const cloneTable = cloneDeep(table)
39
39
  const rowDocs = importToRows(data, cloneTable)
40
40
  syncLastIds(cloneTable, rowDocs.length)
@@ -22,10 +22,6 @@ export interface paths {
22
22
  /** Based on application properties (currently only name) search for applications. */
23
23
  post: operations["appSearch"];
24
24
  };
25
- "/metrics": {
26
- /** Output metrics in OpenMetrics format compatible with Prometheus */
27
- get: operations["metricsGet"];
28
- };
29
25
  "/queries/{queryId}": {
30
26
  /** Queries which have been created within a Budibase app can be executed using this, */
31
27
  post: operations["queryExecute"];
@@ -848,17 +844,6 @@ export interface operations {
848
844
  };
849
845
  };
850
846
  };
851
- /** Output metrics in OpenMetrics format compatible with Prometheus */
852
- metricsGet: {
853
- responses: {
854
- /** Returns tenant metrics. */
855
- 200: {
856
- content: {
857
- "text/plain": string;
858
- };
859
- };
860
- };
861
- };
862
847
  /** Queries which have been created within a Budibase app can be executed using this, */
863
848
  queryExecute: {
864
849
  parameters: {
@@ -245,10 +245,6 @@ class GoogleSheetsIntegration implements DatasourcePlus {
245
245
  }
246
246
 
247
247
  async buildSchema(datasourceId: string, entities: Record<string, Table>) {
248
- // not fully configured yet
249
- if (!this.config.auth) {
250
- return
251
- }
252
248
  await this.connect()
253
249
  const sheets = this.client.sheetsByIndex
254
250
  const tables: Record<string, Table> = {}
@@ -92,7 +92,7 @@ class RedisIntegration {
92
92
  }
93
93
 
94
94
  async disconnect() {
95
- return this.client.quit()
95
+ return this.client.disconnect()
96
96
  }
97
97
 
98
98
  async redisContext(query: Function) {
@@ -39,10 +39,6 @@ describe("Google Sheets Integration", () => {
39
39
  config.setGoogleAuth("test")
40
40
  })
41
41
 
42
- afterAll(async () => {
43
- await config.end()
44
- })
45
-
46
42
  beforeEach(async () => {
47
43
  integration = new GoogleSheetsIntegration.integration({
48
44
  spreadsheetId: "randomId",
@@ -3,17 +3,17 @@ import { default as RedisIntegration } from "../redis"
3
3
 
4
4
  class TestConfiguration {
5
5
  integration: any
6
+ redis: any
6
7
 
7
8
  constructor(config: any = {}) {
8
9
  this.integration = new RedisIntegration.integration(config)
9
- // have to kill the basic integration before replacing it
10
- this.integration.client.quit()
11
- this.integration.client = new Redis({
10
+ this.redis = new Redis({
12
11
  data: {
13
12
  test: "test",
14
13
  result: "1",
15
14
  },
16
15
  })
16
+ this.integration.client = this.redis
17
17
  }
18
18
  }
19
19
 
@@ -24,17 +24,13 @@ describe("Redis Integration", () => {
24
24
  config = new TestConfiguration()
25
25
  })
26
26
 
27
- afterAll(() => {
28
- config.integration.disconnect()
29
- })
30
-
31
27
  it("calls the create method with the correct params", async () => {
32
28
  const body = {
33
29
  key: "key",
34
30
  value: "value",
35
31
  }
36
32
  await config.integration.create(body)
37
- expect(await config.integration.client.get("key")).toEqual("value")
33
+ expect(await config.redis.get("key")).toEqual("value")
38
34
  })
39
35
 
40
36
  it("calls the read method with the correct params", async () => {
@@ -50,7 +46,7 @@ describe("Redis Integration", () => {
50
46
  key: "test",
51
47
  }
52
48
  await config.integration.delete(body)
53
- expect(await config.integration.client.get(body.key)).toEqual(null)
49
+ expect(await config.redis.get(body.key)).toEqual(null)
54
50
  })
55
51
 
56
52
  it("calls the pipeline method with the correct params", async () => {
@@ -2,6 +2,7 @@ import {
2
2
  utils,
3
3
  constants,
4
4
  roles,
5
+ db as dbCore,
5
6
  tenancy,
6
7
  context,
7
8
  } from "@budibase/backend-core"
@@ -9,15 +10,34 @@ import { generateUserMetadataID, isDevAppID } from "../db/utils"
9
10
  import { getCachedSelf } from "../utilities/global"
10
11
  import env from "../environment"
11
12
  import { isWebhookEndpoint } from "./utils"
12
- import { UserCtx } from "@budibase/types"
13
+ import { BBContext } from "@budibase/types"
13
14
 
14
- export default async (ctx: UserCtx, next: any) => {
15
+ export default async (ctx: BBContext, next: any) => {
15
16
  // try to get the appID from the request
16
17
  let requestAppId = await utils.getAppIdFromCtx(ctx)
17
- if (!requestAppId) {
18
+ // get app cookie if it exists
19
+ let appCookie: { appId?: string } | undefined
20
+ try {
21
+ appCookie = utils.getCookie(ctx, constants.Cookie.CurrentApp)
22
+ } catch (err) {
23
+ utils.clearCookie(ctx, constants.Cookie.CurrentApp)
24
+ }
25
+ if (!appCookie && !requestAppId) {
18
26
  return next()
19
27
  }
20
28
 
29
+ // check the app exists referenced in cookie
30
+ if (appCookie) {
31
+ const appId = appCookie.appId
32
+ const exists = await dbCore.dbExists(appId)
33
+ if (!exists) {
34
+ utils.clearCookie(ctx, constants.Cookie.CurrentApp)
35
+ return next()
36
+ }
37
+ // if the request app ID wasn't set, update it with the cookie
38
+ requestAppId = requestAppId || appId
39
+ }
40
+
21
41
  // deny access to application preview
22
42
  if (!env.isTest()) {
23
43
  if (
@@ -25,6 +45,7 @@ export default async (ctx: UserCtx, next: any) => {
25
45
  !isWebhookEndpoint(ctx) &&
26
46
  (!ctx.user || !ctx.user.builder || !ctx.user.builder.global)
27
47
  ) {
48
+ utils.clearCookie(ctx, constants.Cookie.CurrentApp)
28
49
  return ctx.redirect("/")
29
50
  }
30
51
  }
@@ -106,6 +127,14 @@ export default async (ctx: UserCtx, next: any) => {
106
127
  role: await roles.getRole(roleId),
107
128
  }
108
129
  }
130
+ if (
131
+ (requestAppId !== appId ||
132
+ appCookie == null ||
133
+ appCookie.appId !== requestAppId) &&
134
+ !skipCookie
135
+ ) {
136
+ utils.setCookie(ctx, { appId }, constants.Cookie.CurrentApp)
137
+ }
109
138
 
110
139
  return next()
111
140
  })
@@ -158,22 +158,27 @@ describe("Current app middleware", () => {
158
158
  })
159
159
 
160
160
  describe("check functionality when logged in", () => {
161
- async function checkExpected() {
161
+ async function checkExpected(setCookie) {
162
162
  config.setUser()
163
163
  await config.executeMiddleware()
164
-
164
+ let { utils } = require("@budibase/backend-core")
165
+ if (setCookie) {
166
+ expect(utils.setCookie).toHaveBeenCalled()
167
+ } else {
168
+ expect(utils.setCookie).not.toHaveBeenCalled()
169
+ }
165
170
  expect(config.ctx.roleId).toEqual("PUBLIC")
166
171
  expect(config.ctx.user.role._id).toEqual("PUBLIC")
167
172
  expect(config.ctx.appId).toEqual("app_test")
168
173
  expect(config.next).toHaveBeenCalled()
169
174
  }
170
175
 
171
- it("should be able to setup an app token on a first call", async () => {
176
+ it("should be able to setup an app token when cookie not setup", async () => {
172
177
  mockAuthWithCookie()
173
- await checkExpected()
178
+ await checkExpected(true)
174
179
  })
175
180
 
176
- it("should perform correct on a first call", async () => {
181
+ it("should perform correct when no cookie exists", async () => {
177
182
  mockReset()
178
183
  jest.mock("@budibase/backend-core", () => {
179
184
  const core = jest.requireActual("@budibase/backend-core")
@@ -201,7 +206,38 @@ describe("Current app middleware", () => {
201
206
  },
202
207
  }
203
208
  })
204
- await checkExpected()
209
+ await checkExpected(true)
210
+ })
211
+
212
+ it("lastly check what occurs when cookie doesn't need updated", async () => {
213
+ mockReset()
214
+ jest.mock("@budibase/backend-core", () => {
215
+ const core = jest.requireActual("@budibase/backend-core")
216
+ return {
217
+ ...core,
218
+ db: {
219
+ ...core.db,
220
+ dbExists: () => true,
221
+ },
222
+ utils: {
223
+ getAppIdFromCtx: () => {
224
+ return "app_test"
225
+ },
226
+ setCookie: jest.fn(),
227
+ getCookie: () => ({ appId: "app_test", roleId: "PUBLIC" }),
228
+ },
229
+ cache: {
230
+ user: {
231
+ getUser: async id => {
232
+ return {
233
+ _id: "us_uuid1",
234
+ }
235
+ },
236
+ },
237
+ },
238
+ }
239
+ })
240
+ await checkExpected(false)
205
241
  })
206
242
  })
207
243
  })
@@ -6,33 +6,22 @@ import {
6
6
  InternalTables,
7
7
  } from "../../db/utils"
8
8
  import { isEqual } from "lodash"
9
- import { ContextUser, UserMetadata } from "@budibase/types"
10
9
 
11
- export function combineMetadataAndUser(
12
- user: ContextUser,
13
- metadata: UserMetadata | UserMetadata[]
14
- ) {
15
- const metadataId = generateUserMetadataID(user._id!)
16
- const found = Array.isArray(metadata)
17
- ? metadata.find(doc => doc._id === metadataId)
18
- : metadata
10
+ export function combineMetadataAndUser(user: any, metadata: any) {
19
11
  // skip users with no access
20
- if (
21
- user.roleId == null ||
22
- user.roleId === rolesCore.BUILTIN_ROLE_IDS.PUBLIC
23
- ) {
24
- // If it exists and it should not, we must remove it
25
- if (found?._id) {
26
- return { ...found, _deleted: true }
27
- }
12
+ if (user.roleId === rolesCore.BUILTIN_ROLE_IDS.PUBLIC) {
28
13
  return null
29
14
  }
30
15
  delete user._rev
16
+ const metadataId = generateUserMetadataID(user._id)
31
17
  const newDoc = {
32
18
  ...user,
33
19
  _id: metadataId,
34
20
  tableId: InternalTables.USER_METADATA,
35
21
  }
22
+ const found = Array.isArray(metadata)
23
+ ? metadata.find(doc => doc._id === metadataId)
24
+ : metadata
36
25
  // copy rev over for the purposes of equality check
37
26
  if (found) {
38
27
  newDoc._rev = found._rev
@@ -66,7 +55,7 @@ export async function syncGlobalUsers() {
66
55
  ])
67
56
  const toWrite = []
68
57
  for (let user of users) {
69
- const combined = combineMetadataAndUser(user, metadata)
58
+ const combined = await combineMetadataAndUser(user, metadata)
70
59
  if (combined) {
71
60
  toWrite.push(combined)
72
61
  }
@@ -1,6 +1,6 @@
1
1
  import "./logging"
2
2
  import env from "../environment"
3
- import { env as coreEnv, timers } from "@budibase/backend-core"
3
+ import { env as coreEnv } from "@budibase/backend-core"
4
4
  import { testContainerUtils } from "@budibase/backend-core/tests"
5
5
 
6
6
  if (!process.env.DEBUG) {
@@ -17,7 +17,3 @@ if (!process.env.CI) {
17
17
  }
18
18
 
19
19
  testContainerUtils.setupEnv(env, coreEnv)
20
-
21
- afterAll(() => {
22
- timers.cleanup()
23
- })
@@ -47,7 +47,6 @@ import {
47
47
  SourceName,
48
48
  Table,
49
49
  SearchFilters,
50
- UserRoles,
51
50
  } from "@budibase/types"
52
51
 
53
52
  type DefaultUserValues = {
@@ -166,8 +165,6 @@ class TestConfiguration {
166
165
  }
167
166
  if (this.server) {
168
167
  this.server.close()
169
- } else {
170
- require("../../app").default.close()
171
168
  }
172
169
  if (this.allApps) {
173
170
  cleanup(this.allApps.map(app => app.appId))
@@ -278,7 +275,7 @@ class TestConfiguration {
278
275
  email?: string
279
276
  builder?: boolean
280
277
  admin?: boolean
281
- roles?: UserRoles
278
+ roles?: any
282
279
  } = {}
283
280
  ) {
284
281
  let { id, firstName, lastName, email, builder, admin, roles } = user
@@ -331,13 +328,21 @@ class TestConfiguration {
331
328
  sessionId: "sessionid",
332
329
  tenantId: this.getTenantId(),
333
330
  }
331
+ const app = {
332
+ roleId: roleId,
333
+ appId,
334
+ }
334
335
  const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET)
336
+ const appToken = auth.jwt.sign(app, coreEnv.JWT_SECRET)
335
337
 
336
338
  // returning necessary request headers
337
339
  await cache.user.invalidateUser(userId)
338
340
  return {
339
341
  Accept: "application/json",
340
- Cookie: [`${constants.Cookie.Auth}=${authToken}`],
342
+ Cookie: [
343
+ `${constants.Cookie.Auth}=${authToken}`,
344
+ `${constants.Cookie.CurrentApp}=${appToken}`,
345
+ ],
341
346
  [constants.Header.APP_ID]: appId,
342
347
  }
343
348
  })
@@ -352,11 +357,18 @@ class TestConfiguration {
352
357
  sessionId: "sessionid",
353
358
  tenantId,
354
359
  }
360
+ const app = {
361
+ roleId: roles.BUILTIN_ROLE_IDS.ADMIN,
362
+ appId: this.appId,
363
+ }
355
364
  const authToken = auth.jwt.sign(authObj, coreEnv.JWT_SECRET)
356
-
365
+ const appToken = auth.jwt.sign(app, coreEnv.JWT_SECRET)
357
366
  const headers: any = {
358
367
  Accept: "application/json",
359
- Cookie: [`${constants.Cookie.Auth}=${authToken}`],
368
+ Cookie: [
369
+ `${constants.Cookie.Auth}=${authToken}`,
370
+ `${constants.Cookie.CurrentApp}=${appToken}`,
371
+ ],
360
372
  [constants.Header.CSRF_TOKEN]: this.defaultUserValues.csrfToken,
361
373
  Host: this.tenantHost(),
362
374
  ...extras,
@@ -106,7 +106,7 @@ export function newAutomation({ steps, trigger }: any = {}) {
106
106
  return automation
107
107
  }
108
108
 
109
- export function basicAutomation(appId?: string) {
109
+ export function basicAutomation() {
110
110
  return {
111
111
  name: "My Automation",
112
112
  screenId: "kasdkfldsafkl",
@@ -114,23 +114,11 @@ export function basicAutomation(appId?: string) {
114
114
  uiTree: {},
115
115
  definition: {
116
116
  trigger: {
117
- stepId: AutomationTriggerStepId.APP,
118
- name: "test",
119
- tagline: "test",
120
- icon: "test",
121
- description: "test",
122
- type: "trigger",
123
- id: "test",
124
117
  inputs: {},
125
- schema: {
126
- inputs: {},
127
- outputs: {},
128
- },
129
118
  },
130
119
  steps: [],
131
120
  },
132
121
  type: "automation",
133
- appId,
134
122
  }
135
123
  }
136
124
 
@@ -24,10 +24,6 @@ export const init = () => {
24
24
  }
25
25
  }
26
26
  }
27
- const clientLibPath = join(budibaseTempDir(), "budibase-client.js")
28
- if (env.isTest() && !fs.existsSync(clientLibPath)) {
29
- fs.copyFileSync(require.resolve("@budibase/client"), clientLibPath)
30
- }
31
27
  }
32
28
 
33
29
  /**
@@ -8,7 +8,7 @@ import {
8
8
  } from "@budibase/backend-core"
9
9
  import env from "../environment"
10
10
  import { groups } from "@budibase/pro"
11
- import { UserCtx, ContextUser, User, UserGroup } from "@budibase/types"
11
+ import { BBContext, ContextUser, User } from "@budibase/types"
12
12
 
13
13
  export function updateAppRole(
14
14
  user: ContextUser,
@@ -43,40 +43,33 @@ export function updateAppRole(
43
43
 
44
44
  async function checkGroupRoles(
45
45
  user: ContextUser,
46
- opts: { appId?: string; groups?: UserGroup[] } = {}
46
+ { appId }: { appId?: string } = {}
47
47
  ) {
48
48
  if (user.roleId && user.roleId !== roles.BUILTIN_ROLE_IDS.PUBLIC) {
49
49
  return user
50
50
  }
51
- if (opts.appId) {
52
- user.roleId = await groups.getGroupRoleId(user as User, opts.appId, {
53
- groups: opts.groups,
54
- })
55
- }
56
- // final fallback, simply couldn't find a role - user must be public
57
- if (!user.roleId) {
58
- user.roleId = roles.BUILTIN_ROLE_IDS.PUBLIC
51
+ if (appId) {
52
+ user.roleId = await groups.getGroupRoleId(user as User, appId)
59
53
  }
60
54
  return user
61
55
  }
62
56
 
63
57
  async function processUser(
64
58
  user: ContextUser,
65
- opts: { appId?: string; groups?: UserGroup[] } = {}
59
+ { appId }: { appId?: string } = {}
66
60
  ) {
67
61
  if (user) {
68
62
  delete user.password
69
63
  }
70
- const appId = opts.appId || context.getAppId()
71
- user = updateAppRole(user, { appId })
64
+ user = await updateAppRole(user, { appId })
72
65
  if (!user.roleId && user?.userGroups?.length) {
73
- user = await checkGroupRoles(user, { appId, groups: opts?.groups })
66
+ user = await checkGroupRoles(user, { appId })
74
67
  }
75
68
 
76
69
  return user
77
70
  }
78
71
 
79
- export async function getCachedSelf(ctx: UserCtx, appId: string) {
72
+ export async function getCachedSelf(ctx: BBContext, appId: string) {
80
73
  // this has to be tenant aware, can't depend on the context to find it out
81
74
  // running some middlewares before the tenancy causes context to break
82
75
  const user = await cache.user.getUser(ctx.user?._id!)
@@ -97,7 +90,6 @@ export async function getGlobalUser(userId: string) {
97
90
  export async function getGlobalUsers(users?: ContextUser[]) {
98
91
  const appId = context.getAppId()
99
92
  const db = tenancy.getGlobalDB()
100
- const allGroups = await groups.fetch()
101
93
  let globalUsers
102
94
  if (users) {
103
95
  const globalIds = users.map(user =>
@@ -126,11 +118,7 @@ export async function getGlobalUsers(users?: ContextUser[]) {
126
118
  return globalUsers
127
119
  }
128
120
 
129
- // pass in the groups, meaning we don't actually need to retrieve them for
130
- // each user individually
131
- return Promise.all(
132
- globalUsers.map(user => processUser(user, { groups: allGroups }))
133
- )
121
+ return globalUsers.map(user => updateAppRole(user))
134
122
  }
135
123
 
136
124
  export async function getGlobalUsersFromMetadata(users: ContextUser[]) {
@@ -131,7 +131,7 @@ export function coerce(row: any, type: string) {
131
131
  * @returns {object} the row which has been prepared to be written to the DB.
132
132
  */
133
133
  export function inputProcessing(
134
- user: ContextUser | null,
134
+ user: ContextUser,
135
135
  table: Table,
136
136
  row: Row,
137
137
  opts?: AutoColumnProcessingOpts