@budibase/worker 3.13.8 → 3.13.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@budibase/worker",
3
3
  "email": "hi@budibase.com",
4
- "version": "3.13.8",
4
+ "version": "3.13.10",
5
5
  "description": "Budibase background service",
6
6
  "main": "src/index.ts",
7
7
  "repository": {
@@ -113,5 +113,5 @@
113
113
  }
114
114
  }
115
115
  },
116
- "gitHead": "3550187f1ceddaa3d86735f514c3b771603ac596"
116
+ "gitHead": "9d6b86cc387bd1e3cc4ec8f3a1c7f8f3a94d1205"
117
117
  }
@@ -16,25 +16,27 @@ import {
16
16
 
17
17
  export async function fetch(ctx: Ctx<void, FetchGlobalRolesResponse>) {
18
18
  const tenantId = ctx.user!.tenantId
19
- // always use the dev apps as they'll be most up to date (true)
20
- const apps = (await dbCore.getAllApps({ tenantId, all: true })) as App[]
21
- const promises = []
22
- for (let app of apps) {
23
- // use dev app IDs
24
- promises.push(roles.getAllRoles(app.appId))
25
- }
26
- const roleList = await Promise.all(promises)
27
- const response: any = {}
28
- for (let app of apps) {
29
- const deployedAppId = dbCore.getProdAppID(app.appId)
30
- response[deployedAppId] = {
31
- roles: roleList.shift(),
32
- name: app.name,
33
- version: app.version,
34
- url: app.url,
19
+ await context.doInTenant(tenantId, async () => {
20
+ // always use the dev apps as they'll be most up to date (true)
21
+ const apps = await dbCore.getAllApps({ all: true })
22
+ const promises = []
23
+ for (let app of apps) {
24
+ // use dev app IDs
25
+ promises.push(roles.getAllRoles(app.appId))
35
26
  }
36
- }
37
- ctx.body = response
27
+ const roleList = await Promise.all(promises)
28
+ const response: any = {}
29
+ for (let app of apps) {
30
+ const deployedAppId = dbCore.getProdAppID(app.appId)
31
+ response[deployedAppId] = {
32
+ roles: roleList.shift(),
33
+ name: app.name,
34
+ version: app.version,
35
+ url: app.url,
36
+ }
37
+ }
38
+ ctx.body = response
39
+ })
38
40
  }
39
41
 
40
42
  export async function find(ctx: Ctx<void, FindGlobalRoleResponse>) {
@@ -7,6 +7,7 @@ import {
7
7
  AddSSoUserResponse,
8
8
  BulkUserRequest,
9
9
  BulkUserResponse,
10
+ ChangeTenantOwnerEmailRequest,
10
11
  CheckInviteResponse,
11
12
  CountUserResponse,
12
13
  CreateAdminUserRequest,
@@ -106,6 +107,31 @@ export const save = async (ctx: UserCtx<UnsavedUser, SaveUserResponse>) => {
106
107
  }
107
108
  }
108
109
 
110
+ export const changeTenantOwnerEmail = async (
111
+ ctx: Ctx<ChangeTenantOwnerEmailRequest, void>
112
+ ) => {
113
+ const { newAccountEmail, originalEmail, tenantIds } = ctx.request.body
114
+ try {
115
+ for (const tenantId of tenantIds) {
116
+ await tenancy.doInTenant(tenantId, async () => {
117
+ const tenantUser = await userSdk.db.getUserByEmail(originalEmail)
118
+ if (!tenantUser) {
119
+ return
120
+ }
121
+ tenantUser.email = newAccountEmail
122
+ await userSdk.db.save(tenantUser, {
123
+ currentUserId: tenantUser._id,
124
+ isAccountHolder: true,
125
+ allowChangingEmail: true,
126
+ })
127
+ })
128
+ }
129
+ ctx.status = 200
130
+ } catch (err: any) {
131
+ ctx.throw(err.status || 400, err)
132
+ }
133
+ }
134
+
109
135
  export const addSsoSupport = async (
110
136
  ctx: Ctx<AddSSoUserRequest, AddSSoUserResponse>
111
137
  ) => {
package/src/api/index.ts CHANGED
@@ -120,6 +120,10 @@ const NO_TENANCY_ENDPOINTS = [
120
120
  route: "/api/global/users/accountholder",
121
121
  method: "GET",
122
122
  },
123
+ {
124
+ route: "/api/global/users/tenant/owner",
125
+ method: "PUT",
126
+ },
123
127
  ]
124
128
 
125
129
  // most public endpoints are gets, but some are posts
@@ -294,6 +294,23 @@ describe("/api/global/groups", () => {
294
294
  })
295
295
  })
296
296
 
297
+ describe("role filtering", () => {
298
+ it("should filter out roles for non-existent apps when enriching group", async () => {
299
+ const fakeAppId = "app_fake"
300
+ const group = structures.groups.UserGroup()
301
+
302
+ const { body: savedGroup } = await config.api.groups.saveGroup(group)
303
+ await config.api.groups.updateGroupApps(savedGroup._id, {
304
+ add: [{ appId: fakeAppId, roleId: "BASIC" }],
305
+ })
306
+ const { body: retrievedGroup } = await config.api.groups.find(
307
+ savedGroup._id
308
+ )
309
+
310
+ expect(Object.keys(retrievedGroup.roles)).not.toContain(fakeAppId)
311
+ })
312
+ })
313
+
297
314
  describe("with global builder role", () => {
298
315
  let builder: User
299
316
  let group: UserGroup
@@ -59,6 +59,16 @@ function buildInviteAcceptValidation() {
59
59
  }).required().unknown(true))
60
60
  }
61
61
 
62
+ function buildChangeTenantOwnerEmailValidation() {
63
+ return auth.joiValidator.body(
64
+ Joi.object({
65
+ newAccountEmail: Joi.string().required(),
66
+ originalEmail: Joi.string().required(),
67
+ tenantIds: Joi.array().items(Joi.string()).required(),
68
+ }).required()
69
+ )
70
+ }
71
+
62
72
  router
63
73
  .post(
64
74
  "/api/global/users",
@@ -140,5 +150,11 @@ router
140
150
  .get("/api/global/users/tenant/:id", controller.tenantUserLookup)
141
151
  // global endpoint but needs to come at end (blocks other endpoints otherwise)
142
152
  .get("/api/global/users/:id", auth.builderOrAdmin, controller.find)
153
+ .put(
154
+ "/api/global/users/tenant/owner",
155
+ cloudRestricted,
156
+ buildChangeTenantOwnerEmailValidation(),
157
+ controller.changeTenantOwnerEmail
158
+ )
143
159
 
144
160
  export default router
@@ -1,4 +1,4 @@
1
- import { UserGroup } from "@budibase/types"
1
+ import { UserGroup, UpdateGroupAppRequest } from "@budibase/types"
2
2
  import { TestAPI } from "./base"
3
3
 
4
4
  export class GroupsAPI extends TestAPI {
@@ -53,6 +53,19 @@ export class GroupsAPI extends TestAPI {
53
53
  .expect(expect)
54
54
  }
55
55
 
56
+ updateGroupApps = (
57
+ groupId: string,
58
+ body: UpdateGroupAppRequest,
59
+ { expect } = { expect: 200 }
60
+ ) => {
61
+ return this.request
62
+ .post(`/api/global/groups/${groupId}/apps`)
63
+ .send(body)
64
+ .set(this.config.defaultHeaders())
65
+ .expect("Content-Type", /json/)
66
+ .expect(expect)
67
+ }
68
+
56
69
  fetch = ({ expect } = { expect: 200 }) => {
57
70
  return this.request
58
71
  .get(`/api/global/groups`)